tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

VMFunctions.h (29424B)


      1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
      2 * vim: set ts=8 sts=2 et sw=2 tw=80:
      3 * This Source Code Form is subject to the terms of the Mozilla Public
      4 * License, v. 2.0. If a copy of the MPL was not distributed with this
      5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
      6 
      7 #ifndef jit_VMFunctions_h
      8 #define jit_VMFunctions_h
      9 
     10 #include "mozilla/Assertions.h"
     11 #include "mozilla/HashFunctions.h"
     12 
     13 #include <stddef.h>
     14 #include <stdint.h>
     15 
     16 #include "jstypes.h"
     17 #include "NamespaceImports.h"
     18 
     19 #include "gc/AllocKind.h"
     20 #include "js/ScalarType.h"
     21 #include "js/TypeDecls.h"
     22 #include "vm/TypeofEqOperand.h"
     23 #include "vm/UsingHint.h"
     24 
     25 class JSJitInfo;
     26 class JSLinearString;
     27 
     28 namespace js {
     29 
     30 class AbstractGeneratorObject;
     31 class ArrayObject;
     32 class DateObject;
     33 class FixedLengthTypedArrayObject;
     34 class GlobalObject;
     35 class InterpreterFrame;
     36 class LexicalScope;
     37 class ClassBodyScope;
     38 class MapObject;
     39 class NativeObject;
     40 class PlainObject;
     41 class PropertyName;
     42 class SetObject;
     43 class Shape;
     44 class TypedArrayObject;
     45 class WithScope;
     46 class MegamorphicCacheEntry;
     47 
     48 namespace gc {
     49 
     50 struct Cell;
     51 
     52 }  // namespace gc
     53 
     54 namespace wasm {
     55 
     56 class AnyRef;
     57 
     58 }  // namespace wasm
     59 
     60 namespace jit {
     61 
     62 class BaselineFrame;
     63 class InterpreterStubExitFrameLayout;
     64 
     65 enum DataType : uint8_t {
     66  Type_Void,
     67  Type_Bool,
     68  Type_Int32,
     69  Type_Double,
     70  Type_Pointer,
     71  Type_Cell,
     72  Type_Value,
     73  Type_Handle
     74 };
     75 
     76 // [SMDOC] JIT-to-C++ Function Calls. (callVM)
     77 //
     78 // Sometimes it is easier to reuse C++ code by calling VM's functions. Calling a
     79 // function from the VM can be achieved with the use of callWithABI but this is
     80 // discouraged when the called functions might trigger exceptions and/or
     81 // garbage collections which are expecting to walk the stack. VMFunctions and
     82 // callVM are interfaces provided to handle the exception handling and register
     83 // the stack end (JITActivation) such that walking the stack is made possible.
     84 //
     85 // VMFunctionData is a structure which contains the necessary information needed
     86 // for generating a trampoline function to make a call (with generateVMWrapper)
     87 // and to root the arguments of the function (in TraceJitExitFrame).
     88 // VMFunctionData is created with the VMFunctionDataHelper template, which
     89 // infers the VMFunctionData fields from the function signature. The rooting and
     90 // trampoline code is therefore determined by the arguments of a function and
     91 // their locations in the signature of a function.
     92 //
     93 // VM functions all expect a JSContext* as first argument. This argument is
     94 // implicitly provided by the trampoline code (in generateVMWrapper) and used
     95 // for creating new objects or reporting errors. If your function does not make
     96 // use of a JSContext* argument, then you might probably use a callWithABI
     97 // call.
     98 //
     99 // Functions described using the VMFunction system must conform to a simple
    100 // protocol: the return type must have a special "failure" value (for example,
    101 // false for bool, or nullptr for Objects). If the function is designed to
    102 // return a value that does not meet this requirement - such as
    103 // object-or-nullptr, or an integer, an optional, final outParam can be
    104 // specified. In this case, the return type must be boolean to indicate
    105 // failure.
    106 //
    107 // JIT Code usage:
    108 //
    109 // Different JIT compilers in SpiderMonkey have their own implementations of
    110 // callVM to call VM functions. However, the general shape of them is that
    111 // arguments (excluding the JSContext or trailing out-param) are pushed on to
    112 // the stack from right to left (rightmost argument is pushed first).
    113 //
    114 // Regardless of return value protocol being used (final outParam, or return
    115 // value) the generated trampolines ensure the return value ends up in
    116 // JSReturnOperand, ReturnReg or ReturnDoubleReg.
    117 //
    118 // Example:
    119 //
    120 // The details will differ slightly between the different compilers in
    121 // SpiderMonkey, but the general shape of our usage looks like this:
    122 //
    123 // Suppose we have a function Foo:
    124 //
    125 //      bool Foo(JSContext* cx, HandleObject x, HandleId y,
    126 //               MutableHandleValue z);
    127 //
    128 // This function returns true on success, and z is the outparam return value.
    129 //
    130 // A VM function wrapper for this can be created by adding an entry to
    131 // VM_FUNCTION_LIST in VMFunctionList-inl.h:
    132 //
    133 //    _(Foo, js::Foo)
    134 //
    135 // In the compiler code the call would then be issued like this:
    136 //
    137 //      masm.Push(id);
    138 //      masm.Push(obj);
    139 //
    140 //      using Fn = bool (*)(JSContext*, HandleObject, HandleId,
    141 //                          MutableHandleValue);
    142 //      if (!callVM<Fn, js::Foo>()) {
    143 //          return false;
    144 //      }
    145 //
    146 // After this, the result value is in the return value register.
    147 
    148 // Data for a VM function. All VMFunctionDatas are stored in a constexpr array.
    149 struct VMFunctionData {
    150 #if defined(DEBUG) || defined(JS_JITSPEW) || defined(JS_ION_PERF)
    151  // Informative name of the wrapped function. The name should not be present
    152  // in release builds in order to save memory.
    153  const char* name_;
    154 #endif
    155 
    156  // Note: a maximum of seven root types is supported.
    157  enum RootType : uint8_t {
    158    RootNone = 0,
    159    RootObject,
    160    RootString,
    161    RootId,
    162    RootValue,
    163    RootCell,
    164    RootBigInt
    165  };
    166 
    167  // Contains an combination of enumerated types used by the gc for marking
    168  // arguments of the VM wrapper.
    169  uint64_t argumentRootTypes;
    170 
    171  enum ArgProperties {
    172    WordByValue = 0,
    173    DoubleByValue = 1,
    174    WordByRef = 2,
    175    DoubleByRef = 3,
    176    // BitMask version.
    177    Word = 0,
    178    Double = 1,
    179    ByRef = 2
    180  };
    181 
    182  // Contains properties about the first 16 arguments.
    183  uint32_t argumentProperties;
    184 
    185  // Which arguments should be passed in float register on platforms that
    186  // have them.
    187  uint32_t argumentPassedInFloatRegs;
    188 
    189  // Number of arguments expected, excluding JSContext * as an implicit
    190  // first argument and an outparam as a possible implicit final argument.
    191  uint8_t explicitArgs;
    192 
    193  // The root type of the out param if outParam == Type_Handle.
    194  RootType outParamRootType;
    195 
    196  // The outparam may be any Type_*, and must be the final argument to the
    197  // function, if not Void. outParam != Void implies that the return type
    198  // has a boolean failure mode.
    199  DataType outParam;
    200 
    201  // Type returned by the C function and used by the VMFunction wrapper to
    202  // check for failures of the C function.  Valid failure/return types are
    203  // boolean and object pointers which are asserted inside the VMFunction
    204  // constructor. If the C function use an outparam (!= Type_Void), then
    205  // the only valid failure/return type is boolean -- object pointers are
    206  // pointless because the wrapper will only use it to compare it against
    207  // nullptr before discarding its value.
    208  DataType returnType;
    209 
    210  // Number of Values the VM wrapper should pop from the stack when it returns.
    211  // Used by baseline IC stubs so that they can use tail calls to call the VM
    212  // wrapper.
    213  uint8_t extraValuesToPop;
    214 
    215  uint32_t argc() const {
    216    // JSContext * + args + (OutParam? *)
    217    return 1 + explicitArgc() + ((outParam == Type_Void) ? 0 : 1);
    218  }
    219 
    220  DataType failType() const { return returnType; }
    221 
    222  // Whether this function returns anything more than a boolean flag for
    223  // failures.
    224  bool returnsData() const {
    225    return returnType == Type_Cell || outParam != Type_Void;
    226  }
    227 
    228  ArgProperties argProperties(uint32_t explicitArg) const {
    229    return ArgProperties((argumentProperties >> (2 * explicitArg)) & 3);
    230  }
    231 
    232  RootType argRootType(uint32_t explicitArg) const {
    233    return RootType((argumentRootTypes >> (3 * explicitArg)) & 7);
    234  }
    235 
    236  bool argPassedInFloatReg(uint32_t explicitArg) const {
    237    return ((argumentPassedInFloatRegs >> explicitArg) & 1) == 1;
    238  }
    239 
    240 #if defined(DEBUG) || defined(JS_JITSPEW) || defined(JS_ION_PERF)
    241  const char* name() const { return name_; }
    242 #endif
    243 
    244  // Return the stack size consumed by explicit arguments.
    245  size_t explicitStackSlots() const {
    246    size_t stackSlots = explicitArgs;
    247 
    248    // Fetch all double-word flags of explicit arguments.
    249    uint32_t n = ((1 << (explicitArgs * 2)) - 1)  // = Explicit argument mask.
    250                 & 0x55555555                     // = Mask double-size args.
    251                 & argumentProperties;
    252 
    253    // Add the number of double-word flags. (expect a few loop
    254    // iteration)
    255    while (n) {
    256      stackSlots++;
    257      n &= n - 1;
    258    }
    259    return stackSlots;
    260  }
    261 
    262  // Double-size argument which are passed by value are taking the space
    263  // of 2 C arguments.  This function is used to compute the number of
    264  // argument expected by the C function.  This is not the same as
    265  // explicitStackSlots because reference to stack slots may take one less
    266  // register in the total count.
    267  size_t explicitArgc() const {
    268    size_t stackSlots = explicitArgs;
    269 
    270    // Fetch all explicit arguments.
    271    uint32_t n = ((1 << (explicitArgs * 2)) - 1)  // = Explicit argument mask.
    272                 & argumentProperties;
    273 
    274    // Filter double-size arguments (0x5 = 0b0101) and remove (& ~)
    275    // arguments passed by reference (0b1010 >> 1 == 0b0101).
    276    n = (n & 0x55555555) & ~(n >> 1);
    277 
    278    // Add the number of double-word transfered by value. (expect a few
    279    // loop iteration)
    280    while (n) {
    281      stackSlots++;
    282      n &= n - 1;
    283    }
    284    return stackSlots;
    285  }
    286 
    287  size_t doubleByRefArgs() const {
    288    size_t count = 0;
    289 
    290    // Fetch all explicit arguments.
    291    uint32_t n = ((1 << (explicitArgs * 2)) - 1)  // = Explicit argument mask.
    292                 & argumentProperties;
    293 
    294    // Filter double-size arguments (0x5 = 0b0101) and take (&) only
    295    // arguments passed by reference (0b1010 >> 1 == 0b0101).
    296    n = (n & 0x55555555) & (n >> 1);
    297 
    298    // Add the number of double-word transfered by refference. (expect a
    299    // few loop iterations)
    300    while (n) {
    301      count++;
    302      n &= n - 1;
    303    }
    304    return count;
    305  }
    306 
    307  size_t sizeOfOutParamStackSlot() const;
    308 
    309  constexpr VMFunctionData(const char* name, uint32_t explicitArgs,
    310                           uint32_t argumentProperties,
    311                           uint32_t argumentPassedInFloatRegs,
    312                           uint64_t argRootTypes, DataType outParam,
    313                           RootType outParamRootType, DataType returnType,
    314                           uint8_t extraValuesToPop = 0)
    315      :
    316 #if defined(DEBUG) || defined(JS_JITSPEW) || defined(JS_ION_PERF)
    317        name_(name),
    318 #endif
    319        argumentRootTypes(argRootTypes),
    320        argumentProperties(argumentProperties),
    321        argumentPassedInFloatRegs(argumentPassedInFloatRegs),
    322        explicitArgs(explicitArgs),
    323        outParamRootType(outParamRootType),
    324        outParam(outParam),
    325        returnType(returnType),
    326        extraValuesToPop(extraValuesToPop) {
    327    // Check for valid failure/return type.
    328    MOZ_ASSERT_IF(outParam != Type_Void,
    329                  returnType == Type_Void || returnType == Type_Bool);
    330    MOZ_ASSERT(returnType == Type_Void || returnType == Type_Bool ||
    331               returnType == Type_Cell);
    332  }
    333 
    334  constexpr VMFunctionData(const VMFunctionData& o) = default;
    335 };
    336 
    337 // Extract the last element of a list of types.
    338 template <typename... ArgTypes>
    339 struct LastArg;
    340 
    341 template <>
    342 struct LastArg<> {
    343  using Type = void;
    344 };
    345 
    346 template <typename HeadType>
    347 struct LastArg<HeadType> {
    348  using Type = HeadType;
    349 };
    350 
    351 template <typename HeadType, typename... TailTypes>
    352 struct LastArg<HeadType, TailTypes...> {
    353  using Type = typename LastArg<TailTypes...>::Type;
    354 };
    355 
    356 [[nodiscard]] bool InvokeFunction(JSContext* cx, HandleObject obj0,
    357                                  bool constructing, bool ignoresReturnValue,
    358                                  uint32_t argc, Value* argv,
    359                                  MutableHandleValue rval);
    360 
    361 bool InvokeFromInterpreterStub(JSContext* cx,
    362                               InterpreterStubExitFrameLayout* frame);
    363 void* GetContextSensitiveInterpreterStub();
    364 
    365 bool CheckOverRecursed(JSContext* cx);
    366 bool CheckOverRecursedBaseline(JSContext* cx, BaselineFrame* frame);
    367 
    368 [[nodiscard]] bool MutatePrototype(JSContext* cx, Handle<PlainObject*> obj,
    369                                   HandleValue value);
    370 
    371 enum class EqualityKind : bool { NotEqual, Equal };
    372 
    373 template <EqualityKind Kind>
    374 bool StringsEqual(JSContext* cx, HandleString lhs, HandleString rhs, bool* res);
    375 
    376 enum class ComparisonKind : bool { GreaterThanOrEqual, LessThan };
    377 
    378 template <ComparisonKind Kind>
    379 bool StringsCompare(JSContext* cx, HandleString lhs, HandleString rhs,
    380                    bool* res);
    381 
    382 JSString* ArrayJoin(JSContext* cx, HandleObject array, HandleString sep);
    383 [[nodiscard]] bool SetArrayLength(JSContext* cx, HandleObject obj,
    384                                  HandleValue value, bool strict);
    385 
    386 [[nodiscard]] bool CharCodeAt(JSContext* cx, HandleString str, int32_t index,
    387                              uint32_t* code);
    388 [[nodiscard]] bool CodePointAt(JSContext* cx, HandleString str, int32_t index,
    389                               uint32_t* code);
    390 JSLinearString* StringFromCharCodeNoGC(JSContext* cx, int32_t code);
    391 JSLinearString* LinearizeForCharAccessPure(JSString* str);
    392 JSLinearString* LinearizeForCharAccess(JSContext* cx, JSString* str);
    393 int32_t StringTrimStartIndex(const JSString* str);
    394 int32_t StringTrimEndIndex(const JSString* str, int32_t start);
    395 JSString* CharCodeToLowerCase(JSContext* cx, int32_t code);
    396 JSString* CharCodeToUpperCase(JSContext* cx, int32_t code);
    397 
    398 [[nodiscard]] bool SetProperty(JSContext* cx, HandleObject obj,
    399                               Handle<PropertyName*> name, HandleValue value,
    400                               bool strict, jsbytecode* pc);
    401 
    402 [[nodiscard]] bool InterruptCheck(JSContext* cx);
    403 
    404 JSObject* NewStringObject(JSContext* cx, HandleString str);
    405 
    406 bool OperatorIn(JSContext* cx, HandleValue key, HandleObject obj, bool* out);
    407 
    408 [[nodiscard]] bool GetIntrinsicValue(JSContext* cx, Handle<PropertyName*> name,
    409                                     MutableHandleValue rval);
    410 
    411 [[nodiscard]] bool CreateThisFromIC(JSContext* cx, HandleObject callee,
    412                                    HandleObject newTarget,
    413                                    MutableHandleValue rval);
    414 [[nodiscard]] bool CreateThisFromIon(JSContext* cx, HandleObject callee,
    415                                     HandleObject newTarget,
    416                                     MutableHandleValue rval);
    417 
    418 void PostWriteBarrier(JSRuntime* rt, js::gc::Cell* cell);
    419 void PostGlobalWriteBarrier(JSRuntime* rt, GlobalObject* obj);
    420 
    421 void PostWriteElementBarrier(JSRuntime* rt, JSObject* obj, int32_t index);
    422 
    423 // If |str| represents an int32, assign it to |result| and return true.
    424 // Otherwise return false.
    425 bool GetInt32FromStringPure(JSContext* cx, JSString* str, int32_t* result);
    426 
    427 // If |str| is an index in the range [0, INT32_MAX], return it. If the string
    428 // is not an index in this range, return -1.
    429 int32_t GetIndexFromString(JSString* str);
    430 
    431 JSObject* WrapObjectPure(JSContext* cx, JSObject* obj);
    432 
    433 [[nodiscard]] bool DebugPrologue(JSContext* cx, BaselineFrame* frame);
    434 [[nodiscard]] bool DebugEpilogue(JSContext* cx, BaselineFrame* frame,
    435                                 const jsbytecode* pc, bool ok);
    436 [[nodiscard]] bool DebugEpilogueOnBaselineReturn(JSContext* cx,
    437                                                 BaselineFrame* frame,
    438                                                 const jsbytecode* pc);
    439 void FrameIsDebuggeeCheck(BaselineFrame* frame);
    440 
    441 JSObject* CreateGeneratorFromFrame(JSContext* cx, BaselineFrame* frame);
    442 JSObject* CreateGenerator(JSContext* cx, HandleFunction, HandleScript,
    443                          HandleObject, HandleObject);
    444 
    445 [[nodiscard]] bool NormalSuspend(JSContext* cx, HandleObject obj,
    446                                 BaselineFrame* frame, uint32_t frameSize,
    447                                 const jsbytecode* pc);
    448 [[nodiscard]] bool FinalSuspend(JSContext* cx, HandleObject obj,
    449                                const jsbytecode* pc);
    450 [[nodiscard]] bool InterpretResume(JSContext* cx, HandleObject obj,
    451                                   Value* stackValues, MutableHandleValue rval);
    452 [[nodiscard]] bool DebugAfterYield(JSContext* cx, BaselineFrame* frame);
    453 [[nodiscard]] bool GeneratorThrowOrReturn(
    454    JSContext* cx, BaselineFrame* frame,
    455    Handle<AbstractGeneratorObject*> genObj, HandleValue arg,
    456    int32_t resumeKindArg);
    457 
    458 [[nodiscard]] bool GlobalDeclInstantiationFromIon(JSContext* cx,
    459                                                  HandleScript script,
    460                                                  const jsbytecode* pc);
    461 [[nodiscard]] bool InitFunctionEnvironmentObjects(JSContext* cx,
    462                                                  BaselineFrame* frame);
    463 
    464 [[nodiscard]] bool NewArgumentsObject(JSContext* cx, BaselineFrame* frame,
    465                                      MutableHandleValue res);
    466 
    467 ArrayObject* NewArrayObjectEnsureDenseInitLength(JSContext* cx, int32_t count);
    468 
    469 ArrayObject* InitRestParameter(JSContext* cx, uint32_t length, Value* rest,
    470                               Handle<ArrayObject*> arrRes);
    471 
    472 [[nodiscard]] bool HandleDebugTrap(JSContext* cx, BaselineFrame* frame,
    473                                   const uint8_t* retAddr);
    474 [[nodiscard]] bool OnDebuggerStatement(JSContext* cx, BaselineFrame* frame);
    475 [[nodiscard]] bool GlobalHasLiveOnDebuggerStatement(JSContext* cx);
    476 
    477 [[nodiscard]] bool EnterWith(JSContext* cx, BaselineFrame* frame,
    478                             HandleValue val, Handle<WithScope*> templ);
    479 [[nodiscard]] bool LeaveWith(JSContext* cx, BaselineFrame* frame);
    480 
    481 [[nodiscard]] bool PushLexicalEnv(JSContext* cx, BaselineFrame* frame,
    482                                  Handle<LexicalScope*> scope);
    483 [[nodiscard]] bool PushClassBodyEnv(JSContext* cx, BaselineFrame* frame,
    484                                    Handle<ClassBodyScope*> scope);
    485 [[nodiscard]] bool DebugLeaveThenPopLexicalEnv(JSContext* cx,
    486                                               BaselineFrame* frame,
    487                                               const jsbytecode* pc);
    488 [[nodiscard]] bool FreshenLexicalEnv(JSContext* cx, BaselineFrame* frame);
    489 [[nodiscard]] bool DebuggeeFreshenLexicalEnv(JSContext* cx,
    490                                             BaselineFrame* frame,
    491                                             const jsbytecode* pc);
    492 [[nodiscard]] bool RecreateLexicalEnv(JSContext* cx, BaselineFrame* frame);
    493 [[nodiscard]] bool DebuggeeRecreateLexicalEnv(JSContext* cx,
    494                                              BaselineFrame* frame,
    495                                              const jsbytecode* pc);
    496 [[nodiscard]] bool DebugLeaveLexicalEnv(JSContext* cx, BaselineFrame* frame,
    497                                        const jsbytecode* pc);
    498 
    499 [[nodiscard]] bool PushVarEnv(JSContext* cx, BaselineFrame* frame,
    500                              Handle<Scope*> scope);
    501 
    502 [[nodiscard]] bool InitBaselineFrameForOsr(BaselineFrame* frame,
    503                                           InterpreterFrame* interpFrame,
    504                                           uint32_t numStackValues);
    505 
    506 JSString* StringReplace(JSContext* cx, HandleString string,
    507                        HandleString pattern, HandleString repl);
    508 
    509 void AssertValidBigIntPtr(JSContext* cx, JS::BigInt* bi);
    510 void AssertValidObjectPtr(JSContext* cx, JSObject* obj);
    511 void AssertValidStringPtr(JSContext* cx, JSString* str);
    512 void AssertValidSymbolPtr(JSContext* cx, JS::Symbol* sym);
    513 void AssertValidValue(JSContext* cx, Value* v);
    514 
    515 void JitValuePreWriteBarrier(JSRuntime* rt, Value* vp);
    516 void JitStringPreWriteBarrier(JSRuntime* rt, JSString** stringp);
    517 void JitObjectPreWriteBarrier(JSRuntime* rt, JSObject** objp);
    518 void JitShapePreWriteBarrier(JSRuntime* rt, Shape** shapep);
    519 void JitWasmAnyRefPreWriteBarrier(JSRuntime* rt, wasm::AnyRef* refp);
    520 
    521 bool ObjectIsCallable(JSObject* obj);
    522 bool ObjectIsConstructor(JSObject* obj);
    523 JSObject* ObjectKeys(JSContext* cx, HandleObject obj);
    524 JSObject* ObjectKeysFromIterator(JSContext* cx, HandleObject iterObj);
    525 bool ObjectKeysLength(JSContext* cx, HandleObject obj, int32_t* length);
    526 
    527 [[nodiscard]] bool ThrowRuntimeLexicalError(JSContext* cx,
    528                                            unsigned errorNumber);
    529 
    530 [[nodiscard]] bool ThrowBadDerivedReturnOrUninitializedThis(JSContext* cx,
    531                                                            HandleValue v);
    532 
    533 [[nodiscard]] bool BaselineGetFunctionThis(JSContext* cx, BaselineFrame* frame,
    534                                           MutableHandleValue res);
    535 
    536 [[nodiscard]] bool CallNativeGetter(JSContext* cx, HandleFunction callee,
    537                                    HandleValue receiver,
    538                                    MutableHandleValue result);
    539 
    540 bool CallDOMGetter(JSContext* cx, const JSJitInfo* jitInfo, HandleObject obj,
    541                   MutableHandleValue result);
    542 
    543 bool CallDOMSetter(JSContext* cx, const JSJitInfo* jitInfo, HandleObject obj,
    544                   HandleValue value);
    545 
    546 [[nodiscard]] bool CallNativeSetter(JSContext* cx, HandleFunction callee,
    547                                    HandleObject obj, HandleValue rhs);
    548 
    549 [[nodiscard]] bool EqualStringsHelperPure(JSString* str1, JSString* str2);
    550 
    551 void HandleCodeCoverageAtPC(BaselineFrame* frame, jsbytecode* pc);
    552 void HandleCodeCoverageAtPrologue(BaselineFrame* frame);
    553 
    554 bool CheckProxyGetByValueResult(JSContext* cx, HandleObject obj, HandleValue id,
    555                                HandleValue value, MutableHandleValue result);
    556 
    557 bool GetNativeDataPropertyPure(JSContext* cx, JSObject* obj, PropertyKey id,
    558                               MegamorphicCacheEntry* entry, Value* vp);
    559 
    560 bool GetNativeDataPropertyPureWithCacheLookup(JSContext* cx, JSObject* obj,
    561                                              PropertyKey id,
    562                                              MegamorphicCacheEntry* entry,
    563                                              Value* vp);
    564 
    565 bool GetNativeDataPropertyByValuePure(JSContext* cx, JSObject* obj,
    566                                      MegamorphicCacheEntry* cacheEntry,
    567                                      Value* vp);
    568 
    569 bool GetPropMaybeCached(JSContext* cx, HandleObject obj, HandleId id,
    570                        MegamorphicCacheEntry* cacheEntry,
    571                        MutableHandleValue result);
    572 
    573 bool GetElemMaybeCached(JSContext* cx, HandleObject obj, HandleValue id,
    574                        MegamorphicCacheEntry* cacheEntry,
    575                        MutableHandleValue result);
    576 
    577 template <bool HasOwn>
    578 bool HasNativeDataPropertyPure(JSContext* cx, JSObject* obj,
    579                               MegamorphicCacheEntry* cacheEntry, Value* vp);
    580 
    581 bool HasNativeElementPure(JSContext* cx, NativeObject* obj, int32_t index,
    582                          Value* vp);
    583 
    584 bool ObjectHasGetterSetterPure(JSContext* cx, JSObject* objArg, jsid id,
    585                               GetterSetter* getterSetter);
    586 
    587 template <bool Cached>
    588 bool SetElementMegamorphic(JSContext* cx, HandleObject obj, HandleValue index,
    589                           HandleValue value, bool strict);
    590 
    591 template <bool Cached>
    592 bool SetPropertyMegamorphic(JSContext* cx, HandleObject obj, HandleId id,
    593                            HandleValue value, bool strict);
    594 
    595 JSString* TypeOfNameObject(JSObject* obj, JSRuntime* rt);
    596 
    597 bool TypeOfEqObject(JSObject* obj, TypeofEqOperand operand);
    598 
    599 bool GetPrototypeOf(JSContext* cx, HandleObject target,
    600                    MutableHandleValue rval);
    601 
    602 bool DoConcatStringObject(JSContext* cx, HandleValue lhs, HandleValue rhs,
    603                          MutableHandleValue res);
    604 
    605 bool IsPossiblyWrappedTypedArray(JSContext* cx, JSObject* obj, bool* result);
    606 
    607 void* AllocateDependentString(JSContext* cx);
    608 void* AllocateFatInlineString(JSContext* cx);
    609 void* AllocateBigIntNoGC(JSContext* cx, bool requestMinorGC);
    610 void AllocateAndInitTypedArrayBuffer(JSContext* cx,
    611                                     FixedLengthTypedArrayObject* obj,
    612                                     int32_t count, size_t inlineCapacity);
    613 
    614 #ifdef JS_GC_PROBES
    615 void TraceCreateObject(JSObject* obj);
    616 #endif
    617 
    618 bool PreserveWrapper(JSContext* cx, JSObject* obj);
    619 
    620 bool DoStringToInt64(JSContext* cx, HandleString str, uint64_t* res);
    621 
    622 BigInt* CreateBigIntFromInt32(JSContext* cx, int32_t i32);
    623 
    624 #if JS_BITS_PER_WORD == 32
    625 BigInt* CreateBigIntFromInt64(JSContext* cx, uint32_t low, uint32_t high);
    626 BigInt* CreateBigIntFromUint64(JSContext* cx, uint32_t low, uint32_t high);
    627 #else
    628 BigInt* CreateBigIntFromInt64(JSContext* cx, uint64_t i64);
    629 BigInt* CreateBigIntFromUint64(JSContext* cx, uint64_t i64);
    630 #endif
    631 
    632 template <EqualityKind Kind>
    633 bool BigIntEqual(BigInt* x, BigInt* y);
    634 
    635 template <ComparisonKind Kind>
    636 bool BigIntCompare(BigInt* x, BigInt* y);
    637 
    638 template <EqualityKind Kind>
    639 bool BigIntNumberEqual(BigInt* x, double y);
    640 
    641 template <ComparisonKind Kind>
    642 bool BigIntNumberCompare(BigInt* x, double y);
    643 
    644 template <ComparisonKind Kind>
    645 bool NumberBigIntCompare(double x, BigInt* y);
    646 
    647 template <EqualityKind Kind>
    648 bool BigIntStringEqual(JSContext* cx, HandleBigInt x, HandleString y,
    649                       bool* res);
    650 
    651 template <ComparisonKind Kind>
    652 bool BigIntStringCompare(JSContext* cx, HandleBigInt x, HandleString y,
    653                         bool* res);
    654 
    655 template <ComparisonKind Kind>
    656 bool StringBigIntCompare(JSContext* cx, HandleString x, HandleBigInt y,
    657                         bool* res);
    658 
    659 BigInt* BigIntAsIntN(JSContext* cx, HandleBigInt x, int32_t bits);
    660 BigInt* BigIntAsUintN(JSContext* cx, HandleBigInt x, int32_t bits);
    661 
    662 using AtomicsCompareExchangeFn = int32_t (*)(TypedArrayObject*, size_t, int32_t,
    663                                             int32_t);
    664 
    665 using AtomicsReadWriteModifyFn = int32_t (*)(TypedArrayObject*, size_t,
    666                                             int32_t);
    667 
    668 AtomicsCompareExchangeFn AtomicsCompareExchange(Scalar::Type elementType);
    669 AtomicsReadWriteModifyFn AtomicsExchange(Scalar::Type elementType);
    670 AtomicsReadWriteModifyFn AtomicsAdd(Scalar::Type elementType);
    671 AtomicsReadWriteModifyFn AtomicsSub(Scalar::Type elementType);
    672 AtomicsReadWriteModifyFn AtomicsAnd(Scalar::Type elementType);
    673 AtomicsReadWriteModifyFn AtomicsOr(Scalar::Type elementType);
    674 AtomicsReadWriteModifyFn AtomicsXor(Scalar::Type elementType);
    675 
    676 BigInt* AtomicsLoad64(JSContext* cx, TypedArrayObject* typedArray,
    677                      size_t index);
    678 
    679 void AtomicsStore64(TypedArrayObject* typedArray, size_t index,
    680                    const BigInt* value);
    681 
    682 BigInt* AtomicsCompareExchange64(JSContext* cx, TypedArrayObject* typedArray,
    683                                 size_t index, const BigInt* expected,
    684                                 const BigInt* replacement);
    685 
    686 BigInt* AtomicsExchange64(JSContext* cx, TypedArrayObject* typedArray,
    687                          size_t index, const BigInt* value);
    688 
    689 BigInt* AtomicsAdd64(JSContext* cx, TypedArrayObject* typedArray, size_t index,
    690                     const BigInt* value);
    691 BigInt* AtomicsAnd64(JSContext* cx, TypedArrayObject* typedArray, size_t index,
    692                     const BigInt* value);
    693 BigInt* AtomicsOr64(JSContext* cx, TypedArrayObject* typedArray, size_t index,
    694                    const BigInt* value);
    695 BigInt* AtomicsSub64(JSContext* cx, TypedArrayObject* typedArray, size_t index,
    696                     const BigInt* value);
    697 BigInt* AtomicsXor64(JSContext* cx, TypedArrayObject* typedArray, size_t index,
    698                     const BigInt* value);
    699 
    700 float RoundFloat16ToFloat32(int32_t d);
    701 float RoundFloat16ToFloat32(float d);
    702 float RoundFloat16ToFloat32(double d);
    703 
    704 float Float16ToFloat32(int32_t value);
    705 int32_t Float32ToFloat16(float value);
    706 
    707 void DateFillLocalTimeSlots(DateObject* dateObj);
    708 
    709 JSAtom* AtomizeStringNoGC(JSContext* cx, JSString* str);
    710 
    711 bool SetObjectHas(JSContext* cx, Handle<SetObject*> obj, HandleValue key,
    712                  bool* rval);
    713 bool SetObjectDelete(JSContext* cx, Handle<SetObject*> obj, HandleValue key,
    714                     bool* rval);
    715 bool SetObjectAdd(JSContext* cx, Handle<SetObject*> obj, HandleValue key);
    716 bool SetObjectAddFromIC(JSContext* cx, Handle<SetObject*> obj, HandleValue key,
    717                        MutableHandleValue rval);
    718 bool MapObjectHas(JSContext* cx, Handle<MapObject*> obj, HandleValue key,
    719                  bool* rval);
    720 bool MapObjectGet(JSContext* cx, Handle<MapObject*> obj, HandleValue key,
    721                  MutableHandleValue rval);
    722 bool MapObjectDelete(JSContext* cx, Handle<MapObject*> obj, HandleValue key,
    723                     bool* rval);
    724 bool MapObjectSet(JSContext* cx, Handle<MapObject*> obj, HandleValue key,
    725                  HandleValue val);
    726 bool MapObjectSetFromIC(JSContext* cx, Handle<MapObject*> obj, HandleValue key,
    727                        HandleValue val, MutableHandleValue rval);
    728 
    729 void AssertSetObjectHash(JSContext* cx, SetObject* obj, const Value* value,
    730                         mozilla::HashNumber actualHash);
    731 void AssertMapObjectHash(JSContext* cx, MapObject* obj, const Value* value,
    732                         mozilla::HashNumber actualHash);
    733 
    734 void AssertPropertyLookup(NativeObject* obj, PropertyKey id, uint32_t slot);
    735 
    736 void ReadBarrier(gc::Cell* cell);
    737 
    738 // Functions used when JS_MASM_VERBOSE is enabled.
    739 void AssumeUnreachable(const char* output);
    740 void Printf0(const char* output);
    741 void Printf1(const char* output, uintptr_t value);
    742 
    743 enum class VMFunctionId;
    744 
    745 extern const VMFunctionData& GetVMFunction(VMFunctionId id);
    746 
    747 extern size_t NumVMFunctions();
    748 
    749 }  // namespace jit
    750 }  // namespace js
    751 
    752 #if defined(JS_CODEGEN_ARM)
    753 extern "C" {
    754 extern MOZ_EXPORT int64_t __aeabi_idivmod(int, int);
    755 extern MOZ_EXPORT int64_t __aeabi_uidivmod(int, int);
    756 }
    757 #endif
    758 
    759 #endif /* jit_VMFunctions_h */