/* -*- 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 */