| /* -*- 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 DeclEnvObject; |
| class StaticWithObject; |
| class InlineTypedObject; |
| class GeneratorObject; |
| |
| 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; |
| |
| // 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; |
| } |
| |
| // 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() |
| : wrapped(nullptr), |
| explicitArgs(0), |
| argumentProperties(0), |
| argumentPassedInFloatRegs(0), |
| outParam(Type_Void), |
| returnType(Type_Void), |
| outParamRootType(RootNone), |
| extraValuesToPop(0) |
| { |
| } |
| |
| |
| VMFunction(void* wrapped, 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), |
| 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<DeclEnvObject*> { static const DataType result = Type_Object; }; |
| template <> struct TypeToDataType<ArrayObject*> { 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<StaticWithObject*> > { static const DataType result = Type_Handle; }; |
| template <> struct TypeToDataType<Handle<StaticBlockObject*> > { 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<StaticWithObject*> > { |
| static const uint32_t result = TypeToArgProperties<StaticWithObject*>::result | VMFunction::ByRef; |
| }; |
| template <> struct TypeToArgProperties<Handle<StaticBlockObject*> > { |
| static const uint32_t result = TypeToArgProperties<StaticBlockObject*>::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<StaticBlockObject*> > { |
| static const uint32_t result = VMFunction::RootObject; |
| }; |
| template <> struct TypeToRootType<Handle<StaticWithObject*> > { |
| 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 MOZ_CONSTEXPR_VAR size_t nbArgs = 0; |
| }; |
| |
| template <typename HeadType> |
| struct LastArg<HeadType> |
| { |
| typedef HeadType Type; |
| static MOZ_CONSTEXPR_VAR size_t nbArgs = 1; |
| }; |
| |
| template <typename HeadType, typename... TailTypes> |
| struct LastArg<HeadType, TailTypes...> |
| { |
| typedef typename LastArg<TailTypes...>::Type Type; |
| static MOZ_CONSTEXPR_VAR 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 MOZ_CONSTEXPR_VAR 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 MOZ_CONSTEXPR_VAR 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, PopValues extraValuesToPop = PopValues(0)) |
| : VMFunction(JS_FUNC_TO_DATA_PTR(void*, fun), explicitArgs(), |
| argumentProperties(), argumentPassedInFloatRegs(), |
| argumentRootTypes(), outParam(), outParamRootType(), |
| returnType(), extraValuesToPop.numValues, NonTailCall) |
| { |
| static_assert(MatchContext<Context>::valid, "Invalid cx type in VMFunction"); |
| } |
| explicit FunctionInfo(pf fun, MaybeTailCall expectTailCall, |
| PopValues extraValuesToPop = PopValues(0)) |
| : VMFunction(JS_FUNC_TO_DATA_PTR(void*, fun), 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(); |
| } |
| }; |
| |
| bool InvokeFunction(JSContext* cx, HandleObject obj0, bool constructing, uint32_t argc, |
| Value* argv, MutableHandleValue rval); |
| 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); |
| |
| bool DefVar(JSContext* cx, HandlePropertyName dn, unsigned attrs, HandleObject scopeChain); |
| bool DefLexical(JSContext* cx, HandlePropertyName dn, unsigned attrs, HandleObject scopeChain); |
| bool DefGlobalLexical(JSContext* cx, HandlePropertyName dn, unsigned attrs); |
| bool MutatePrototype(JSContext* cx, HandlePlainObject obj, HandleValue value); |
| 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); |
| |
| bool ArrayPopDense(JSContext* cx, HandleObject obj, MutableHandleValue rval); |
| bool ArrayPushDense(JSContext* cx, HandleObject obj, HandleValue v, uint32_t* length); |
| bool ArrayShiftDense(JSContext* cx, HandleObject obj, MutableHandleValue rval); |
| JSObject* ArrayConcatDense(JSContext* cx, HandleObject obj1, HandleObject obj2, HandleObject res); |
| JSString* ArrayJoin(JSContext* cx, HandleObject array, HandleString sep); |
| |
| bool CharCodeAt(JSContext* cx, HandleString str, int32_t index, uint32_t* code); |
| JSFlatString* StringFromCharCode(JSContext* cx, int32_t code); |
| |
| bool SetProperty(JSContext* cx, HandleObject obj, HandlePropertyName name, HandleValue value, |
| bool strict, jsbytecode* pc); |
| |
| bool InterruptCheck(JSContext* cx); |
| |
| void* MallocWrapper(JSRuntime* rt, size_t nbytes); |
| JSObject* NewCallObject(JSContext* cx, HandleShape shape, HandleObjectGroup group, |
| uint32_t lexicalBegin); |
| JSObject* NewSingletonCallObject(JSContext* cx, HandleShape shape, uint32_t lexicalBegin); |
| 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); |
| |
| bool GetIntrinsicValue(JSContext* cx, HandlePropertyName name, MutableHandleValue rval); |
| |
| 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 PostGlobalWriteBarrier(JSRuntime* rt, JSObject* obj); |
| |
| uint32_t GetIndexFromString(JSString* str); |
| |
| bool DebugPrologue(JSContext* cx, BaselineFrame* frame, jsbytecode* pc, bool* mustReturn); |
| bool DebugEpilogue(JSContext* cx, BaselineFrame* frame, jsbytecode* pc, bool ok); |
| bool DebugEpilogueOnBaselineReturn(JSContext* cx, BaselineFrame* frame, jsbytecode* pc); |
| void FrameIsDebuggeeCheck(BaselineFrame* frame); |
| |
| JSObject* CreateGenerator(JSContext* cx, BaselineFrame* frame); |
| bool NormalSuspend(JSContext* cx, HandleObject obj, BaselineFrame* frame, jsbytecode* pc, |
| uint32_t stackDepth); |
| bool FinalSuspend(JSContext* cx, HandleObject obj, BaselineFrame* frame, jsbytecode* pc); |
| bool InterpretResume(JSContext* cx, HandleObject obj, HandleValue val, HandlePropertyName kind, |
| MutableHandleValue rval); |
| bool DebugAfterYield(JSContext* cx, BaselineFrame* frame); |
| bool GeneratorThrowOrClose(JSContext* cx, BaselineFrame* frame, Handle<GeneratorObject*> genObj, |
| HandleValue arg, uint32_t resumeKind); |
| |
| bool GlobalNameConflictsCheckFromIon(JSContext* cx, HandleScript script); |
| bool InitGlobalOrEvalScopeObjects(JSContext* cx, BaselineFrame* frame); |
| bool InitFunctionScopeObjects(JSContext* cx, BaselineFrame* frame); |
| |
| bool NewArgumentsObject(JSContext* cx, BaselineFrame* frame, MutableHandleValue res); |
| |
| JSObject* InitRestParameter(JSContext* cx, uint32_t length, Value* rest, HandleObject templateObj, |
| HandleObject res); |
| |
| bool HandleDebugTrap(JSContext* cx, BaselineFrame* frame, uint8_t* retAddr, bool* mustReturn); |
| bool OnDebuggerStatement(JSContext* cx, BaselineFrame* frame, jsbytecode* pc, bool* mustReturn); |
| bool GlobalHasLiveOnDebuggerStatement(JSContext* cx); |
| |
| bool EnterWith(JSContext* cx, BaselineFrame* frame, HandleValue val, |
| Handle<StaticWithObject*> templ); |
| bool LeaveWith(JSContext* cx, BaselineFrame* frame); |
| |
| bool PushBlockScope(JSContext* cx, BaselineFrame* frame, Handle<StaticBlockObject*> block); |
| bool PopBlockScope(JSContext* cx, BaselineFrame* frame); |
| bool DebugLeaveThenPopBlockScope(JSContext* cx, BaselineFrame* frame, jsbytecode* pc); |
| bool FreshenBlockScope(JSContext* cx, BaselineFrame* frame); |
| bool DebugLeaveThenFreshenBlockScope(JSContext* cx, BaselineFrame* frame, jsbytecode* pc); |
| bool DebugLeaveBlock(JSContext* cx, BaselineFrame* frame, jsbytecode* pc); |
| |
| bool InitBaselineFrameForOsr(BaselineFrame* frame, InterpreterFrame* interpFrame, |
| uint32_t numStackValues); |
| |
| JSObject* CreateDerivedTypedObj(JSContext* cx, HandleObject descr, |
| HandleObject owner, int32_t offset); |
| |
| bool ArraySpliceDense(JSContext* cx, HandleObject obj, uint32_t start, uint32_t deleteCount); |
| |
| bool Recompile(JSContext* cx); |
| bool ForcedRecompile(JSContext* cx); |
| JSString* RegExpReplace(JSContext* cx, HandleString string, HandleObject regexp, |
| HandleString repl); |
| JSString* StringReplace(JSContext* cx, HandleString string, HandleString pattern, |
| HandleString repl); |
| |
| 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 ThrowRuntimeLexicalError(JSContext* cx, unsigned errorNumber); |
| bool BaselineThrowUninitializedThis(JSContext* cx, BaselineFrame* frame); |
| bool ThrowBadDerivedReturn(JSContext* cx, HandleValue v); |
| |
| bool ThrowObjectCoercible(JSContext* cx, HandleValue v); |
| |
| bool BaselineGetFunctionThis(JSContext* cx, BaselineFrame* frame, MutableHandleValue res); |
| |
| } // namespace jit |
| } // namespace js |
| |
| #endif /* jit_VMFunctions_h */ |