diff options
Diffstat (limited to 'js/src/jit/VMFunctions.h')
-rw-r--r-- | js/src/jit/VMFunctions.h | 808 |
1 files changed, 808 insertions, 0 deletions
diff --git a/js/src/jit/VMFunctions.h b/js/src/jit/VMFunctions.h new file mode 100644 index 0000000000..f754d58c71 --- /dev/null +++ b/js/src/jit/VMFunctions.h @@ -0,0 +1,808 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- + * vim: set ts=8 sts=4 et sw=4 tw=99: + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#ifndef jit_VMFunctions_h +#define jit_VMFunctions_h + +#include "mozilla/Attributes.h" + +#include "jspubtd.h" + +#include "jit/CompileInfo.h" +#include "jit/JitFrames.h" + +namespace js { + +class NamedLambdaObject; +class WithScope; +class InlineTypedObject; +class GeneratorObject; +class TypedArrayObject; + +namespace jit { + +enum DataType { + Type_Void, + Type_Bool, + Type_Int32, + Type_Double, + Type_Pointer, + Type_Object, + Type_Value, + Type_Handle +}; + +struct PopValues +{ + uint32_t numValues; + + explicit PopValues(uint32_t numValues) + : numValues(numValues) + { } +}; + +enum MaybeTailCall { + TailCall, + NonTailCall +}; + +// Contains information about a virtual machine function that can be called +// from JIT code. Functions described in this manner must conform to a simple +// protocol: the return type must have a special "failure" value (for example, +// false for bool, or nullptr for Objects). If the function is designed to +// return a value that does not meet this requirement - such as +// object-or-nullptr, or an integer, an optional, final outParam can be +// specified. In this case, the return type must be boolean to indicate +// failure. +// +// All functions described by VMFunction take a JSContext * as a first +// argument, and are treated as re-entrant into the VM and therefore fallible. +struct VMFunction +{ + // Global linked list of all VMFunctions. + static VMFunction* functions; + VMFunction* next; + + // Address of the C function. + void* wrapped; + + const char* name_; + + // Number of arguments expected, excluding JSContext * as an implicit + // first argument and an outparam as a possible implicit final argument. + uint32_t explicitArgs; + + enum ArgProperties { + WordByValue = 0, + DoubleByValue = 1, + WordByRef = 2, + DoubleByRef = 3, + // BitMask version. + Word = 0, + Double = 1, + ByRef = 2 + }; + + // Contains properties about the first 16 arguments. + uint32_t argumentProperties; + + // Which arguments should be passed in float register on platforms that + // have them. + uint32_t argumentPassedInFloatRegs; + + // The outparam may be any Type_*, and must be the final argument to the + // function, if not Void. outParam != Void implies that the return type + // has a boolean failure mode. + DataType outParam; + + // Type returned by the C function and used by the VMFunction wrapper to + // check for failures of the C function. Valid failure/return types are + // boolean and object pointers which are asserted inside the VMFunction + // constructor. If the C function use an outparam (!= Type_Void), then + // the only valid failure/return type is boolean -- object pointers are + // pointless because the wrapper will only use it to compare it against + // nullptr before discarding its value. + DataType returnType; + + // Note: a maximum of seven root types is supported. + enum RootType { + RootNone = 0, + RootObject, + RootString, + RootPropertyName, + RootFunction, + RootValue, + RootCell + }; + + // Contains an combination of enumerated types used by the gc for marking + // arguments of the VM wrapper. + uint64_t argumentRootTypes; + + // The root type of the out param if outParam == Type_Handle. + RootType outParamRootType; + + // Number of Values the VM wrapper should pop from the stack when it returns. + // Used by baseline IC stubs so that they can use tail calls to call the VM + // wrapper. + uint32_t extraValuesToPop; + + // On some architectures, called functions need to explicitly push their + // return address, for a tail call, there is nothing to push, so tail-callness + // needs to be known at compile time. + MaybeTailCall expectTailCall; + + uint32_t argc() const { + // JSContext * + args + (OutParam? *) + return 1 + explicitArgc() + ((outParam == Type_Void) ? 0 : 1); + } + + DataType failType() const { + return returnType; + } + + ArgProperties argProperties(uint32_t explicitArg) const { + return ArgProperties((argumentProperties >> (2 * explicitArg)) & 3); + } + + RootType argRootType(uint32_t explicitArg) const { + return RootType((argumentRootTypes >> (3 * explicitArg)) & 7); + } + + bool argPassedInFloatReg(uint32_t explicitArg) const { + return ((argumentPassedInFloatRegs >> explicitArg) & 1) == 1; + } + + const char* name() const { + return name_; + } + + // Return the stack size consumed by explicit arguments. + size_t explicitStackSlots() const { + size_t stackSlots = explicitArgs; + + // Fetch all double-word flags of explicit arguments. + uint32_t n = + ((1 << (explicitArgs * 2)) - 1) // = Explicit argument mask. + & 0x55555555 // = Mask double-size args. + & argumentProperties; + + // Add the number of double-word flags. (expect a few loop + // iteration) + while (n) { + stackSlots++; + n &= n - 1; + } + return stackSlots; + } + + // Double-size argument which are passed by value are taking the space + // of 2 C arguments. This function is used to compute the number of + // argument expected by the C function. This is not the same as + // explicitStackSlots because reference to stack slots may take one less + // register in the total count. + size_t explicitArgc() const { + size_t stackSlots = explicitArgs; + + // Fetch all explicit arguments. + uint32_t n = + ((1 << (explicitArgs * 2)) - 1) // = Explicit argument mask. + & argumentProperties; + + // Filter double-size arguments (0x5 = 0b0101) and remove (& ~) + // arguments passed by reference (0b1010 >> 1 == 0b0101). + n = (n & 0x55555555) & ~(n >> 1); + + // Add the number of double-word transfered by value. (expect a few + // loop iteration) + while (n) { + stackSlots++; + n &= n - 1; + } + return stackSlots; + } + + size_t doubleByRefArgs() const { + size_t count = 0; + + // Fetch all explicit arguments. + uint32_t n = + ((1 << (explicitArgs * 2)) - 1) // = Explicit argument mask. + & argumentProperties; + + // Filter double-size arguments (0x5 = 0b0101) and take (&) only + // arguments passed by reference (0b1010 >> 1 == 0b0101). + n = (n & 0x55555555) & (n >> 1); + + // Add the number of double-word transfered by refference. (expect a + // few loop iterations) + while (n) { + count++; + n &= n - 1; + } + return count; + } + + VMFunction(void* wrapped, const char* name, uint32_t explicitArgs, uint32_t argumentProperties, + uint32_t argumentPassedInFloatRegs, uint64_t argRootTypes, + DataType outParam, RootType outParamRootType, DataType returnType, + uint32_t extraValuesToPop = 0, MaybeTailCall expectTailCall = NonTailCall) + : wrapped(wrapped), + name_(name), + explicitArgs(explicitArgs), + argumentProperties(argumentProperties), + argumentPassedInFloatRegs(argumentPassedInFloatRegs), + outParam(outParam), + returnType(returnType), + argumentRootTypes(argRootTypes), + outParamRootType(outParamRootType), + extraValuesToPop(extraValuesToPop), + expectTailCall(expectTailCall) + { + // Check for valid failure/return type. + MOZ_ASSERT_IF(outParam != Type_Void, returnType == Type_Bool); + MOZ_ASSERT(returnType == Type_Bool || + returnType == Type_Object); + } + + VMFunction(const VMFunction& o) { + *this = o; + addToFunctions(); + } + + private: + // Add this to the global list of VMFunctions. + void addToFunctions(); +}; + +template <class> struct TypeToDataType { /* Unexpected return type for a VMFunction. */ }; +template <> struct TypeToDataType<bool> { static const DataType result = Type_Bool; }; +template <> struct TypeToDataType<JSObject*> { static const DataType result = Type_Object; }; +template <> struct TypeToDataType<NativeObject*> { static const DataType result = Type_Object; }; +template <> struct TypeToDataType<PlainObject*> { static const DataType result = Type_Object; }; +template <> struct TypeToDataType<InlineTypedObject*> { static const DataType result = Type_Object; }; +template <> struct TypeToDataType<NamedLambdaObject*> { static const DataType result = Type_Object; }; +template <> struct TypeToDataType<ArrayObject*> { static const DataType result = Type_Object; }; +template <> struct TypeToDataType<TypedArrayObject*> { static const DataType result = Type_Object; }; +template <> struct TypeToDataType<JSString*> { static const DataType result = Type_Object; }; +template <> struct TypeToDataType<JSFlatString*> { static const DataType result = Type_Object; }; +template <> struct TypeToDataType<HandleObject> { static const DataType result = Type_Handle; }; +template <> struct TypeToDataType<HandleString> { static const DataType result = Type_Handle; }; +template <> struct TypeToDataType<HandlePropertyName> { static const DataType result = Type_Handle; }; +template <> struct TypeToDataType<HandleFunction> { static const DataType result = Type_Handle; }; +template <> struct TypeToDataType<Handle<NativeObject*> > { static const DataType result = Type_Handle; }; +template <> struct TypeToDataType<Handle<InlineTypedObject*> > { static const DataType result = Type_Handle; }; +template <> struct TypeToDataType<Handle<ArrayObject*> > { static const DataType result = Type_Handle; }; +template <> struct TypeToDataType<Handle<GeneratorObject*> > { static const DataType result = Type_Handle; }; +template <> struct TypeToDataType<Handle<PlainObject*> > { static const DataType result = Type_Handle; }; +template <> struct TypeToDataType<Handle<WithScope*> > { static const DataType result = Type_Handle; }; +template <> struct TypeToDataType<Handle<LexicalScope*> > { static const DataType result = Type_Handle; }; +template <> struct TypeToDataType<Handle<Scope*> > { static const DataType result = Type_Handle; }; +template <> struct TypeToDataType<HandleScript> { static const DataType result = Type_Handle; }; +template <> struct TypeToDataType<HandleValue> { static const DataType result = Type_Handle; }; +template <> struct TypeToDataType<MutableHandleValue> { static const DataType result = Type_Handle; }; + +// Convert argument types to properties of the argument known by the jit. +template <class T> struct TypeToArgProperties { + static const uint32_t result = + (sizeof(T) <= sizeof(void*) ? VMFunction::Word : VMFunction::Double); +}; +template <> struct TypeToArgProperties<const Value&> { + static const uint32_t result = TypeToArgProperties<Value>::result | VMFunction::ByRef; +}; +template <> struct TypeToArgProperties<HandleObject> { + static const uint32_t result = TypeToArgProperties<JSObject*>::result | VMFunction::ByRef; +}; +template <> struct TypeToArgProperties<HandleString> { + static const uint32_t result = TypeToArgProperties<JSString*>::result | VMFunction::ByRef; +}; +template <> struct TypeToArgProperties<HandlePropertyName> { + static const uint32_t result = TypeToArgProperties<PropertyName*>::result | VMFunction::ByRef; +}; +template <> struct TypeToArgProperties<HandleFunction> { + static const uint32_t result = TypeToArgProperties<JSFunction*>::result | VMFunction::ByRef; +}; +template <> struct TypeToArgProperties<Handle<NativeObject*> > { + static const uint32_t result = TypeToArgProperties<NativeObject*>::result | VMFunction::ByRef; +}; +template <> struct TypeToArgProperties<Handle<InlineTypedObject*> > { + static const uint32_t result = TypeToArgProperties<InlineTypedObject*>::result | VMFunction::ByRef; +}; +template <> struct TypeToArgProperties<Handle<ArrayObject*> > { + static const uint32_t result = TypeToArgProperties<ArrayObject*>::result | VMFunction::ByRef; +}; +template <> struct TypeToArgProperties<Handle<GeneratorObject*> > { + static const uint32_t result = TypeToArgProperties<GeneratorObject*>::result | VMFunction::ByRef; +}; +template <> struct TypeToArgProperties<Handle<PlainObject*> > { + static const uint32_t result = TypeToArgProperties<PlainObject*>::result | VMFunction::ByRef; +}; +template <> struct TypeToArgProperties<Handle<WithScope*> > { + static const uint32_t result = TypeToArgProperties<WithScope*>::result | VMFunction::ByRef; +}; +template <> struct TypeToArgProperties<Handle<LexicalScope*> > { + static const uint32_t result = TypeToArgProperties<LexicalScope*>::result | VMFunction::ByRef; +}; +template <> struct TypeToArgProperties<Handle<Scope*> > { + static const uint32_t result = TypeToArgProperties<Scope*>::result | VMFunction::ByRef; +}; +template <> struct TypeToArgProperties<HandleScript> { + static const uint32_t result = TypeToArgProperties<JSScript*>::result | VMFunction::ByRef; +}; +template <> struct TypeToArgProperties<HandleValue> { + static const uint32_t result = TypeToArgProperties<Value>::result | VMFunction::ByRef; +}; +template <> struct TypeToArgProperties<MutableHandleValue> { + static const uint32_t result = TypeToArgProperties<Value>::result | VMFunction::ByRef; +}; +template <> struct TypeToArgProperties<HandleShape> { + static const uint32_t result = TypeToArgProperties<Shape*>::result | VMFunction::ByRef; +}; +template <> struct TypeToArgProperties<HandleObjectGroup> { + static const uint32_t result = TypeToArgProperties<ObjectGroup*>::result | VMFunction::ByRef; +}; + +// Convert argument type to whether or not it should be passed in a float +// register on platforms that have them, like x64. +template <class T> struct TypeToPassInFloatReg { + static const uint32_t result = 0; +}; +template <> struct TypeToPassInFloatReg<double> { + static const uint32_t result = 1; +}; + +// Convert argument types to root types used by the gc, see MarkJitExitFrame. +template <class T> struct TypeToRootType { + static const uint32_t result = VMFunction::RootNone; +}; +template <> struct TypeToRootType<HandleObject> { + static const uint32_t result = VMFunction::RootObject; +}; +template <> struct TypeToRootType<HandleString> { + static const uint32_t result = VMFunction::RootString; +}; +template <> struct TypeToRootType<HandlePropertyName> { + static const uint32_t result = VMFunction::RootPropertyName; +}; +template <> struct TypeToRootType<HandleFunction> { + static const uint32_t result = VMFunction::RootFunction; +}; +template <> struct TypeToRootType<HandleValue> { + static const uint32_t result = VMFunction::RootValue; +}; +template <> struct TypeToRootType<MutableHandleValue> { + static const uint32_t result = VMFunction::RootValue; +}; +template <> struct TypeToRootType<HandleShape> { + static const uint32_t result = VMFunction::RootCell; +}; +template <> struct TypeToRootType<HandleObjectGroup> { + static const uint32_t result = VMFunction::RootCell; +}; +template <> struct TypeToRootType<HandleScript> { + static const uint32_t result = VMFunction::RootCell; +}; +template <> struct TypeToRootType<Handle<NativeObject*> > { + static const uint32_t result = VMFunction::RootObject; +}; +template <> struct TypeToRootType<Handle<InlineTypedObject*> > { + static const uint32_t result = VMFunction::RootObject; +}; +template <> struct TypeToRootType<Handle<ArrayObject*> > { + static const uint32_t result = VMFunction::RootObject; +}; +template <> struct TypeToRootType<Handle<GeneratorObject*> > { + static const uint32_t result = VMFunction::RootObject; +}; +template <> struct TypeToRootType<Handle<PlainObject*> > { + static const uint32_t result = VMFunction::RootObject; +}; +template <> struct TypeToRootType<Handle<LexicalScope*> > { + static const uint32_t result = VMFunction::RootCell; +}; +template <> struct TypeToRootType<Handle<WithScope*> > { + static const uint32_t result = VMFunction::RootCell; +}; +template <> struct TypeToRootType<Handle<Scope*> > { + static const uint32_t result = VMFunction::RootCell; +}; +template <class T> struct TypeToRootType<Handle<T> > { + // Fail for Handle types that aren't specialized above. +}; + +template <class> struct OutParamToDataType { static const DataType result = Type_Void; }; +template <> struct OutParamToDataType<Value*> { static const DataType result = Type_Value; }; +template <> struct OutParamToDataType<int*> { static const DataType result = Type_Int32; }; +template <> struct OutParamToDataType<uint32_t*> { static const DataType result = Type_Int32; }; +template <> struct OutParamToDataType<uint8_t**> { static const DataType result = Type_Pointer; }; +template <> struct OutParamToDataType<bool*> { static const DataType result = Type_Bool; }; +template <> struct OutParamToDataType<double*> { static const DataType result = Type_Double; }; +template <> struct OutParamToDataType<MutableHandleValue> { static const DataType result = Type_Handle; }; +template <> struct OutParamToDataType<MutableHandleObject> { static const DataType result = Type_Handle; }; +template <> struct OutParamToDataType<MutableHandleString> { static const DataType result = Type_Handle; }; + +template <class> struct OutParamToRootType { + static const VMFunction::RootType result = VMFunction::RootNone; +}; +template <> struct OutParamToRootType<MutableHandleValue> { + static const VMFunction::RootType result = VMFunction::RootValue; +}; +template <> struct OutParamToRootType<MutableHandleObject> { + static const VMFunction::RootType result = VMFunction::RootObject; +}; +template <> struct OutParamToRootType<MutableHandleString> { + static const VMFunction::RootType result = VMFunction::RootString; +}; + +template <class> struct MatchContext { }; +template <> struct MatchContext<JSContext*> { + static const bool valid = true; +}; +template <> struct MatchContext<ExclusiveContext*> { + static const bool valid = true; +}; + +// Extract the last element of a list of types. +template <typename... ArgTypes> +struct LastArg; + +template <> +struct LastArg<> +{ + typedef void Type; + static constexpr size_t nbArgs = 0; +}; + +template <typename HeadType> +struct LastArg<HeadType> +{ + typedef HeadType Type; + static constexpr size_t nbArgs = 1; +}; + +template <typename HeadType, typename... TailTypes> +struct LastArg<HeadType, TailTypes...> +{ + typedef typename LastArg<TailTypes...>::Type Type; + static constexpr size_t nbArgs = LastArg<TailTypes...>::nbArgs + 1; +}; + +// Construct a bit mask from a list of types. The mask is constructed as an OR +// of the mask produced for each argument. The result of each argument is +// shifted by its index, such that the result of the first argument is on the +// low bits of the mask, and the result of the last argument in part of the +// high bits of the mask. +template <template<typename> class Each, typename ResultType, size_t Shift, + typename... Args> +struct BitMask; + +template <template<typename> class Each, typename ResultType, size_t Shift> +struct BitMask<Each, ResultType, Shift> +{ + static constexpr ResultType result = ResultType(); +}; + +template <template<typename> class Each, typename ResultType, size_t Shift, + typename HeadType, typename... TailTypes> +struct BitMask<Each, ResultType, Shift, HeadType, TailTypes...> +{ + static_assert(ResultType(Each<HeadType>::result) < (1 << Shift), + "not enough bits reserved by the shift for individual results"); + static_assert(LastArg<TailTypes...>::nbArgs < (8 * sizeof(ResultType) / Shift), + "not enough bits in the result type to store all bit masks"); + + static constexpr ResultType result = + ResultType(Each<HeadType>::result) | + (BitMask<Each, ResultType, Shift, TailTypes...>::result << Shift); +}; + +// Extract VMFunction properties based on the signature of the function. The +// properties are used to generate the logic for calling the VM function, and +// also for marking the stack during GCs. +template <typename... Args> +struct FunctionInfo; + +template <class R, class Context, typename... Args> +struct FunctionInfo<R (*)(Context, Args...)> : public VMFunction +{ + typedef R (*pf)(Context, Args...); + + static DataType returnType() { + return TypeToDataType<R>::result; + } + static DataType outParam() { + return OutParamToDataType<typename LastArg<Args...>::Type>::result; + } + static RootType outParamRootType() { + return OutParamToRootType<typename LastArg<Args...>::Type>::result; + } + static size_t NbArgs() { + return LastArg<Args...>::nbArgs; + } + static size_t explicitArgs() { + return NbArgs() - (outParam() != Type_Void ? 1 : 0); + } + static uint32_t argumentProperties() { + return BitMask<TypeToArgProperties, uint32_t, 2, Args...>::result; + } + static uint32_t argumentPassedInFloatRegs() { + return BitMask<TypeToPassInFloatReg, uint32_t, 2, Args...>::result; + } + static uint64_t argumentRootTypes() { + return BitMask<TypeToRootType, uint64_t, 3, Args...>::result; + } + explicit FunctionInfo(pf fun, const char* name, PopValues extraValuesToPop = PopValues(0)) + : VMFunction(JS_FUNC_TO_DATA_PTR(void*, fun), name, explicitArgs(), + argumentProperties(), argumentPassedInFloatRegs(), + argumentRootTypes(), outParam(), outParamRootType(), + returnType(), extraValuesToPop.numValues, NonTailCall) + { + static_assert(MatchContext<Context>::valid, "Invalid cx type in VMFunction"); + } + explicit FunctionInfo(pf fun, const char* name, MaybeTailCall expectTailCall, + PopValues extraValuesToPop = PopValues(0)) + : VMFunction(JS_FUNC_TO_DATA_PTR(void*, fun), name, explicitArgs(), + argumentProperties(), argumentPassedInFloatRegs(), + argumentRootTypes(), outParam(), outParamRootType(), + returnType(), extraValuesToPop.numValues, expectTailCall) + { + static_assert(MatchContext<Context>::valid, "Invalid cx type in VMFunction"); + } +}; + +class AutoDetectInvalidation +{ + JSContext* cx_; + IonScript* ionScript_; + MutableHandleValue rval_; + bool disabled_; + + void setReturnOverride(); + + public: + AutoDetectInvalidation(JSContext* cx, MutableHandleValue rval, IonScript* ionScript) + : cx_(cx), ionScript_(ionScript), rval_(rval), disabled_(false) + { + MOZ_ASSERT(ionScript); + } + + AutoDetectInvalidation(JSContext* cx, MutableHandleValue rval); + + void disable() { + MOZ_ASSERT(!disabled_); + disabled_ = true; + } + + ~AutoDetectInvalidation() { + if (!disabled_ && ionScript_->invalidated()) + setReturnOverride(); + } +}; + +MOZ_MUST_USE bool +InvokeFunction(JSContext* cx, HandleObject obj0, bool constructing, uint32_t argc, Value* argv, + MutableHandleValue rval); +MOZ_MUST_USE bool +InvokeFunctionShuffleNewTarget(JSContext* cx, HandleObject obj, uint32_t numActualArgs, + uint32_t numFormalArgs, Value* argv, MutableHandleValue rval); + +bool CheckOverRecursed(JSContext* cx); +bool CheckOverRecursedWithExtra(JSContext* cx, BaselineFrame* frame, + uint32_t extra, uint32_t earlyCheck); + +JSObject* BindVar(JSContext* cx, HandleObject scopeChain); +MOZ_MUST_USE bool +DefVar(JSContext* cx, HandlePropertyName dn, unsigned attrs, HandleObject scopeChain); +MOZ_MUST_USE bool +DefLexical(JSContext* cx, HandlePropertyName dn, unsigned attrs, HandleObject scopeChain); +MOZ_MUST_USE bool +DefGlobalLexical(JSContext* cx, HandlePropertyName dn, unsigned attrs); +MOZ_MUST_USE bool +MutatePrototype(JSContext* cx, HandlePlainObject obj, HandleValue value); +MOZ_MUST_USE bool +InitProp(JSContext* cx, HandleObject obj, HandlePropertyName name, HandleValue value, + jsbytecode* pc); + +template<bool Equal> +bool LooselyEqual(JSContext* cx, MutableHandleValue lhs, MutableHandleValue rhs, bool* res); + +template<bool Equal> +bool StrictlyEqual(JSContext* cx, MutableHandleValue lhs, MutableHandleValue rhs, bool* res); + +bool LessThan(JSContext* cx, MutableHandleValue lhs, MutableHandleValue rhs, bool* res); +bool LessThanOrEqual(JSContext* cx, MutableHandleValue lhs, MutableHandleValue rhs, bool* res); +bool GreaterThan(JSContext* cx, MutableHandleValue lhs, MutableHandleValue rhs, bool* res); +bool GreaterThanOrEqual(JSContext* cx, MutableHandleValue lhs, MutableHandleValue rhs, bool* res); + +template<bool Equal> +bool StringsEqual(JSContext* cx, HandleString left, HandleString right, bool* res); + +MOZ_MUST_USE bool ArrayPopDense(JSContext* cx, HandleObject obj, MutableHandleValue rval); +MOZ_MUST_USE bool ArrayPushDense(JSContext* cx, HandleObject obj, HandleValue v, uint32_t* length); +MOZ_MUST_USE bool ArrayShiftDense(JSContext* cx, HandleObject obj, MutableHandleValue rval); +JSString* ArrayJoin(JSContext* cx, HandleObject array, HandleString sep); + +MOZ_MUST_USE bool +CharCodeAt(JSContext* cx, HandleString str, int32_t index, uint32_t* code); +JSFlatString* StringFromCharCode(JSContext* cx, int32_t code); +JSString* StringFromCodePoint(JSContext* cx, int32_t codePoint); + +MOZ_MUST_USE bool +SetProperty(JSContext* cx, HandleObject obj, HandlePropertyName name, HandleValue value, + bool strict, jsbytecode* pc); + +MOZ_MUST_USE bool +InterruptCheck(JSContext* cx); + +void* MallocWrapper(JSRuntime* rt, size_t nbytes); +JSObject* NewCallObject(JSContext* cx, HandleShape shape, HandleObjectGroup group); +JSObject* NewSingletonCallObject(JSContext* cx, HandleShape shape); +JSObject* NewStringObject(JSContext* cx, HandleString str); + +bool OperatorIn(JSContext* cx, HandleValue key, HandleObject obj, bool* out); +bool OperatorInI(JSContext* cx, uint32_t index, HandleObject obj, bool* out); + +MOZ_MUST_USE bool +GetIntrinsicValue(JSContext* cx, HandlePropertyName name, MutableHandleValue rval); + +MOZ_MUST_USE bool +CreateThis(JSContext* cx, HandleObject callee, HandleObject newTarget, MutableHandleValue rval); + +void GetDynamicName(JSContext* cx, JSObject* scopeChain, JSString* str, Value* vp); + +void PostWriteBarrier(JSRuntime* rt, JSObject* obj); +void PostWriteElementBarrier(JSRuntime* rt, JSObject* obj, int32_t index); +void PostGlobalWriteBarrier(JSRuntime* rt, JSObject* obj); + +uint32_t GetIndexFromString(JSString* str); + +MOZ_MUST_USE bool +DebugPrologue(JSContext* cx, BaselineFrame* frame, jsbytecode* pc, bool* mustReturn); +MOZ_MUST_USE bool +DebugEpilogue(JSContext* cx, BaselineFrame* frame, jsbytecode* pc, bool ok); +MOZ_MUST_USE bool +DebugEpilogueOnBaselineReturn(JSContext* cx, BaselineFrame* frame, jsbytecode* pc); +void FrameIsDebuggeeCheck(BaselineFrame* frame); + +JSObject* CreateGenerator(JSContext* cx, BaselineFrame* frame); + +MOZ_MUST_USE bool +NormalSuspend(JSContext* cx, HandleObject obj, BaselineFrame* frame, jsbytecode* pc, + uint32_t stackDepth); +MOZ_MUST_USE bool +FinalSuspend(JSContext* cx, HandleObject obj, BaselineFrame* frame, jsbytecode* pc); +MOZ_MUST_USE bool +InterpretResume(JSContext* cx, HandleObject obj, HandleValue val, HandlePropertyName kind, + MutableHandleValue rval); +MOZ_MUST_USE bool +DebugAfterYield(JSContext* cx, BaselineFrame* frame); +MOZ_MUST_USE bool +GeneratorThrowOrClose(JSContext* cx, BaselineFrame* frame, Handle<GeneratorObject*> genObj, + HandleValue arg, uint32_t resumeKind); + +MOZ_MUST_USE bool +GlobalNameConflictsCheckFromIon(JSContext* cx, HandleScript script); +MOZ_MUST_USE bool +CheckGlobalOrEvalDeclarationConflicts(JSContext* cx, BaselineFrame* frame); +MOZ_MUST_USE bool +InitFunctionEnvironmentObjects(JSContext* cx, BaselineFrame* frame); + +MOZ_MUST_USE bool +NewArgumentsObject(JSContext* cx, BaselineFrame* frame, MutableHandleValue res); + +JSObject* InitRestParameter(JSContext* cx, uint32_t length, Value* rest, HandleObject templateObj, + HandleObject res); + +MOZ_MUST_USE bool +HandleDebugTrap(JSContext* cx, BaselineFrame* frame, uint8_t* retAddr, bool* mustReturn); +MOZ_MUST_USE bool +OnDebuggerStatement(JSContext* cx, BaselineFrame* frame, jsbytecode* pc, bool* mustReturn); +MOZ_MUST_USE bool +GlobalHasLiveOnDebuggerStatement(JSContext* cx); + +MOZ_MUST_USE bool +EnterWith(JSContext* cx, BaselineFrame* frame, HandleValue val, Handle<WithScope*> templ); +MOZ_MUST_USE bool +LeaveWith(JSContext* cx, BaselineFrame* frame); + +MOZ_MUST_USE bool +PushLexicalEnv(JSContext* cx, BaselineFrame* frame, Handle<LexicalScope*> scope); +MOZ_MUST_USE bool +PopLexicalEnv(JSContext* cx, BaselineFrame* frame); +MOZ_MUST_USE bool +DebugLeaveThenPopLexicalEnv(JSContext* cx, BaselineFrame* frame, jsbytecode* pc); +MOZ_MUST_USE bool +FreshenLexicalEnv(JSContext* cx, BaselineFrame* frame); +MOZ_MUST_USE bool +DebugLeaveThenFreshenLexicalEnv(JSContext* cx, BaselineFrame* frame, jsbytecode* pc); +MOZ_MUST_USE bool +RecreateLexicalEnv(JSContext* cx, BaselineFrame* frame); +MOZ_MUST_USE bool +DebugLeaveThenRecreateLexicalEnv(JSContext* cx, BaselineFrame* frame, jsbytecode* pc); +MOZ_MUST_USE bool +DebugLeaveLexicalEnv(JSContext* cx, BaselineFrame* frame, jsbytecode* pc); + +MOZ_MUST_USE bool +PushVarEnv(JSContext* cx, BaselineFrame* frame, HandleScope scope); +MOZ_MUST_USE bool +PopVarEnv(JSContext* cx, BaselineFrame* frame); + +MOZ_MUST_USE bool +InitBaselineFrameForOsr(BaselineFrame* frame, InterpreterFrame* interpFrame, + uint32_t numStackValues); + +JSObject* CreateDerivedTypedObj(JSContext* cx, HandleObject descr, + HandleObject owner, int32_t offset); + +MOZ_MUST_USE bool +ArraySpliceDense(JSContext* cx, HandleObject obj, uint32_t start, uint32_t deleteCount); + +MOZ_MUST_USE bool +Recompile(JSContext* cx); +MOZ_MUST_USE bool +ForcedRecompile(JSContext* cx); +JSString* StringReplace(JSContext* cx, HandleString string, HandleString pattern, + HandleString repl); + +MOZ_MUST_USE bool SetDenseOrUnboxedArrayElement(JSContext* cx, HandleObject obj, int32_t index, + HandleValue value, bool strict); + +void AssertValidObjectPtr(JSContext* cx, JSObject* obj); +void AssertValidObjectOrNullPtr(JSContext* cx, JSObject* obj); +void AssertValidStringPtr(JSContext* cx, JSString* str); +void AssertValidSymbolPtr(JSContext* cx, JS::Symbol* sym); +void AssertValidValue(JSContext* cx, Value* v); + +void MarkValueFromIon(JSRuntime* rt, Value* vp); +void MarkStringFromIon(JSRuntime* rt, JSString** stringp); +void MarkObjectFromIon(JSRuntime* rt, JSObject** objp); +void MarkShapeFromIon(JSRuntime* rt, Shape** shapep); +void MarkObjectGroupFromIon(JSRuntime* rt, ObjectGroup** groupp); + +// Helper for generatePreBarrier. +inline void* +IonMarkFunction(MIRType type) +{ + switch (type) { + case MIRType::Value: + return JS_FUNC_TO_DATA_PTR(void*, MarkValueFromIon); + case MIRType::String: + return JS_FUNC_TO_DATA_PTR(void*, MarkStringFromIon); + case MIRType::Object: + return JS_FUNC_TO_DATA_PTR(void*, MarkObjectFromIon); + case MIRType::Shape: + return JS_FUNC_TO_DATA_PTR(void*, MarkShapeFromIon); + case MIRType::ObjectGroup: + return JS_FUNC_TO_DATA_PTR(void*, MarkObjectGroupFromIon); + default: MOZ_CRASH(); + } +} + +bool ObjectIsCallable(JSObject* obj); +bool ObjectIsConstructor(JSObject* obj); + +MOZ_MUST_USE bool +ThrowRuntimeLexicalError(JSContext* cx, unsigned errorNumber); + +MOZ_MUST_USE bool +ThrowReadOnlyError(JSContext* cx, int32_t index); + +MOZ_MUST_USE bool +BaselineThrowUninitializedThis(JSContext* cx, BaselineFrame* frame); + +MOZ_MUST_USE bool +ThrowBadDerivedReturn(JSContext* cx, HandleValue v); + +MOZ_MUST_USE bool +ThrowObjectCoercible(JSContext* cx, HandleValue v); + +MOZ_MUST_USE bool +BaselineGetFunctionThis(JSContext* cx, BaselineFrame* frame, MutableHandleValue res); + +} // namespace jit +} // namespace js + +#endif /* jit_VMFunctions_h */ |