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