michael@0: /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- michael@0: * vim: set ts=8 sts=4 et sw=4 tw=99: michael@0: * This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this michael@0: * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: #ifndef jit_VMFunctions_h michael@0: #define jit_VMFunctions_h michael@0: michael@0: #include "jspubtd.h" michael@0: michael@0: #include "jit/CompileInfo.h" michael@0: #include "jit/IonFrames.h" michael@0: michael@0: namespace js { michael@0: michael@0: class DeclEnvObject; michael@0: class ForkJoinContext; michael@0: class StaticWithObject; michael@0: michael@0: namespace jit { michael@0: michael@0: enum DataType { michael@0: Type_Void, michael@0: Type_Bool, michael@0: Type_Int32, michael@0: Type_Double, michael@0: Type_Pointer, michael@0: Type_Object, michael@0: Type_Value, michael@0: Type_Handle michael@0: }; michael@0: michael@0: struct PopValues michael@0: { michael@0: uint32_t numValues; michael@0: michael@0: explicit PopValues(uint32_t numValues) michael@0: : numValues(numValues) michael@0: { } michael@0: }; michael@0: michael@0: // Contains information about a virtual machine function that can be called michael@0: // from JIT code. Functions described in this manner must conform to a simple michael@0: // protocol: the return type must have a special "failure" value (for example, michael@0: // false for bool, or nullptr for Objects). If the function is designed to michael@0: // return a value that does not meet this requirement - such as michael@0: // object-or-nullptr, or an integer, an optional, final outParam can be michael@0: // specified. In this case, the return type must be boolean to indicate michael@0: // failure. michael@0: // michael@0: // All functions described by VMFunction take a JSContext * as a first michael@0: // argument, and are treated as re-entrant into the VM and therefore fallible. michael@0: struct VMFunction michael@0: { michael@0: // Global linked list of all VMFunctions. michael@0: static VMFunction *functions; michael@0: VMFunction *next; michael@0: michael@0: // Address of the C function. michael@0: void *wrapped; michael@0: michael@0: // Number of arguments expected, excluding JSContext * as an implicit michael@0: // first argument and an outparam as a possible implicit final argument. michael@0: uint32_t explicitArgs; michael@0: michael@0: enum ArgProperties { michael@0: WordByValue = 0, michael@0: DoubleByValue = 1, michael@0: WordByRef = 2, michael@0: DoubleByRef = 3, michael@0: // BitMask version. michael@0: Word = 0, michael@0: Double = 1, michael@0: ByRef = 2 michael@0: }; michael@0: michael@0: // Contains properties about the first 16 arguments. michael@0: uint32_t argumentProperties; michael@0: michael@0: // Which arguments should be passed in float register on platforms that michael@0: // have them. michael@0: uint32_t argumentPassedInFloatRegs; michael@0: michael@0: // The outparam may be any Type_*, and must be the final argument to the michael@0: // function, if not Void. outParam != Void implies that the return type michael@0: // has a boolean failure mode. michael@0: DataType outParam; michael@0: michael@0: // Type returned by the C function and used by the VMFunction wrapper to michael@0: // check for failures of the C function. Valid failure/return types are michael@0: // boolean and object pointers which are asserted inside the VMFunction michael@0: // constructor. If the C function use an outparam (!= Type_Void), then michael@0: // the only valid failure/return type is boolean -- object pointers are michael@0: // pointless because the wrapper will only use it to compare it against michael@0: // nullptr before discarding its value. michael@0: DataType returnType; michael@0: michael@0: // Note: a maximum of seven root types is supported. michael@0: enum RootType { michael@0: RootNone = 0, michael@0: RootObject, michael@0: RootString, michael@0: RootPropertyName, michael@0: RootFunction, michael@0: RootValue, michael@0: RootCell michael@0: }; michael@0: michael@0: // Contains an combination of enumerated types used by the gc for marking michael@0: // arguments of the VM wrapper. michael@0: uint64_t argumentRootTypes; michael@0: michael@0: // The root type of the out param if outParam == Type_Handle. michael@0: RootType outParamRootType; michael@0: michael@0: // Does this function take a ForkJoinContext * or a JSContext *? michael@0: ExecutionMode executionMode; michael@0: michael@0: // Number of Values the VM wrapper should pop from the stack when it returns. michael@0: // Used by baseline IC stubs so that they can use tail calls to call the VM michael@0: // wrapper. michael@0: uint32_t extraValuesToPop; michael@0: michael@0: uint32_t argc() const { michael@0: // JSContext * + args + (OutParam? *) michael@0: return 1 + explicitArgc() + ((outParam == Type_Void) ? 0 : 1); michael@0: } michael@0: michael@0: DataType failType() const { michael@0: return returnType; michael@0: } michael@0: michael@0: ArgProperties argProperties(uint32_t explicitArg) const { michael@0: return ArgProperties((argumentProperties >> (2 * explicitArg)) & 3); michael@0: } michael@0: michael@0: RootType argRootType(uint32_t explicitArg) const { michael@0: return RootType((argumentRootTypes >> (3 * explicitArg)) & 7); michael@0: } michael@0: michael@0: bool argPassedInFloatReg(uint32_t explicitArg) const { michael@0: return ((argumentPassedInFloatRegs >> explicitArg) & 1) == 1; michael@0: } michael@0: michael@0: // Return the stack size consumed by explicit arguments. michael@0: size_t explicitStackSlots() const { michael@0: size_t stackSlots = explicitArgs; michael@0: michael@0: // Fetch all double-word flags of explicit arguments. michael@0: uint32_t n = michael@0: ((1 << (explicitArgs * 2)) - 1) // = Explicit argument mask. michael@0: & 0x55555555 // = Mask double-size args. michael@0: & argumentProperties; michael@0: michael@0: // Add the number of double-word flags. (expect a few loop michael@0: // iteration) michael@0: while (n) { michael@0: stackSlots++; michael@0: n &= n - 1; michael@0: } michael@0: return stackSlots; michael@0: } michael@0: michael@0: // Double-size argument which are passed by value are taking the space michael@0: // of 2 C arguments. This function is used to compute the number of michael@0: // argument expected by the C function. This is not the same as michael@0: // explicitStackSlots because reference to stack slots may take one less michael@0: // register in the total count. michael@0: size_t explicitArgc() const { michael@0: size_t stackSlots = explicitArgs; michael@0: michael@0: // Fetch all explicit arguments. michael@0: uint32_t n = michael@0: ((1 << (explicitArgs * 2)) - 1) // = Explicit argument mask. michael@0: & argumentProperties; michael@0: michael@0: // Filter double-size arguments (0x5 = 0b0101) and remove (& ~) michael@0: // arguments passed by reference (0b1010 >> 1 == 0b0101). michael@0: n = (n & 0x55555555) & ~(n >> 1); michael@0: michael@0: // Add the number of double-word transfered by value. (expect a few michael@0: // loop iteration) michael@0: while (n) { michael@0: stackSlots++; michael@0: n &= n - 1; michael@0: } michael@0: return stackSlots; michael@0: } michael@0: michael@0: VMFunction() michael@0: : wrapped(nullptr), michael@0: explicitArgs(0), michael@0: argumentProperties(0), michael@0: argumentPassedInFloatRegs(0), michael@0: outParam(Type_Void), michael@0: returnType(Type_Void), michael@0: outParamRootType(RootNone), michael@0: executionMode(SequentialExecution), michael@0: extraValuesToPop(0) michael@0: { michael@0: } michael@0: michael@0: michael@0: VMFunction(void *wrapped, uint32_t explicitArgs, uint32_t argumentProperties, michael@0: uint32_t argumentPassedInFloatRegs, uint64_t argRootTypes, michael@0: DataType outParam, RootType outParamRootType, DataType returnType, michael@0: ExecutionMode executionMode, uint32_t extraValuesToPop = 0) michael@0: : wrapped(wrapped), michael@0: explicitArgs(explicitArgs), michael@0: argumentProperties(argumentProperties), michael@0: argumentPassedInFloatRegs(argumentPassedInFloatRegs), michael@0: outParam(outParam), michael@0: returnType(returnType), michael@0: argumentRootTypes(argRootTypes), michael@0: outParamRootType(outParamRootType), michael@0: executionMode(executionMode), michael@0: extraValuesToPop(extraValuesToPop) michael@0: { michael@0: // Check for valid failure/return type. michael@0: JS_ASSERT_IF(outParam != Type_Void && executionMode == SequentialExecution, michael@0: returnType == Type_Bool); michael@0: JS_ASSERT(returnType == Type_Bool || michael@0: returnType == Type_Object); michael@0: } michael@0: michael@0: VMFunction(const VMFunction &o) { michael@0: init(o); michael@0: } michael@0: michael@0: void init(const VMFunction &o) { michael@0: JS_ASSERT(!wrapped); michael@0: *this = o; michael@0: addToFunctions(); michael@0: } michael@0: michael@0: private: michael@0: // Add this to the global list of VMFunctions. michael@0: void addToFunctions(); michael@0: }; michael@0: michael@0: // A collection of VM functions for each execution mode. michael@0: struct VMFunctionsModal michael@0: { michael@0: VMFunctionsModal(const VMFunction &info) { michael@0: add(info); michael@0: } michael@0: VMFunctionsModal(const VMFunction &info1, const VMFunction &info2) { michael@0: add(info1); michael@0: add(info2); michael@0: } michael@0: michael@0: inline const VMFunction &operator[](ExecutionMode mode) const { michael@0: JS_ASSERT((unsigned)mode < NumExecutionModes); michael@0: return funs_[mode]; michael@0: } michael@0: michael@0: private: michael@0: void add(const VMFunction &info) { michael@0: JS_ASSERT((unsigned)info.executionMode < NumExecutionModes); michael@0: funs_[info.executionMode].init(info); michael@0: } michael@0: michael@0: mozilla::Array funs_; michael@0: }; michael@0: michael@0: template struct TypeToDataType { /* Unexpected return type for a VMFunction. */ }; michael@0: template <> struct TypeToDataType { static const DataType result = Type_Bool; }; michael@0: template <> struct TypeToDataType { static const DataType result = Type_Object; }; michael@0: template <> struct TypeToDataType { static const DataType result = Type_Object; }; michael@0: template <> struct TypeToDataType { static const DataType result = Type_Object; }; michael@0: template <> struct TypeToDataType { static const DataType result = Type_Object; }; michael@0: template <> struct TypeToDataType { static const DataType result = Type_Handle; }; michael@0: template <> struct TypeToDataType { static const DataType result = Type_Handle; }; michael@0: template <> struct TypeToDataType { static const DataType result = Type_Handle; }; michael@0: template <> struct TypeToDataType { static const DataType result = Type_Handle; }; michael@0: template <> struct TypeToDataType > { static const DataType result = Type_Handle; }; michael@0: template <> struct TypeToDataType > { static const DataType result = Type_Handle; }; michael@0: template <> struct TypeToDataType { static const DataType result = Type_Handle; }; michael@0: template <> struct TypeToDataType { static const DataType result = Type_Handle; }; michael@0: template <> struct TypeToDataType { static const DataType result = Type_Handle; }; michael@0: michael@0: // Convert argument types to properties of the argument known by the jit. michael@0: template struct TypeToArgProperties { michael@0: static const uint32_t result = michael@0: (sizeof(T) <= sizeof(void *) ? VMFunction::Word : VMFunction::Double); michael@0: }; michael@0: template <> struct TypeToArgProperties { michael@0: static const uint32_t result = TypeToArgProperties::result | VMFunction::ByRef; michael@0: }; michael@0: template <> struct TypeToArgProperties { michael@0: static const uint32_t result = TypeToArgProperties::result | VMFunction::ByRef; michael@0: }; michael@0: template <> struct TypeToArgProperties { michael@0: static const uint32_t result = TypeToArgProperties::result | VMFunction::ByRef; michael@0: }; michael@0: template <> struct TypeToArgProperties { michael@0: static const uint32_t result = TypeToArgProperties::result | VMFunction::ByRef; michael@0: }; michael@0: template <> struct TypeToArgProperties { michael@0: static const uint32_t result = TypeToArgProperties::result | VMFunction::ByRef; michael@0: }; michael@0: template <> struct TypeToArgProperties > { michael@0: static const uint32_t result = TypeToArgProperties::result | VMFunction::ByRef; michael@0: }; michael@0: template <> struct TypeToArgProperties > { michael@0: static const uint32_t result = TypeToArgProperties::result | VMFunction::ByRef; michael@0: }; michael@0: template <> struct TypeToArgProperties { michael@0: static const uint32_t result = TypeToArgProperties::result | VMFunction::ByRef; michael@0: }; michael@0: template <> struct TypeToArgProperties { michael@0: static const uint32_t result = TypeToArgProperties::result | VMFunction::ByRef; michael@0: }; michael@0: template <> struct TypeToArgProperties { michael@0: static const uint32_t result = TypeToArgProperties::result | VMFunction::ByRef; michael@0: }; michael@0: template <> struct TypeToArgProperties { michael@0: static const uint32_t result = TypeToArgProperties::result | VMFunction::ByRef; michael@0: }; michael@0: template <> struct TypeToArgProperties { michael@0: static const uint32_t result = TypeToArgProperties::result | VMFunction::ByRef; michael@0: }; michael@0: michael@0: // Convert argument type to whether or not it should be passed in a float michael@0: // register on platforms that have them, like x64. michael@0: template struct TypeToPassInFloatReg { michael@0: static const uint32_t result = 0; michael@0: }; michael@0: template <> struct TypeToPassInFloatReg { michael@0: static const uint32_t result = 1; michael@0: }; michael@0: michael@0: // Convert argument types to root types used by the gc, see MarkJitExitFrame. michael@0: template struct TypeToRootType { michael@0: static const uint32_t result = VMFunction::RootNone; michael@0: }; michael@0: template <> struct TypeToRootType { michael@0: static const uint32_t result = VMFunction::RootObject; michael@0: }; michael@0: template <> struct TypeToRootType { michael@0: static const uint32_t result = VMFunction::RootString; michael@0: }; michael@0: template <> struct TypeToRootType { michael@0: static const uint32_t result = VMFunction::RootPropertyName; michael@0: }; michael@0: template <> struct TypeToRootType { michael@0: static const uint32_t result = VMFunction::RootFunction; michael@0: }; michael@0: template <> struct TypeToRootType { michael@0: static const uint32_t result = VMFunction::RootValue; michael@0: }; michael@0: template <> struct TypeToRootType { michael@0: static const uint32_t result = VMFunction::RootValue; michael@0: }; michael@0: template <> struct TypeToRootType { michael@0: static const uint32_t result = VMFunction::RootCell; michael@0: }; michael@0: template <> struct TypeToRootType { michael@0: static const uint32_t result = VMFunction::RootCell; michael@0: }; michael@0: template <> struct TypeToRootType { michael@0: static const uint32_t result = VMFunction::RootCell; michael@0: }; michael@0: template <> struct TypeToRootType > { michael@0: static const uint32_t result = VMFunction::RootObject; michael@0: }; michael@0: template <> struct TypeToRootType > { michael@0: static const uint32_t result = VMFunction::RootCell; michael@0: }; michael@0: template struct TypeToRootType > { michael@0: // Fail for Handle types that aren't specialized above. michael@0: }; michael@0: michael@0: template struct OutParamToDataType { static const DataType result = Type_Void; }; michael@0: template <> struct OutParamToDataType { static const DataType result = Type_Value; }; michael@0: template <> struct OutParamToDataType { static const DataType result = Type_Int32; }; michael@0: template <> struct OutParamToDataType { static const DataType result = Type_Int32; }; michael@0: template <> struct OutParamToDataType { static const DataType result = Type_Pointer; }; michael@0: template <> struct OutParamToDataType { static const DataType result = Type_Bool; }; michael@0: template <> struct OutParamToDataType { static const DataType result = Type_Double; }; michael@0: template <> struct OutParamToDataType { static const DataType result = Type_Handle; }; michael@0: template <> struct OutParamToDataType { static const DataType result = Type_Handle; }; michael@0: template <> struct OutParamToDataType { static const DataType result = Type_Handle; }; michael@0: michael@0: template struct OutParamToRootType { michael@0: static const VMFunction::RootType result = VMFunction::RootNone; michael@0: }; michael@0: template <> struct OutParamToRootType { michael@0: static const VMFunction::RootType result = VMFunction::RootValue; michael@0: }; michael@0: template <> struct OutParamToRootType { michael@0: static const VMFunction::RootType result = VMFunction::RootObject; michael@0: }; michael@0: template <> struct OutParamToRootType { michael@0: static const VMFunction::RootType result = VMFunction::RootString; michael@0: }; michael@0: michael@0: template struct MatchContext { }; michael@0: template <> struct MatchContext { michael@0: static const ExecutionMode execMode = SequentialExecution; michael@0: }; michael@0: template <> struct MatchContext { michael@0: static const ExecutionMode execMode = SequentialExecution; michael@0: }; michael@0: template <> struct MatchContext { michael@0: static const ExecutionMode execMode = ParallelExecution; michael@0: }; michael@0: template <> struct MatchContext { michael@0: // ThreadSafeContext functions can be called from either mode, but for michael@0: // calling from parallel they should be wrapped first, so we default to michael@0: // SequentialExecution here. michael@0: static const ExecutionMode execMode = SequentialExecution; michael@0: }; michael@0: michael@0: #define FOR_EACH_ARGS_1(Macro, Sep, Last) Macro(1) Last(1) michael@0: #define FOR_EACH_ARGS_2(Macro, Sep, Last) FOR_EACH_ARGS_1(Macro, Sep, Sep) Macro(2) Last(2) michael@0: #define FOR_EACH_ARGS_3(Macro, Sep, Last) FOR_EACH_ARGS_2(Macro, Sep, Sep) Macro(3) Last(3) michael@0: #define FOR_EACH_ARGS_4(Macro, Sep, Last) FOR_EACH_ARGS_3(Macro, Sep, Sep) Macro(4) Last(4) michael@0: #define FOR_EACH_ARGS_5(Macro, Sep, Last) FOR_EACH_ARGS_4(Macro, Sep, Sep) Macro(5) Last(5) michael@0: #define FOR_EACH_ARGS_6(Macro, Sep, Last) FOR_EACH_ARGS_5(Macro, Sep, Sep) Macro(6) Last(6) michael@0: michael@0: #define COMPUTE_INDEX(NbArg) NbArg michael@0: #define COMPUTE_OUTPARAM_RESULT(NbArg) OutParamToDataType::result michael@0: #define COMPUTE_OUTPARAM_ROOT(NbArg) OutParamToRootType::result michael@0: #define COMPUTE_ARG_PROP(NbArg) (TypeToArgProperties::result << (2 * (NbArg - 1))) michael@0: #define COMPUTE_ARG_ROOT(NbArg) (uint64_t(TypeToRootType::result) << (3 * (NbArg - 1))) michael@0: #define COMPUTE_ARG_FLOAT(NbArg) (TypeToPassInFloatReg::result) << (NbArg - 1) michael@0: #define SEP_OR(_) | michael@0: #define NOTHING(_) michael@0: michael@0: #define FUNCTION_INFO_STRUCT_BODY(ForEachNb) \ michael@0: static inline ExecutionMode executionMode() { \ michael@0: return MatchContext::execMode; \ michael@0: } \ michael@0: static inline DataType returnType() { \ michael@0: return TypeToDataType::result; \ michael@0: } \ michael@0: static inline DataType outParam() { \ michael@0: return ForEachNb(NOTHING, NOTHING, COMPUTE_OUTPARAM_RESULT); \ michael@0: } \ michael@0: static inline RootType outParamRootType() { \ michael@0: return ForEachNb(NOTHING, NOTHING, COMPUTE_OUTPARAM_ROOT); \ michael@0: } \ michael@0: static inline size_t NbArgs() { \ michael@0: return ForEachNb(NOTHING, NOTHING, COMPUTE_INDEX); \ michael@0: } \ michael@0: static inline size_t explicitArgs() { \ michael@0: return NbArgs() - (outParam() != Type_Void ? 1 : 0); \ michael@0: } \ michael@0: static inline uint32_t argumentProperties() { \ michael@0: return ForEachNb(COMPUTE_ARG_PROP, SEP_OR, NOTHING); \ michael@0: } \ michael@0: static inline uint32_t argumentPassedInFloatRegs() { \ michael@0: return ForEachNb(COMPUTE_ARG_FLOAT, SEP_OR, NOTHING); \ michael@0: } \ michael@0: static inline uint64_t argumentRootTypes() { \ michael@0: return ForEachNb(COMPUTE_ARG_ROOT, SEP_OR, NOTHING); \ michael@0: } \ michael@0: FunctionInfo(pf fun, PopValues extraValuesToPop = PopValues(0)) \ michael@0: : VMFunction(JS_FUNC_TO_DATA_PTR(void *, fun), explicitArgs(), \ michael@0: argumentProperties(), argumentPassedInFloatRegs(), \ michael@0: argumentRootTypes(), outParam(), outParamRootType(), \ michael@0: returnType(), executionMode(), \ michael@0: extraValuesToPop.numValues) \ michael@0: { } michael@0: michael@0: template michael@0: struct FunctionInfo { michael@0: }; michael@0: michael@0: // VMFunction wrapper with no explicit arguments. michael@0: template michael@0: struct FunctionInfo : public VMFunction { michael@0: typedef R (*pf)(Context); michael@0: michael@0: static inline ExecutionMode executionMode() { michael@0: return MatchContext::execMode; michael@0: } michael@0: static inline DataType returnType() { michael@0: return TypeToDataType::result; michael@0: } michael@0: static inline DataType outParam() { michael@0: return Type_Void; michael@0: } michael@0: static inline RootType outParamRootType() { michael@0: return RootNone; michael@0: } michael@0: static inline size_t explicitArgs() { michael@0: return 0; michael@0: } michael@0: static inline uint32_t argumentProperties() { michael@0: return 0; michael@0: } michael@0: static inline uint32_t argumentPassedInFloatRegs() { michael@0: return 0; michael@0: } michael@0: static inline uint64_t argumentRootTypes() { michael@0: return 0; michael@0: } michael@0: FunctionInfo(pf fun) michael@0: : VMFunction(JS_FUNC_TO_DATA_PTR(void *, fun), explicitArgs(), michael@0: argumentProperties(), argumentPassedInFloatRegs(), michael@0: argumentRootTypes(), outParam(), outParamRootType(), michael@0: returnType(), executionMode()) michael@0: { } michael@0: }; michael@0: michael@0: // Specialize the class for each number of argument used by VMFunction. michael@0: // Keep it verbose unless you find a readable macro for it. michael@0: template michael@0: struct FunctionInfo : public VMFunction { michael@0: typedef R (*pf)(Context, A1); michael@0: FUNCTION_INFO_STRUCT_BODY(FOR_EACH_ARGS_1) michael@0: }; michael@0: michael@0: template michael@0: struct FunctionInfo : public VMFunction { michael@0: typedef R (*pf)(Context, A1, A2); michael@0: FUNCTION_INFO_STRUCT_BODY(FOR_EACH_ARGS_2) michael@0: }; michael@0: michael@0: template michael@0: struct FunctionInfo : public VMFunction { michael@0: typedef R (*pf)(Context, A1, A2, A3); michael@0: FUNCTION_INFO_STRUCT_BODY(FOR_EACH_ARGS_3) michael@0: }; michael@0: michael@0: template michael@0: struct FunctionInfo : public VMFunction { michael@0: typedef R (*pf)(Context, A1, A2, A3, A4); michael@0: FUNCTION_INFO_STRUCT_BODY(FOR_EACH_ARGS_4) michael@0: }; michael@0: michael@0: template michael@0: struct FunctionInfo : public VMFunction { michael@0: typedef R (*pf)(Context, A1, A2, A3, A4, A5); michael@0: FUNCTION_INFO_STRUCT_BODY(FOR_EACH_ARGS_5) michael@0: }; michael@0: michael@0: template michael@0: struct FunctionInfo : public VMFunction { michael@0: typedef R (*pf)(Context, A1, A2, A3, A4, A5, A6); michael@0: FUNCTION_INFO_STRUCT_BODY(FOR_EACH_ARGS_6) michael@0: }; michael@0: michael@0: #undef FUNCTION_INFO_STRUCT_BODY michael@0: michael@0: #undef FOR_EACH_ARGS_6 michael@0: #undef FOR_EACH_ARGS_5 michael@0: #undef FOR_EACH_ARGS_4 michael@0: #undef FOR_EACH_ARGS_3 michael@0: #undef FOR_EACH_ARGS_2 michael@0: #undef FOR_EACH_ARGS_1 michael@0: michael@0: #undef COMPUTE_INDEX michael@0: #undef COMPUTE_OUTPARAM_RESULT michael@0: #undef COMPUTE_OUTPARAM_ROOT michael@0: #undef COMPUTE_ARG_PROP michael@0: #undef COMPUTE_ARG_FLOAT michael@0: #undef SEP_OR michael@0: #undef NOTHING michael@0: michael@0: class AutoDetectInvalidation michael@0: { michael@0: JSContext *cx_; michael@0: IonScript *ionScript_; michael@0: Value *rval_; michael@0: bool disabled_; michael@0: michael@0: public: michael@0: AutoDetectInvalidation(JSContext *cx, Value *rval, IonScript *ionScript = nullptr); michael@0: michael@0: void disable() { michael@0: JS_ASSERT(!disabled_); michael@0: disabled_ = true; michael@0: } michael@0: michael@0: ~AutoDetectInvalidation() { michael@0: if (!disabled_ && ionScript_->invalidated()) michael@0: cx_->runtime()->setIonReturnOverride(*rval_); michael@0: } michael@0: }; michael@0: michael@0: bool InvokeFunction(JSContext *cx, HandleObject obj0, uint32_t argc, Value *argv, Value *rval); michael@0: JSObject *NewGCObject(JSContext *cx, gc::AllocKind allocKind, gc::InitialHeap initialHeap); michael@0: michael@0: bool CheckOverRecursed(JSContext *cx); michael@0: bool CheckOverRecursedWithExtra(JSContext *cx, BaselineFrame *frame, michael@0: uint32_t extra, uint32_t earlyCheck); michael@0: michael@0: bool DefVarOrConst(JSContext *cx, HandlePropertyName dn, unsigned attrs, HandleObject scopeChain); michael@0: bool SetConst(JSContext *cx, HandlePropertyName name, HandleObject scopeChain, HandleValue rval); michael@0: bool MutatePrototype(JSContext *cx, HandleObject obj, HandleValue value); michael@0: bool InitProp(JSContext *cx, HandleObject obj, HandlePropertyName name, HandleValue value); michael@0: michael@0: template michael@0: bool LooselyEqual(JSContext *cx, MutableHandleValue lhs, MutableHandleValue rhs, bool *res); michael@0: michael@0: template michael@0: bool StrictlyEqual(JSContext *cx, MutableHandleValue lhs, MutableHandleValue rhs, bool *res); michael@0: michael@0: bool LessThan(JSContext *cx, MutableHandleValue lhs, MutableHandleValue rhs, bool *res); michael@0: bool LessThanOrEqual(JSContext *cx, MutableHandleValue lhs, MutableHandleValue rhs, bool *res); michael@0: bool GreaterThan(JSContext *cx, MutableHandleValue lhs, MutableHandleValue rhs, bool *res); michael@0: bool GreaterThanOrEqual(JSContext *cx, MutableHandleValue lhs, MutableHandleValue rhs, bool *res); michael@0: michael@0: template michael@0: bool StringsEqual(JSContext *cx, HandleString left, HandleString right, bool *res); michael@0: michael@0: bool IteratorMore(JSContext *cx, HandleObject obj, bool *res); michael@0: michael@0: // Allocation functions for JSOP_NEWARRAY and JSOP_NEWOBJECT and parallel array inlining michael@0: JSObject *NewInitParallelArray(JSContext *cx, HandleObject templateObj); michael@0: JSObject *NewInitArray(JSContext *cx, uint32_t count, types::TypeObject *type); michael@0: JSObject *NewInitObject(JSContext *cx, HandleObject templateObject); michael@0: JSObject *NewInitObjectWithClassPrototype(JSContext *cx, HandleObject templateObject); michael@0: michael@0: bool ArrayPopDense(JSContext *cx, HandleObject obj, MutableHandleValue rval); michael@0: bool ArrayPushDense(JSContext *cx, HandleObject obj, HandleValue v, uint32_t *length); michael@0: bool ArrayShiftDense(JSContext *cx, HandleObject obj, MutableHandleValue rval); michael@0: JSObject *ArrayConcatDense(JSContext *cx, HandleObject obj1, HandleObject obj2, HandleObject res); michael@0: michael@0: bool CharCodeAt(JSContext *cx, HandleString str, int32_t index, uint32_t *code); michael@0: JSFlatString *StringFromCharCode(JSContext *cx, int32_t code); michael@0: michael@0: bool SetProperty(JSContext *cx, HandleObject obj, HandlePropertyName name, HandleValue value, michael@0: bool strict, jsbytecode *pc); michael@0: michael@0: bool InterruptCheck(JSContext *cx); michael@0: michael@0: HeapSlot *NewSlots(JSRuntime *rt, unsigned nslots); michael@0: JSObject *NewCallObject(JSContext *cx, HandleShape shape, HandleTypeObject type, HeapSlot *slots); michael@0: JSObject *NewSingletonCallObject(JSContext *cx, HandleShape shape, HeapSlot *slots); michael@0: JSObject *NewStringObject(JSContext *cx, HandleString str); michael@0: michael@0: bool SPSEnter(JSContext *cx, HandleScript script); michael@0: bool SPSExit(JSContext *cx, HandleScript script); michael@0: michael@0: bool OperatorIn(JSContext *cx, HandleValue key, HandleObject obj, bool *out); michael@0: bool OperatorInI(JSContext *cx, uint32_t index, HandleObject obj, bool *out); michael@0: michael@0: bool GetIntrinsicValue(JSContext *cx, HandlePropertyName name, MutableHandleValue rval); michael@0: michael@0: bool CreateThis(JSContext *cx, HandleObject callee, MutableHandleValue rval); michael@0: michael@0: void GetDynamicName(JSContext *cx, JSObject *scopeChain, JSString *str, Value *vp); michael@0: michael@0: bool FilterArgumentsOrEval(JSContext *cx, JSString *str); michael@0: michael@0: #ifdef JSGC_GENERATIONAL michael@0: void PostWriteBarrier(JSRuntime *rt, JSObject *obj); michael@0: void PostGlobalWriteBarrier(JSRuntime *rt, JSObject *obj); michael@0: #endif michael@0: michael@0: uint32_t GetIndexFromString(JSString *str); michael@0: michael@0: bool DebugPrologue(JSContext *cx, BaselineFrame *frame, jsbytecode *pc, bool *mustReturn); michael@0: bool DebugEpilogue(JSContext *cx, BaselineFrame *frame, jsbytecode *pc, bool ok); michael@0: michael@0: bool StrictEvalPrologue(JSContext *cx, BaselineFrame *frame); michael@0: bool HeavyweightFunPrologue(JSContext *cx, BaselineFrame *frame); michael@0: michael@0: bool NewArgumentsObject(JSContext *cx, BaselineFrame *frame, MutableHandleValue res); michael@0: michael@0: JSObject *InitRestParameter(JSContext *cx, uint32_t length, Value *rest, HandleObject templateObj, michael@0: HandleObject res); michael@0: michael@0: bool HandleDebugTrap(JSContext *cx, BaselineFrame *frame, uint8_t *retAddr, bool *mustReturn); michael@0: bool OnDebuggerStatement(JSContext *cx, BaselineFrame *frame, jsbytecode *pc, bool *mustReturn); michael@0: michael@0: bool EnterWith(JSContext *cx, BaselineFrame *frame, HandleValue val, michael@0: Handle templ); michael@0: bool LeaveWith(JSContext *cx, BaselineFrame *frame); michael@0: michael@0: bool PushBlockScope(JSContext *cx, BaselineFrame *frame, Handle block); michael@0: bool PopBlockScope(JSContext *cx, BaselineFrame *frame); michael@0: bool DebugLeaveBlock(JSContext *cx, BaselineFrame *frame, jsbytecode *pc); michael@0: michael@0: bool InitBaselineFrameForOsr(BaselineFrame *frame, InterpreterFrame *interpFrame, michael@0: uint32_t numStackValues); michael@0: michael@0: JSObject *CreateDerivedTypedObj(JSContext *cx, HandleObject descr, michael@0: HandleObject owner, int32_t offset); michael@0: michael@0: bool ArraySpliceDense(JSContext *cx, HandleObject obj, uint32_t start, uint32_t deleteCount); michael@0: michael@0: bool Recompile(JSContext *cx); michael@0: JSString *RegExpReplace(JSContext *cx, HandleString string, HandleObject regexp, michael@0: HandleString repl); michael@0: JSString *StringReplace(JSContext *cx, HandleString string, HandleString pattern, michael@0: HandleString repl); michael@0: michael@0: bool SetDenseElement(JSContext *cx, HandleObject obj, int32_t index, HandleValue value, michael@0: bool strict); michael@0: michael@0: #ifdef DEBUG michael@0: void AssertValidObjectPtr(JSContext *cx, JSObject *obj); michael@0: void AssertValidStringPtr(JSContext *cx, JSString *str); michael@0: void AssertValidValue(JSContext *cx, Value *v); michael@0: #endif michael@0: michael@0: } // namespace jit michael@0: } // namespace js michael@0: michael@0: #endif /* jit_VMFunctions_h */