tor-browser

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

PortableBaselineInterpret.cpp (329309B)


      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 /*
      8 * JavaScript "portable baseline interpreter": an interpreter that is
      9 * capable of running ICs, but without any native code.
     10 *
     11 * See the [SMDOC] in vm/PortableBaselineInterpret.h for a high-level
     12 * overview.
     13 */
     14 
     15 #include "vm/PortableBaselineInterpret.h"
     16 
     17 #include "mozilla/Maybe.h"
     18 
     19 #include <algorithm>
     20 #include <cmath>
     21 
     22 #include "fdlibm.h"
     23 #include "jsapi.h"
     24 
     25 #include "builtin/DataViewObject.h"
     26 #include "builtin/MapObject.h"
     27 #include "builtin/Object.h"
     28 #include "builtin/RegExp.h"
     29 #include "builtin/String.h"
     30 #include "debugger/DebugAPI.h"
     31 #include "jit/BaselineFrame.h"
     32 #include "jit/BaselineIC.h"
     33 #include "jit/BaselineJIT.h"
     34 #include "jit/CacheIR.h"
     35 #include "jit/CacheIRCompiler.h"
     36 #include "jit/CacheIRReader.h"
     37 #include "jit/JitFrames.h"
     38 #include "jit/JitScript.h"
     39 #include "jit/JSJitFrameIter.h"
     40 #include "jit/VMFunctions.h"
     41 #include "proxy/DeadObjectProxy.h"
     42 #include "proxy/DOMProxy.h"
     43 #include "util/Unicode.h"
     44 #include "vm/AsyncFunction.h"
     45 #include "vm/AsyncIteration.h"
     46 #include "vm/DateObject.h"
     47 #include "vm/EnvironmentObject.h"
     48 #include "vm/EqualityOperations.h"
     49 #include "vm/GeneratorObject.h"
     50 #include "vm/Interpreter.h"
     51 #include "vm/Iteration.h"
     52 #include "vm/JitActivation.h"
     53 #include "vm/JSObject.h"
     54 #include "vm/JSScript.h"
     55 #include "vm/ObjectFuse.h"
     56 #include "vm/Opcodes.h"
     57 #include "vm/PlainObject.h"
     58 #include "vm/Shape.h"
     59 #include "vm/TypeofEqOperand.h"  // TypeofEqOperand
     60 #include "vm/WrapperObject.h"
     61 
     62 #include "debugger/DebugAPI-inl.h"
     63 #include "jit/BaselineFrame-inl.h"
     64 #include "jit/JitScript-inl.h"
     65 #include "vm/EnvironmentObject-inl.h"
     66 #include "vm/Interpreter-inl.h"
     67 #include "vm/JSScript-inl.h"
     68 #include "vm/PlainObject-inl.h"
     69 
     70 namespace js {
     71 namespace pbl {
     72 
     73 using namespace js::jit;
     74 
     75 /*
     76 * Debugging: enable `TRACE_INTERP` for an extremely detailed dump of
     77 * what PBL is doing at every opcode step.
     78 */
     79 
     80 // #define TRACE_INTERP
     81 
     82 #ifdef TRACE_INTERP
     83 #  define TRACE_PRINTF(...) \
     84    do {                    \
     85      printf(__VA_ARGS__);  \
     86      fflush(stdout);       \
     87    } while (0)
     88 #else
     89 #  define TRACE_PRINTF(...) \
     90    do {                    \
     91    } while (0)
     92 #endif
     93 
     94 #define PBL_HYBRID_ICS_DEFAULT true
     95 
     96 // Whether we are using the "hybrid" strategy for ICs (see the [SMDOC]
     97 // in PortableBaselineInterpret.h for more). This is currently a
     98 // constant, but may become configurable in the future.
     99 static const bool kHybridICsInterp = PBL_HYBRID_ICS_DEFAULT;
    100 
    101 // Whether to compile interpreter dispatch loops using computed gotos
    102 // or direct switches.
    103 #if !defined(__wasi__) && !defined(TRACE_INTERP)
    104 #  define ENABLE_COMPUTED_GOTO_DISPATCH
    105 #endif
    106 
    107 // Whether to compile in interrupt checks in the main interpreter loop.
    108 #ifndef __wasi__
    109 // On WASI, with a single thread, there is no possibility for an
    110 // interrupt to come asynchronously.
    111 #  define ENABLE_INTERRUPT_CHECKS
    112 #endif
    113 
    114 // Whether to compile in coverage counting in the main interpreter loop.
    115 #ifndef __wasi__
    116 #  define ENABLE_COVERAGE
    117 #endif
    118 
    119 /*
    120 * -----------------------------------------------
    121 * Stack handling
    122 * -----------------------------------------------
    123 */
    124 
    125 // Large enough for an exit frame.
    126 static const size_t kStackMargin = 1024;
    127 
    128 /*
    129 * A 64-bit value on the auxiliary stack. May either be a raw uint64_t
    130 * or a `Value` (JS NaN-boxed value).
    131 */
    132 struct StackVal {
    133  uint64_t value;
    134 
    135  explicit StackVal(uint64_t v) : value(v) {}
    136  explicit StackVal(const Value& v) : value(v.asRawBits()) {}
    137 
    138  uint64_t asUInt64() const { return value; }
    139  Value asValue() const { return Value::fromRawBits(value); }
    140 };
    141 
    142 /*
    143 * A native-pointer-sized value on the auxiliary stack. This is
    144 * separate from the above because we support running on 32-bit
    145 * systems as well! May either be a `void*` (or cast to a
    146 * `CalleeToken`, which is a typedef for a `void*`), or a `uint32_t`,
    147 * which always fits in a native pointer width on our supported
    148 * platforms. (See static_assert below.)
    149 */
    150 struct StackValNative {
    151  static_assert(sizeof(uintptr_t) >= sizeof(uint32_t),
    152                "Must be at least a 32-bit system to use PBL.");
    153 
    154  uintptr_t value;
    155 
    156  explicit StackValNative(void* v) : value(reinterpret_cast<uintptr_t>(v)) {}
    157  explicit StackValNative(uint32_t v) : value(v) {}
    158 
    159  void* asVoidPtr() const { return reinterpret_cast<void*>(value); }
    160  CalleeToken asCalleeToken() const {
    161    return reinterpret_cast<CalleeToken>(value);
    162  }
    163 };
    164 
    165 // Assert that the stack alignment is no more than the size of a
    166 // StackValNative -- we rely on this when setting up call frames.
    167 static_assert(JitStackAlignment <= sizeof(StackValNative));
    168 
    169 #define PUSH(val) *--sp = (val)
    170 #define POP() (*sp++)
    171 #define POPN(n) sp += (n)
    172 
    173 #define PUSHNATIVE(val)                                               \
    174  do {                                                                \
    175    StackValNative* nativeSP = reinterpret_cast<StackValNative*>(sp); \
    176    *--nativeSP = (val);                                              \
    177    sp = reinterpret_cast<StackVal*>(nativeSP);                       \
    178  } while (0)
    179 #define POPNNATIVE(n) \
    180  sp = reinterpret_cast<StackVal*>(reinterpret_cast<StackValNative*>(sp) + (n))
    181 
    182 /*
    183 * Helper class to manage the auxiliary stack and push/pop frames.
    184 */
    185 struct Stack {
    186  StackVal* fp;
    187  StackVal* base;
    188  StackVal* top;
    189  StackVal* unwindingSP;
    190  StackVal* unwindingFP;
    191 
    192  explicit Stack(PortableBaselineStack& pbs)
    193      : fp(reinterpret_cast<StackVal*>(pbs.top)),
    194        base(reinterpret_cast<StackVal*>(pbs.base)),
    195        top(reinterpret_cast<StackVal*>(pbs.top)),
    196        unwindingSP(nullptr),
    197        unwindingFP(nullptr) {}
    198 
    199  MOZ_ALWAYS_INLINE bool check(StackVal* sp, size_t size, bool margin = true) {
    200    return reinterpret_cast<uintptr_t>(base) + size +
    201               (margin ? kStackMargin : 0) <=
    202           reinterpret_cast<uintptr_t>(sp);
    203  }
    204 
    205  [[nodiscard]] MOZ_ALWAYS_INLINE StackVal* allocate(StackVal* sp,
    206                                                     size_t size) {
    207    if (!check(sp, size, false)) {
    208      return nullptr;
    209    }
    210    sp = reinterpret_cast<StackVal*>(reinterpret_cast<uintptr_t>(sp) - size);
    211    return sp;
    212  }
    213 
    214  uint32_t frameSize(StackVal* sp, BaselineFrame* curFrame) const {
    215    return sizeof(StackVal) * (reinterpret_cast<StackVal*>(fp) - sp);
    216  }
    217 
    218  [[nodiscard]] MOZ_ALWAYS_INLINE BaselineFrame* pushFrame(StackVal* sp,
    219                                                           JSContext* cx,
    220                                                           JSObject* envChain) {
    221    TRACE_PRINTF("pushFrame: sp = %p fp = %p\n", sp, fp);
    222    if (sp == base) {
    223      return nullptr;
    224    }
    225    PUSHNATIVE(StackValNative(fp));
    226    fp = sp;
    227    TRACE_PRINTF("pushFrame: new fp = %p\n", fp);
    228 
    229    BaselineFrame* frame =
    230        reinterpret_cast<BaselineFrame*>(allocate(sp, BaselineFrame::Size()));
    231    if (!frame) {
    232      return nullptr;
    233    }
    234 
    235    frame->setFlags(BaselineFrame::Flags::RUNNING_IN_INTERPRETER);
    236    frame->setEnvironmentChain(envChain);
    237    JSScript* script = frame->script();
    238    frame->setICScript(script->jitScript()->icScript());
    239    frame->setInterpreterFieldsForPrologue(script);
    240 #ifdef DEBUG
    241    frame->setDebugFrameSize(0);
    242 #endif
    243    return frame;
    244  }
    245 
    246  StackVal* popFrame() {
    247    StackVal* newTOS =
    248        reinterpret_cast<StackVal*>(reinterpret_cast<StackValNative*>(fp) + 1);
    249    fp = reinterpret_cast<StackVal*>(
    250        reinterpret_cast<StackValNative*>(fp)->asVoidPtr());
    251    MOZ_ASSERT(fp);
    252    TRACE_PRINTF("popFrame: fp = %p\n", fp);
    253    return newTOS;
    254  }
    255 
    256  void setFrameSize(StackVal* sp, BaselineFrame* prevFrame) {
    257 #ifdef DEBUG
    258    MOZ_ASSERT(fp != nullptr);
    259    uintptr_t frameSize =
    260        reinterpret_cast<uintptr_t>(fp) - reinterpret_cast<uintptr_t>(sp);
    261    MOZ_ASSERT(reinterpret_cast<uintptr_t>(fp) >=
    262               reinterpret_cast<uintptr_t>(sp));
    263    TRACE_PRINTF("pushExitFrame: fp = %p cur() = %p -> frameSize = %d\n", fp,
    264                 sp, int(frameSize));
    265    MOZ_ASSERT(frameSize >= BaselineFrame::Size());
    266    prevFrame->setDebugFrameSize(frameSize);
    267 #endif
    268  }
    269 
    270  [[nodiscard]] MOZ_ALWAYS_INLINE StackVal* pushExitFrame(
    271      StackVal* sp, BaselineFrame* prevFrame) {
    272    uint8_t* prevFP =
    273        reinterpret_cast<uint8_t*>(prevFrame) + BaselineFrame::Size();
    274    TRACE_PRINTF(
    275        "pushExitFrame: prevFrame = %p sp = %p BaselineFrame::Size() = %d -> "
    276        "computed prevFP = %p actual fp = %p\n",
    277        prevFrame, sp, int(BaselineFrame::Size()), prevFP, fp);
    278    MOZ_ASSERT(reinterpret_cast<StackVal*>(prevFP) == fp);
    279    setFrameSize(sp, prevFrame);
    280 
    281    if (!check(sp, sizeof(StackVal) * 4, false)) {
    282      return nullptr;
    283    }
    284 
    285    PUSHNATIVE(StackValNative(
    286        MakeFrameDescriptorForJitCall(FrameType::BaselineJS, 0)));
    287    PUSHNATIVE(StackValNative(nullptr));  // fake return address.
    288    PUSHNATIVE(StackValNative(prevFP));
    289    StackVal* exitFP = sp;
    290    fp = exitFP;
    291    TRACE_PRINTF(" -> fp = %p\n", fp);
    292    PUSHNATIVE(StackValNative(uint32_t(ExitFrameType::Bare)));
    293    return exitFP;
    294  }
    295 
    296  void popExitFrame(StackVal* fp) {
    297    StackVal* prevFP = reinterpret_cast<StackVal*>(
    298        reinterpret_cast<StackValNative*>(fp)->asVoidPtr());
    299    MOZ_ASSERT(prevFP);
    300    this->fp = prevFP;
    301    TRACE_PRINTF("popExitFrame: fp -> %p\n", fp);
    302  }
    303 
    304  BaselineFrame* frameFromFP() {
    305    return reinterpret_cast<BaselineFrame*>(reinterpret_cast<uintptr_t>(fp) -
    306                                            BaselineFrame::Size());
    307  }
    308 
    309  static HandleValue handle(StackVal* sp) {
    310    return HandleValue::fromMarkedLocation(reinterpret_cast<Value*>(sp));
    311  }
    312  static MutableHandleValue handleMut(StackVal* sp) {
    313    return MutableHandleValue::fromMarkedLocation(reinterpret_cast<Value*>(sp));
    314  }
    315 };
    316 
    317 /*
    318 * -----------------------------------------------
    319 * Interpreter state
    320 * -----------------------------------------------
    321 */
    322 
    323 struct ICRegs {
    324  static const int kMaxICVals = 16;
    325  // Values can be split across two OR'd halves: unboxed bits and
    326  // tags.  We mostly rely on the CacheIRWriter/Reader typed OperandId
    327  // system to ensure "type safety" in CacheIR w.r.t. unboxing: the
    328  // existence of an ObjOperandId implies that the value is unboxed,
    329  // so `icVals` contains a pointer (reinterpret-casted to a
    330  // `uint64_t`) and `icTags` contains the tag bits. An operator that
    331  // requires a tagged Value can OR the two together (this corresponds
    332  // to `useValueRegister` rather than `useRegister` in the native
    333  // baseline compiler).
    334  uint64_t icVals[kMaxICVals];
    335  uint64_t icTags[kMaxICVals];  // Shifted tags.
    336  int extraArgs;
    337 };
    338 
    339 struct State {
    340  RootedValue value0;
    341  RootedValue value1;
    342  RootedValue value2;
    343  RootedValue value3;
    344  RootedValue res;
    345  RootedObject obj0;
    346  RootedObject obj1;
    347  RootedObject obj2;
    348  RootedString str0;
    349  RootedString str1;
    350  RootedString str2;
    351  RootedScript script0;
    352  Rooted<PropertyName*> name0;
    353  Rooted<jsid> id0;
    354  Rooted<JSAtom*> atom0;
    355  RootedFunction fun0;
    356  Rooted<Scope*> scope0;
    357 
    358  explicit State(JSContext* cx)
    359      : value0(cx),
    360        value1(cx),
    361        value2(cx),
    362        value3(cx),
    363        res(cx),
    364        obj0(cx),
    365        obj1(cx),
    366        obj2(cx),
    367        str0(cx),
    368        str1(cx),
    369        str2(cx),
    370        script0(cx),
    371        name0(cx),
    372        id0(cx),
    373        atom0(cx),
    374        fun0(cx),
    375        scope0(cx) {}
    376 };
    377 
    378 /*
    379 * -----------------------------------------------
    380 * RAII helpers for pushing exit frames.
    381 *
    382 * (See [SMDOC] in PortableBaselineInterpret.h for more.)
    383 * -----------------------------------------------
    384 */
    385 
    386 class VMFrameManager {
    387  JSContext* cx;
    388  BaselineFrame* frame;
    389  friend class VMFrame;
    390 
    391 public:
    392  VMFrameManager(JSContext*& cx_, BaselineFrame* frame_)
    393      : cx(cx_), frame(frame_) {
    394    // Once the manager exists, we need to create an exit frame to
    395    // have access to the cx (unless the caller promises it is not
    396    // calling into the rest of the runtime).
    397    cx_ = nullptr;
    398  }
    399 
    400  void switchToFrame(BaselineFrame* frame) { this->frame = frame; }
    401 
    402  // Provides the JSContext, but *only* if no calls into the rest of
    403  // the runtime (that may invoke a GC or stack walk) occur. Avoids
    404  // the overhead of pushing an exit frame.
    405  JSContext* cxForLocalUseOnly() const { return cx; }
    406 };
    407 
    408 class VMFrame {
    409  JSContext* cx;
    410  Stack& stack;
    411  StackVal* exitFP;
    412  void* prevSavedStack;
    413 
    414 public:
    415  VMFrame(VMFrameManager& mgr, Stack& stack_, StackVal* sp)
    416      : cx(mgr.cx), stack(stack_) {
    417    exitFP = stack.pushExitFrame(sp, mgr.frame);
    418    if (!exitFP) {
    419      return;
    420    }
    421    cx->activation()->asJit()->setJSExitFP(reinterpret_cast<uint8_t*>(exitFP));
    422    prevSavedStack = cx->portableBaselineStack().top;
    423    cx->portableBaselineStack().top = reinterpret_cast<void*>(spBelowFrame());
    424  }
    425 
    426  StackVal* spBelowFrame() {
    427    return reinterpret_cast<StackVal*>(reinterpret_cast<uintptr_t>(exitFP) -
    428                                       sizeof(StackValNative));
    429  }
    430 
    431  ~VMFrame() {
    432    stack.popExitFrame(exitFP);
    433    cx->portableBaselineStack().top = prevSavedStack;
    434  }
    435 
    436  JSContext* getCx() const { return cx; }
    437  operator JSContext*() const { return cx; }
    438 
    439  bool success() const { return exitFP != nullptr; }
    440 };
    441 
    442 #define PUSH_EXIT_FRAME_OR_RET(value, init_sp)                  \
    443  VMFrame cx(ctx.frameMgr, ctx.stack, init_sp);                 \
    444  if (!cx.success()) {                                          \
    445    return value;                                               \
    446  }                                                             \
    447  StackVal* sp = cx.spBelowFrame(); /* shadow the definition */ \
    448  (void)sp;                         /* avoid unused-variable warnings */
    449 
    450 #define PUSH_IC_FRAME()         \
    451  ctx.error = PBIResult::Error; \
    452  PUSH_EXIT_FRAME_OR_RET(IC_ERROR_SENTINEL(), ctx.sp())
    453 #define PUSH_FALLBACK_IC_FRAME() \
    454  ctx.error = PBIResult::Error;  \
    455  PUSH_EXIT_FRAME_OR_RET(IC_ERROR_SENTINEL(), sp)
    456 #define PUSH_EXIT_FRAME()      \
    457  frame->interpreterPC() = pc; \
    458  SYNCSP();                    \
    459  PUSH_EXIT_FRAME_OR_RET(PBIResult::Error, sp)
    460 
    461 /*
    462 * -----------------------------------------------
    463 * IC Interpreter
    464 * -----------------------------------------------
    465 */
    466 
    467 // Bundled state for passing to ICs, in order to reduce the number of
    468 // arguments and hence make the call more ABI-efficient. (On some
    469 // platforms, e.g. Wasm on Wasmtime on x86-64, we have as few as four
    470 // register arguments available before args go through the stack.)
    471 struct ICCtx {
    472  BaselineFrame* frame;
    473  VMFrameManager frameMgr;
    474  State& state;
    475  ICRegs icregs;
    476  Stack& stack;
    477  StackVal* sp_;
    478  PBIResult error;
    479  uint64_t arg2;
    480 
    481  ICCtx(JSContext* cx, BaselineFrame* frame_, State& state_, Stack& stack_)
    482      : frame(frame_),
    483        frameMgr(cx, frame_),
    484        state(state_),
    485        icregs(),
    486        stack(stack_),
    487        sp_(nullptr),
    488        error(PBIResult::Ok),
    489        arg2(0) {}
    490 
    491  StackVal* sp() { return sp_; }
    492 };
    493 
    494 #define IC_ERROR_SENTINEL() (JS::MagicValue(JS_GENERIC_MAGIC).asRawBits())
    495 
    496 // Universal signature for an IC stub function.
    497 typedef uint64_t (*ICStubFunc)(uint64_t arg0, uint64_t arg1, ICStub* stub,
    498                               ICCtx& ctx);
    499 
    500 #define PBL_CALL_IC(jitcode, ctx, stubvalue, result, arg0, arg1, arg2value, \
    501                    hasarg2)                                                \
    502  do {                                                                      \
    503    ctx.arg2 = arg2value;                                                   \
    504    ICStubFunc func = reinterpret_cast<ICStubFunc>(jitcode);                \
    505    result = func(arg0, arg1, stubvalue, ctx);                              \
    506  } while (0)
    507 
    508 typedef PBIResult (*PBIFunc)(JSContext* cx_, State& state, Stack& stack,
    509                             StackVal* sp, JSObject* envChain, Value* ret,
    510                             jsbytecode* pc, ImmutableScriptData* isd,
    511                             jsbytecode* restartEntryPC,
    512                             BaselineFrame* restartFrame,
    513                             StackVal* restartEntryFrame,
    514                             PBIResult restartCode);
    515 
    516 static uint64_t CallNextIC(uint64_t arg0, uint64_t arg1, ICStub* stub,
    517                           ICCtx& ctx);
    518 
    519 static double DoubleMinMax(bool isMax, double first, double second) {
    520  if (std::isnan(first) || std::isnan(second)) {
    521    return JS::GenericNaN();
    522  } else if (first == 0 && second == 0) {
    523    // -0 and 0 compare as equal, but we have to distinguish
    524    // them here: min(-0, 0) = -0, max(-0, 0) = 0.
    525    bool firstPos = !std::signbit(first);
    526    bool secondPos = !std::signbit(second);
    527    bool sign = isMax ? (firstPos || secondPos) : (firstPos && secondPos);
    528    return sign ? 0.0 : -0.0;
    529  } else {
    530    return isMax ? ((first >= second) ? first : second)
    531                 : ((first <= second) ? first : second);
    532  }
    533 }
    534 
    535 // Interpreter for CacheIR.
    536 uint64_t ICInterpretOps(uint64_t arg0, uint64_t arg1, ICStub* stub,
    537                        ICCtx& ctx) {
    538  {
    539 #define DECLARE_CACHEOP_CASE(name) __label__ cacheop_##name
    540 
    541 #ifdef ENABLE_COMPUTED_GOTO_DISPATCH
    542 
    543 #  define CACHEOP_CASE(name) cacheop_##name : CACHEOP_TRACE(name)
    544 #  define CACHEOP_CASE_FALLTHROUGH(name) CACHEOP_CASE(name)
    545 
    546 #  define DISPATCH_CACHEOP()          \
    547    cacheop = cacheIRReader.readOp(); \
    548    goto* addresses[long(cacheop)];
    549 
    550 #else  // ENABLE_COMPUTED_GOTO_DISPATCH
    551 
    552 #  define CACHEOP_CASE(name) \
    553    case CacheOp::name:      \
    554      cacheop_##name : CACHEOP_TRACE(name)
    555 #  define CACHEOP_CASE_FALLTHROUGH(name) \
    556    [[fallthrough]];                     \
    557    CACHEOP_CASE(name)
    558 
    559 #  define DISPATCH_CACHEOP()          \
    560    cacheop = cacheIRReader.readOp(); \
    561    goto dispatch;
    562 
    563 #endif  // !ENABLE_COMPUTED_GOTO_DISPATCH
    564 
    565 #define READ_REG(index) ctx.icregs.icVals[(index)]
    566 #define READ_VALUE_REG(index) \
    567  Value::fromRawBits(ctx.icregs.icVals[(index)] | ctx.icregs.icTags[(index)])
    568 #define WRITE_REG(index, value, tag)                                           \
    569  do {                                                                         \
    570    ctx.icregs.icVals[(index)] = (value);                                      \
    571    ctx.icregs.icTags[(index)] = uint64_t(JSVAL_TAG_##tag) << JSVAL_TAG_SHIFT; \
    572  } while (0)
    573 #define WRITE_VALUE_REG(index, value)                 \
    574  do {                                                \
    575    ctx.icregs.icVals[(index)] = (value).asRawBits(); \
    576    ctx.icregs.icTags[(index)] = 0;                   \
    577  } while (0)
    578 
    579    DECLARE_CACHEOP_CASE(ReturnFromIC);
    580    DECLARE_CACHEOP_CASE(GuardToObject);
    581    DECLARE_CACHEOP_CASE(GuardIsNullOrUndefined);
    582    DECLARE_CACHEOP_CASE(GuardIsNull);
    583    DECLARE_CACHEOP_CASE(GuardIsUndefined);
    584    DECLARE_CACHEOP_CASE(GuardIsNotUninitializedLexical);
    585    DECLARE_CACHEOP_CASE(GuardToBoolean);
    586    DECLARE_CACHEOP_CASE(GuardToString);
    587    DECLARE_CACHEOP_CASE(GuardToSymbol);
    588    DECLARE_CACHEOP_CASE(GuardToBigInt);
    589    DECLARE_CACHEOP_CASE(GuardIsNumber);
    590    DECLARE_CACHEOP_CASE(GuardToInt32);
    591    DECLARE_CACHEOP_CASE(GuardToNonGCThing);
    592    DECLARE_CACHEOP_CASE(GuardBooleanToInt32);
    593    DECLARE_CACHEOP_CASE(GuardToInt32Index);
    594    DECLARE_CACHEOP_CASE(Int32ToIntPtr);
    595    DECLARE_CACHEOP_CASE(GuardToInt32ModUint32);
    596    DECLARE_CACHEOP_CASE(GuardNonDoubleType);
    597    DECLARE_CACHEOP_CASE(GuardShape);
    598    DECLARE_CACHEOP_CASE(GuardFuse);
    599    DECLARE_CACHEOP_CASE(GuardObjectFuseProperty);
    600    DECLARE_CACHEOP_CASE(GuardProto);
    601    DECLARE_CACHEOP_CASE(GuardNullProto);
    602    DECLARE_CACHEOP_CASE(GuardClass);
    603    DECLARE_CACHEOP_CASE(GuardAnyClass);
    604    DECLARE_CACHEOP_CASE(GuardGlobalGeneration);
    605    DECLARE_CACHEOP_CASE(HasClassResult);
    606    DECLARE_CACHEOP_CASE(GuardCompartment);
    607    DECLARE_CACHEOP_CASE(GuardIsExtensible);
    608    DECLARE_CACHEOP_CASE(GuardIsNativeObject);
    609    DECLARE_CACHEOP_CASE(GuardIsProxy);
    610    DECLARE_CACHEOP_CASE(GuardIsNotProxy);
    611    DECLARE_CACHEOP_CASE(GuardIsNotArrayBufferMaybeShared);
    612    DECLARE_CACHEOP_CASE(GuardIsTypedArray);
    613    DECLARE_CACHEOP_CASE(GuardHasProxyHandler);
    614    DECLARE_CACHEOP_CASE(GuardIsNotDOMProxy);
    615    DECLARE_CACHEOP_CASE(GuardSpecificObject);
    616    DECLARE_CACHEOP_CASE(GuardObjectIdentity);
    617    DECLARE_CACHEOP_CASE(GuardSpecificFunction);
    618    DECLARE_CACHEOP_CASE(GuardFunctionScript);
    619    DECLARE_CACHEOP_CASE(GuardSpecificAtom);
    620    DECLARE_CACHEOP_CASE(GuardSpecificSymbol);
    621    DECLARE_CACHEOP_CASE(GuardSpecificInt32);
    622    DECLARE_CACHEOP_CASE(GuardNoDenseElements);
    623    DECLARE_CACHEOP_CASE(GuardStringToIndex);
    624    DECLARE_CACHEOP_CASE(GuardStringToInt32);
    625    DECLARE_CACHEOP_CASE(GuardStringToNumber);
    626    DECLARE_CACHEOP_CASE(BooleanToNumber);
    627    DECLARE_CACHEOP_CASE(GuardHasGetterSetter);
    628    DECLARE_CACHEOP_CASE(GuardInt32IsNonNegative);
    629    DECLARE_CACHEOP_CASE(GuardDynamicSlotIsSpecificObject);
    630    DECLARE_CACHEOP_CASE(GuardDynamicSlotIsNotObject);
    631    DECLARE_CACHEOP_CASE(GuardFixedSlotValue);
    632    DECLARE_CACHEOP_CASE(GuardDynamicSlotValue);
    633    DECLARE_CACHEOP_CASE(LoadFixedSlot);
    634    DECLARE_CACHEOP_CASE(LoadDynamicSlot);
    635    DECLARE_CACHEOP_CASE(GuardNoAllocationMetadataBuilder);
    636    DECLARE_CACHEOP_CASE(GuardFunctionHasJitEntry);
    637    DECLARE_CACHEOP_CASE(GuardFunctionHasNoJitEntry);
    638    DECLARE_CACHEOP_CASE(GuardFunctionIsNonBuiltinCtor);
    639    DECLARE_CACHEOP_CASE(GuardFunctionIsConstructor);
    640    DECLARE_CACHEOP_CASE(GuardNotClassConstructor);
    641    DECLARE_CACHEOP_CASE(GuardArrayIsPacked);
    642    DECLARE_CACHEOP_CASE(GuardArgumentsObjectFlags);
    643    DECLARE_CACHEOP_CASE(LoadObject);
    644    DECLARE_CACHEOP_CASE(LoadProtoObject);
    645    DECLARE_CACHEOP_CASE(LoadProto);
    646    DECLARE_CACHEOP_CASE(LoadEnclosingEnvironment);
    647    DECLARE_CACHEOP_CASE(LoadWrapperTarget);
    648    DECLARE_CACHEOP_CASE(LoadValueTag);
    649    DECLARE_CACHEOP_CASE(LoadArgumentFixedSlot);
    650    DECLARE_CACHEOP_CASE(LoadArgumentDynamicSlot);
    651    DECLARE_CACHEOP_CASE(TruncateDoubleToUInt32);
    652    DECLARE_CACHEOP_CASE(MegamorphicLoadSlotResult);
    653    DECLARE_CACHEOP_CASE(MegamorphicLoadSlotByValueResult);
    654    DECLARE_CACHEOP_CASE(MegamorphicSetElement);
    655    DECLARE_CACHEOP_CASE(StoreFixedSlot);
    656    DECLARE_CACHEOP_CASE(StoreDynamicSlot);
    657    DECLARE_CACHEOP_CASE(AddAndStoreFixedSlot);
    658    DECLARE_CACHEOP_CASE(AddAndStoreDynamicSlot);
    659    DECLARE_CACHEOP_CASE(AllocateAndStoreDynamicSlot);
    660    DECLARE_CACHEOP_CASE(StoreDenseElement);
    661    DECLARE_CACHEOP_CASE(StoreDenseElementHole);
    662    DECLARE_CACHEOP_CASE(ArrayPush);
    663    DECLARE_CACHEOP_CASE(IsObjectResult);
    664    DECLARE_CACHEOP_CASE(Int32MinMax);
    665    DECLARE_CACHEOP_CASE(StoreTypedArrayElement);
    666    DECLARE_CACHEOP_CASE(CallInt32ToString);
    667    DECLARE_CACHEOP_CASE(CallScriptedFunction);
    668    DECLARE_CACHEOP_CASE(CallNativeFunction);
    669    DECLARE_CACHEOP_CASE(MetaScriptedThisShape);
    670    DECLARE_CACHEOP_CASE(LoadFixedSlotResult);
    671    DECLARE_CACHEOP_CASE(LoadDynamicSlotResult);
    672    DECLARE_CACHEOP_CASE(LoadDenseElementResult);
    673    DECLARE_CACHEOP_CASE(LoadInt32ArrayLengthResult);
    674    DECLARE_CACHEOP_CASE(LoadInt32ArrayLength);
    675    DECLARE_CACHEOP_CASE(LoadArgumentsObjectArgResult);
    676    DECLARE_CACHEOP_CASE(LinearizeForCharAccess);
    677    DECLARE_CACHEOP_CASE(LoadStringCharResult);
    678    DECLARE_CACHEOP_CASE(LoadStringCharCodeResult);
    679    DECLARE_CACHEOP_CASE(LoadStringLengthResult);
    680    DECLARE_CACHEOP_CASE(LoadObjectResult);
    681    DECLARE_CACHEOP_CASE(LoadStringResult);
    682    DECLARE_CACHEOP_CASE(LoadSymbolResult);
    683    DECLARE_CACHEOP_CASE(LoadInt32Result);
    684    DECLARE_CACHEOP_CASE(LoadDoubleResult);
    685    DECLARE_CACHEOP_CASE(LoadBigIntResult);
    686    DECLARE_CACHEOP_CASE(LoadBooleanResult);
    687    DECLARE_CACHEOP_CASE(LoadInt32Constant);
    688    DECLARE_CACHEOP_CASE(LoadConstantStringResult);
    689    DECLARE_CACHEOP_CASE(Int32AddResult);
    690    DECLARE_CACHEOP_CASE(Int32SubResult);
    691    DECLARE_CACHEOP_CASE(Int32MulResult);
    692    DECLARE_CACHEOP_CASE(Int32DivResult);
    693    DECLARE_CACHEOP_CASE(Int32ModResult);
    694    DECLARE_CACHEOP_CASE(Int32BitOrResult);
    695    DECLARE_CACHEOP_CASE(Int32BitXorResult);
    696    DECLARE_CACHEOP_CASE(Int32BitAndResult);
    697    DECLARE_CACHEOP_CASE(Int32PowResult);
    698    DECLARE_CACHEOP_CASE(Int32IncResult);
    699    DECLARE_CACHEOP_CASE(LoadInt32TruthyResult);
    700    DECLARE_CACHEOP_CASE(LoadStringTruthyResult);
    701    DECLARE_CACHEOP_CASE(LoadObjectTruthyResult);
    702    DECLARE_CACHEOP_CASE(LoadValueResult);
    703    DECLARE_CACHEOP_CASE(LoadOperandResult);
    704    DECLARE_CACHEOP_CASE(ConcatStringsResult);
    705    DECLARE_CACHEOP_CASE(CompareStringResult);
    706    DECLARE_CACHEOP_CASE(CompareInt32Result);
    707    DECLARE_CACHEOP_CASE(CompareNullUndefinedResult);
    708    DECLARE_CACHEOP_CASE(AssertPropertyLookup);
    709    DECLARE_CACHEOP_CASE(GuardIsNonResizableTypedArray);
    710    DECLARE_CACHEOP_CASE(GuardIndexIsNotDenseElement);
    711    DECLARE_CACHEOP_CASE(LoadFixedSlotTypedResult);
    712    DECLARE_CACHEOP_CASE(LoadDenseElementHoleResult);
    713    DECLARE_CACHEOP_CASE(LoadDenseElementExistsResult);
    714    DECLARE_CACHEOP_CASE(LoadTypedArrayElementExistsResult);
    715    DECLARE_CACHEOP_CASE(LoadDenseElementHoleExistsResult);
    716    DECLARE_CACHEOP_CASE(LoadTypedArrayElementResult);
    717    DECLARE_CACHEOP_CASE(RegExpFlagResult);
    718    DECLARE_CACHEOP_CASE(GuardNumberToIntPtrIndex);
    719    DECLARE_CACHEOP_CASE(CallRegExpMatcherResult);
    720    DECLARE_CACHEOP_CASE(CallRegExpSearcherResult);
    721    DECLARE_CACHEOP_CASE(RegExpSearcherLastLimitResult);
    722    DECLARE_CACHEOP_CASE(RegExpHasCaptureGroupsResult);
    723    DECLARE_CACHEOP_CASE(RegExpBuiltinExecMatchResult);
    724    DECLARE_CACHEOP_CASE(RegExpBuiltinExecTestResult);
    725    DECLARE_CACHEOP_CASE(CallSubstringKernelResult);
    726    DECLARE_CACHEOP_CASE(StringReplaceStringResult);
    727    DECLARE_CACHEOP_CASE(StringSplitStringResult);
    728    DECLARE_CACHEOP_CASE(GetFirstDollarIndexResult);
    729    DECLARE_CACHEOP_CASE(StringToAtom);
    730    DECLARE_CACHEOP_CASE(GuardTagNotEqual);
    731    DECLARE_CACHEOP_CASE(IdToStringOrSymbol);
    732    DECLARE_CACHEOP_CASE(MegamorphicStoreSlot);
    733    DECLARE_CACHEOP_CASE(MegamorphicHasPropResult);
    734    DECLARE_CACHEOP_CASE(ObjectToIteratorResult);
    735    DECLARE_CACHEOP_CASE(ArrayJoinResult);
    736    DECLARE_CACHEOP_CASE(ObjectKeysResult);
    737    DECLARE_CACHEOP_CASE(PackedArrayPopResult);
    738    DECLARE_CACHEOP_CASE(PackedArrayShiftResult);
    739    DECLARE_CACHEOP_CASE(PackedArraySliceResult);
    740    DECLARE_CACHEOP_CASE(IsArrayResult);
    741    DECLARE_CACHEOP_CASE(IsPackedArrayResult);
    742    DECLARE_CACHEOP_CASE(IsCallableResult);
    743    DECLARE_CACHEOP_CASE(IsConstructorResult);
    744    DECLARE_CACHEOP_CASE(IsCrossRealmArrayConstructorResult);
    745    DECLARE_CACHEOP_CASE(IsTypedArrayResult);
    746    DECLARE_CACHEOP_CASE(IsTypedArrayConstructorResult);
    747    DECLARE_CACHEOP_CASE(ArrayBufferViewByteOffsetInt32Result);
    748    DECLARE_CACHEOP_CASE(ArrayBufferViewByteOffsetDoubleResult);
    749    DECLARE_CACHEOP_CASE(TypedArrayByteLengthInt32Result);
    750    DECLARE_CACHEOP_CASE(TypedArrayByteLengthDoubleResult);
    751    DECLARE_CACHEOP_CASE(NewStringIteratorResult);
    752    DECLARE_CACHEOP_CASE(NewRegExpStringIteratorResult);
    753    DECLARE_CACHEOP_CASE(ObjectCreateResult);
    754    DECLARE_CACHEOP_CASE(NewArrayFromLengthResult);
    755    DECLARE_CACHEOP_CASE(NewTypedArrayFromArrayBufferResult);
    756    DECLARE_CACHEOP_CASE(NewTypedArrayFromArrayResult);
    757    DECLARE_CACHEOP_CASE(NewTypedArrayFromLengthResult);
    758    DECLARE_CACHEOP_CASE(StringFromCharCodeResult);
    759    DECLARE_CACHEOP_CASE(StringFromCodePointResult);
    760    DECLARE_CACHEOP_CASE(StringIncludesResult);
    761    DECLARE_CACHEOP_CASE(StringIndexOfResult);
    762    DECLARE_CACHEOP_CASE(StringLastIndexOfResult);
    763    DECLARE_CACHEOP_CASE(StringStartsWithResult);
    764    DECLARE_CACHEOP_CASE(StringEndsWithResult);
    765    DECLARE_CACHEOP_CASE(StringToLowerCaseResult);
    766    DECLARE_CACHEOP_CASE(StringToUpperCaseResult);
    767    DECLARE_CACHEOP_CASE(StringTrimResult);
    768    DECLARE_CACHEOP_CASE(StringTrimStartResult);
    769    DECLARE_CACHEOP_CASE(StringTrimEndResult);
    770    DECLARE_CACHEOP_CASE(MathAbsInt32Result);
    771    DECLARE_CACHEOP_CASE(MathAbsNumberResult);
    772    DECLARE_CACHEOP_CASE(MathClz32Result);
    773    DECLARE_CACHEOP_CASE(MathSignInt32Result);
    774    DECLARE_CACHEOP_CASE(MathSignNumberResult);
    775    DECLARE_CACHEOP_CASE(MathSignNumberToInt32Result);
    776    DECLARE_CACHEOP_CASE(MathImulResult);
    777    DECLARE_CACHEOP_CASE(MathSqrtNumberResult);
    778    DECLARE_CACHEOP_CASE(MathFRoundNumberResult);
    779    DECLARE_CACHEOP_CASE(MathRandomResult);
    780    DECLARE_CACHEOP_CASE(MathHypot2NumberResult);
    781    DECLARE_CACHEOP_CASE(MathHypot3NumberResult);
    782    DECLARE_CACHEOP_CASE(MathHypot4NumberResult);
    783    DECLARE_CACHEOP_CASE(MathAtan2NumberResult);
    784    DECLARE_CACHEOP_CASE(MathFloorNumberResult);
    785    DECLARE_CACHEOP_CASE(MathCeilNumberResult);
    786    DECLARE_CACHEOP_CASE(MathTruncNumberResult);
    787    DECLARE_CACHEOP_CASE(MathCeilToInt32Result);
    788    DECLARE_CACHEOP_CASE(MathFloorToInt32Result);
    789    DECLARE_CACHEOP_CASE(MathTruncToInt32Result);
    790    DECLARE_CACHEOP_CASE(MathRoundToInt32Result);
    791    DECLARE_CACHEOP_CASE(NumberMinMax);
    792    DECLARE_CACHEOP_CASE(Int32MinMaxArrayResult);
    793    DECLARE_CACHEOP_CASE(NumberMinMaxArrayResult);
    794    DECLARE_CACHEOP_CASE(MathFunctionNumberResult);
    795    DECLARE_CACHEOP_CASE(NumberParseIntResult);
    796    DECLARE_CACHEOP_CASE(DoubleParseIntResult);
    797    DECLARE_CACHEOP_CASE(ObjectToStringResult);
    798    DECLARE_CACHEOP_CASE(CallNativeSetter);
    799    DECLARE_CACHEOP_CASE(CallSetArrayLength);
    800    DECLARE_CACHEOP_CASE(CallNumberToString);
    801    DECLARE_CACHEOP_CASE(Int32ToStringWithBaseResult);
    802    DECLARE_CACHEOP_CASE(BooleanToString);
    803    DECLARE_CACHEOP_CASE(BindFunctionResult);
    804    DECLARE_CACHEOP_CASE(SpecializedBindFunctionResult);
    805    DECLARE_CACHEOP_CASE(CallGetSparseElementResult);
    806    DECLARE_CACHEOP_CASE(LoadArgumentsObjectLengthResult);
    807    DECLARE_CACHEOP_CASE(LoadArgumentsObjectLength);
    808    DECLARE_CACHEOP_CASE(LoadBoundFunctionNumArgs);
    809    DECLARE_CACHEOP_CASE(LoadBoundFunctionTarget);
    810    DECLARE_CACHEOP_CASE(LoadArrayBufferByteLengthInt32Result);
    811    DECLARE_CACHEOP_CASE(LoadArrayBufferByteLengthDoubleResult);
    812    DECLARE_CACHEOP_CASE(LinearizeForCodePointAccess);
    813    DECLARE_CACHEOP_CASE(LoadArrayBufferViewLengthInt32Result);
    814    DECLARE_CACHEOP_CASE(LoadArrayBufferViewLengthDoubleResult);
    815    DECLARE_CACHEOP_CASE(LoadStringAtResult);
    816    DECLARE_CACHEOP_CASE(LoadStringCodePointResult);
    817    DECLARE_CACHEOP_CASE(CallNativeGetterResult);
    818    DECLARE_CACHEOP_CASE(LoadUndefinedResult);
    819    DECLARE_CACHEOP_CASE(LoadDoubleConstant);
    820    DECLARE_CACHEOP_CASE(LoadBooleanConstant);
    821    DECLARE_CACHEOP_CASE(LoadUndefined);
    822    DECLARE_CACHEOP_CASE(LoadConstantString);
    823    DECLARE_CACHEOP_CASE(LoadInstanceOfObjectResult);
    824    DECLARE_CACHEOP_CASE(LoadTypeOfObjectResult);
    825    DECLARE_CACHEOP_CASE(DoubleAddResult);
    826    DECLARE_CACHEOP_CASE(DoubleSubResult);
    827    DECLARE_CACHEOP_CASE(DoubleMulResult);
    828    DECLARE_CACHEOP_CASE(DoubleDivResult);
    829    DECLARE_CACHEOP_CASE(DoubleModResult);
    830    DECLARE_CACHEOP_CASE(DoublePowResult);
    831    DECLARE_CACHEOP_CASE(Int32LeftShiftResult);
    832    DECLARE_CACHEOP_CASE(Int32RightShiftResult);
    833    DECLARE_CACHEOP_CASE(Int32URightShiftResult);
    834    DECLARE_CACHEOP_CASE(Int32NotResult);
    835    DECLARE_CACHEOP_CASE(LoadDoubleTruthyResult);
    836    DECLARE_CACHEOP_CASE(NewPlainObjectResult);
    837    DECLARE_CACHEOP_CASE(NewArrayObjectResult);
    838    DECLARE_CACHEOP_CASE(CompareObjectResult);
    839    DECLARE_CACHEOP_CASE(CompareSymbolResult);
    840    DECLARE_CACHEOP_CASE(CompareDoubleResult);
    841    DECLARE_CACHEOP_CASE(IndirectTruncateInt32Result);
    842    DECLARE_CACHEOP_CASE(CallScriptedSetter);
    843    DECLARE_CACHEOP_CASE(CallBoundScriptedFunction);
    844    DECLARE_CACHEOP_CASE(CallScriptedGetterResult);
    845 
    846    // Define the computed-goto table regardless of dispatch strategy so
    847    // we don't get unused-label errors. (We need some of the labels
    848    // even without this for the predict-next mechanism, so we can't
    849    // conditionally elide labels either.)
    850    static const void* const addresses[long(CacheOp::NumOpcodes)] = {
    851 #define OP(name, ...) &&cacheop_##name,
    852        CACHE_IR_OPS(OP)
    853 #undef OP
    854    };
    855    (void)addresses;
    856 
    857 #define CACHEOP_TRACE(name) \
    858  TRACE_PRINTF("cacheop (frame %p stub %p): " #name "\n", ctx.frame, cstub);
    859 
    860 #define FAIL_IC() goto next_ic;
    861 
    862 // We set a fixed bound on the number of icVals which is smaller than what IC
    863 // generators may use. As a result we can't evaluate an IC if it defines too
    864 // many values. Note that we don't need to check this when reading from icVals
    865 // because we should have bailed out before the earlier write which defined the
    866 // same value. Similarly, we don't need to check writes to locations which we've
    867 // just read from.
    868 #define BOUNDSCHECK(resultId) \
    869  if (resultId.id() >= ICRegs::kMaxICVals) FAIL_IC();
    870 
    871 #define PREDICT_NEXT(name)                       \
    872  if (cacheIRReader.peekOp() == CacheOp::name) { \
    873    cacheIRReader.readOp();                      \
    874    cacheop = CacheOp::name;                     \
    875    goto cacheop_##name;                         \
    876  }
    877 
    878 #define PREDICT_RETURN()                                 \
    879  if (cacheIRReader.peekOp() == CacheOp::ReturnFromIC) { \
    880    TRACE_PRINTF("stub successful, predicted return\n"); \
    881    return retValue;                                     \
    882  }
    883 
    884    ICCacheIRStub* cstub = stub->toCacheIRStub();
    885    const CacheIRStubInfo* stubInfo = cstub->stubInfo();
    886    CacheIRReader cacheIRReader(stubInfo);
    887    uint64_t retValue = 0;
    888    CacheOp cacheop;
    889 
    890    WRITE_VALUE_REG(0, Value::fromRawBits(arg0));
    891    WRITE_VALUE_REG(1, Value::fromRawBits(arg1));
    892    WRITE_VALUE_REG(2, Value::fromRawBits(ctx.arg2));
    893 
    894    DISPATCH_CACHEOP();
    895 
    896 #ifndef ENABLE_COMPUTED_GOTO_DISPATCH
    897  dispatch:
    898    switch (cacheop)
    899 #endif
    900    {
    901 
    902      CACHEOP_CASE(ReturnFromIC) {
    903        TRACE_PRINTF("stub successful!\n");
    904        return retValue;
    905      }
    906 
    907      CACHEOP_CASE(GuardToObject) {
    908        ValOperandId inputId = cacheIRReader.valOperandId();
    909        Value v = READ_VALUE_REG(inputId.id());
    910        TRACE_PRINTF("GuardToObject: icVal %" PRIx64 "\n",
    911                     READ_REG(inputId.id()));
    912        if (!v.isObject()) {
    913          FAIL_IC();
    914        }
    915        WRITE_REG(inputId.id(), reinterpret_cast<uint64_t>(&v.toObject()),
    916                  OBJECT);
    917        PREDICT_NEXT(GuardShape);
    918        PREDICT_NEXT(GuardSpecificFunction);
    919        DISPATCH_CACHEOP();
    920      }
    921 
    922      CACHEOP_CASE(GuardIsNullOrUndefined) {
    923        ValOperandId inputId = cacheIRReader.valOperandId();
    924        Value v = READ_VALUE_REG(inputId.id());
    925        if (!v.isNullOrUndefined()) {
    926          FAIL_IC();
    927        }
    928        DISPATCH_CACHEOP();
    929      }
    930 
    931      CACHEOP_CASE(GuardIsNull) {
    932        ValOperandId inputId = cacheIRReader.valOperandId();
    933        Value v = READ_VALUE_REG(inputId.id());
    934        if (!v.isNull()) {
    935          FAIL_IC();
    936        }
    937        DISPATCH_CACHEOP();
    938      }
    939 
    940      CACHEOP_CASE(GuardIsUndefined) {
    941        ValOperandId inputId = cacheIRReader.valOperandId();
    942        Value v = READ_VALUE_REG(inputId.id());
    943        if (!v.isUndefined()) {
    944          FAIL_IC();
    945        }
    946        DISPATCH_CACHEOP();
    947      }
    948 
    949      CACHEOP_CASE(GuardIsNotUninitializedLexical) {
    950        ValOperandId valId = cacheIRReader.valOperandId();
    951        Value val = READ_VALUE_REG(valId.id());
    952        if (val == MagicValue(JS_UNINITIALIZED_LEXICAL)) {
    953          FAIL_IC();
    954        }
    955        DISPATCH_CACHEOP();
    956      }
    957 
    958      CACHEOP_CASE(GuardToBoolean) {
    959        ValOperandId inputId = cacheIRReader.valOperandId();
    960        Value v = READ_VALUE_REG(inputId.id());
    961        if (!v.isBoolean()) {
    962          FAIL_IC();
    963        }
    964        WRITE_REG(inputId.id(), v.toBoolean() ? 1 : 0, BOOLEAN);
    965        DISPATCH_CACHEOP();
    966      }
    967 
    968      CACHEOP_CASE(GuardToString) {
    969        ValOperandId inputId = cacheIRReader.valOperandId();
    970        Value v = READ_VALUE_REG(inputId.id());
    971        if (!v.isString()) {
    972          FAIL_IC();
    973        }
    974        WRITE_REG(inputId.id(), reinterpret_cast<uint64_t>(v.toString()),
    975                  STRING);
    976        PREDICT_NEXT(GuardToString);
    977        DISPATCH_CACHEOP();
    978      }
    979 
    980      CACHEOP_CASE(GuardToSymbol) {
    981        ValOperandId inputId = cacheIRReader.valOperandId();
    982        Value v = READ_VALUE_REG(inputId.id());
    983        if (!v.isSymbol()) {
    984          FAIL_IC();
    985        }
    986        WRITE_REG(inputId.id(), reinterpret_cast<uint64_t>(v.toSymbol()),
    987                  SYMBOL);
    988        PREDICT_NEXT(GuardSpecificSymbol);
    989        DISPATCH_CACHEOP();
    990      }
    991 
    992      CACHEOP_CASE(GuardToBigInt) {
    993        ValOperandId inputId = cacheIRReader.valOperandId();
    994        Value v = READ_VALUE_REG(inputId.id());
    995        if (!v.isBigInt()) {
    996          FAIL_IC();
    997        }
    998        WRITE_REG(inputId.id(), reinterpret_cast<uint64_t>(v.toBigInt()),
    999                  BIGINT);
   1000        DISPATCH_CACHEOP();
   1001      }
   1002 
   1003      CACHEOP_CASE(GuardIsNumber) {
   1004        ValOperandId inputId = cacheIRReader.valOperandId();
   1005        Value v = READ_VALUE_REG(inputId.id());
   1006        if (!v.isNumber()) {
   1007          FAIL_IC();
   1008        }
   1009        DISPATCH_CACHEOP();
   1010      }
   1011 
   1012      CACHEOP_CASE(GuardToInt32) {
   1013        ValOperandId inputId = cacheIRReader.valOperandId();
   1014        Value v = READ_VALUE_REG(inputId.id());
   1015        TRACE_PRINTF("GuardToInt32 (%d): icVal %" PRIx64 "\n", inputId.id(),
   1016                     READ_REG(inputId.id()));
   1017        if (!v.isInt32()) {
   1018          FAIL_IC();
   1019        }
   1020        // N.B.: we don't need to unbox because the low 32 bits are
   1021        // already the int32 itself, and we are careful when using
   1022        // `Int32Operand`s to only use those bits.
   1023 
   1024        PREDICT_NEXT(GuardToInt32);
   1025        DISPATCH_CACHEOP();
   1026      }
   1027 
   1028      CACHEOP_CASE(GuardToNonGCThing) {
   1029        ValOperandId inputId = cacheIRReader.valOperandId();
   1030        Value input = READ_VALUE_REG(inputId.id());
   1031        if (input.isGCThing()) {
   1032          FAIL_IC();
   1033        }
   1034        DISPATCH_CACHEOP();
   1035      }
   1036 
   1037      CACHEOP_CASE(GuardBooleanToInt32) {
   1038        ValOperandId inputId = cacheIRReader.valOperandId();
   1039        Int32OperandId resultId = cacheIRReader.int32OperandId();
   1040        BOUNDSCHECK(resultId);
   1041        Value v = READ_VALUE_REG(inputId.id());
   1042        if (!v.isBoolean()) {
   1043          FAIL_IC();
   1044        }
   1045        WRITE_REG(resultId.id(), v.toBoolean() ? 1 : 0, INT32);
   1046        DISPATCH_CACHEOP();
   1047      }
   1048 
   1049      CACHEOP_CASE(GuardToInt32Index) {
   1050        ValOperandId inputId = cacheIRReader.valOperandId();
   1051        Int32OperandId resultId = cacheIRReader.int32OperandId();
   1052        BOUNDSCHECK(resultId);
   1053        Value val = READ_VALUE_REG(inputId.id());
   1054        if (val.isInt32()) {
   1055          WRITE_REG(resultId.id(), val.toInt32(), INT32);
   1056          DISPATCH_CACHEOP();
   1057        } else if (val.isDouble()) {
   1058          double doubleVal = val.toDouble();
   1059          if (int32_t(doubleVal) == doubleVal) {
   1060            WRITE_REG(resultId.id(), int32_t(doubleVal), INT32);
   1061            DISPATCH_CACHEOP();
   1062          }
   1063        }
   1064        FAIL_IC();
   1065      }
   1066 
   1067      CACHEOP_CASE(Int32ToIntPtr) {
   1068        Int32OperandId inputId = cacheIRReader.int32OperandId();
   1069        IntPtrOperandId resultId = cacheIRReader.intPtrOperandId();
   1070        BOUNDSCHECK(resultId);
   1071        int32_t input = int32_t(READ_REG(inputId.id()));
   1072        // Note that this must sign-extend to pointer width:
   1073        WRITE_REG(resultId.id(), intptr_t(input), OBJECT);
   1074        DISPATCH_CACHEOP();
   1075      }
   1076 
   1077      CACHEOP_CASE(GuardToInt32ModUint32) {
   1078        ValOperandId inputId = cacheIRReader.valOperandId();
   1079        Int32OperandId resultId = cacheIRReader.int32OperandId();
   1080        BOUNDSCHECK(resultId);
   1081        Value input = READ_VALUE_REG(inputId.id());
   1082        if (input.isInt32()) {
   1083          WRITE_REG(resultId.id(), input.toInt32(), INT32);
   1084          DISPATCH_CACHEOP();
   1085        } else if (input.isDouble()) {
   1086          double doubleVal = input.toDouble();
   1087          // Accept any double that fits in an int64_t but truncate the top 32
   1088          // bits.
   1089          if (doubleVal >= double(INT64_MIN) &&
   1090              doubleVal <= double(INT64_MAX)) {
   1091            WRITE_REG(resultId.id(), int64_t(doubleVal), INT32);
   1092            DISPATCH_CACHEOP();
   1093          }
   1094        }
   1095        FAIL_IC();
   1096      }
   1097 
   1098      CACHEOP_CASE(GuardNonDoubleType) {
   1099        ValOperandId inputId = cacheIRReader.valOperandId();
   1100        ValueType type = cacheIRReader.valueType();
   1101        Value val = READ_VALUE_REG(inputId.id());
   1102        switch (type) {
   1103          case ValueType::String:
   1104            if (!val.isString()) {
   1105              FAIL_IC();
   1106            }
   1107            break;
   1108          case ValueType::Symbol:
   1109            if (!val.isSymbol()) {
   1110              FAIL_IC();
   1111            }
   1112            break;
   1113          case ValueType::BigInt:
   1114            if (!val.isBigInt()) {
   1115              FAIL_IC();
   1116            }
   1117            break;
   1118          case ValueType::Int32:
   1119            if (!val.isInt32()) {
   1120              FAIL_IC();
   1121            }
   1122            break;
   1123          case ValueType::Boolean:
   1124            if (!val.isBoolean()) {
   1125              FAIL_IC();
   1126            }
   1127            break;
   1128          case ValueType::Undefined:
   1129            if (!val.isUndefined()) {
   1130              FAIL_IC();
   1131            }
   1132            break;
   1133          case ValueType::Null:
   1134            if (!val.isNull()) {
   1135              FAIL_IC();
   1136            }
   1137            break;
   1138          default:
   1139            MOZ_CRASH("Unexpected type");
   1140        }
   1141        DISPATCH_CACHEOP();
   1142      }
   1143 
   1144      CACHEOP_CASE(GuardShape) {
   1145        ObjOperandId objId = cacheIRReader.objOperandId();
   1146        uint32_t shapeOffset = cacheIRReader.stubOffset();
   1147        JSObject* obj = reinterpret_cast<JSObject*>(READ_REG(objId.id()));
   1148        uintptr_t expectedShape = stubInfo->getStubRawWord(cstub, shapeOffset);
   1149        if (reinterpret_cast<uintptr_t>(obj->shape()) != expectedShape) {
   1150          FAIL_IC();
   1151        }
   1152        DISPATCH_CACHEOP();
   1153      }
   1154 
   1155      CACHEOP_CASE(GuardFuse) {
   1156        RealmFuses::FuseIndex fuseIndex = cacheIRReader.realmFuseIndex();
   1157        if (!ctx.frameMgr.cxForLocalUseOnly()
   1158                 ->realm()
   1159                 ->realmFuses.getFuseByIndex(fuseIndex)
   1160                 ->intact()) {
   1161          FAIL_IC();
   1162        }
   1163        DISPATCH_CACHEOP();
   1164      }
   1165 
   1166      CACHEOP_CASE(GuardObjectFuseProperty) {
   1167        auto args = cacheIRReader.argsForGuardObjectFuseProperty();
   1168 #ifdef DEBUG
   1169        JSObject* obj = reinterpret_cast<JSObject*>(READ_REG(args.objId.id()));
   1170        uintptr_t objFuseOwner =
   1171            stubInfo->getStubRawWord(cstub, args.objFuseOwnerOffset);
   1172        MOZ_ASSERT(uintptr_t(obj) == objFuseOwner);
   1173 #endif
   1174        auto* objFuse = reinterpret_cast<ObjectFuse*>(
   1175            stubInfo->getStubRawWord(cstub, args.objFuseOffset));
   1176        uint32_t generation =
   1177            stubInfo->getStubRawInt32(cstub, args.expectedGenerationOffset);
   1178        uint32_t propIndex =
   1179            stubInfo->getStubRawInt32(cstub, args.propIndexOffset);
   1180        uint32_t propMask =
   1181            stubInfo->getStubRawInt32(cstub, args.propMaskOffset);
   1182        uint32_t propSlot =
   1183            ObjectFuse::propertySlotFromIndexAndMask(propIndex, propMask);
   1184        if (!objFuse->checkPropertyIsConstant(generation, propSlot)) {
   1185          FAIL_IC();
   1186        }
   1187        DISPATCH_CACHEOP();
   1188      }
   1189 
   1190      CACHEOP_CASE(GuardProto) {
   1191        ObjOperandId objId = cacheIRReader.objOperandId();
   1192        uint32_t protoOffset = cacheIRReader.stubOffset();
   1193        JSObject* obj = reinterpret_cast<JSObject*>(READ_REG(objId.id()));
   1194        JSObject* proto = reinterpret_cast<JSObject*>(
   1195            stubInfo->getStubRawWord(cstub, protoOffset));
   1196        if (obj->staticPrototype() != proto) {
   1197          FAIL_IC();
   1198        }
   1199        PREDICT_NEXT(LoadProto);
   1200        DISPATCH_CACHEOP();
   1201      }
   1202 
   1203      CACHEOP_CASE(GuardNullProto) {
   1204        ObjOperandId objId = cacheIRReader.objOperandId();
   1205        JSObject* obj = reinterpret_cast<JSObject*>(READ_REG(objId.id()));
   1206        if (obj->taggedProto().raw()) {
   1207          FAIL_IC();
   1208        }
   1209        DISPATCH_CACHEOP();
   1210      }
   1211 
   1212      CACHEOP_CASE(GuardClass) {
   1213        ObjOperandId objId = cacheIRReader.objOperandId();
   1214        GuardClassKind kind = cacheIRReader.guardClassKind();
   1215        JSObject* object = reinterpret_cast<JSObject*>(READ_REG(objId.id()));
   1216        switch (kind) {
   1217          case GuardClassKind::Array:
   1218          case GuardClassKind::PlainObject:
   1219          case GuardClassKind::FixedLengthArrayBuffer:
   1220          case GuardClassKind::ImmutableArrayBuffer:
   1221          case GuardClassKind::ResizableArrayBuffer:
   1222          case GuardClassKind::FixedLengthSharedArrayBuffer:
   1223          case GuardClassKind::GrowableSharedArrayBuffer:
   1224          case GuardClassKind::FixedLengthDataView:
   1225          case GuardClassKind::ImmutableDataView:
   1226          case GuardClassKind::ResizableDataView:
   1227          case GuardClassKind::MappedArguments:
   1228          case GuardClassKind::UnmappedArguments:
   1229          case GuardClassKind::Set:
   1230          case GuardClassKind::Map:
   1231          case GuardClassKind::BoundFunction:
   1232          case GuardClassKind::Date:
   1233          case GuardClassKind::WeakMap:
   1234          case GuardClassKind::WeakSet:
   1235            if (object->getClass() != jit::ClassFor(kind)) {
   1236              FAIL_IC();
   1237            }
   1238            break;
   1239          case GuardClassKind::WindowProxy:
   1240            if (object->getClass() != ctx.frameMgr.cxForLocalUseOnly()
   1241                                          ->runtime()
   1242                                          ->maybeWindowProxyClass()) {
   1243              FAIL_IC();
   1244            }
   1245            break;
   1246          case GuardClassKind::JSFunction:
   1247            if (!object->is<JSFunction>()) {
   1248              FAIL_IC();
   1249            }
   1250            break;
   1251        }
   1252        DISPATCH_CACHEOP();
   1253      }
   1254 
   1255      CACHEOP_CASE(GuardAnyClass) {
   1256        ObjOperandId objId = cacheIRReader.objOperandId();
   1257        uint32_t claspOffset = cacheIRReader.stubOffset();
   1258        JSObject* obj = reinterpret_cast<JSObject*>(READ_REG(objId.id()));
   1259        JSClass* clasp = reinterpret_cast<JSClass*>(
   1260            stubInfo->getStubRawWord(cstub, claspOffset));
   1261        if (obj->getClass() != clasp) {
   1262          FAIL_IC();
   1263        }
   1264        DISPATCH_CACHEOP();
   1265      }
   1266 
   1267      CACHEOP_CASE(GuardGlobalGeneration) {
   1268        uint32_t expectedOffset = cacheIRReader.stubOffset();
   1269        uint32_t generationAddrOffset = cacheIRReader.stubOffset();
   1270        uint32_t expected = stubInfo->getStubRawInt32(cstub, expectedOffset);
   1271        uint32_t* generationAddr = reinterpret_cast<uint32_t*>(
   1272            stubInfo->getStubRawWord(cstub, generationAddrOffset));
   1273        if (*generationAddr != expected) {
   1274          FAIL_IC();
   1275        }
   1276        DISPATCH_CACHEOP();
   1277      }
   1278 
   1279      CACHEOP_CASE(HasClassResult) {
   1280        ObjOperandId objId = cacheIRReader.objOperandId();
   1281        uint32_t claspOffset = cacheIRReader.stubOffset();
   1282        JSObject* obj = reinterpret_cast<JSObject*>(READ_REG(objId.id()));
   1283        JSClass* clasp = reinterpret_cast<JSClass*>(
   1284            stubInfo->getStubRawWord(cstub, claspOffset));
   1285        retValue = BooleanValue(obj->getClass() == clasp).asRawBits();
   1286        PREDICT_RETURN();
   1287        DISPATCH_CACHEOP();
   1288      }
   1289 
   1290      CACHEOP_CASE(GuardCompartment) {
   1291        ObjOperandId objId = cacheIRReader.objOperandId();
   1292        uint32_t globalOffset = cacheIRReader.stubOffset();
   1293        uint32_t compartmentOffset = cacheIRReader.stubOffset();
   1294        JSObject* obj = reinterpret_cast<JSObject*>(READ_REG(objId.id()));
   1295        JSObject* global = reinterpret_cast<JSObject*>(
   1296            stubInfo->getStubRawWord(cstub, globalOffset));
   1297        JS::Compartment* compartment = reinterpret_cast<JS::Compartment*>(
   1298            stubInfo->getStubRawWord(cstub, compartmentOffset));
   1299        if (IsDeadProxyObject(global)) {
   1300          FAIL_IC();
   1301        }
   1302        if (obj->compartment() != compartment) {
   1303          FAIL_IC();
   1304        }
   1305        DISPATCH_CACHEOP();
   1306      }
   1307 
   1308      CACHEOP_CASE(GuardIsExtensible) {
   1309        ObjOperandId objId = cacheIRReader.objOperandId();
   1310        JSObject* obj = reinterpret_cast<JSObject*>(READ_REG(objId.id()));
   1311        if (obj->nonProxyIsExtensible()) {
   1312          FAIL_IC();
   1313        }
   1314        DISPATCH_CACHEOP();
   1315      }
   1316 
   1317      CACHEOP_CASE(GuardIsNativeObject) {
   1318        ObjOperandId objId = cacheIRReader.objOperandId();
   1319        JSObject* obj = reinterpret_cast<JSObject*>(READ_REG(objId.id()));
   1320        if (!obj->is<NativeObject>()) {
   1321          FAIL_IC();
   1322        }
   1323        DISPATCH_CACHEOP();
   1324      }
   1325 
   1326      CACHEOP_CASE(GuardIsProxy) {
   1327        ObjOperandId objId = cacheIRReader.objOperandId();
   1328        JSObject* obj = reinterpret_cast<JSObject*>(READ_REG(objId.id()));
   1329        if (!obj->is<ProxyObject>()) {
   1330          FAIL_IC();
   1331        }
   1332        DISPATCH_CACHEOP();
   1333      }
   1334 
   1335      CACHEOP_CASE(GuardIsNotProxy) {
   1336        ObjOperandId objId = cacheIRReader.objOperandId();
   1337        JSObject* obj = reinterpret_cast<JSObject*>(READ_REG(objId.id()));
   1338        if (obj->is<ProxyObject>()) {
   1339          FAIL_IC();
   1340        }
   1341        DISPATCH_CACHEOP();
   1342      }
   1343 
   1344      CACHEOP_CASE(GuardIsNotArrayBufferMaybeShared) {
   1345        ObjOperandId objId = cacheIRReader.objOperandId();
   1346        JSObject* obj = reinterpret_cast<JSObject*>(READ_REG(objId.id()));
   1347        const JSClass* clasp = obj->getClass();
   1348        if (clasp == &FixedLengthArrayBufferObject::class_ ||
   1349            clasp == &FixedLengthSharedArrayBufferObject::class_ ||
   1350            clasp == &ResizableArrayBufferObject::class_ ||
   1351            clasp == &GrowableSharedArrayBufferObject::class_) {
   1352          FAIL_IC();
   1353        }
   1354        DISPATCH_CACHEOP();
   1355      }
   1356 
   1357      CACHEOP_CASE(GuardIsTypedArray) {
   1358        ObjOperandId objId = cacheIRReader.objOperandId();
   1359        JSObject* obj = reinterpret_cast<JSObject*>(READ_REG(objId.id()));
   1360        if (!IsTypedArrayClass(obj->getClass())) {
   1361          FAIL_IC();
   1362        }
   1363        DISPATCH_CACHEOP();
   1364      }
   1365 
   1366      CACHEOP_CASE(GuardIsNonResizableTypedArray) {
   1367        ObjOperandId objId = cacheIRReader.objOperandId();
   1368        JSObject* obj = reinterpret_cast<JSObject*>(READ_REG(objId.id()));
   1369        if (!IsFixedLengthTypedArrayClass(obj->getClass()) &&
   1370            !IsImmutableTypedArrayClass(obj->getClass())) {
   1371          FAIL_IC();
   1372        }
   1373        DISPATCH_CACHEOP();
   1374      }
   1375 
   1376      CACHEOP_CASE(GuardHasProxyHandler) {
   1377        ObjOperandId objId = cacheIRReader.objOperandId();
   1378        uint32_t handlerOffset = cacheIRReader.stubOffset();
   1379        JSObject* obj = reinterpret_cast<JSObject*>(READ_REG(objId.id()));
   1380        BaseProxyHandler* handler = reinterpret_cast<BaseProxyHandler*>(
   1381            stubInfo->getStubRawWord(cstub, handlerOffset));
   1382        if (obj->as<ProxyObject>().handler() != handler) {
   1383          FAIL_IC();
   1384        }
   1385        DISPATCH_CACHEOP();
   1386      }
   1387 
   1388      CACHEOP_CASE(GuardIsNotDOMProxy) {
   1389        ObjOperandId objId = cacheIRReader.objOperandId();
   1390        JSObject* obj = reinterpret_cast<JSObject*>(READ_REG(objId.id()));
   1391        if (obj->as<ProxyObject>().handler()->family() ==
   1392            GetDOMProxyHandlerFamily()) {
   1393          FAIL_IC();
   1394        }
   1395        DISPATCH_CACHEOP();
   1396      }
   1397 
   1398      CACHEOP_CASE(GuardSpecificObject) {
   1399        ObjOperandId objId = cacheIRReader.objOperandId();
   1400        uint32_t expectedOffset = cacheIRReader.stubOffset();
   1401        JSObject* obj = reinterpret_cast<JSObject*>(READ_REG(objId.id()));
   1402        JSObject* expected = reinterpret_cast<JSObject*>(
   1403            stubInfo->getStubRawWord(cstub, expectedOffset));
   1404        if (obj != expected) {
   1405          FAIL_IC();
   1406        }
   1407        DISPATCH_CACHEOP();
   1408      }
   1409 
   1410      CACHEOP_CASE(GuardObjectIdentity) {
   1411        ObjOperandId obj1Id = cacheIRReader.objOperandId();
   1412        ObjOperandId obj2Id = cacheIRReader.objOperandId();
   1413        JSObject* obj1 = reinterpret_cast<JSObject*>(READ_REG(obj1Id.id()));
   1414        JSObject* obj2 = reinterpret_cast<JSObject*>(READ_REG(obj2Id.id()));
   1415        if (obj1 != obj2) {
   1416          FAIL_IC();
   1417        }
   1418        DISPATCH_CACHEOP();
   1419      }
   1420 
   1421      CACHEOP_CASE(GuardSpecificFunction) {
   1422        auto args = cacheIRReader.argsForGuardSpecificFunction();
   1423        uintptr_t expected =
   1424            stubInfo->getStubRawWord(cstub, args.expectedOffset);
   1425        if (expected != READ_REG(args.funId.id())) {
   1426          FAIL_IC();
   1427        }
   1428        PREDICT_NEXT(LoadArgumentFixedSlot);
   1429        DISPATCH_CACHEOP();
   1430      }
   1431 
   1432      CACHEOP_CASE(GuardFunctionScript) {
   1433        auto args = cacheIRReader.argsForGuardFunctionScript();
   1434        auto* fun = reinterpret_cast<JSFunction*>(READ_REG(args.objId.id()));
   1435        BaseScript* expected = reinterpret_cast<BaseScript*>(
   1436            stubInfo->getStubRawWord(cstub, args.expectedOffset));
   1437 
   1438        if (!fun->hasBaseScript() || fun->baseScript() != expected) {
   1439          FAIL_IC();
   1440        }
   1441 
   1442        PREDICT_NEXT(CallScriptedFunction);
   1443        DISPATCH_CACHEOP();
   1444      }
   1445 
   1446      CACHEOP_CASE(GuardSpecificAtom) {
   1447        StringOperandId strId = cacheIRReader.stringOperandId();
   1448        uint32_t expectedOffset = cacheIRReader.stubOffset();
   1449        uintptr_t expected = stubInfo->getStubRawWord(cstub, expectedOffset);
   1450        if (expected != READ_REG(strId.id())) {
   1451          // TODO: BaselineCacheIRCompiler also checks for equal strings
   1452          FAIL_IC();
   1453        }
   1454        DISPATCH_CACHEOP();
   1455      }
   1456 
   1457      CACHEOP_CASE(GuardSpecificSymbol) {
   1458        SymbolOperandId symId = cacheIRReader.symbolOperandId();
   1459        uint32_t expectedOffset = cacheIRReader.stubOffset();
   1460        uintptr_t expected = stubInfo->getStubRawWord(cstub, expectedOffset);
   1461        if (expected != READ_REG(symId.id())) {
   1462          FAIL_IC();
   1463        }
   1464        DISPATCH_CACHEOP();
   1465      }
   1466 
   1467      CACHEOP_CASE(GuardSpecificInt32) {
   1468        Int32OperandId numId = cacheIRReader.int32OperandId();
   1469        int32_t expected = cacheIRReader.int32Immediate();
   1470        if (expected != int32_t(READ_REG(numId.id()))) {
   1471          FAIL_IC();
   1472        }
   1473        DISPATCH_CACHEOP();
   1474      }
   1475 
   1476      CACHEOP_CASE(GuardNoDenseElements) {
   1477        ObjOperandId objId = cacheIRReader.objOperandId();
   1478        JSObject* obj = reinterpret_cast<JSObject*>(READ_REG(objId.id()));
   1479        if (obj->as<NativeObject>().getDenseInitializedLength() != 0) {
   1480          FAIL_IC();
   1481        }
   1482        DISPATCH_CACHEOP();
   1483      }
   1484 
   1485      CACHEOP_CASE(GuardStringToIndex) {
   1486        StringOperandId strId = cacheIRReader.stringOperandId();
   1487        Int32OperandId resultId = cacheIRReader.int32OperandId();
   1488        BOUNDSCHECK(resultId);
   1489        JSString* str = reinterpret_cast<JSString*>(READ_REG(strId.id()));
   1490        int32_t result;
   1491        if (str->hasIndexValue()) {
   1492          uint32_t index = str->getIndexValue();
   1493          MOZ_ASSERT(index <= INT32_MAX);
   1494          result = index;
   1495        } else {
   1496          result = GetIndexFromString(str);
   1497          if (result < 0) {
   1498            FAIL_IC();
   1499          }
   1500        }
   1501        WRITE_REG(resultId.id(), result, INT32);
   1502        DISPATCH_CACHEOP();
   1503      }
   1504 
   1505      CACHEOP_CASE(GuardStringToInt32) {
   1506        StringOperandId strId = cacheIRReader.stringOperandId();
   1507        Int32OperandId resultId = cacheIRReader.int32OperandId();
   1508        BOUNDSCHECK(resultId);
   1509        JSString* str = reinterpret_cast<JSString*>(READ_REG(strId.id()));
   1510        int32_t result;
   1511        // Use indexed value as fast path if possible.
   1512        if (str->hasIndexValue()) {
   1513          uint32_t index = str->getIndexValue();
   1514          MOZ_ASSERT(index <= INT32_MAX);
   1515          result = index;
   1516        } else {
   1517          if (!GetInt32FromStringPure(ctx.frameMgr.cxForLocalUseOnly(), str,
   1518                                      &result)) {
   1519            FAIL_IC();
   1520          }
   1521        }
   1522        WRITE_REG(resultId.id(), result, INT32);
   1523        DISPATCH_CACHEOP();
   1524      }
   1525 
   1526      CACHEOP_CASE(GuardStringToNumber) {
   1527        StringOperandId strId = cacheIRReader.stringOperandId();
   1528        NumberOperandId resultId = cacheIRReader.numberOperandId();
   1529        BOUNDSCHECK(resultId);
   1530        JSString* str = reinterpret_cast<JSString*>(READ_REG(strId.id()));
   1531        Value result;
   1532        // Use indexed value as fast path if possible.
   1533        if (str->hasIndexValue()) {
   1534          uint32_t index = str->getIndexValue();
   1535          MOZ_ASSERT(index <= INT32_MAX);
   1536          result = Int32Value(index);
   1537        } else {
   1538          double value;
   1539          if (!StringToNumberPure(ctx.frameMgr.cxForLocalUseOnly(), str,
   1540                                  &value)) {
   1541            FAIL_IC();
   1542          }
   1543          result = DoubleValue(value);
   1544        }
   1545        WRITE_VALUE_REG(resultId.id(), result);
   1546        DISPATCH_CACHEOP();
   1547      }
   1548 
   1549      CACHEOP_CASE(BooleanToNumber) {
   1550        BooleanOperandId booleanId = cacheIRReader.booleanOperandId();
   1551        NumberOperandId resultId = cacheIRReader.numberOperandId();
   1552        BOUNDSCHECK(resultId);
   1553        uint64_t boolean = READ_REG(booleanId.id());
   1554        MOZ_ASSERT((boolean & ~1) == 0);
   1555        WRITE_VALUE_REG(resultId.id(), Int32Value(boolean));
   1556        DISPATCH_CACHEOP();
   1557      }
   1558 
   1559      CACHEOP_CASE(GuardHasGetterSetter) {
   1560        ObjOperandId objId = cacheIRReader.objOperandId();
   1561        uint32_t idOffset = cacheIRReader.stubOffset();
   1562        uint32_t getterSetterOffset = cacheIRReader.stubOffset();
   1563        JSObject* obj = reinterpret_cast<JSObject*>(READ_REG(objId.id()));
   1564        jsid id = jsid::fromRawBits(stubInfo->getStubRawWord(cstub, idOffset));
   1565        Value getterSetterVal = Value::fromRawBits(
   1566            stubInfo->getStubRawInt64(cstub, getterSetterOffset));
   1567        auto* getterSetter = getterSetterVal.toGCThing()->as<GetterSetter>();
   1568        if (!ObjectHasGetterSetterPure(ctx.frameMgr.cxForLocalUseOnly(), obj,
   1569                                       id, getterSetter)) {
   1570          FAIL_IC();
   1571        }
   1572        DISPATCH_CACHEOP();
   1573      }
   1574 
   1575      CACHEOP_CASE(GuardInt32IsNonNegative) {
   1576        Int32OperandId indexId = cacheIRReader.int32OperandId();
   1577        int32_t index = int32_t(READ_REG(indexId.id()));
   1578        if (index < 0) {
   1579          FAIL_IC();
   1580        }
   1581        DISPATCH_CACHEOP();
   1582      }
   1583 
   1584      CACHEOP_CASE(GuardDynamicSlotIsSpecificObject) {
   1585        ObjOperandId objId = cacheIRReader.objOperandId();
   1586        ObjOperandId expectedId = cacheIRReader.objOperandId();
   1587        uint32_t slotOffset = cacheIRReader.stubOffset();
   1588        JSObject* expected =
   1589            reinterpret_cast<JSObject*>(READ_REG(expectedId.id()));
   1590        uintptr_t slot = stubInfo->getStubRawInt32(cstub, slotOffset);
   1591        NativeObject* nobj =
   1592            reinterpret_cast<NativeObject*>(READ_REG(objId.id()));
   1593        HeapSlot* slots = nobj->getSlotsUnchecked();
   1594        // Note that unlike similar opcodes, GuardDynamicSlotIsSpecificObject
   1595        // takes a slot index rather than a byte offset.
   1596        Value actual = slots[slot];
   1597        if (actual != ObjectValue(*expected)) {
   1598          FAIL_IC();
   1599        }
   1600        DISPATCH_CACHEOP();
   1601      }
   1602 
   1603      CACHEOP_CASE(GuardDynamicSlotIsNotObject) {
   1604        ObjOperandId objId = cacheIRReader.objOperandId();
   1605        uint32_t slotOffset = cacheIRReader.stubOffset();
   1606        JSObject* obj = reinterpret_cast<JSObject*>(READ_REG(objId.id()));
   1607        uint32_t slot = stubInfo->getStubRawInt32(cstub, slotOffset);
   1608        NativeObject* nobj = &obj->as<NativeObject>();
   1609        HeapSlot* slots = nobj->getSlotsUnchecked();
   1610        // Note that unlike similar opcodes, GuardDynamicSlotIsNotObject takes a
   1611        // slot index rather than a byte offset.
   1612        Value actual = slots[slot];
   1613        if (actual.isObject()) {
   1614          FAIL_IC();
   1615        }
   1616        DISPATCH_CACHEOP();
   1617      }
   1618 
   1619      CACHEOP_CASE(GuardFixedSlotValue) {
   1620        ObjOperandId objId = cacheIRReader.objOperandId();
   1621        uint32_t offsetOffset = cacheIRReader.stubOffset();
   1622        uint32_t valOffset = cacheIRReader.stubOffset();
   1623        JSObject* obj = reinterpret_cast<JSObject*>(READ_REG(objId.id()));
   1624        uint32_t offset = stubInfo->getStubRawInt32(cstub, offsetOffset);
   1625        Value val =
   1626            Value::fromRawBits(stubInfo->getStubRawInt64(cstub, valOffset));
   1627        GCPtr<Value>* slot = reinterpret_cast<GCPtr<Value>*>(
   1628            reinterpret_cast<uintptr_t>(obj) + offset);
   1629        Value actual = slot->get();
   1630        if (actual != val) {
   1631          FAIL_IC();
   1632        }
   1633        DISPATCH_CACHEOP();
   1634      }
   1635 
   1636      CACHEOP_CASE(GuardDynamicSlotValue) {
   1637        ObjOperandId objId = cacheIRReader.objOperandId();
   1638        uint32_t offsetOffset = cacheIRReader.stubOffset();
   1639        uint32_t valOffset = cacheIRReader.stubOffset();
   1640        JSObject* obj = reinterpret_cast<JSObject*>(READ_REG(objId.id()));
   1641        uint32_t offset = stubInfo->getStubRawInt32(cstub, offsetOffset);
   1642        Value val =
   1643            Value::fromRawBits(stubInfo->getStubRawInt64(cstub, valOffset));
   1644        NativeObject* nobj = &obj->as<NativeObject>();
   1645        HeapSlot* slots = nobj->getSlotsUnchecked();
   1646        Value actual = slots[offset / sizeof(Value)];
   1647        if (actual != val) {
   1648          FAIL_IC();
   1649        }
   1650        DISPATCH_CACHEOP();
   1651      }
   1652 
   1653      CACHEOP_CASE(LoadFixedSlot) {
   1654        ValOperandId resultId = cacheIRReader.valOperandId();
   1655        BOUNDSCHECK(resultId);
   1656        ObjOperandId objId = cacheIRReader.objOperandId();
   1657        uint32_t offsetOffset = cacheIRReader.stubOffset();
   1658        JSObject* obj = reinterpret_cast<JSObject*>(READ_REG(objId.id()));
   1659        uint32_t offset = stubInfo->getStubRawInt32(cstub, offsetOffset);
   1660        GCPtr<Value>* slot = reinterpret_cast<GCPtr<Value>*>(
   1661            reinterpret_cast<uintptr_t>(obj) + offset);
   1662        Value actual = slot->get();
   1663        WRITE_VALUE_REG(resultId.id(), actual);
   1664        DISPATCH_CACHEOP();
   1665      }
   1666 
   1667      CACHEOP_CASE(LoadDynamicSlot) {
   1668        ValOperandId resultId = cacheIRReader.valOperandId();
   1669        BOUNDSCHECK(resultId);
   1670        ObjOperandId objId = cacheIRReader.objOperandId();
   1671        uint32_t slotOffset = cacheIRReader.stubOffset();
   1672        JSObject* obj = reinterpret_cast<JSObject*>(READ_REG(objId.id()));
   1673        uint32_t slot = stubInfo->getStubRawInt32(cstub, slotOffset);
   1674        NativeObject* nobj = &obj->as<NativeObject>();
   1675        HeapSlot* slots = nobj->getSlotsUnchecked();
   1676        // Note that unlike similar opcodes, LoadDynamicSlot takes a slot index
   1677        // rather than a byte offset.
   1678        Value actual = slots[slot];
   1679        WRITE_VALUE_REG(resultId.id(), actual);
   1680        DISPATCH_CACHEOP();
   1681      }
   1682 
   1683      CACHEOP_CASE(GuardNoAllocationMetadataBuilder) {
   1684        uint32_t builderAddrOffset = cacheIRReader.stubOffset();
   1685        uintptr_t builderAddr =
   1686            stubInfo->getStubRawWord(cstub, builderAddrOffset);
   1687        if (*reinterpret_cast<uintptr_t*>(builderAddr) != 0) {
   1688          FAIL_IC();
   1689        }
   1690        DISPATCH_CACHEOP();
   1691      }
   1692 
   1693      CACHEOP_CASE(GuardFunctionHasJitEntry) {
   1694        ObjOperandId funId = cacheIRReader.objOperandId();
   1695        JSObject* fun = reinterpret_cast<JSObject*>(READ_REG(funId.id()));
   1696        uint16_t flags = FunctionFlags::HasJitEntryFlags();
   1697        if (!fun->as<JSFunction>().flags().hasFlags(flags)) {
   1698          FAIL_IC();
   1699        }
   1700        DISPATCH_CACHEOP();
   1701      }
   1702 
   1703      CACHEOP_CASE(GuardFunctionHasNoJitEntry) {
   1704        ObjOperandId funId = cacheIRReader.objOperandId();
   1705        JSObject* fun = reinterpret_cast<JSObject*>(READ_REG(funId.id()));
   1706        uint16_t flags = FunctionFlags::HasJitEntryFlags();
   1707        if (fun->as<JSFunction>().flags().hasFlags(flags)) {
   1708          FAIL_IC();
   1709        }
   1710        DISPATCH_CACHEOP();
   1711      }
   1712 
   1713      CACHEOP_CASE(GuardFunctionIsNonBuiltinCtor) {
   1714        ObjOperandId funId = cacheIRReader.objOperandId();
   1715        JSObject* fun = reinterpret_cast<JSObject*>(READ_REG(funId.id()));
   1716        if (!fun->as<JSFunction>().isNonBuiltinConstructor()) {
   1717          FAIL_IC();
   1718        }
   1719        DISPATCH_CACHEOP();
   1720      }
   1721 
   1722      CACHEOP_CASE(GuardFunctionIsConstructor) {
   1723        ObjOperandId funId = cacheIRReader.objOperandId();
   1724        JSObject* fun = reinterpret_cast<JSObject*>(READ_REG(funId.id()));
   1725        if (!fun->as<JSFunction>().isConstructor()) {
   1726          FAIL_IC();
   1727        }
   1728        DISPATCH_CACHEOP();
   1729      }
   1730 
   1731      CACHEOP_CASE(GuardNotClassConstructor) {
   1732        ObjOperandId funId = cacheIRReader.objOperandId();
   1733        JSObject* fun = reinterpret_cast<JSObject*>(READ_REG(funId.id()));
   1734        if (fun->as<JSFunction>().isClassConstructor()) {
   1735          FAIL_IC();
   1736        }
   1737        DISPATCH_CACHEOP();
   1738      }
   1739 
   1740      CACHEOP_CASE(GuardArrayIsPacked) {
   1741        ObjOperandId arrayId = cacheIRReader.objOperandId();
   1742        JSObject* array = reinterpret_cast<JSObject*>(READ_REG(arrayId.id()));
   1743        if (!IsPackedArray(array)) {
   1744          FAIL_IC();
   1745        }
   1746        DISPATCH_CACHEOP();
   1747      }
   1748 
   1749      CACHEOP_CASE(GuardArgumentsObjectFlags) {
   1750        ObjOperandId objId = cacheIRReader.objOperandId();
   1751        uint8_t flags = cacheIRReader.readByte();
   1752        JSObject* obj = reinterpret_cast<JSObject*>(READ_REG(objId.id()));
   1753        if (obj->as<ArgumentsObject>().hasFlags(flags)) {
   1754          FAIL_IC();
   1755        }
   1756        DISPATCH_CACHEOP();
   1757      }
   1758 
   1759      CACHEOP_CASE(LoadObject) {
   1760        ObjOperandId resultId = cacheIRReader.objOperandId();
   1761        BOUNDSCHECK(resultId);
   1762        uint32_t objOffset = cacheIRReader.stubOffset();
   1763        intptr_t obj = stubInfo->getStubRawWord(cstub, objOffset);
   1764        WRITE_REG(resultId.id(), obj, OBJECT);
   1765        PREDICT_NEXT(GuardShape);
   1766        DISPATCH_CACHEOP();
   1767      }
   1768 
   1769      CACHEOP_CASE(LoadProtoObject) {
   1770        auto args = cacheIRReader.argsForLoadProtoObject();
   1771        BOUNDSCHECK(args.resultId);
   1772        intptr_t obj = stubInfo->getStubRawWord(cstub, args.protoObjOffset);
   1773        WRITE_REG(args.resultId.id(), obj, OBJECT);
   1774        PREDICT_NEXT(GuardShape);
   1775        DISPATCH_CACHEOP();
   1776      }
   1777 
   1778      CACHEOP_CASE(LoadProto) {
   1779        ObjOperandId objId = cacheIRReader.objOperandId();
   1780        ObjOperandId resultId = cacheIRReader.objOperandId();
   1781        BOUNDSCHECK(resultId);
   1782        NativeObject* nobj =
   1783            reinterpret_cast<NativeObject*>(READ_REG(objId.id()));
   1784        WRITE_REG(resultId.id(),
   1785                  reinterpret_cast<uint64_t>(nobj->staticPrototype()), OBJECT);
   1786        DISPATCH_CACHEOP();
   1787      }
   1788 
   1789      CACHEOP_CASE(LoadEnclosingEnvironment) {
   1790        ObjOperandId objId = cacheIRReader.objOperandId();
   1791        ObjOperandId resultId = cacheIRReader.objOperandId();
   1792        BOUNDSCHECK(resultId);
   1793        JSObject* obj = reinterpret_cast<JSObject*>(READ_REG(objId.id()));
   1794        JSObject* env = &obj->as<EnvironmentObject>().enclosingEnvironment();
   1795        WRITE_REG(resultId.id(), reinterpret_cast<uint64_t>(env), OBJECT);
   1796        DISPATCH_CACHEOP();
   1797      }
   1798 
   1799      CACHEOP_CASE(LoadWrapperTarget) {
   1800        ObjOperandId objId = cacheIRReader.objOperandId();
   1801        ObjOperandId resultId = cacheIRReader.objOperandId();
   1802        bool fallible = cacheIRReader.readBool();
   1803        BOUNDSCHECK(resultId);
   1804        JSObject* obj = reinterpret_cast<JSObject*>(READ_REG(objId.id()));
   1805        JSObject* target = obj->as<ProxyObject>().private_().toObjectOrNull();
   1806        if (fallible && !target) {
   1807          FAIL_IC();
   1808        }
   1809        WRITE_REG(resultId.id(), reinterpret_cast<uintptr_t>(target), OBJECT);
   1810        DISPATCH_CACHEOP();
   1811      }
   1812 
   1813      CACHEOP_CASE(LoadValueTag) {
   1814        ValOperandId valId = cacheIRReader.valOperandId();
   1815        ValueTagOperandId resultId = cacheIRReader.valueTagOperandId();
   1816        BOUNDSCHECK(resultId);
   1817        Value val = READ_VALUE_REG(valId.id());
   1818        WRITE_REG(resultId.id(), val.asRawBits() >> JSVAL_TAG_SHIFT, INT32);
   1819        DISPATCH_CACHEOP();
   1820      }
   1821 
   1822      CACHEOP_CASE(LoadArgumentFixedSlot) {
   1823        ValOperandId resultId = cacheIRReader.valOperandId();
   1824        BOUNDSCHECK(resultId);
   1825        uint8_t slotIndex = cacheIRReader.readByte();
   1826        StackVal* sp = ctx.sp();
   1827        Value val = sp[slotIndex].asValue();
   1828        TRACE_PRINTF(" -> slot %d: val %" PRIx64 "\n", int(slotIndex),
   1829                     val.asRawBits());
   1830        WRITE_VALUE_REG(resultId.id(), val);
   1831        DISPATCH_CACHEOP();
   1832      }
   1833 
   1834      CACHEOP_CASE(LoadArgumentDynamicSlot) {
   1835        ValOperandId resultId = cacheIRReader.valOperandId();
   1836        BOUNDSCHECK(resultId);
   1837        Int32OperandId argcId = cacheIRReader.int32OperandId();
   1838        uint8_t slotIndex = cacheIRReader.readByte();
   1839        int32_t argc = int32_t(READ_REG(argcId.id()));
   1840        StackVal* sp = ctx.sp();
   1841        Value val = sp[slotIndex + argc].asValue();
   1842        WRITE_VALUE_REG(resultId.id(), val);
   1843        DISPATCH_CACHEOP();
   1844      }
   1845 
   1846      CACHEOP_CASE(TruncateDoubleToUInt32) {
   1847        NumberOperandId inputId = cacheIRReader.numberOperandId();
   1848        Int32OperandId resultId = cacheIRReader.int32OperandId();
   1849        BOUNDSCHECK(resultId);
   1850        Value input = READ_VALUE_REG(inputId.id());
   1851        WRITE_REG(resultId.id(), JS::ToInt32(input.toNumber()), INT32);
   1852        DISPATCH_CACHEOP();
   1853      }
   1854 
   1855      CACHEOP_CASE(MegamorphicLoadSlotResult) {
   1856        ObjOperandId objId = cacheIRReader.objOperandId();
   1857        uint32_t nameOffset = cacheIRReader.stubOffset();
   1858        JSObject* obj = reinterpret_cast<JSObject*>(READ_REG(objId.id()));
   1859        jsid name =
   1860            jsid::fromRawBits(stubInfo->getStubRawWord(cstub, nameOffset));
   1861        if (!obj->shape()->isNative()) {
   1862          FAIL_IC();
   1863        }
   1864        Value result;
   1865        if (!GetNativeDataPropertyPureWithCacheLookup(
   1866                ctx.frameMgr.cxForLocalUseOnly(), obj, name, nullptr,
   1867                &result)) {
   1868          FAIL_IC();
   1869        }
   1870        retValue = result.asRawBits();
   1871        DISPATCH_CACHEOP();
   1872      }
   1873 
   1874      CACHEOP_CASE(MegamorphicLoadSlotByValueResult) {
   1875        ObjOperandId objId = cacheIRReader.objOperandId();
   1876        ValOperandId idId = cacheIRReader.valOperandId();
   1877        JSObject* obj = reinterpret_cast<JSObject*>(READ_REG(objId.id()));
   1878        Value id = READ_VALUE_REG(idId.id());
   1879        if (!obj->shape()->isNative()) {
   1880          FAIL_IC();
   1881        }
   1882        Value values[2] = {id};
   1883        if (!GetNativeDataPropertyByValuePure(ctx.frameMgr.cxForLocalUseOnly(),
   1884                                              obj, nullptr, values)) {
   1885          FAIL_IC();
   1886        }
   1887        retValue = values[1].asRawBits();
   1888        DISPATCH_CACHEOP();
   1889      }
   1890 
   1891      CACHEOP_CASE(MegamorphicSetElement) {
   1892        auto args = cacheIRReader.argsForMegamorphicSetElement();
   1893        JSObject* obj = reinterpret_cast<JSObject*>(READ_REG(args.objId.id()));
   1894        Value id = READ_VALUE_REG(args.idId.id());
   1895        Value rhs = READ_VALUE_REG(args.rhsId.id());
   1896        {
   1897          PUSH_IC_FRAME();
   1898          ReservedRooted<JSObject*> obj0(&ctx.state.obj0, obj);
   1899          ReservedRooted<Value> value0(&ctx.state.value0, id);
   1900          ReservedRooted<Value> value1(&ctx.state.value1, rhs);
   1901          if (!SetElementMegamorphic<false>(cx, obj0, value0, value1,
   1902                                            args.strict)) {
   1903            ctx.error = PBIResult::Error;
   1904            return IC_ERROR_SENTINEL();
   1905          }
   1906        }
   1907        DISPATCH_CACHEOP();
   1908      }
   1909 
   1910      CACHEOP_CASE(StoreFixedSlot) {
   1911        ObjOperandId objId = cacheIRReader.objOperandId();
   1912        uint32_t offsetOffset = cacheIRReader.stubOffset();
   1913        ValOperandId rhsId = cacheIRReader.valOperandId();
   1914        uintptr_t offset = stubInfo->getStubRawInt32(cstub, offsetOffset);
   1915        NativeObject* nobj =
   1916            reinterpret_cast<NativeObject*>(READ_REG(objId.id()));
   1917        GCPtr<Value>* slot = reinterpret_cast<GCPtr<Value>*>(
   1918            reinterpret_cast<uintptr_t>(nobj) + offset);
   1919        Value val = READ_VALUE_REG(rhsId.id());
   1920        slot->set(val);
   1921        PREDICT_RETURN();
   1922        DISPATCH_CACHEOP();
   1923      }
   1924 
   1925      CACHEOP_CASE(StoreDynamicSlot) {
   1926        ObjOperandId objId = cacheIRReader.objOperandId();
   1927        uint32_t offsetOffset = cacheIRReader.stubOffset();
   1928        ValOperandId rhsId = cacheIRReader.valOperandId();
   1929        uint32_t offset = stubInfo->getStubRawInt32(cstub, offsetOffset);
   1930        NativeObject* nobj =
   1931            reinterpret_cast<NativeObject*>(READ_REG(objId.id()));
   1932        HeapSlot* slots = nobj->getSlotsUnchecked();
   1933        Value val = READ_VALUE_REG(rhsId.id());
   1934        size_t dynSlot = offset / sizeof(Value);
   1935        size_t slot = dynSlot + nobj->numFixedSlots();
   1936        slots[dynSlot].set(nobj, HeapSlot::Slot, slot, val);
   1937        PREDICT_RETURN();
   1938        DISPATCH_CACHEOP();
   1939      }
   1940 
   1941      CACHEOP_CASE(AddAndStoreFixedSlot) {
   1942        ObjOperandId objId = cacheIRReader.objOperandId();
   1943        uint32_t offsetOffset = cacheIRReader.stubOffset();
   1944        ValOperandId rhsId = cacheIRReader.valOperandId();
   1945        uint32_t newShapeOffset = cacheIRReader.stubOffset();
   1946        bool preserveWrapper = cacheIRReader.readBool();
   1947        JSObject* obj = reinterpret_cast<JSObject*>(READ_REG(objId.id()));
   1948        if (preserveWrapper &&
   1949            !PreserveWrapper(ctx.frameMgr.cxForLocalUseOnly(), obj)) {
   1950          FAIL_IC();
   1951        }
   1952        int32_t offset = stubInfo->getStubRawInt32(cstub, offsetOffset);
   1953        Value rhs = READ_VALUE_REG(rhsId.id());
   1954        Shape* newShape = reinterpret_cast<Shape*>(
   1955            stubInfo->getStubRawWord(cstub, newShapeOffset));
   1956        obj->setShape(newShape);
   1957        GCPtr<Value>* slot = reinterpret_cast<GCPtr<Value>*>(
   1958            reinterpret_cast<uintptr_t>(obj) + offset);
   1959        slot->init(rhs);
   1960        PREDICT_RETURN();
   1961        DISPATCH_CACHEOP();
   1962      }
   1963 
   1964      CACHEOP_CASE(AddAndStoreDynamicSlot) {
   1965        ObjOperandId objId = cacheIRReader.objOperandId();
   1966        uint32_t offsetOffset = cacheIRReader.stubOffset();
   1967        ValOperandId rhsId = cacheIRReader.valOperandId();
   1968        uint32_t newShapeOffset = cacheIRReader.stubOffset();
   1969        bool preserveWrapper = cacheIRReader.readBool();
   1970        JSObject* obj = reinterpret_cast<JSObject*>(READ_REG(objId.id()));
   1971        if (preserveWrapper &&
   1972            !PreserveWrapper(ctx.frameMgr.cxForLocalUseOnly(), obj)) {
   1973          FAIL_IC();
   1974        }
   1975        int32_t offset = stubInfo->getStubRawInt32(cstub, offsetOffset);
   1976        Value rhs = READ_VALUE_REG(rhsId.id());
   1977        Shape* newShape = reinterpret_cast<Shape*>(
   1978            stubInfo->getStubRawWord(cstub, newShapeOffset));
   1979        NativeObject* nobj = &obj->as<NativeObject>();
   1980        obj->setShape(newShape);
   1981        HeapSlot* slots = nobj->getSlotsUnchecked();
   1982        size_t dynSlot = offset / sizeof(Value);
   1983        size_t slot = dynSlot + nobj->numFixedSlots();
   1984        slots[dynSlot].init(nobj, HeapSlot::Slot, slot, rhs);
   1985        PREDICT_RETURN();
   1986        DISPATCH_CACHEOP();
   1987      }
   1988 
   1989      CACHEOP_CASE(AllocateAndStoreDynamicSlot) {
   1990        ObjOperandId objId = cacheIRReader.objOperandId();
   1991        uint32_t offsetOffset = cacheIRReader.stubOffset();
   1992        ValOperandId rhsId = cacheIRReader.valOperandId();
   1993        uint32_t newShapeOffset = cacheIRReader.stubOffset();
   1994        uint32_t numNewSlotsOffset = cacheIRReader.stubOffset();
   1995        bool preserveWrapper = cacheIRReader.readBool();
   1996        JSObject* obj = reinterpret_cast<JSObject*>(READ_REG(objId.id()));
   1997        if (preserveWrapper &&
   1998            !PreserveWrapper(ctx.frameMgr.cxForLocalUseOnly(), obj)) {
   1999          FAIL_IC();
   2000        }
   2001        int32_t offset = stubInfo->getStubRawInt32(cstub, offsetOffset);
   2002        Value rhs = READ_VALUE_REG(rhsId.id());
   2003        Shape* newShape = reinterpret_cast<Shape*>(
   2004            stubInfo->getStubRawWord(cstub, newShapeOffset));
   2005        int32_t numNewSlots =
   2006            stubInfo->getStubRawInt32(cstub, numNewSlotsOffset);
   2007        NativeObject* nobj = &obj->as<NativeObject>();
   2008        // We have to (re)allocate dynamic slots. Do this first, as it's the
   2009        // only fallible operation here. Note that growSlotsPure is fallible but
   2010        // does not GC. Otherwise this is the same as AddAndStoreDynamicSlot
   2011        // above.
   2012        if (!NativeObject::growSlotsPure(ctx.frameMgr.cxForLocalUseOnly(), nobj,
   2013                                         numNewSlots)) {
   2014          FAIL_IC();
   2015        }
   2016        obj->setShape(newShape);
   2017        HeapSlot* slots = nobj->getSlotsUnchecked();
   2018        size_t dynSlot = offset / sizeof(Value);
   2019        size_t slot = dynSlot + nobj->numFixedSlots();
   2020        slots[dynSlot].init(nobj, HeapSlot::Slot, slot, rhs);
   2021        PREDICT_RETURN();
   2022        DISPATCH_CACHEOP();
   2023      }
   2024 
   2025      CACHEOP_CASE(StoreDenseElement) {
   2026        ObjOperandId objId = cacheIRReader.objOperandId();
   2027        Int32OperandId indexId = cacheIRReader.int32OperandId();
   2028        ValOperandId rhsId = cacheIRReader.valOperandId();
   2029        bool expectPackedElements = cacheIRReader.readBool();
   2030        NativeObject* nobj =
   2031            reinterpret_cast<NativeObject*>(READ_REG(objId.id()));
   2032        ObjectElements* elems = nobj->getElementsHeader();
   2033        int32_t index = int32_t(READ_REG(indexId.id()));
   2034        if (index < 0 || uint32_t(index) >= nobj->getDenseInitializedLength()) {
   2035          FAIL_IC();
   2036        }
   2037        if (expectPackedElements && !elems->isPacked()) {
   2038          FAIL_IC();
   2039        }
   2040        HeapSlot* slot = &elems->elements()[index];
   2041        if (!expectPackedElements && slot->get().isMagic()) {
   2042          FAIL_IC();
   2043        }
   2044        Value val = READ_VALUE_REG(rhsId.id());
   2045        slot->set(nobj, HeapSlot::Element, index + elems->numShiftedElements(),
   2046                  val);
   2047        PREDICT_RETURN();
   2048        DISPATCH_CACHEOP();
   2049      }
   2050 
   2051      CACHEOP_CASE(StoreDenseElementHole) {
   2052        ObjOperandId objId = cacheIRReader.objOperandId();
   2053        Int32OperandId indexId = cacheIRReader.int32OperandId();
   2054        ValOperandId rhsId = cacheIRReader.valOperandId();
   2055        bool handleAdd = cacheIRReader.readBool();
   2056        JSObject* obj = reinterpret_cast<JSObject*>(READ_REG(objId.id()));
   2057        uint32_t index = uint32_t(READ_REG(indexId.id()));
   2058        Value rhs = READ_VALUE_REG(rhsId.id());
   2059        NativeObject* nobj = &obj->as<NativeObject>();
   2060        uint32_t initLength = nobj->getDenseInitializedLength();
   2061        if (index < initLength) {
   2062          nobj->setDenseElement(index, rhs);
   2063        } else if (!handleAdd || index > initLength) {
   2064          FAIL_IC();
   2065        } else {
   2066          if (index >= nobj->getDenseCapacity()) {
   2067            if (!NativeObject::addDenseElementPure(
   2068                    ctx.frameMgr.cxForLocalUseOnly(), nobj)) {
   2069              FAIL_IC();
   2070            }
   2071          }
   2072          nobj->setDenseInitializedLength(initLength + 1);
   2073 
   2074          // Baseline always updates the length field by directly accessing its
   2075          // offset in ObjectElements. If the object is not an ArrayObject then
   2076          // this field is never read, so it's okay to skip the update here in
   2077          // that case.
   2078          if (nobj->is<ArrayObject>()) {
   2079            ArrayObject* aobj = &nobj->as<ArrayObject>();
   2080            uint32_t len = aobj->length();
   2081            if (len <= index) {
   2082              aobj->setLength(ctx.frameMgr.cxForLocalUseOnly(), len + 1);
   2083            }
   2084          }
   2085 
   2086          nobj->initDenseElement(index, rhs);
   2087        }
   2088        PREDICT_RETURN();
   2089        DISPATCH_CACHEOP();
   2090      }
   2091 
   2092      CACHEOP_CASE(ArrayPush) {
   2093        ObjOperandId objId = cacheIRReader.objOperandId();
   2094        ValOperandId rhsId = cacheIRReader.valOperandId();
   2095        JSObject* obj = reinterpret_cast<JSObject*>(READ_REG(objId.id()));
   2096        Value rhs = READ_VALUE_REG(rhsId.id());
   2097        ArrayObject* aobj = &obj->as<ArrayObject>();
   2098        uint32_t initLength = aobj->getDenseInitializedLength();
   2099        if (aobj->length() != initLength) {
   2100          FAIL_IC();
   2101        }
   2102        if (initLength >= aobj->getDenseCapacity()) {
   2103          if (!NativeObject::addDenseElementPure(
   2104                  ctx.frameMgr.cxForLocalUseOnly(), aobj)) {
   2105            FAIL_IC();
   2106          }
   2107        }
   2108        aobj->setDenseInitializedLength(initLength + 1);
   2109        aobj->setLengthToInitializedLength();
   2110        aobj->initDenseElement(initLength, rhs);
   2111        retValue = Int32Value(initLength + 1).asRawBits();
   2112        PREDICT_RETURN();
   2113        DISPATCH_CACHEOP();
   2114      }
   2115 
   2116      CACHEOP_CASE(IsObjectResult) {
   2117        ValOperandId inputId = cacheIRReader.valOperandId();
   2118        Value val = READ_VALUE_REG(inputId.id());
   2119        retValue = BooleanValue(val.isObject()).asRawBits();
   2120        PREDICT_RETURN();
   2121        DISPATCH_CACHEOP();
   2122      }
   2123 
   2124      CACHEOP_CASE(Int32MinMax) {
   2125        bool isMax = cacheIRReader.readBool();
   2126        Int32OperandId firstId = cacheIRReader.int32OperandId();
   2127        Int32OperandId secondId = cacheIRReader.int32OperandId();
   2128        Int32OperandId resultId = cacheIRReader.int32OperandId();
   2129        BOUNDSCHECK(resultId);
   2130        int32_t lhs = int32_t(READ_REG(firstId.id()));
   2131        int32_t rhs = int32_t(READ_REG(secondId.id()));
   2132        int32_t result = ((lhs > rhs) ^ isMax) ? rhs : lhs;
   2133        WRITE_REG(resultId.id(), result, INT32);
   2134        DISPATCH_CACHEOP();
   2135      }
   2136 
   2137      CACHEOP_CASE(StoreTypedArrayElement) {
   2138        auto args = cacheIRReader.argsForStoreTypedArrayElement();
   2139        JSObject* obj = reinterpret_cast<JSObject*>(READ_REG(args.objId.id()));
   2140        uintptr_t index = uintptr_t(READ_REG(args.indexId.id()));
   2141        uint64_t rhs = READ_REG(args.rhsId);
   2142        if (obj->as<TypedArrayObject>().length().isNothing()) {
   2143          FAIL_IC();
   2144        }
   2145        if (index >= obj->as<TypedArrayObject>().length().value()) {
   2146          if (!args.handleOOB) {
   2147            FAIL_IC();
   2148          }
   2149        } else {
   2150          Value v;
   2151          switch (args.elementType) {
   2152            case Scalar::Int8:
   2153            case Scalar::Uint8:
   2154            case Scalar::Int16:
   2155            case Scalar::Uint16:
   2156            case Scalar::Int32:
   2157            case Scalar::Uint32:
   2158            case Scalar::Uint8Clamped:
   2159              v = Int32Value(rhs);
   2160              break;
   2161 
   2162            case Scalar::Float16:
   2163            case Scalar::Float32:
   2164            case Scalar::Float64:
   2165              v = Value::fromRawBits(rhs);
   2166              MOZ_ASSERT(v.isNumber());
   2167              break;
   2168 
   2169            case Scalar::BigInt64:
   2170            case Scalar::BigUint64:
   2171              v = BigIntValue(reinterpret_cast<JS::BigInt*>(rhs));
   2172              break;
   2173 
   2174            case Scalar::MaxTypedArrayViewType:
   2175            case Scalar::Int64:
   2176            case Scalar::Simd128:
   2177              MOZ_CRASH("Unsupported TypedArray type");
   2178          }
   2179 
   2180          // SetTypedArrayElement doesn't do anything that can actually GC or
   2181          // need a new context when the value can only be Int32, Double, or
   2182          // BigInt, as the above switch statement enforces.
   2183          FakeRooted<TypedArrayObject*> obj0(nullptr,
   2184                                             &obj->as<TypedArrayObject>());
   2185          FakeRooted<Value> value0(nullptr, v);
   2186          ObjectOpResult result;
   2187          MOZ_ASSERT(args.elementType == obj0->type());
   2188          MOZ_ALWAYS_TRUE(SetTypedArrayElement(ctx.frameMgr.cxForLocalUseOnly(),
   2189                                               obj0, index, value0, result));
   2190          MOZ_ALWAYS_TRUE(result.ok());
   2191        }
   2192        DISPATCH_CACHEOP();
   2193      }
   2194 
   2195      CACHEOP_CASE(LoadTypedArrayElementExistsResult) {
   2196        auto args = cacheIRReader.argsForLoadTypedArrayElementExistsResult();
   2197        JSObject* obj = reinterpret_cast<JSObject*>(READ_REG(args.objId.id()));
   2198        uintptr_t index = uintptr_t(READ_REG(args.indexId.id()));
   2199        if (obj->as<TypedArrayObject>().length().isNothing()) {
   2200          FAIL_IC();
   2201        }
   2202        retValue =
   2203            BooleanValue(index < obj->as<TypedArrayObject>().length().value())
   2204                .asRawBits();
   2205        DISPATCH_CACHEOP();
   2206      }
   2207 
   2208      CACHEOP_CASE(LoadTypedArrayElementResult) {
   2209        auto args = cacheIRReader.argsForLoadTypedArrayElementResult();
   2210        JSObject* obj = reinterpret_cast<JSObject*>(READ_REG(args.objId.id()));
   2211        uintptr_t index = uintptr_t(READ_REG(args.indexId.id()));
   2212        if (obj->as<TypedArrayObject>().length().isNothing()) {
   2213          FAIL_IC();
   2214        }
   2215        if (index >= obj->as<TypedArrayObject>().length().value()) {
   2216          FAIL_IC();
   2217        }
   2218        Value v;
   2219        if (!obj->as<TypedArrayObject>().getElementPure(index, &v)) {
   2220          FAIL_IC();
   2221        }
   2222        if (args.forceDoubleForUint32) {
   2223          if (v.isInt32()) {
   2224            v.setNumber(v.toInt32());
   2225          }
   2226        }
   2227        retValue = v.asRawBits();
   2228        PREDICT_RETURN();
   2229        DISPATCH_CACHEOP();
   2230      }
   2231 
   2232      CACHEOP_CASE(CallInt32ToString) {
   2233        Int32OperandId inputId = cacheIRReader.int32OperandId();
   2234        StringOperandId resultId = cacheIRReader.stringOperandId();
   2235        BOUNDSCHECK(resultId);
   2236        int32_t input = int32_t(READ_REG(inputId.id()));
   2237        JSLinearString* str =
   2238            Int32ToStringPure(ctx.frameMgr.cxForLocalUseOnly(), input);
   2239        if (str) {
   2240          WRITE_REG(resultId.id(), reinterpret_cast<uintptr_t>(str), STRING);
   2241        } else {
   2242          FAIL_IC();
   2243        }
   2244        DISPATCH_CACHEOP();
   2245      }
   2246 
   2247      CACHEOP_CASE(CallScriptedFunction)
   2248      CACHEOP_CASE_FALLTHROUGH(CallNativeFunction) {
   2249        bool isNative = cacheop == CacheOp::CallNativeFunction;
   2250        TRACE_PRINTF("CallScriptedFunction / CallNativeFunction (native: %d)\n",
   2251                     isNative);
   2252        ObjOperandId calleeId = cacheIRReader.objOperandId();
   2253        Int32OperandId argcId = cacheIRReader.int32OperandId();
   2254        CallFlags flags = cacheIRReader.callFlags();
   2255        uint32_t argcFixed = cacheIRReader.uint32Immediate();
   2256        bool ignoresRv = false;
   2257        if (isNative) {
   2258          ignoresRv = cacheIRReader.readBool();
   2259        }
   2260 
   2261        TRACE_PRINTF("isConstructing = %d needsUninitializedThis = %d\n",
   2262                     int(flags.isConstructing()),
   2263                     int(flags.needsUninitializedThis()));
   2264 
   2265        JSFunction* callee =
   2266            reinterpret_cast<JSFunction*>(READ_REG(calleeId.id()));
   2267        uint32_t argc = uint32_t(READ_REG(argcId.id()));
   2268        (void)argcFixed;
   2269 
   2270        if (!isNative) {
   2271          if (!callee->hasBaseScript() ||
   2272              !callee->baseScript()->hasBytecode() ||
   2273              !callee->baseScript()->hasJitScript()) {
   2274            FAIL_IC();
   2275          }
   2276        }
   2277 
   2278        // For now, fail any different-realm cases.
   2279        if (!flags.isSameRealm()) {
   2280          TRACE_PRINTF("failing: not same realm\n");
   2281          FAIL_IC();
   2282        }
   2283        // And support only "standard" arg formats.
   2284        if (flags.getArgFormat() != CallFlags::Standard) {
   2285          TRACE_PRINTF("failing: not standard arg format\n");
   2286          FAIL_IC();
   2287        }
   2288 
   2289        // Fail constructing on a non-constructor callee.
   2290        if (flags.isConstructing() && !callee->isConstructor()) {
   2291          TRACE_PRINTF("failing: constructing a non-constructor\n");
   2292          FAIL_IC();
   2293        }
   2294 
   2295        // Handle arg-underflow (but only for scripted targets).
   2296        uint32_t undefArgs = (!isNative && (argc < callee->nargs()))
   2297                                 ? (callee->nargs() - argc)
   2298                                 : 0;
   2299        uint32_t extra = 1 + flags.isConstructing() + isNative;
   2300        uint32_t totalArgs = argc + undefArgs + extra;
   2301        StackVal* origArgs = ctx.sp();
   2302 
   2303        {
   2304          PUSH_IC_FRAME();
   2305 
   2306          if (!ctx.stack.check(sp, sizeof(StackVal) * (totalArgs + 6))) {
   2307            ReportOverRecursed(ctx.frameMgr.cxForLocalUseOnly());
   2308            ctx.error = PBIResult::Error;
   2309            return IC_ERROR_SENTINEL();
   2310          }
   2311 
   2312          // Create `this` if we are constructing and this is a
   2313          // scripted function.
   2314          Value thisVal;
   2315          // Force JIT scripts to stick around, so we don't have to
   2316          // fail the IC after GC'ing. This is critical, because
   2317          // `stub` is not rooted (we don't have a BaselineStub frame
   2318          // in PBL, only an exit frame directly below a baseline
   2319          // function frame), so we cannot fall back to the next stub
   2320          // once we pass this point.
   2321          AutoKeepJitScripts keepJitScripts(cx);
   2322          if (flags.isConstructing() && !isNative) {
   2323            if (flags.needsUninitializedThis()) {
   2324              thisVal = MagicValue(JS_UNINITIALIZED_LEXICAL);
   2325            } else {
   2326              ReservedRooted<JSObject*> calleeObj(&ctx.state.obj0, callee);
   2327              ReservedRooted<JSObject*> newTargetRooted(
   2328                  &ctx.state.obj1, &origArgs[0].asValue().toObject());
   2329              ReservedRooted<Value> result(&ctx.state.value0);
   2330              if (!CreateThisFromIC(cx, calleeObj, newTargetRooted, &result)) {
   2331                ctx.error = PBIResult::Error;
   2332                return IC_ERROR_SENTINEL();
   2333              }
   2334              thisVal = result;
   2335              // `callee` may have moved.
   2336              callee = &calleeObj->as<JSFunction>();
   2337            }
   2338          }
   2339          // This will not be an Exit frame but a BaselineStub frame, so
   2340          // replace the ExitFrameType with the ICStub pointer.
   2341          POPNNATIVE(1);
   2342          PUSHNATIVE(StackValNative(cstub));
   2343 
   2344          // `origArgs` is (in index order, i.e. increasing address order)
   2345          // - normal, scripted: arg[argc-1] ... arg[0] thisv
   2346          // - ctor, scripted: newTarget arg[argc-1] ... arg[0] thisv
   2347          // - normal, native: arg[argc-1] ... arg[0] thisv callee
   2348          // - ctor, native: newTarget arg[argc-1] ... arg[0] thisv callee
   2349          //
   2350          // and we need to push them in reverse order -- from sp
   2351          // upward (in increasing address order) -- with args filled
   2352          // in with `undefined` if fewer than the number of formals.
   2353 
   2354          // Push args: newTarget if constructing, extra undef's added
   2355          // if underflow, then original args, and `callee` if
   2356          // native. Replace `this` if constructing.
   2357          if (flags.isConstructing()) {
   2358            PUSH(origArgs[0]);
   2359            origArgs++;
   2360          }
   2361          for (uint32_t i = 0; i < undefArgs; i++) {
   2362            PUSH(StackVal(UndefinedValue()));
   2363          }
   2364          for (uint32_t i = 0; i < argc + 1 + isNative; i++) {
   2365            PUSH(origArgs[i]);
   2366          }
   2367          if (flags.isConstructing() && !isNative) {
   2368            sp[0] = StackVal(thisVal);
   2369          }
   2370          Value* args = reinterpret_cast<Value*>(sp);
   2371 
   2372          if (isNative) {
   2373            PUSHNATIVE(StackValNative(argc));
   2374            PUSHNATIVE(
   2375                StackValNative(MakeFrameDescriptor(FrameType::BaselineStub)));
   2376 
   2377            // We *also* need an exit frame (the native baseline
   2378            // execution would invoke a trampoline here).
   2379            StackVal* trampolinePrevFP = ctx.stack.fp;
   2380            PUSHNATIVE(StackValNative(nullptr));  // fake return address.
   2381            PUSHNATIVE(StackValNative(ctx.stack.fp));
   2382            ctx.stack.fp = sp;
   2383            PUSHNATIVE(StackValNative(
   2384                uint32_t(flags.isConstructing() ? ExitFrameType::ConstructNative
   2385                                                : ExitFrameType::CallNative)));
   2386            cx.getCx()->activation()->asJit()->setJSExitFP(
   2387                reinterpret_cast<uint8_t*>(ctx.stack.fp));
   2388            cx.getCx()->portableBaselineStack().top =
   2389                reinterpret_cast<void*>(sp);
   2390 
   2391            JSNative native = ignoresRv
   2392                                  ? callee->jitInfo()->ignoresReturnValueMethod
   2393                                  : callee->native();
   2394            bool success = native(cx, argc, args);
   2395 
   2396            ctx.stack.fp = trampolinePrevFP;
   2397            POPNNATIVE(4);
   2398 
   2399            if (!success) {
   2400              ctx.error = PBIResult::Error;
   2401              return IC_ERROR_SENTINEL();
   2402            }
   2403            retValue = args[0].asRawBits();
   2404          } else {
   2405            TRACE_PRINTF("pushing callee: %p\n", callee);
   2406            PUSHNATIVE(
   2407                StackValNative(CalleeToToken(callee, flags.isConstructing())));
   2408 
   2409            PUSHNATIVE(StackValNative(
   2410                MakeFrameDescriptorForJitCall(FrameType::BaselineStub, argc)));
   2411 
   2412            JSScript* script = callee->nonLazyScript();
   2413            jsbytecode* pc = script->code();
   2414            ImmutableScriptData* isd = script->immutableScriptData();
   2415            PBIResult result;
   2416            Value ret;
   2417            result = PortableBaselineInterpret<false, kHybridICsInterp>(
   2418                cx, ctx.state, ctx.stack, sp,
   2419                /* envChain = */ nullptr, &ret, pc, isd, nullptr, nullptr,
   2420                nullptr, PBIResult::Ok);
   2421            if (result != PBIResult::Ok) {
   2422              ctx.error = result;
   2423              return IC_ERROR_SENTINEL();
   2424            }
   2425            if (flags.isConstructing() && !ret.isObject()) {
   2426              ret = args[0];
   2427            }
   2428            retValue = ret.asRawBits();
   2429          }
   2430        }
   2431 
   2432        PREDICT_RETURN();
   2433        DISPATCH_CACHEOP();
   2434      }
   2435 
   2436      CACHEOP_CASE(CallScriptedGetterResult)
   2437      CACHEOP_CASE_FALLTHROUGH(CallScriptedSetter) {
   2438        bool isSetter = cacheop == CacheOp::CallScriptedSetter;
   2439        ObjOperandId receiverId = cacheIRReader.objOperandId();
   2440        ObjOperandId calleeId = cacheIRReader.objOperandId();
   2441        ValOperandId rhsId =
   2442            isSetter ? cacheIRReader.valOperandId() : ValOperandId();
   2443        bool sameRealm = cacheIRReader.readBool();
   2444        uint32_t nargsAndFlagsOffset = cacheIRReader.stubOffset();
   2445        (void)nargsAndFlagsOffset;
   2446 
   2447        Value receiver = isSetter ? ObjectValue(*reinterpret_cast<JSObject*>(
   2448                                        READ_REG(receiverId.id())))
   2449                                  : READ_VALUE_REG(receiverId.id());
   2450        JSFunction* callee =
   2451            reinterpret_cast<JSFunction*>(READ_REG(calleeId.id()));
   2452        Value rhs = isSetter ? READ_VALUE_REG(rhsId.id()) : UndefinedValue();
   2453 
   2454        if (!sameRealm) {
   2455          FAIL_IC();
   2456        }
   2457 
   2458        if (!callee->hasBaseScript() || !callee->baseScript()->hasBytecode() ||
   2459            !callee->baseScript()->hasJitScript()) {
   2460          FAIL_IC();
   2461        }
   2462 
   2463        // For now, fail any arg-underflow case.
   2464        if (callee->nargs() != isSetter ? 1 : 0) {
   2465          TRACE_PRINTF(
   2466              "failing: getter/setter does not have exactly 0/1 arg (has %d "
   2467              "instead)\n",
   2468              int(callee->nargs()));
   2469          FAIL_IC();
   2470        }
   2471 
   2472        {
   2473          PUSH_IC_FRAME();
   2474 
   2475          if (!ctx.stack.check(sp, sizeof(StackVal) * 8)) {
   2476            ReportOverRecursed(ctx.frameMgr.cxForLocalUseOnly());
   2477            ctx.error = PBIResult::Error;
   2478            return IC_ERROR_SENTINEL();
   2479          }
   2480 
   2481          // This will not be an Exit frame but a BaselineStub frame, so
   2482          // replace the ExitFrameType with the ICStub pointer.
   2483          POPNNATIVE(1);
   2484          PUSHNATIVE(StackValNative(cstub));
   2485 
   2486          if (isSetter) {
   2487            // Push arg: value.
   2488            PUSH(StackVal(rhs));
   2489          }
   2490          TRACE_PRINTF("pushing receiver: %" PRIx64 "\n", receiver.asRawBits());
   2491          // Push thisv: receiver.
   2492          PUSH(StackVal(receiver));
   2493 
   2494          TRACE_PRINTF("pushing callee: %p\n", callee);
   2495          PUSHNATIVE(StackValNative(
   2496              CalleeToToken(callee, /* isConstructing = */ false)));
   2497 
   2498          PUSHNATIVE(StackValNative(MakeFrameDescriptorForJitCall(
   2499              FrameType::BaselineStub, /* argc = */ isSetter ? 1 : 0)));
   2500 
   2501          JSScript* script = callee->nonLazyScript();
   2502          jsbytecode* pc = script->code();
   2503          ImmutableScriptData* isd = script->immutableScriptData();
   2504          PBIResult result;
   2505          Value ret;
   2506          result = PortableBaselineInterpret<false, kHybridICsInterp>(
   2507              cx, ctx.state, ctx.stack, sp, /* envChain = */ nullptr, &ret, pc,
   2508              isd, nullptr, nullptr, nullptr, PBIResult::Ok);
   2509          if (result != PBIResult::Ok) {
   2510            ctx.error = result;
   2511            return IC_ERROR_SENTINEL();
   2512          }
   2513          retValue = ret.asRawBits();
   2514        }
   2515 
   2516        PREDICT_RETURN();
   2517        DISPATCH_CACHEOP();
   2518      }
   2519 
   2520      CACHEOP_CASE(CallBoundScriptedFunction) {
   2521        ObjOperandId calleeId = cacheIRReader.objOperandId();
   2522        ObjOperandId targetId = cacheIRReader.objOperandId();
   2523        Int32OperandId argcId = cacheIRReader.int32OperandId();
   2524        CallFlags flags = cacheIRReader.callFlags();
   2525        uint32_t numBoundArgs = cacheIRReader.uint32Immediate();
   2526 
   2527        BoundFunctionObject* boundFunc =
   2528            reinterpret_cast<BoundFunctionObject*>(READ_REG(calleeId.id()));
   2529        JSFunction* callee = &boundFunc->getTarget()->as<JSFunction>();
   2530        uint32_t argc = uint32_t(READ_REG(argcId.id()));
   2531        (void)targetId;
   2532 
   2533        if (!callee->hasBaseScript() || !callee->baseScript()->hasBytecode() ||
   2534            !callee->baseScript()->hasJitScript()) {
   2535          FAIL_IC();
   2536        }
   2537 
   2538        // For now, fail any constructing or different-realm cases.
   2539        if (flags.isConstructing()) {
   2540          TRACE_PRINTF("failing: constructing\n");
   2541          FAIL_IC();
   2542        }
   2543        if (!flags.isSameRealm()) {
   2544          TRACE_PRINTF("failing: not same realm\n");
   2545          FAIL_IC();
   2546        }
   2547        // And support only "standard" arg formats.
   2548        if (flags.getArgFormat() != CallFlags::Standard) {
   2549          TRACE_PRINTF("failing: not standard arg format\n");
   2550          FAIL_IC();
   2551        }
   2552 
   2553        uint32_t totalArgs = numBoundArgs + argc;
   2554 
   2555        // For now, fail any arg-underflow case.
   2556        if (totalArgs < callee->nargs()) {
   2557          TRACE_PRINTF("failing: too few args\n");
   2558          FAIL_IC();
   2559        }
   2560 
   2561        StackVal* origArgs = ctx.sp();
   2562 
   2563        {
   2564          PUSH_IC_FRAME();
   2565 
   2566          if (!ctx.stack.check(sp, sizeof(StackVal) * (totalArgs + 6))) {
   2567            ReportOverRecursed(ctx.frameMgr.cxForLocalUseOnly());
   2568            ctx.error = PBIResult::Error;
   2569            return IC_ERROR_SENTINEL();
   2570          }
   2571 
   2572          // This will not be an Exit frame but a BaselineStub frame, so
   2573          // replace the ExitFrameType with the ICStub pointer.
   2574          POPNNATIVE(1);
   2575          PUSHNATIVE(StackValNative(cstub));
   2576 
   2577          // Push args.
   2578          for (uint32_t i = 0; i < argc; i++) {
   2579            PUSH(origArgs[i]);
   2580          }
   2581          // Push bound args.
   2582          for (uint32_t i = 0; i < numBoundArgs; i++) {
   2583            PUSH(StackVal(boundFunc->getBoundArg(numBoundArgs - 1 - i)));
   2584          }
   2585          // Push bound `this`.
   2586          PUSH(StackVal(boundFunc->getBoundThis()));
   2587 
   2588          TRACE_PRINTF("pushing callee: %p\n", callee);
   2589          PUSHNATIVE(StackValNative(
   2590              CalleeToToken(callee, /* isConstructing = */ false)));
   2591 
   2592          PUSHNATIVE(StackValNative(MakeFrameDescriptorForJitCall(
   2593              FrameType::BaselineStub, totalArgs)));
   2594 
   2595          JSScript* script = callee->nonLazyScript();
   2596          jsbytecode* pc = script->code();
   2597          ImmutableScriptData* isd = script->immutableScriptData();
   2598          PBIResult result;
   2599          Value ret;
   2600          result = PortableBaselineInterpret<false, kHybridICsInterp>(
   2601              cx, ctx.state, ctx.stack, sp, /* envChain = */ nullptr, &ret, pc,
   2602              isd, nullptr, nullptr, nullptr, PBIResult::Ok);
   2603          if (result != PBIResult::Ok) {
   2604            ctx.error = result;
   2605            return IC_ERROR_SENTINEL();
   2606          }
   2607          retValue = ret.asRawBits();
   2608        }
   2609 
   2610        PREDICT_RETURN();
   2611        DISPATCH_CACHEOP();
   2612      }
   2613 
   2614      CACHEOP_CASE(MetaScriptedThisShape) {
   2615        // This op is only metadata for the Warp Transpiler and should be
   2616        // ignored.
   2617        cacheIRReader.argsForMetaScriptedThisShape();
   2618        PREDICT_NEXT(CallScriptedFunction);
   2619        DISPATCH_CACHEOP();
   2620      }
   2621 
   2622      CACHEOP_CASE(LoadFixedSlotResult)
   2623      CACHEOP_CASE_FALLTHROUGH(LoadFixedSlotTypedResult) {
   2624        ObjOperandId objId = cacheIRReader.objOperandId();
   2625        uint32_t offsetOffset = cacheIRReader.stubOffset();
   2626        if (cacheop == CacheOp::LoadFixedSlotTypedResult) {
   2627          // Type is unused here.
   2628          (void)cacheIRReader.valueType();
   2629        }
   2630        uintptr_t offset = stubInfo->getStubRawInt32(cstub, offsetOffset);
   2631        NativeObject* nobj =
   2632            reinterpret_cast<NativeObject*>(READ_REG(objId.id()));
   2633        Value* slot = reinterpret_cast<Value*>(
   2634            reinterpret_cast<uintptr_t>(nobj) + offset);
   2635        TRACE_PRINTF(
   2636            "LoadFixedSlotResult: obj %p offsetOffset %d offset %d slotPtr %p "
   2637            "slot %" PRIx64 "\n",
   2638            nobj, int(offsetOffset), int(offset), slot, slot->asRawBits());
   2639        retValue = slot->asRawBits();
   2640        PREDICT_RETURN();
   2641        DISPATCH_CACHEOP();
   2642      }
   2643 
   2644      CACHEOP_CASE(LoadDynamicSlotResult) {
   2645        ObjOperandId objId = cacheIRReader.objOperandId();
   2646        uint32_t offsetOffset = cacheIRReader.stubOffset();
   2647        uintptr_t offset = stubInfo->getStubRawInt32(cstub, offsetOffset);
   2648        NativeObject* nobj =
   2649            reinterpret_cast<NativeObject*>(READ_REG(objId.id()));
   2650        HeapSlot* slots = nobj->getSlotsUnchecked();
   2651        retValue = slots[offset / sizeof(Value)].get().asRawBits();
   2652        PREDICT_RETURN();
   2653        DISPATCH_CACHEOP();
   2654      }
   2655 
   2656      CACHEOP_CASE(LoadDenseElementResult) {
   2657        ObjOperandId objId = cacheIRReader.objOperandId();
   2658        Int32OperandId indexId = cacheIRReader.int32OperandId();
   2659        bool expectPackedElements = cacheIRReader.readBool();
   2660        NativeObject* nobj =
   2661            reinterpret_cast<NativeObject*>(READ_REG(objId.id()));
   2662        ObjectElements* elems = nobj->getElementsHeader();
   2663        int32_t index = int32_t(READ_REG(indexId.id()));
   2664        if (index < 0 || uint32_t(index) >= nobj->getDenseInitializedLength()) {
   2665          FAIL_IC();
   2666        }
   2667        if (expectPackedElements && !elems->isPacked()) {
   2668          FAIL_IC();
   2669        }
   2670        HeapSlot* slot = &elems->elements()[index];
   2671        Value val = slot->get();
   2672        if (!expectPackedElements && val.isMagic()) {
   2673          FAIL_IC();
   2674        }
   2675        retValue = val.asRawBits();
   2676        PREDICT_RETURN();
   2677        DISPATCH_CACHEOP();
   2678      }
   2679 
   2680      CACHEOP_CASE(LoadDenseElementHoleResult) {
   2681        ObjOperandId objId = cacheIRReader.objOperandId();
   2682        Int32OperandId indexId = cacheIRReader.int32OperandId();
   2683        NativeObject* nobj =
   2684            reinterpret_cast<NativeObject*>(READ_REG(objId.id()));
   2685        ObjectElements* elems = nobj->getElementsHeader();
   2686        int32_t index = int32_t(READ_REG(indexId.id()));
   2687        if (index < 0 || uint32_t(index) >= nobj->getDenseInitializedLength()) {
   2688          FAIL_IC();
   2689        }
   2690        HeapSlot* slot = &elems->elements()[index];
   2691        Value val = slot->get();
   2692        if (val.isMagic()) {
   2693          val.setUndefined();
   2694        }
   2695        retValue = val.asRawBits();
   2696        PREDICT_RETURN();
   2697        DISPATCH_CACHEOP();
   2698      }
   2699 
   2700      CACHEOP_CASE(LoadDenseElementExistsResult) {
   2701        ObjOperandId objId = cacheIRReader.objOperandId();
   2702        Int32OperandId indexId = cacheIRReader.int32OperandId();
   2703        NativeObject* nobj =
   2704            reinterpret_cast<NativeObject*>(READ_REG(objId.id()));
   2705        ObjectElements* elems = nobj->getElementsHeader();
   2706        int32_t index = int32_t(READ_REG(indexId.id()));
   2707        if (index < 0 || uint32_t(index) >= nobj->getDenseInitializedLength()) {
   2708          FAIL_IC();
   2709        }
   2710        HeapSlot* slot = &elems->elements()[index];
   2711        Value val = slot->get();
   2712        if (val.isMagic()) {
   2713          FAIL_IC();
   2714        }
   2715        retValue = BooleanValue(true).asRawBits();
   2716        PREDICT_RETURN();
   2717        DISPATCH_CACHEOP();
   2718      }
   2719 
   2720      CACHEOP_CASE(LoadDenseElementHoleExistsResult) {
   2721        ObjOperandId objId = cacheIRReader.objOperandId();
   2722        Int32OperandId indexId = cacheIRReader.int32OperandId();
   2723        NativeObject* nobj =
   2724            reinterpret_cast<NativeObject*>(READ_REG(objId.id()));
   2725        ObjectElements* elems = nobj->getElementsHeader();
   2726        int32_t index = int32_t(READ_REG(indexId.id()));
   2727        if (index < 0 || uint32_t(index) >= nobj->getDenseInitializedLength()) {
   2728          retValue = BooleanValue(false).asRawBits();
   2729        } else {
   2730          HeapSlot* slot = &elems->elements()[index];
   2731          Value val = slot->get();
   2732          retValue = BooleanValue(!val.isMagic()).asRawBits();
   2733        }
   2734        PREDICT_RETURN();
   2735        DISPATCH_CACHEOP();
   2736      }
   2737 
   2738      CACHEOP_CASE(GuardIndexIsNotDenseElement) {
   2739        ObjOperandId objId = cacheIRReader.objOperandId();
   2740        Int32OperandId indexId = cacheIRReader.int32OperandId();
   2741        NativeObject* nobj =
   2742            reinterpret_cast<NativeObject*>(READ_REG(objId.id()));
   2743        ObjectElements* elems = nobj->getElementsHeader();
   2744        int32_t index = int32_t(READ_REG(indexId.id()));
   2745        if (index < 0 || uint32_t(index) >= nobj->getDenseInitializedLength()) {
   2746          // OK -- not in the dense index range.
   2747        } else {
   2748          HeapSlot* slot = &elems->elements()[index];
   2749          Value val = slot->get();
   2750          if (!val.isMagic()) {
   2751            // Not a magic value -- not the hole, so guard fails.
   2752            FAIL_IC();
   2753          }
   2754        }
   2755        DISPATCH_CACHEOP();
   2756      }
   2757 
   2758      CACHEOP_CASE(LoadInt32ArrayLengthResult) {
   2759        ObjOperandId objId = cacheIRReader.objOperandId();
   2760        ArrayObject* aobj =
   2761            reinterpret_cast<ArrayObject*>(READ_REG(objId.id()));
   2762        uint32_t length = aobj->length();
   2763        if (length > uint32_t(INT32_MAX)) {
   2764          FAIL_IC();
   2765        }
   2766        retValue = Int32Value(length).asRawBits();
   2767        PREDICT_RETURN();
   2768        DISPATCH_CACHEOP();
   2769      }
   2770 
   2771      CACHEOP_CASE(LoadInt32ArrayLength) {
   2772        ObjOperandId objId = cacheIRReader.objOperandId();
   2773        Int32OperandId resultId = cacheIRReader.int32OperandId();
   2774        BOUNDSCHECK(resultId);
   2775        ArrayObject* aobj =
   2776            reinterpret_cast<ArrayObject*>(READ_REG(objId.id()));
   2777        uint32_t length = aobj->length();
   2778        if (length > uint32_t(INT32_MAX)) {
   2779          FAIL_IC();
   2780        }
   2781        WRITE_REG(resultId.id(), length, INT32);
   2782        DISPATCH_CACHEOP();
   2783      }
   2784 
   2785      CACHEOP_CASE(LoadArrayBufferByteLengthInt32Result) {
   2786        ObjOperandId objId = cacheIRReader.objOperandId();
   2787        ArrayBufferObject* abo =
   2788            reinterpret_cast<ArrayBufferObject*>(READ_REG(objId.id()));
   2789        size_t len = abo->byteLength();
   2790        if (len > size_t(INT32_MAX)) {
   2791          FAIL_IC();
   2792        }
   2793        retValue = Int32Value(int32_t(len)).asRawBits();
   2794        PREDICT_RETURN();
   2795        DISPATCH_CACHEOP();
   2796      }
   2797 
   2798      CACHEOP_CASE(LoadArrayBufferByteLengthDoubleResult) {
   2799        ObjOperandId objId = cacheIRReader.objOperandId();
   2800        ArrayBufferObject* abo =
   2801            reinterpret_cast<ArrayBufferObject*>(READ_REG(objId.id()));
   2802        size_t len = abo->byteLength();
   2803        retValue = DoubleValue(double(len)).asRawBits();
   2804        PREDICT_RETURN();
   2805        DISPATCH_CACHEOP();
   2806      }
   2807 
   2808      CACHEOP_CASE(LoadArrayBufferViewLengthInt32Result) {
   2809        ObjOperandId objId = cacheIRReader.objOperandId();
   2810        ArrayBufferViewObject* abvo =
   2811            reinterpret_cast<ArrayBufferViewObject*>(READ_REG(objId.id()));
   2812        size_t len = size_t(
   2813            abvo->getFixedSlot(ArrayBufferViewObject::LENGTH_SLOT).toPrivate());
   2814        if (len > size_t(INT32_MAX)) {
   2815          FAIL_IC();
   2816        }
   2817        retValue = Int32Value(int32_t(len)).asRawBits();
   2818        PREDICT_RETURN();
   2819        DISPATCH_CACHEOP();
   2820      }
   2821 
   2822      CACHEOP_CASE(LoadArrayBufferViewLengthDoubleResult) {
   2823        ObjOperandId objId = cacheIRReader.objOperandId();
   2824        ArrayBufferViewObject* abvo =
   2825            reinterpret_cast<ArrayBufferViewObject*>(READ_REG(objId.id()));
   2826        size_t len = size_t(
   2827            abvo->getFixedSlot(ArrayBufferViewObject::LENGTH_SLOT).toPrivate());
   2828        retValue = DoubleValue(double(len)).asRawBits();
   2829        PREDICT_RETURN();
   2830        DISPATCH_CACHEOP();
   2831      }
   2832 
   2833      CACHEOP_CASE(LoadArgumentsObjectArgResult) {
   2834        ObjOperandId objId = cacheIRReader.objOperandId();
   2835        Int32OperandId indexId = cacheIRReader.int32OperandId();
   2836        JSObject* obj = reinterpret_cast<JSObject*>(READ_REG(objId.id()));
   2837        uint32_t index = uint32_t(READ_REG(indexId.id()));
   2838        ArgumentsObject* args = &obj->as<ArgumentsObject>();
   2839        if (index >= args->initialLength() || args->hasOverriddenElement()) {
   2840          FAIL_IC();
   2841        }
   2842        if (args->argIsForwarded(index)) {
   2843          FAIL_IC();
   2844        }
   2845        retValue = args->arg(index).asRawBits();
   2846        DISPATCH_CACHEOP();
   2847      }
   2848 
   2849      CACHEOP_CASE(LinearizeForCharAccess) {
   2850        StringOperandId strId = cacheIRReader.stringOperandId();
   2851        Int32OperandId indexId = cacheIRReader.int32OperandId();
   2852        StringOperandId resultId = cacheIRReader.stringOperandId();
   2853        BOUNDSCHECK(resultId);
   2854        JSString* str = reinterpret_cast<JSLinearString*>(READ_REG(strId.id()));
   2855        (void)indexId;
   2856 
   2857        WRITE_REG(resultId.id(), reinterpret_cast<uintptr_t>(str), STRING);
   2858        if (str->isRope()) {
   2859          PUSH_IC_FRAME();
   2860          JSLinearString* result = LinearizeForCharAccess(cx, str);
   2861          if (!result) {
   2862            ctx.error = PBIResult::Error;
   2863            return IC_ERROR_SENTINEL();
   2864          }
   2865          WRITE_REG(resultId.id(), reinterpret_cast<uintptr_t>(result), STRING);
   2866        }
   2867        PREDICT_NEXT(LoadStringCharResult);
   2868        DISPATCH_CACHEOP();
   2869      }
   2870 
   2871      CACHEOP_CASE(LinearizeForCodePointAccess) {
   2872        StringOperandId strId = cacheIRReader.stringOperandId();
   2873        Int32OperandId indexId = cacheIRReader.int32OperandId();
   2874        StringOperandId resultId = cacheIRReader.stringOperandId();
   2875        BOUNDSCHECK(resultId);
   2876        JSString* str = reinterpret_cast<JSLinearString*>(READ_REG(strId.id()));
   2877        (void)indexId;
   2878 
   2879        WRITE_REG(resultId.id(), reinterpret_cast<uintptr_t>(str), STRING);
   2880        if (str->isRope()) {
   2881          PUSH_IC_FRAME();
   2882          JSLinearString* result = LinearizeForCharAccess(cx, str);
   2883          if (!result) {
   2884            ctx.error = PBIResult::Error;
   2885            return IC_ERROR_SENTINEL();
   2886          }
   2887          WRITE_REG(resultId.id(), reinterpret_cast<uintptr_t>(result), STRING);
   2888        }
   2889        PREDICT_NEXT(LoadStringCodePointResult);
   2890        DISPATCH_CACHEOP();
   2891      }
   2892 
   2893      CACHEOP_CASE(LoadStringCharResult)
   2894      CACHEOP_CASE_FALLTHROUGH(LoadStringAtResult) {
   2895        StringOperandId strId = cacheIRReader.stringOperandId();
   2896        Int32OperandId indexId = cacheIRReader.int32OperandId();
   2897        bool handleOOB = cacheIRReader.readBool();
   2898 
   2899        JSString* str = reinterpret_cast<JSLinearString*>(READ_REG(strId.id()));
   2900        int32_t index = int32_t(READ_REG(indexId.id()));
   2901        JSString* result = nullptr;
   2902        if (index < 0 || size_t(index) >= str->length()) {
   2903          if (handleOOB) {
   2904            if (cacheop == CacheOp::LoadStringCharResult) {
   2905              // Return an empty string.
   2906              retValue =
   2907                  StringValue(ctx.frameMgr.cxForLocalUseOnly()->names().empty_)
   2908                      .asRawBits();
   2909            } else {
   2910              // Return `undefined`.
   2911              retValue = UndefinedValue().asRawBits();
   2912            }
   2913          } else {
   2914            FAIL_IC();
   2915          }
   2916        } else {
   2917          char16_t c;
   2918          // Guaranteed to always work because this CacheIR op is
   2919          // always preceded by LinearizeForCharAccess.
   2920          MOZ_ALWAYS_TRUE(str->getChar(/* cx = */ nullptr, index, &c));
   2921          StaticStrings& sstr =
   2922              ctx.frameMgr.cxForLocalUseOnly()->staticStrings();
   2923          if (sstr.hasUnit(c)) {
   2924            result = sstr.getUnit(c);
   2925          } else {
   2926            PUSH_IC_FRAME();
   2927            result = StringFromCharCode(cx, c);
   2928            if (!result) {
   2929              ctx.error = PBIResult::Error;
   2930              return IC_ERROR_SENTINEL();
   2931            }
   2932          }
   2933          retValue = StringValue(result).asRawBits();
   2934        }
   2935        PREDICT_RETURN();
   2936        DISPATCH_CACHEOP();
   2937      }
   2938 
   2939      CACHEOP_CASE(LoadStringCharCodeResult) {
   2940        StringOperandId strId = cacheIRReader.stringOperandId();
   2941        Int32OperandId indexId = cacheIRReader.int32OperandId();
   2942        bool handleOOB = cacheIRReader.readBool();
   2943 
   2944        JSString* str = reinterpret_cast<JSLinearString*>(READ_REG(strId.id()));
   2945        int32_t index = int32_t(READ_REG(indexId.id()));
   2946        Value result;
   2947        if (index < 0 || size_t(index) >= str->length()) {
   2948          if (handleOOB) {
   2949            // Return NaN.
   2950            result = JS::NaNValue();
   2951          } else {
   2952            FAIL_IC();
   2953          }
   2954        } else {
   2955          char16_t c;
   2956          // Guaranteed to always work because this CacheIR op is
   2957          // always preceded by LinearizeForCharAccess.
   2958          MOZ_ALWAYS_TRUE(str->getChar(/* cx = */ nullptr, index, &c));
   2959          result = Int32Value(c);
   2960        }
   2961        retValue = result.asRawBits();
   2962        PREDICT_RETURN();
   2963        DISPATCH_CACHEOP();
   2964      }
   2965 
   2966      CACHEOP_CASE(LoadStringCodePointResult) {
   2967        StringOperandId strId = cacheIRReader.stringOperandId();
   2968        Int32OperandId indexId = cacheIRReader.int32OperandId();
   2969        bool handleOOB = cacheIRReader.readBool();
   2970 
   2971        JSString* str = reinterpret_cast<JSLinearString*>(READ_REG(strId.id()));
   2972        int32_t index = int32_t(READ_REG(indexId.id()));
   2973        Value result;
   2974        if (index < 0 || size_t(index) >= str->length()) {
   2975          if (handleOOB) {
   2976            // Return undefined.
   2977            result = UndefinedValue();
   2978          } else {
   2979            FAIL_IC();
   2980          }
   2981        } else {
   2982          char32_t c;
   2983          // Guaranteed to be always work because this CacheIR op is
   2984          // always preceded by LinearizeForCharAccess.
   2985          MOZ_ALWAYS_TRUE(str->getCodePoint(/* cx = */ nullptr, index, &c));
   2986          result = Int32Value(c);
   2987        }
   2988        retValue = result.asRawBits();
   2989        PREDICT_RETURN();
   2990        DISPATCH_CACHEOP();
   2991      }
   2992 
   2993      CACHEOP_CASE(LoadStringLengthResult) {
   2994        StringOperandId strId = cacheIRReader.stringOperandId();
   2995        JSString* str = reinterpret_cast<JSString*>(READ_REG(strId.id()));
   2996        size_t length = str->length();
   2997        if (length > size_t(INT32_MAX)) {
   2998          FAIL_IC();
   2999        }
   3000        retValue = Int32Value(length).asRawBits();
   3001        PREDICT_RETURN();
   3002        DISPATCH_CACHEOP();
   3003      }
   3004 
   3005      CACHEOP_CASE(LoadObjectResult) {
   3006        ObjOperandId objId = cacheIRReader.objOperandId();
   3007        retValue =
   3008            ObjectValue(*reinterpret_cast<JSObject*>(READ_REG(objId.id())))
   3009                .asRawBits();
   3010        PREDICT_RETURN();
   3011        DISPATCH_CACHEOP();
   3012      }
   3013 
   3014      CACHEOP_CASE(LoadStringResult) {
   3015        StringOperandId strId = cacheIRReader.stringOperandId();
   3016        retValue =
   3017            StringValue(reinterpret_cast<JSString*>(READ_REG(strId.id())))
   3018                .asRawBits();
   3019        PREDICT_RETURN();
   3020        DISPATCH_CACHEOP();
   3021      }
   3022 
   3023      CACHEOP_CASE(LoadSymbolResult) {
   3024        SymbolOperandId symId = cacheIRReader.symbolOperandId();
   3025        retValue =
   3026            SymbolValue(reinterpret_cast<JS::Symbol*>(READ_REG(symId.id())))
   3027                .asRawBits();
   3028        PREDICT_RETURN();
   3029        DISPATCH_CACHEOP();
   3030      }
   3031 
   3032      CACHEOP_CASE(LoadInt32Result) {
   3033        Int32OperandId valId = cacheIRReader.int32OperandId();
   3034        retValue = Int32Value(READ_REG(valId.id())).asRawBits();
   3035        PREDICT_RETURN();
   3036        DISPATCH_CACHEOP();
   3037      }
   3038 
   3039      CACHEOP_CASE(LoadDoubleResult) {
   3040        NumberOperandId valId = cacheIRReader.numberOperandId();
   3041        Value val = READ_VALUE_REG(valId.id());
   3042        if (val.isInt32()) {
   3043          val = DoubleValue(val.toInt32());
   3044        }
   3045        retValue = val.asRawBits();
   3046        PREDICT_RETURN();
   3047        DISPATCH_CACHEOP();
   3048      }
   3049 
   3050      CACHEOP_CASE(LoadBigIntResult) {
   3051        BigIntOperandId valId = cacheIRReader.bigIntOperandId();
   3052        retValue =
   3053            BigIntValue(reinterpret_cast<JS::BigInt*>(READ_REG(valId.id())))
   3054                .asRawBits();
   3055        PREDICT_RETURN();
   3056        DISPATCH_CACHEOP();
   3057      }
   3058 
   3059      CACHEOP_CASE(LoadBooleanResult) {
   3060        bool val = cacheIRReader.readBool();
   3061        retValue = BooleanValue(val).asRawBits();
   3062        PREDICT_RETURN();
   3063        DISPATCH_CACHEOP();
   3064      }
   3065 
   3066      CACHEOP_CASE(LoadInt32Constant) {
   3067        uint32_t valOffset = cacheIRReader.stubOffset();
   3068        Int32OperandId resultId = cacheIRReader.int32OperandId();
   3069        BOUNDSCHECK(resultId);
   3070        uint32_t value = stubInfo->getStubRawInt32(cstub, valOffset);
   3071        WRITE_REG(resultId.id(), value, INT32);
   3072        DISPATCH_CACHEOP();
   3073      }
   3074 
   3075      CACHEOP_CASE(LoadConstantStringResult) {
   3076        uint32_t strOffset = cacheIRReader.stubOffset();
   3077        JSString* str = reinterpret_cast<JSString*>(
   3078            stubInfo->getStubRawWord(cstub, strOffset));
   3079        retValue = StringValue(str).asRawBits();
   3080        PREDICT_RETURN();
   3081        DISPATCH_CACHEOP();
   3082      }
   3083 
   3084      CACHEOP_CASE(DoubleAddResult) {
   3085        NumberOperandId lhsId = cacheIRReader.numberOperandId();
   3086        NumberOperandId rhsId = cacheIRReader.numberOperandId();
   3087        Value lhs = READ_VALUE_REG(lhsId.id());
   3088        Value rhs = READ_VALUE_REG(rhsId.id());
   3089        retValue = DoubleValue(lhs.toNumber() + rhs.toNumber()).asRawBits();
   3090        PREDICT_RETURN();
   3091        DISPATCH_CACHEOP();
   3092      }
   3093 
   3094      CACHEOP_CASE(DoubleSubResult) {
   3095        NumberOperandId lhsId = cacheIRReader.numberOperandId();
   3096        NumberOperandId rhsId = cacheIRReader.numberOperandId();
   3097        Value lhs = READ_VALUE_REG(lhsId.id());
   3098        Value rhs = READ_VALUE_REG(rhsId.id());
   3099        retValue = DoubleValue(lhs.toNumber() - rhs.toNumber()).asRawBits();
   3100        PREDICT_RETURN();
   3101        DISPATCH_CACHEOP();
   3102      }
   3103 
   3104      CACHEOP_CASE(DoubleMulResult) {
   3105        NumberOperandId lhsId = cacheIRReader.numberOperandId();
   3106        NumberOperandId rhsId = cacheIRReader.numberOperandId();
   3107        Value lhs = READ_VALUE_REG(lhsId.id());
   3108        Value rhs = READ_VALUE_REG(rhsId.id());
   3109        retValue = DoubleValue(lhs.toNumber() * rhs.toNumber()).asRawBits();
   3110        PREDICT_RETURN();
   3111        DISPATCH_CACHEOP();
   3112      }
   3113 
   3114      CACHEOP_CASE(DoubleDivResult) {
   3115        NumberOperandId lhsId = cacheIRReader.numberOperandId();
   3116        NumberOperandId rhsId = cacheIRReader.numberOperandId();
   3117        Value lhs = READ_VALUE_REG(lhsId.id());
   3118        Value rhs = READ_VALUE_REG(rhsId.id());
   3119        retValue =
   3120            DoubleValue(NumberDiv(lhs.toNumber(), rhs.toNumber())).asRawBits();
   3121        PREDICT_RETURN();
   3122        DISPATCH_CACHEOP();
   3123      }
   3124 
   3125      CACHEOP_CASE(DoubleModResult) {
   3126        NumberOperandId lhsId = cacheIRReader.numberOperandId();
   3127        NumberOperandId rhsId = cacheIRReader.numberOperandId();
   3128        Value lhs = READ_VALUE_REG(lhsId.id());
   3129        Value rhs = READ_VALUE_REG(rhsId.id());
   3130        retValue =
   3131            DoubleValue(NumberMod(lhs.toNumber(), rhs.toNumber())).asRawBits();
   3132        PREDICT_RETURN();
   3133        DISPATCH_CACHEOP();
   3134      }
   3135 
   3136      CACHEOP_CASE(DoublePowResult) {
   3137        NumberOperandId lhsId = cacheIRReader.numberOperandId();
   3138        NumberOperandId rhsId = cacheIRReader.numberOperandId();
   3139        Value lhs = READ_VALUE_REG(lhsId.id());
   3140        Value rhs = READ_VALUE_REG(rhsId.id());
   3141        retValue =
   3142            DoubleValue(ecmaPow(lhs.toNumber(), rhs.toNumber())).asRawBits();
   3143        PREDICT_RETURN();
   3144        DISPATCH_CACHEOP();
   3145      }
   3146 
   3147 #define INT32_OP(name, op, extra_check)                    \
   3148  CACHEOP_CASE(Int32##name##Result) {                      \
   3149    Int32OperandId lhsId = cacheIRReader.int32OperandId(); \
   3150    Int32OperandId rhsId = cacheIRReader.int32OperandId(); \
   3151    int64_t lhs = int64_t(int32_t(READ_REG(lhsId.id())));  \
   3152    int64_t rhs = int64_t(int32_t(READ_REG(rhsId.id())));  \
   3153    extra_check;                                           \
   3154    int64_t result = lhs op rhs;                           \
   3155    if (result < INT32_MIN || result > INT32_MAX) {        \
   3156      FAIL_IC();                                           \
   3157    }                                                      \
   3158    retValue = Int32Value(int32_t(result)).asRawBits();    \
   3159    PREDICT_RETURN();                                      \
   3160    DISPATCH_CACHEOP();                                    \
   3161  }
   3162 
   3163      // clang-format off
   3164  INT32_OP(Add, +, {});
   3165  INT32_OP(Sub, -, {});
   3166      // clang-format on
   3167      INT32_OP(Mul, *, {
   3168        if (rhs * lhs == 0 && ((rhs < 0) ^ (lhs < 0))) {
   3169          FAIL_IC();
   3170        }
   3171      });
   3172      INT32_OP(Div, /, {
   3173        if (rhs == 0 || (lhs == INT32_MIN && rhs == -1)) {
   3174          FAIL_IC();
   3175        }
   3176        if (lhs == 0 && rhs < 0) {
   3177          FAIL_IC();
   3178        }
   3179        if (lhs % rhs != 0) {
   3180          FAIL_IC();
   3181        }
   3182      });
   3183      INT32_OP(Mod, %, {
   3184        if (rhs == 0 || (lhs == INT32_MIN && rhs == -1)) {
   3185          FAIL_IC();
   3186        }
   3187        if (lhs % rhs == 0 && lhs < 0) {
   3188          FAIL_IC();
   3189        }
   3190      });
   3191      // clang-format off
   3192  INT32_OP(BitOr, |, {});
   3193  INT32_OP(BitXor, ^, {});
   3194  INT32_OP(BitAnd, &, {});
   3195      // clang-format on
   3196 
   3197      CACHEOP_CASE(Int32PowResult) {
   3198        Int32OperandId lhsId = cacheIRReader.int32OperandId();
   3199        Int32OperandId rhsId = cacheIRReader.int32OperandId();
   3200        int64_t lhs = int64_t(int32_t(READ_REG(lhsId.id())));
   3201        uint64_t rhs = uint64_t(int32_t(READ_REG(rhsId.id())));
   3202        int64_t result;
   3203 
   3204        if (lhs == 1) {
   3205          result = 1;
   3206        } else if (rhs >= uint64_t(INT64_MIN)) {
   3207          FAIL_IC();
   3208        } else {
   3209          result = 1;
   3210          int64_t runningSquare = lhs;
   3211          while (rhs) {
   3212            if (rhs & 1) {
   3213              result *= runningSquare;
   3214              if (result > int64_t(INT32_MAX)) {
   3215                FAIL_IC();
   3216              }
   3217            }
   3218            rhs >>= 1;
   3219            if (rhs == 0) {
   3220              break;
   3221            }
   3222            runningSquare *= runningSquare;
   3223            if (runningSquare > int64_t(INT32_MAX)) {
   3224              FAIL_IC();
   3225            }
   3226          }
   3227        }
   3228 
   3229        retValue = Int32Value(int32_t(result)).asRawBits();
   3230        PREDICT_RETURN();
   3231        DISPATCH_CACHEOP();
   3232      }
   3233 
   3234      CACHEOP_CASE(Int32IncResult) {
   3235        Int32OperandId inputId = cacheIRReader.int32OperandId();
   3236        int64_t value = int64_t(int32_t(READ_REG(inputId.id())));
   3237        value++;
   3238        if (value > INT32_MAX) {
   3239          FAIL_IC();
   3240        }
   3241        retValue = Int32Value(int32_t(value)).asRawBits();
   3242        PREDICT_RETURN();
   3243        DISPATCH_CACHEOP();
   3244      }
   3245 
   3246      CACHEOP_CASE(Int32LeftShiftResult) {
   3247        Int32OperandId lhsId = cacheIRReader.int32OperandId();
   3248        Int32OperandId rhsId = cacheIRReader.int32OperandId();
   3249        int32_t lhs = int32_t(READ_REG(lhsId.id()));
   3250        int32_t rhs = int32_t(READ_REG(rhsId.id()));
   3251        int32_t result = lhs << (rhs & 0x1F);
   3252        retValue = Int32Value(result).asRawBits();
   3253        PREDICT_RETURN();
   3254        DISPATCH_CACHEOP();
   3255      }
   3256 
   3257      CACHEOP_CASE(Int32RightShiftResult) {
   3258        Int32OperandId lhsId = cacheIRReader.int32OperandId();
   3259        Int32OperandId rhsId = cacheIRReader.int32OperandId();
   3260        int32_t lhs = int32_t(READ_REG(lhsId.id()));
   3261        int32_t rhs = int32_t(READ_REG(rhsId.id()));
   3262        int32_t result = lhs >> (rhs & 0x1F);
   3263        retValue = Int32Value(result).asRawBits();
   3264        PREDICT_RETURN();
   3265        DISPATCH_CACHEOP();
   3266      }
   3267 
   3268      CACHEOP_CASE(Int32URightShiftResult) {
   3269        Int32OperandId lhsId = cacheIRReader.int32OperandId();
   3270        Int32OperandId rhsId = cacheIRReader.int32OperandId();
   3271        bool forceDouble = cacheIRReader.readBool();
   3272        (void)forceDouble;
   3273        uint32_t lhs = uint32_t(READ_REG(lhsId.id()));
   3274        int32_t rhs = int32_t(READ_REG(rhsId.id()));
   3275        uint32_t result = lhs >> (rhs & 0x1F);
   3276        retValue = (result >= 0x80000000)
   3277                       ? DoubleValue(double(result)).asRawBits()
   3278                       : Int32Value(int32_t(result)).asRawBits();
   3279        PREDICT_RETURN();
   3280        DISPATCH_CACHEOP();
   3281      }
   3282 
   3283      CACHEOP_CASE(Int32NotResult) {
   3284        Int32OperandId inputId = cacheIRReader.int32OperandId();
   3285        int32_t input = int32_t(READ_REG(inputId.id()));
   3286        retValue = Int32Value(~input).asRawBits();
   3287        PREDICT_RETURN();
   3288        DISPATCH_CACHEOP();
   3289      }
   3290 
   3291      CACHEOP_CASE(LoadInt32TruthyResult) {
   3292        ValOperandId inputId = cacheIRReader.valOperandId();
   3293        int32_t val = int32_t(READ_REG(inputId.id()));
   3294        retValue = BooleanValue(val != 0).asRawBits();
   3295        PREDICT_RETURN();
   3296        DISPATCH_CACHEOP();
   3297      }
   3298 
   3299      CACHEOP_CASE(LoadDoubleTruthyResult) {
   3300        NumberOperandId inputId = cacheIRReader.numberOperandId();
   3301        double input = READ_VALUE_REG(inputId.id()).toNumber();
   3302        // NaN is falsy, not truthy.
   3303        retValue = BooleanValue(input != 0.0 && !std::isnan(input)).asRawBits();
   3304        PREDICT_RETURN();
   3305        DISPATCH_CACHEOP();
   3306      }
   3307 
   3308      CACHEOP_CASE(LoadStringTruthyResult) {
   3309        StringOperandId strId = cacheIRReader.stringOperandId();
   3310        JSString* str = reinterpret_cast<JSLinearString*>(READ_REG(strId.id()));
   3311        retValue = BooleanValue(str->length() > 0).asRawBits();
   3312        PREDICT_RETURN();
   3313        DISPATCH_CACHEOP();
   3314      }
   3315 
   3316      CACHEOP_CASE(LoadObjectTruthyResult) {
   3317        ObjOperandId objId = cacheIRReader.objOperandId();
   3318        JSObject* obj = reinterpret_cast<JSObject*>(READ_REG(objId.id()));
   3319        const JSClass* cls = obj->getClass();
   3320        if (cls->isProxyObject()) {
   3321          FAIL_IC();
   3322        }
   3323        retValue = BooleanValue(!cls->emulatesUndefined()).asRawBits();
   3324        PREDICT_RETURN();
   3325        DISPATCH_CACHEOP();
   3326      }
   3327 
   3328      CACHEOP_CASE(LoadValueResult) {
   3329        uint32_t valOffset = cacheIRReader.stubOffset();
   3330        retValue = stubInfo->getStubRawInt64(cstub, valOffset);
   3331        PREDICT_RETURN();
   3332        DISPATCH_CACHEOP();
   3333      }
   3334 
   3335      CACHEOP_CASE(LoadOperandResult) {
   3336        ValOperandId inputId = cacheIRReader.valOperandId();
   3337        retValue = READ_REG(inputId.id());
   3338        PREDICT_RETURN();
   3339        DISPATCH_CACHEOP();
   3340      }
   3341 
   3342      CACHEOP_CASE(ConcatStringsResult) {
   3343        StringOperandId lhsId = cacheIRReader.stringOperandId();
   3344        StringOperandId rhsId = cacheIRReader.stringOperandId();
   3345        {
   3346          PUSH_IC_FRAME();
   3347          ReservedRooted<JSString*> lhs(
   3348              &ctx.state.str0,
   3349              reinterpret_cast<JSString*>(READ_REG(lhsId.id())));
   3350          ReservedRooted<JSString*> rhs(
   3351              &ctx.state.str1,
   3352              reinterpret_cast<JSString*>(READ_REG(rhsId.id())));
   3353          JSString* result =
   3354              ConcatStrings<CanGC>(ctx.frameMgr.cxForLocalUseOnly(), lhs, rhs);
   3355          if (result) {
   3356            retValue = StringValue(result).asRawBits();
   3357          } else {
   3358            ctx.error = PBIResult::Error;
   3359            return IC_ERROR_SENTINEL();
   3360          }
   3361        }
   3362        PREDICT_RETURN();
   3363        DISPATCH_CACHEOP();
   3364      }
   3365 
   3366      CACHEOP_CASE(CompareStringResult) {
   3367        JSOp op = cacheIRReader.jsop();
   3368        StringOperandId lhsId = cacheIRReader.stringOperandId();
   3369        StringOperandId rhsId = cacheIRReader.stringOperandId();
   3370        {
   3371          PUSH_IC_FRAME();
   3372          ReservedRooted<JSString*> lhs(
   3373              &ctx.state.str0,
   3374              reinterpret_cast<JSString*>(READ_REG(lhsId.id())));
   3375          ReservedRooted<JSString*> rhs(
   3376              &ctx.state.str1,
   3377              reinterpret_cast<JSString*>(READ_REG(rhsId.id())));
   3378          bool result;
   3379          if (lhs == rhs) {
   3380            // If operands point to the same instance, the strings are trivially
   3381            // equal.
   3382            result = op == JSOp::Eq || op == JSOp::StrictEq || op == JSOp::Le ||
   3383                     op == JSOp::Ge;
   3384          } else {
   3385            switch (op) {
   3386              case JSOp::Eq:
   3387              case JSOp::StrictEq:
   3388                if (lhs->isAtom() && rhs->isAtom()) {
   3389                  result = false;
   3390                  break;
   3391                }
   3392                if (lhs->length() != rhs->length()) {
   3393                  result = false;
   3394                  break;
   3395                }
   3396                if (!StringsEqual<EqualityKind::Equal>(cx, lhs, rhs, &result)) {
   3397                  ctx.error = PBIResult::Error;
   3398                  return IC_ERROR_SENTINEL();
   3399                }
   3400                break;
   3401              case JSOp::Ne:
   3402              case JSOp::StrictNe:
   3403                if (lhs->isAtom() && rhs->isAtom()) {
   3404                  result = true;
   3405                  break;
   3406                }
   3407                if (lhs->length() != rhs->length()) {
   3408                  result = true;
   3409                  break;
   3410                }
   3411                if (!StringsEqual<EqualityKind::NotEqual>(cx, lhs, rhs,
   3412                                                          &result)) {
   3413                  ctx.error = PBIResult::Error;
   3414                  return IC_ERROR_SENTINEL();
   3415                }
   3416                break;
   3417              case JSOp::Lt:
   3418                if (!StringsCompare<ComparisonKind::LessThan>(cx, lhs, rhs,
   3419                                                              &result)) {
   3420                  ctx.error = PBIResult::Error;
   3421                  return IC_ERROR_SENTINEL();
   3422                }
   3423                break;
   3424              case JSOp::Ge:
   3425                if (!StringsCompare<ComparisonKind::GreaterThanOrEqual>(
   3426                        cx, lhs, rhs, &result)) {
   3427                  ctx.error = PBIResult::Error;
   3428                  return IC_ERROR_SENTINEL();
   3429                }
   3430                break;
   3431              case JSOp::Le:
   3432                if (!StringsCompare<ComparisonKind::GreaterThanOrEqual>(
   3433                        cx, /* N.B. swapped order */ rhs, lhs, &result)) {
   3434                  ctx.error = PBIResult::Error;
   3435                  return IC_ERROR_SENTINEL();
   3436                }
   3437                break;
   3438              case JSOp::Gt:
   3439                if (!StringsCompare<ComparisonKind::LessThan>(
   3440                        cx, /* N.B. swapped order */ rhs, lhs, &result)) {
   3441                  ctx.error = PBIResult::Error;
   3442                  return IC_ERROR_SENTINEL();
   3443                }
   3444                break;
   3445              default:
   3446                MOZ_CRASH("bad opcode");
   3447            }
   3448          }
   3449          retValue = BooleanValue(result).asRawBits();
   3450        }
   3451        PREDICT_RETURN();
   3452        DISPATCH_CACHEOP();
   3453      }
   3454 
   3455      CACHEOP_CASE(CompareInt32Result) {
   3456        JSOp op = cacheIRReader.jsop();
   3457        Int32OperandId lhsId = cacheIRReader.int32OperandId();
   3458        Int32OperandId rhsId = cacheIRReader.int32OperandId();
   3459        int64_t lhs = int64_t(int32_t(READ_REG(lhsId.id())));
   3460        int64_t rhs = int64_t(int32_t(READ_REG(rhsId.id())));
   3461        TRACE_PRINTF("lhs (%d) = %" PRIi64 " rhs (%d) = %" PRIi64 "\n",
   3462                     lhsId.id(), lhs, rhsId.id(), rhs);
   3463        bool result;
   3464        switch (op) {
   3465          case JSOp::Eq:
   3466          case JSOp::StrictEq:
   3467            result = lhs == rhs;
   3468            break;
   3469          case JSOp::Ne:
   3470          case JSOp::StrictNe:
   3471            result = lhs != rhs;
   3472            break;
   3473          case JSOp::Lt:
   3474            result = lhs < rhs;
   3475            break;
   3476          case JSOp::Le:
   3477            result = lhs <= rhs;
   3478            break;
   3479          case JSOp::Gt:
   3480            result = lhs > rhs;
   3481            break;
   3482          case JSOp::Ge:
   3483            result = lhs >= rhs;
   3484            break;
   3485          default:
   3486            MOZ_CRASH("Unexpected opcode");
   3487        }
   3488        retValue = BooleanValue(result).asRawBits();
   3489        PREDICT_RETURN();
   3490        DISPATCH_CACHEOP();
   3491      }
   3492 
   3493      CACHEOP_CASE(CompareDoubleResult) {
   3494        JSOp op = cacheIRReader.jsop();
   3495        NumberOperandId lhsId = cacheIRReader.numberOperandId();
   3496        NumberOperandId rhsId = cacheIRReader.numberOperandId();
   3497        double lhs = READ_VALUE_REG(lhsId.id()).toNumber();
   3498        double rhs = READ_VALUE_REG(rhsId.id()).toNumber();
   3499        bool result;
   3500        switch (op) {
   3501          case JSOp::Eq:
   3502          case JSOp::StrictEq:
   3503            result = lhs == rhs;
   3504            break;
   3505          case JSOp::Ne:
   3506          case JSOp::StrictNe:
   3507            result = lhs != rhs;
   3508            break;
   3509          case JSOp::Lt:
   3510            result = lhs < rhs;
   3511            break;
   3512          case JSOp::Le:
   3513            result = lhs <= rhs;
   3514            break;
   3515          case JSOp::Gt:
   3516            result = lhs > rhs;
   3517            break;
   3518          case JSOp::Ge:
   3519            result = lhs >= rhs;
   3520            break;
   3521          default:
   3522            MOZ_CRASH("Unexpected opcode");
   3523        }
   3524        retValue = BooleanValue(result).asRawBits();
   3525        PREDICT_RETURN();
   3526        DISPATCH_CACHEOP();
   3527      }
   3528 
   3529      CACHEOP_CASE(CompareNullUndefinedResult) {
   3530        JSOp op = cacheIRReader.jsop();
   3531        bool isUndefined = cacheIRReader.readBool();
   3532        ValOperandId inputId = cacheIRReader.valOperandId();
   3533        Value val = READ_VALUE_REG(inputId.id());
   3534        if (val.isObject() && val.toObject().getClass()->isProxyObject()) {
   3535          FAIL_IC();
   3536        }
   3537 
   3538        bool result;
   3539        switch (op) {
   3540          case JSOp::Eq:
   3541            result = val.isUndefined() || val.isNull() ||
   3542                     (val.isObject() &&
   3543                      val.toObject().getClass()->emulatesUndefined());
   3544            break;
   3545          case JSOp::Ne:
   3546            result = !(val.isUndefined() || val.isNull() ||
   3547                       (val.isObject() &&
   3548                        val.toObject().getClass()->emulatesUndefined()));
   3549            break;
   3550          case JSOp::StrictEq:
   3551            result = isUndefined ? val.isUndefined() : val.isNull();
   3552            break;
   3553          case JSOp::StrictNe:
   3554            result = !(isUndefined ? val.isUndefined() : val.isNull());
   3555            break;
   3556          default:
   3557            MOZ_CRASH("bad opcode");
   3558        }
   3559        retValue = BooleanValue(result).asRawBits();
   3560        PREDICT_RETURN();
   3561        DISPATCH_CACHEOP();
   3562      }
   3563 
   3564      CACHEOP_CASE(CompareObjectResult) {
   3565        auto args = cacheIRReader.argsForCompareObjectResult();
   3566        auto* lhs = reinterpret_cast<JSObject*>(READ_REG(args.lhsId.id()));
   3567        auto* rhs = reinterpret_cast<JSObject*>(READ_REG(args.rhsId.id()));
   3568        switch (args.op) {
   3569          case JSOp::Eq:
   3570          case JSOp::StrictEq:
   3571            retValue = BooleanValue(lhs == rhs).asRawBits();
   3572            break;
   3573          case JSOp::Ne:
   3574          case JSOp::StrictNe:
   3575            retValue = BooleanValue(lhs != rhs).asRawBits();
   3576            break;
   3577          default:
   3578            FAIL_IC();
   3579        }
   3580        PREDICT_RETURN();
   3581        DISPATCH_CACHEOP();
   3582      }
   3583 
   3584      CACHEOP_CASE(CompareSymbolResult) {
   3585        auto args = cacheIRReader.argsForCompareSymbolResult();
   3586        auto* lhs = reinterpret_cast<JS::Symbol*>(READ_REG(args.lhsId.id()));
   3587        auto* rhs = reinterpret_cast<JS::Symbol*>(READ_REG(args.rhsId.id()));
   3588        switch (args.op) {
   3589          case JSOp::Eq:
   3590          case JSOp::StrictEq:
   3591            retValue = BooleanValue(lhs == rhs).asRawBits();
   3592            break;
   3593          case JSOp::Ne:
   3594          case JSOp::StrictNe:
   3595            retValue = BooleanValue(lhs != rhs).asRawBits();
   3596            break;
   3597          default:
   3598            FAIL_IC();
   3599        }
   3600        PREDICT_RETURN();
   3601        DISPATCH_CACHEOP();
   3602      }
   3603 
   3604      CACHEOP_CASE(AssertPropertyLookup) {
   3605        // Debug-only assertion; we can ignore.
   3606        cacheIRReader.argsForAssertPropertyLookup();
   3607        DISPATCH_CACHEOP();
   3608      }
   3609 
   3610      CACHEOP_CASE(MathSqrtNumberResult) {
   3611        NumberOperandId inputId = cacheIRReader.numberOperandId();
   3612        double input = READ_VALUE_REG(inputId.id()).toNumber();
   3613        retValue = NumberValue(sqrt(input)).asRawBits();
   3614        PREDICT_RETURN();
   3615        DISPATCH_CACHEOP();
   3616      }
   3617 
   3618      CACHEOP_CASE(MathAbsInt32Result) {
   3619        Int32OperandId inputId = cacheIRReader.int32OperandId();
   3620        int32_t input = int32_t(READ_REG(inputId.id()));
   3621        if (input == INT32_MIN) {
   3622          FAIL_IC();
   3623        }
   3624        if (input < 0) {
   3625          input = -input;
   3626        }
   3627        retValue = Int32Value(input).asRawBits();
   3628        PREDICT_RETURN();
   3629        DISPATCH_CACHEOP();
   3630      }
   3631 
   3632      CACHEOP_CASE(MathAbsNumberResult) {
   3633        NumberOperandId inputId = cacheIRReader.numberOperandId();
   3634        double input = READ_VALUE_REG(inputId.id()).toNumber();
   3635        retValue = DoubleValue(fabs(input)).asRawBits();
   3636        PREDICT_RETURN();
   3637        DISPATCH_CACHEOP();
   3638      }
   3639 
   3640      CACHEOP_CASE(MathClz32Result) {
   3641        Int32OperandId inputId = cacheIRReader.int32OperandId();
   3642        int32_t input = int32_t(READ_REG(inputId.id()));
   3643        int32_t result =
   3644            (input == 0) ? 32 : mozilla::CountLeadingZeroes32(input);
   3645        retValue = Int32Value(result).asRawBits();
   3646        PREDICT_RETURN();
   3647        DISPATCH_CACHEOP();
   3648      }
   3649 
   3650      CACHEOP_CASE(MathSignInt32Result) {
   3651        Int32OperandId inputId = cacheIRReader.int32OperandId();
   3652        int32_t input = int32_t(READ_REG(inputId.id()));
   3653        int32_t result = (input == 0) ? 0 : ((input > 0) ? 1 : -1);
   3654        retValue = Int32Value(result).asRawBits();
   3655        PREDICT_RETURN();
   3656        DISPATCH_CACHEOP();
   3657      }
   3658 
   3659      CACHEOP_CASE(MathSignNumberResult) {
   3660        NumberOperandId inputId = cacheIRReader.numberOperandId();
   3661        double input = READ_VALUE_REG(inputId.id()).toNumber();
   3662        double result = 0;
   3663        if (std::isnan(input)) {
   3664          result = JS::GenericNaN();
   3665        } else if (input == 0 && std::signbit(input)) {
   3666          result = -0.0;
   3667        } else if (input == 0) {
   3668          result = 0;
   3669        } else if (input > 0) {
   3670          result = 1;
   3671        } else {
   3672          result = -1;
   3673        }
   3674        retValue = DoubleValue(result).asRawBits();
   3675        PREDICT_RETURN();
   3676        DISPATCH_CACHEOP();
   3677      }
   3678 
   3679      CACHEOP_CASE(MathSignNumberToInt32Result) {
   3680        NumberOperandId inputId = cacheIRReader.numberOperandId();
   3681        double input = READ_VALUE_REG(inputId.id()).toNumber();
   3682        int32_t result = 0;
   3683        if (std::isnan(input) || (input == 0.0 && std::signbit(input))) {
   3684          FAIL_IC();
   3685        } else if (input == 0) {
   3686          result = 0;
   3687        } else if (input > 0) {
   3688          result = 1;
   3689        } else {
   3690          result = -1;
   3691        }
   3692        retValue = Int32Value(result).asRawBits();
   3693        PREDICT_RETURN();
   3694        DISPATCH_CACHEOP();
   3695      }
   3696 
   3697      CACHEOP_CASE(MathImulResult) {
   3698        Int32OperandId lhsId = cacheIRReader.int32OperandId();
   3699        Int32OperandId rhsId = cacheIRReader.int32OperandId();
   3700        int32_t lhs = int32_t(READ_REG(lhsId.id()));
   3701        int32_t rhs = int32_t(READ_REG(rhsId.id()));
   3702        int32_t result = lhs * rhs;
   3703        retValue = Int32Value(result).asRawBits();
   3704        PREDICT_RETURN();
   3705        DISPATCH_CACHEOP();
   3706      }
   3707 
   3708      CACHEOP_CASE(MathFRoundNumberResult) {
   3709        NumberOperandId inputId = cacheIRReader.numberOperandId();
   3710        double input = READ_VALUE_REG(inputId.id()).toNumber();
   3711        retValue = DoubleValue(double(float(input))).asRawBits();
   3712        PREDICT_RETURN();
   3713        DISPATCH_CACHEOP();
   3714      }
   3715 
   3716      CACHEOP_CASE(MathRandomResult) {
   3717        uint32_t rngOffset = cacheIRReader.stubOffset();
   3718        auto* rng = reinterpret_cast<mozilla::non_crypto::XorShift128PlusRNG*>(
   3719            stubInfo->getStubRawWord(cstub, rngOffset));
   3720        retValue = DoubleValue(rng->nextDouble()).asRawBits();
   3721        PREDICT_RETURN();
   3722        DISPATCH_CACHEOP();
   3723      }
   3724 
   3725      CACHEOP_CASE(MathHypot2NumberResult) {
   3726        NumberOperandId firstId = cacheIRReader.numberOperandId();
   3727        double first = READ_VALUE_REG(firstId.id()).toNumber();
   3728        NumberOperandId secondId = cacheIRReader.numberOperandId();
   3729        double second = READ_VALUE_REG(secondId.id()).toNumber();
   3730        retValue = DoubleValue(ecmaHypot(first, second)).asRawBits();
   3731        PREDICT_RETURN();
   3732        DISPATCH_CACHEOP();
   3733      }
   3734 
   3735      CACHEOP_CASE(MathHypot3NumberResult) {
   3736        NumberOperandId firstId = cacheIRReader.numberOperandId();
   3737        double first = READ_VALUE_REG(firstId.id()).toNumber();
   3738        NumberOperandId secondId = cacheIRReader.numberOperandId();
   3739        double second = READ_VALUE_REG(secondId.id()).toNumber();
   3740        NumberOperandId thirdId = cacheIRReader.numberOperandId();
   3741        double third = READ_VALUE_REG(thirdId.id()).toNumber();
   3742        retValue = DoubleValue(hypot3(first, second, third)).asRawBits();
   3743        PREDICT_RETURN();
   3744        DISPATCH_CACHEOP();
   3745      }
   3746 
   3747      CACHEOP_CASE(MathHypot4NumberResult) {
   3748        NumberOperandId firstId = cacheIRReader.numberOperandId();
   3749        double first = READ_VALUE_REG(firstId.id()).toNumber();
   3750        NumberOperandId secondId = cacheIRReader.numberOperandId();
   3751        double second = READ_VALUE_REG(secondId.id()).toNumber();
   3752        NumberOperandId thirdId = cacheIRReader.numberOperandId();
   3753        double third = READ_VALUE_REG(thirdId.id()).toNumber();
   3754        NumberOperandId fourthId = cacheIRReader.numberOperandId();
   3755        double fourth = READ_VALUE_REG(fourthId.id()).toNumber();
   3756        retValue =
   3757            DoubleValue(hypot4(first, second, third, fourth)).asRawBits();
   3758        PREDICT_RETURN();
   3759        DISPATCH_CACHEOP();
   3760      }
   3761 
   3762      CACHEOP_CASE(MathAtan2NumberResult) {
   3763        NumberOperandId lhsId = cacheIRReader.numberOperandId();
   3764        double lhs = READ_VALUE_REG(lhsId.id()).toNumber();
   3765        NumberOperandId rhsId = cacheIRReader.numberOperandId();
   3766        double rhs = READ_VALUE_REG(rhsId.id()).toNumber();
   3767        retValue = DoubleValue(ecmaAtan2(lhs, rhs)).asRawBits();
   3768        PREDICT_RETURN();
   3769        DISPATCH_CACHEOP();
   3770      }
   3771 
   3772      CACHEOP_CASE(MathFloorNumberResult) {
   3773        NumberOperandId inputId = cacheIRReader.numberOperandId();
   3774        double input = READ_VALUE_REG(inputId.id()).toNumber();
   3775        double result = std::floor(input);
   3776        retValue = DoubleValue(result).asRawBits();
   3777        PREDICT_RETURN();
   3778        DISPATCH_CACHEOP();
   3779      }
   3780 
   3781      CACHEOP_CASE(MathCeilNumberResult) {
   3782        NumberOperandId inputId = cacheIRReader.numberOperandId();
   3783        double input = READ_VALUE_REG(inputId.id()).toNumber();
   3784        double result = std::ceil(input);
   3785        retValue = DoubleValue(result).asRawBits();
   3786        PREDICT_RETURN();
   3787        DISPATCH_CACHEOP();
   3788      }
   3789 
   3790      CACHEOP_CASE(MathTruncNumberResult) {
   3791        NumberOperandId inputId = cacheIRReader.numberOperandId();
   3792        double input = READ_VALUE_REG(inputId.id()).toNumber();
   3793        double result = std::trunc(input);
   3794        retValue = DoubleValue(result).asRawBits();
   3795        PREDICT_RETURN();
   3796        DISPATCH_CACHEOP();
   3797      }
   3798 
   3799      CACHEOP_CASE(MathFloorToInt32Result) {
   3800        NumberOperandId inputId = cacheIRReader.numberOperandId();
   3801        double input = READ_VALUE_REG(inputId.id()).toNumber();
   3802        if (input == 0.0 && std::signbit(input)) {
   3803          FAIL_IC();
   3804        }
   3805        double result = std::floor(input);
   3806        int32_t intResult = int32_t(result);
   3807        if (double(intResult) != result) {
   3808          FAIL_IC();
   3809        }
   3810        retValue = Int32Value(intResult).asRawBits();
   3811        PREDICT_RETURN();
   3812        DISPATCH_CACHEOP();
   3813      }
   3814 
   3815      CACHEOP_CASE(MathCeilToInt32Result) {
   3816        NumberOperandId inputId = cacheIRReader.numberOperandId();
   3817        double input = READ_VALUE_REG(inputId.id()).toNumber();
   3818        if (input > -1.0 && std::signbit(input)) {
   3819          FAIL_IC();
   3820        }
   3821        double result = std::ceil(input);
   3822        int32_t intResult = int32_t(result);
   3823        if (double(intResult) != result) {
   3824          FAIL_IC();
   3825        }
   3826        retValue = Int32Value(intResult).asRawBits();
   3827        PREDICT_RETURN();
   3828        DISPATCH_CACHEOP();
   3829      }
   3830 
   3831      CACHEOP_CASE(MathTruncToInt32Result) {
   3832        NumberOperandId inputId = cacheIRReader.numberOperandId();
   3833        double input = READ_VALUE_REG(inputId.id()).toNumber();
   3834        if (input == 0.0 && std::signbit(input)) {
   3835          FAIL_IC();
   3836        }
   3837        double result = std::trunc(input);
   3838        int32_t intResult = int32_t(result);
   3839        if (double(intResult) != result) {
   3840          FAIL_IC();
   3841        }
   3842        retValue = Int32Value(intResult).asRawBits();
   3843        PREDICT_RETURN();
   3844        DISPATCH_CACHEOP();
   3845      }
   3846 
   3847      CACHEOP_CASE(MathRoundToInt32Result) {
   3848        NumberOperandId inputId = cacheIRReader.numberOperandId();
   3849        double input = READ_VALUE_REG(inputId.id()).toNumber();
   3850        if (input == 0.0 && std::signbit(input)) {
   3851          FAIL_IC();
   3852        }
   3853        int32_t intResult = int32_t(input);
   3854        if (double(intResult) != input) {
   3855          FAIL_IC();
   3856        }
   3857        retValue = Int32Value(intResult).asRawBits();
   3858        PREDICT_RETURN();
   3859        DISPATCH_CACHEOP();
   3860      }
   3861 
   3862      CACHEOP_CASE(NumberMinMax) {
   3863        auto args = cacheIRReader.argsForNumberMinMax();
   3864        BOUNDSCHECK(args.resultId);
   3865        double first = READ_VALUE_REG(args.firstId.id()).toNumber();
   3866        double second = READ_VALUE_REG(args.secondId.id()).toNumber();
   3867        double result = DoubleMinMax(args.isMax, first, second);
   3868        WRITE_VALUE_REG(args.resultId.id(), DoubleValue(result));
   3869        DISPATCH_CACHEOP();
   3870      }
   3871 
   3872      CACHEOP_CASE(Int32MinMaxArrayResult) {
   3873        ObjOperandId arrayId = cacheIRReader.objOperandId();
   3874        bool isMax = cacheIRReader.readBool();
   3875        // ICs that use this opcode depend on implicit unboxing due to
   3876        // type-overload on ObjOperandId when a value is loaded
   3877        // directly from an argument slot. We explicitly unbox here.
   3878        NativeObject* nobj = reinterpret_cast<NativeObject*>(
   3879            &READ_VALUE_REG(arrayId.id()).toObject());
   3880        uint32_t len = nobj->getDenseInitializedLength();
   3881        if (len == 0) {
   3882          FAIL_IC();
   3883        }
   3884        ObjectElements* elems = nobj->getElementsHeader();
   3885        int32_t accum = 0;
   3886        for (uint32_t i = 0; i < len; i++) {
   3887          HeapSlot* slot = &elems->elements()[i];
   3888          Value val = slot->get();
   3889          if (!val.isInt32()) {
   3890            FAIL_IC();
   3891          }
   3892          int32_t valInt = val.toInt32();
   3893          if (i > 0) {
   3894            accum = isMax ? ((valInt > accum) ? valInt : accum)
   3895                          : ((valInt < accum) ? valInt : accum);
   3896          } else {
   3897            accum = valInt;
   3898          }
   3899        }
   3900        retValue = Int32Value(accum).asRawBits();
   3901        PREDICT_RETURN();
   3902        DISPATCH_CACHEOP();
   3903      }
   3904 
   3905      CACHEOP_CASE(NumberMinMaxArrayResult) {
   3906        ObjOperandId arrayId = cacheIRReader.objOperandId();
   3907        bool isMax = cacheIRReader.readBool();
   3908        // ICs that use this opcode depend on implicit unboxing due to
   3909        // type-overload on ObjOperandId when a value is loaded
   3910        // directly from an argument slot. We explicitly unbox here.
   3911        NativeObject* nobj = reinterpret_cast<NativeObject*>(
   3912            &READ_VALUE_REG(arrayId.id()).toObject());
   3913        uint32_t len = nobj->getDenseInitializedLength();
   3914        if (len == 0) {
   3915          FAIL_IC();
   3916        }
   3917        ObjectElements* elems = nobj->getElementsHeader();
   3918        double accum = 0;
   3919        for (uint32_t i = 0; i < len; i++) {
   3920          HeapSlot* slot = &elems->elements()[i];
   3921          Value val = slot->get();
   3922          if (!val.isNumber()) {
   3923            FAIL_IC();
   3924          }
   3925          double valDouble = val.toNumber();
   3926          if (i > 0) {
   3927            accum = DoubleMinMax(isMax, accum, valDouble);
   3928          } else {
   3929            accum = valDouble;
   3930          }
   3931        }
   3932        retValue = DoubleValue(accum).asRawBits();
   3933        PREDICT_RETURN();
   3934        DISPATCH_CACHEOP();
   3935      }
   3936 
   3937      CACHEOP_CASE(MathFunctionNumberResult) {
   3938        NumberOperandId inputId = cacheIRReader.numberOperandId();
   3939        UnaryMathFunction fun = cacheIRReader.unaryMathFunction();
   3940        double input = READ_VALUE_REG(inputId.id()).toNumber();
   3941        auto funPtr = GetUnaryMathFunctionPtr(fun);
   3942        retValue = DoubleValue(funPtr(input)).asRawBits();
   3943        PREDICT_RETURN();
   3944        DISPATCH_CACHEOP();
   3945      }
   3946 
   3947      CACHEOP_CASE(NumberParseIntResult) {
   3948        StringOperandId strId = cacheIRReader.stringOperandId();
   3949        Int32OperandId radixId = cacheIRReader.int32OperandId();
   3950        JSString* str = reinterpret_cast<JSString*>(READ_REG(strId.id()));
   3951        int32_t radix = int32_t(READ_REG(radixId.id()));
   3952        {
   3953          PUSH_IC_FRAME();
   3954          ReservedRooted<JSString*> str0(&ctx.state.str0, str);
   3955          ReservedRooted<Value> result(&ctx.state.value0);
   3956          if (!NumberParseInt(cx, str0, radix, &result)) {
   3957            ctx.error = PBIResult::Error;
   3958            return IC_ERROR_SENTINEL();
   3959          }
   3960          retValue = result.asRawBits();
   3961        }
   3962        PREDICT_RETURN();
   3963        DISPATCH_CACHEOP();
   3964      }
   3965 
   3966      CACHEOP_CASE(DoubleParseIntResult) {
   3967        NumberOperandId inputId = cacheIRReader.numberOperandId();
   3968        double input = READ_VALUE_REG(inputId.id()).toNumber();
   3969        if (std::isnan(input)) {
   3970          FAIL_IC();
   3971        }
   3972        int32_t result = int32_t(input);
   3973        if (double(result) != input) {
   3974          FAIL_IC();
   3975        }
   3976        retValue = Int32Value(result).asRawBits();
   3977        PREDICT_RETURN();
   3978        DISPATCH_CACHEOP();
   3979      }
   3980 
   3981      CACHEOP_CASE(GuardTagNotEqual) {
   3982        ValueTagOperandId lhsId = cacheIRReader.valueTagOperandId();
   3983        ValueTagOperandId rhsId = cacheIRReader.valueTagOperandId();
   3984        int32_t lhs = int32_t(READ_REG(lhsId.id()));
   3985        int32_t rhs = int32_t(READ_REG(rhsId.id()));
   3986        if (lhs == rhs) {
   3987          FAIL_IC();
   3988        }
   3989        if (JSValueTag(lhs) <= JSVAL_TAG_INT32 ||
   3990            JSValueTag(rhs) <= JSVAL_TAG_INT32) {
   3991          FAIL_IC();
   3992        }
   3993        DISPATCH_CACHEOP();
   3994      }
   3995 
   3996      CACHEOP_CASE(GuardNumberToIntPtrIndex) {
   3997        auto args = cacheIRReader.argsForGuardNumberToIntPtrIndex();
   3998        BOUNDSCHECK(args.resultId);
   3999        double input = READ_VALUE_REG(args.inputId.id()).toNumber();
   4000        // For simplicity, support only uint32 range for now. This
   4001        // covers 32-bit and 64-bit systems.
   4002        if (input < 0.0 || input >= (uint64_t(1) << 32)) {
   4003          FAIL_IC();
   4004        }
   4005        uintptr_t result = static_cast<uintptr_t>(input);
   4006        // Convert back and compare to detect rounded fractional
   4007        // parts.
   4008        if (static_cast<double>(result) != input) {
   4009          FAIL_IC();
   4010        }
   4011        WRITE_REG(args.resultId.id(), uint64_t(result), OBJECT);
   4012        DISPATCH_CACHEOP();
   4013      }
   4014 
   4015      CACHEOP_CASE(LoadTypeOfObjectResult) {
   4016        ObjOperandId objId = cacheIRReader.objOperandId();
   4017        JSObject* obj = reinterpret_cast<JSObject*>(READ_REG(objId.id()));
   4018        const JSClass* cls = obj->getClass();
   4019        if (cls->isProxyObject()) {
   4020          FAIL_IC();
   4021        }
   4022        if (obj->is<JSFunction>()) {
   4023          retValue =
   4024              StringValue(ctx.frameMgr.cxForLocalUseOnly()->names().function)
   4025                  .asRawBits();
   4026        } else if (cls->emulatesUndefined()) {
   4027          retValue =
   4028              StringValue(ctx.frameMgr.cxForLocalUseOnly()->names().undefined)
   4029                  .asRawBits();
   4030        } else {
   4031          retValue =
   4032              StringValue(ctx.frameMgr.cxForLocalUseOnly()->names().object)
   4033                  .asRawBits();
   4034        }
   4035        PREDICT_RETURN();
   4036        DISPATCH_CACHEOP();
   4037      }
   4038 
   4039      CACHEOP_CASE(PackedArrayPopResult) {
   4040        ObjOperandId objId = cacheIRReader.objOperandId();
   4041        ArrayObject* aobj =
   4042            reinterpret_cast<ArrayObject*>(READ_REG(objId.id()));
   4043        ObjectElements* elements = aobj->getElementsHeader();
   4044        if (!elements->isPacked() || elements->hasNonwritableArrayLength() ||
   4045            elements->isNotExtensible() || elements->maybeInIteration()) {
   4046          FAIL_IC();
   4047        }
   4048        size_t len = aobj->length();
   4049        if (len != aobj->getDenseInitializedLength()) {
   4050          FAIL_IC();
   4051        }
   4052        if (len == 0) {
   4053          retValue = UndefinedValue().asRawBits();
   4054        } else {
   4055          HeapSlot* slot = &elements->elements()[len - 1];
   4056          retValue = slot->get().asRawBits();
   4057          len--;
   4058          aobj->setDenseInitializedLength(len);
   4059          aobj->setLengthToInitializedLength();
   4060        }
   4061        PREDICT_RETURN();
   4062        DISPATCH_CACHEOP();
   4063      }
   4064 
   4065      CACHEOP_CASE(PackedArrayShiftResult) {
   4066        ObjOperandId objId = cacheIRReader.objOperandId();
   4067        ArrayObject* aobj =
   4068            reinterpret_cast<ArrayObject*>(READ_REG(objId.id()));
   4069        ObjectElements* elements = aobj->getElementsHeader();
   4070        if (!elements->isPacked() || elements->hasNonwritableArrayLength() ||
   4071            elements->isNotExtensible() || elements->maybeInIteration()) {
   4072          FAIL_IC();
   4073        }
   4074        size_t len = aobj->length();
   4075        if (len != aobj->getDenseInitializedLength()) {
   4076          FAIL_IC();
   4077        }
   4078        if (len == 0) {
   4079          retValue = UndefinedValue().asRawBits();
   4080        } else {
   4081          HeapSlot* slot = &elements->elements()[0];
   4082          retValue = slot->get().asRawBits();
   4083          ArrayShiftMoveElements(aobj);
   4084        }
   4085        PREDICT_RETURN();
   4086        DISPATCH_CACHEOP();
   4087      }
   4088 
   4089      CACHEOP_CASE(PackedArraySliceResult) {
   4090        uint32_t templateObjectOffset = cacheIRReader.stubOffset();
   4091        ObjOperandId arrayId = cacheIRReader.objOperandId();
   4092        Int32OperandId beginId = cacheIRReader.int32OperandId();
   4093        Int32OperandId endId = cacheIRReader.int32OperandId();
   4094        (void)templateObjectOffset;
   4095        ArrayObject* aobj =
   4096            reinterpret_cast<ArrayObject*>(READ_REG(arrayId.id()));
   4097        int32_t begin = int32_t(READ_REG(beginId.id()));
   4098        int32_t end = int32_t(READ_REG(endId.id()));
   4099        if (!aobj->getElementsHeader()->isPacked()) {
   4100          FAIL_IC();
   4101        }
   4102        {
   4103          PUSH_IC_FRAME();
   4104          ReservedRooted<JSObject*> arr(&ctx.state.obj0, aobj);
   4105          JSObject* ret = ArraySliceDense(cx, arr, begin, end, nullptr);
   4106          if (!ret) {
   4107            FAIL_IC();
   4108          }
   4109          retValue = ObjectValue(*ret).asRawBits();
   4110        }
   4111        PREDICT_RETURN();
   4112        DISPATCH_CACHEOP();
   4113      }
   4114 
   4115      CACHEOP_CASE(IsPackedArrayResult) {
   4116        ObjOperandId objId = cacheIRReader.objOperandId();
   4117        JSObject* obj = reinterpret_cast<JSObject*>(READ_REG(objId.id()));
   4118        if (!obj->is<ArrayObject>()) {
   4119          retValue = BooleanValue(false).asRawBits();
   4120          PREDICT_RETURN();
   4121          DISPATCH_CACHEOP();
   4122        }
   4123        ArrayObject* aobj =
   4124            reinterpret_cast<ArrayObject*>(READ_REG(objId.id()));
   4125        if (aobj->length() != aobj->getDenseInitializedLength()) {
   4126          retValue = BooleanValue(false).asRawBits();
   4127          PREDICT_RETURN();
   4128          DISPATCH_CACHEOP();
   4129        }
   4130        retValue = BooleanValue(aobj->denseElementsArePacked()).asRawBits();
   4131        PREDICT_RETURN();
   4132        DISPATCH_CACHEOP();
   4133      }
   4134 
   4135      CACHEOP_CASE(LoadArgumentsObjectLengthResult) {
   4136        ObjOperandId objId = cacheIRReader.objOperandId();
   4137        ArgumentsObject* obj =
   4138            reinterpret_cast<ArgumentsObject*>(READ_REG(objId.id()));
   4139        if (obj->hasOverriddenLength()) {
   4140          FAIL_IC();
   4141        }
   4142        retValue = Int32Value(obj->initialLength()).asRawBits();
   4143        PREDICT_RETURN();
   4144        DISPATCH_CACHEOP();
   4145      }
   4146 
   4147      CACHEOP_CASE(LoadArgumentsObjectLength) {
   4148        ObjOperandId objId = cacheIRReader.objOperandId();
   4149        Int32OperandId resultId = cacheIRReader.int32OperandId();
   4150        BOUNDSCHECK(resultId);
   4151        ArgumentsObject* obj =
   4152            reinterpret_cast<ArgumentsObject*>(READ_REG(objId.id()));
   4153        if (obj->hasOverriddenLength()) {
   4154          FAIL_IC();
   4155        }
   4156        WRITE_REG(resultId.id(), obj->initialLength(), INT32);
   4157        DISPATCH_CACHEOP();
   4158      }
   4159 
   4160      CACHEOP_CASE(ObjectToIteratorResult) {
   4161        ObjOperandId objId = cacheIRReader.objOperandId();
   4162        uint32_t enumeratorsAddr = cacheIRReader.stubOffset();
   4163        JSObject* obj = reinterpret_cast<JSObject*>(READ_REG(objId.id()));
   4164        (void)enumeratorsAddr;
   4165        {
   4166          PUSH_IC_FRAME();
   4167          ReservedRooted<JSObject*> rootedObj(&ctx.state.obj0, obj);
   4168          auto* iter = GetIterator(cx, rootedObj);
   4169          if (!iter) {
   4170            ctx.error = PBIResult::Error;
   4171            return IC_ERROR_SENTINEL();
   4172          }
   4173          retValue = ObjectValue(*iter).asRawBits();
   4174        }
   4175        PREDICT_RETURN();
   4176        DISPATCH_CACHEOP();
   4177      }
   4178 
   4179      CACHEOP_CASE(LoadUndefinedResult) {
   4180        retValue = UndefinedValue().asRawBits();
   4181        PREDICT_RETURN();
   4182        DISPATCH_CACHEOP();
   4183      }
   4184 
   4185      CACHEOP_CASE(LoadDoubleConstant) {
   4186        uint32_t valOffset = cacheIRReader.stubOffset();
   4187        NumberOperandId resultId = cacheIRReader.numberOperandId();
   4188        BOUNDSCHECK(resultId);
   4189        WRITE_VALUE_REG(
   4190            resultId.id(),
   4191            Value::fromRawBits(stubInfo->getStubRawInt64(cstub, valOffset)));
   4192        DISPATCH_CACHEOP();
   4193      }
   4194 
   4195      CACHEOP_CASE(LoadBooleanConstant) {
   4196        bool val = cacheIRReader.readBool();
   4197        BooleanOperandId resultId = cacheIRReader.booleanOperandId();
   4198        BOUNDSCHECK(resultId);
   4199        WRITE_REG(resultId.id(), val ? 1 : 0, BOOLEAN);
   4200        DISPATCH_CACHEOP();
   4201      }
   4202 
   4203      CACHEOP_CASE(LoadUndefined) {
   4204        ValOperandId resultId = cacheIRReader.numberOperandId();
   4205        BOUNDSCHECK(resultId);
   4206        WRITE_VALUE_REG(resultId.id(), UndefinedValue());
   4207        DISPATCH_CACHEOP();
   4208      }
   4209 
   4210      CACHEOP_CASE(LoadConstantString) {
   4211        uint32_t valOffset = cacheIRReader.stubOffset();
   4212        StringOperandId resultId = cacheIRReader.stringOperandId();
   4213        BOUNDSCHECK(resultId);
   4214        JSString* str = reinterpret_cast<JSString*>(
   4215            stubInfo->getStubRawWord(cstub, valOffset));
   4216        WRITE_REG(resultId.id(), reinterpret_cast<uint64_t>(str), STRING);
   4217        DISPATCH_CACHEOP();
   4218      }
   4219 
   4220      CACHEOP_CASE(NewPlainObjectResult) {
   4221        auto args = cacheIRReader.argsForNewPlainObjectResult();
   4222        SharedShape* shape = reinterpret_cast<SharedShape*>(
   4223            stubInfo->getStubRawWord(cstub, args.shapeOffset));
   4224        gc::AllocSite* site = reinterpret_cast<gc::AllocSite*>(
   4225            stubInfo->getStubRawWord(cstub, args.siteOffset));
   4226        {
   4227          PUSH_IC_FRAME();
   4228          Rooted<SharedShape*> rootedShape(cx, shape);
   4229          auto* result = NewPlainObjectBaselineFallback(cx, rootedShape,
   4230                                                        args.allocKind, site);
   4231          if (!result) {
   4232            ctx.error = PBIResult::Error;
   4233            return IC_ERROR_SENTINEL();
   4234          }
   4235          retValue = ObjectValue(*result).asRawBits();
   4236        }
   4237        PREDICT_RETURN();
   4238        DISPATCH_CACHEOP();
   4239      }
   4240 
   4241      CACHEOP_CASE(NewArrayObjectResult) {
   4242        uint32_t arrayLength = cacheIRReader.uint32Immediate();
   4243        uint32_t shapeOffset = cacheIRReader.stubOffset();
   4244        uint32_t siteOffset = cacheIRReader.stubOffset();
   4245        (void)shapeOffset;
   4246        gc::AllocSite* site = reinterpret_cast<gc::AllocSite*>(
   4247            stubInfo->getStubRawWord(cstub, siteOffset));
   4248        gc::AllocKind allocKind = GuessArrayGCKind(arrayLength);
   4249        MOZ_ASSERT(gc::GetObjectFinalizeKind(&ArrayObject::class_) ==
   4250                   gc::FinalizeKind::None);
   4251        MOZ_ASSERT(!IsFinalizedKind(allocKind));
   4252        {
   4253          PUSH_IC_FRAME();
   4254          auto* result =
   4255              NewArrayObjectBaselineFallback(cx, arrayLength, allocKind, site);
   4256          if (!result) {
   4257            ctx.error = PBIResult::Error;
   4258            return IC_ERROR_SENTINEL();
   4259          }
   4260          retValue = ObjectValue(*result).asRawBits();
   4261        }
   4262        PREDICT_RETURN();
   4263        DISPATCH_CACHEOP();
   4264      }
   4265 
   4266      CACHEOP_CASE(NewArrayFromLengthResult) {
   4267        uint32_t templateObjectOffset = cacheIRReader.stubOffset();
   4268        Int32OperandId lengthId = cacheIRReader.int32OperandId();
   4269        uint32_t siteOffset = cacheIRReader.stubOffset();
   4270        ArrayObject* templateObject = reinterpret_cast<ArrayObject*>(
   4271            stubInfo->getStubRawWord(cstub, templateObjectOffset));
   4272        gc::AllocSite* site = reinterpret_cast<gc::AllocSite*>(
   4273            stubInfo->getStubRawWord(cstub, siteOffset));
   4274        int32_t length = int32_t(READ_REG(lengthId.id()));
   4275        {
   4276          PUSH_IC_FRAME();
   4277          Rooted<ArrayObject*> templateObjectRooted(cx, templateObject);
   4278          auto* result =
   4279              ArrayConstructorOneArg(cx, templateObjectRooted, length, site);
   4280          if (!result) {
   4281            ctx.error = PBIResult::Error;
   4282            return IC_ERROR_SENTINEL();
   4283          }
   4284          retValue = ObjectValue(*result).asRawBits();
   4285        }
   4286        PREDICT_RETURN();
   4287        DISPATCH_CACHEOP();
   4288      }
   4289 
   4290      CACHEOP_CASE(NewTypedArrayFromLengthResult) {
   4291        uint32_t templateObjectOffset = cacheIRReader.stubOffset();
   4292        Int32OperandId lengthId = cacheIRReader.int32OperandId();
   4293        TypedArrayObject* templateObject = reinterpret_cast<TypedArrayObject*>(
   4294            stubInfo->getStubRawWord(cstub, templateObjectOffset));
   4295        int32_t length = int32_t(READ_REG(lengthId.id()));
   4296        {
   4297          PUSH_IC_FRAME();
   4298          ReservedRooted<JSObject*> templateObjectRooted(&ctx.state.obj0,
   4299                                                         templateObject);
   4300          auto* result = NewTypedArrayWithTemplateAndLength(
   4301              cx, templateObjectRooted, length);
   4302          if (!result) {
   4303            ctx.error = PBIResult::Error;
   4304            return IC_ERROR_SENTINEL();
   4305          }
   4306          retValue = ObjectValue(*result).asRawBits();
   4307        }
   4308        PREDICT_RETURN();
   4309        DISPATCH_CACHEOP();
   4310      }
   4311 
   4312      CACHEOP_CASE(NewTypedArrayFromArrayBufferResult) {
   4313        uint32_t templateObjectOffset = cacheIRReader.stubOffset();
   4314        ObjOperandId bufferId = cacheIRReader.objOperandId();
   4315        ValOperandId byteOffsetId = cacheIRReader.valOperandId();
   4316        ValOperandId lengthId = cacheIRReader.valOperandId();
   4317        TypedArrayObject* templateObject = reinterpret_cast<TypedArrayObject*>(
   4318            stubInfo->getStubRawWord(cstub, templateObjectOffset));
   4319        JSObject* buffer = reinterpret_cast<JSObject*>(READ_REG(bufferId.id()));
   4320        Value byteOffset = READ_VALUE_REG(byteOffsetId.id());
   4321        Value length = READ_VALUE_REG(lengthId.id());
   4322        {
   4323          PUSH_IC_FRAME();
   4324          ReservedRooted<JSObject*> templateObjectRooted(&ctx.state.obj0,
   4325                                                         templateObject);
   4326          ReservedRooted<JSObject*> bufferRooted(&ctx.state.obj1, buffer);
   4327          ReservedRooted<Value> byteOffsetRooted(&ctx.state.value0, byteOffset);
   4328          ReservedRooted<Value> lengthRooted(&ctx.state.value1, length);
   4329          auto* result = NewTypedArrayWithTemplateAndBuffer(
   4330              cx, templateObjectRooted, bufferRooted, byteOffsetRooted,
   4331              lengthRooted);
   4332          if (!result) {
   4333            ctx.error = PBIResult::Error;
   4334            return IC_ERROR_SENTINEL();
   4335          }
   4336          retValue = ObjectValue(*result).asRawBits();
   4337        }
   4338        PREDICT_RETURN();
   4339        DISPATCH_CACHEOP();
   4340      }
   4341 
   4342      CACHEOP_CASE(NewTypedArrayFromArrayResult) {
   4343        uint32_t templateObjectOffset = cacheIRReader.stubOffset();
   4344        ObjOperandId arrayId = cacheIRReader.objOperandId();
   4345        TypedArrayObject* templateObject = reinterpret_cast<TypedArrayObject*>(
   4346            stubInfo->getStubRawWord(cstub, templateObjectOffset));
   4347        JSObject* array = reinterpret_cast<JSObject*>(READ_REG(arrayId.id()));
   4348        {
   4349          PUSH_IC_FRAME();
   4350          ReservedRooted<JSObject*> templateObjectRooted(&ctx.state.obj0,
   4351                                                         templateObject);
   4352          ReservedRooted<JSObject*> arrayRooted(&ctx.state.obj1, array);
   4353          auto* result = NewTypedArrayWithTemplateAndArray(
   4354              cx, templateObjectRooted, arrayRooted);
   4355          if (!result) {
   4356            ctx.error = PBIResult::Error;
   4357            return IC_ERROR_SENTINEL();
   4358          }
   4359          retValue = ObjectValue(*result).asRawBits();
   4360        }
   4361        PREDICT_RETURN();
   4362        DISPATCH_CACHEOP();
   4363      }
   4364 
   4365      CACHEOP_CASE(ObjectToStringResult) {
   4366        ObjOperandId objId = cacheIRReader.objOperandId();
   4367        JSObject* obj = reinterpret_cast<JSObject*>(READ_REG(objId.id()));
   4368        {
   4369          PUSH_IC_FRAME();
   4370          auto* result = ObjectClassToString(cx, obj);
   4371          if (!result) {
   4372            FAIL_IC();
   4373          }
   4374          retValue = StringValue(result).asRawBits();
   4375        }
   4376        PREDICT_RETURN();
   4377        DISPATCH_CACHEOP();
   4378      }
   4379 
   4380      CACHEOP_CASE(CallNativeGetterResult) {
   4381        ValOperandId receiverId = cacheIRReader.valOperandId();
   4382        uint32_t getterOffset = cacheIRReader.stubOffset();
   4383        bool sameRealm = cacheIRReader.readBool();
   4384        uint32_t nargsAndFlagsOffset = cacheIRReader.stubOffset();
   4385        (void)sameRealm;
   4386        (void)nargsAndFlagsOffset;
   4387        Value receiver = READ_VALUE_REG(receiverId.id());
   4388        JSFunction* getter = reinterpret_cast<JSFunction*>(
   4389            stubInfo->getStubRawWord(cstub, getterOffset));
   4390        {
   4391          PUSH_IC_FRAME();
   4392          ReservedRooted<JSFunction*> getterRooted(&ctx.state.fun0, getter);
   4393          ReservedRooted<Value> receiverRooted(&ctx.state.value0, receiver);
   4394          ReservedRooted<Value> resultRooted(&ctx.state.value1);
   4395          if (!CallNativeGetter(cx, getterRooted, receiverRooted,
   4396                                &resultRooted)) {
   4397            ctx.error = PBIResult::Error;
   4398            return IC_ERROR_SENTINEL();
   4399          }
   4400          retValue = resultRooted.asRawBits();
   4401        }
   4402        PREDICT_RETURN();
   4403        DISPATCH_CACHEOP();
   4404      }
   4405 
   4406      CACHEOP_CASE(CallNativeSetter) {
   4407        ValOperandId receiverId = cacheIRReader.valOperandId();
   4408        uint32_t setterOffset = cacheIRReader.stubOffset();
   4409        ObjOperandId rhsId = cacheIRReader.objOperandId();
   4410        bool sameRealm = cacheIRReader.readBool();
   4411        uint32_t nargsAndFlagsOffset = cacheIRReader.stubOffset();
   4412        (void)sameRealm;
   4413        (void)nargsAndFlagsOffset;
   4414        JSObject* receiver =
   4415            reinterpret_cast<JSObject*>(READ_REG(receiverId.id()));
   4416        Value rhs = READ_VALUE_REG(rhsId.id());
   4417        JSFunction* setter = reinterpret_cast<JSFunction*>(
   4418            stubInfo->getStubRawWord(cstub, setterOffset));
   4419        {
   4420          PUSH_IC_FRAME();
   4421          ReservedRooted<JSFunction*> setterRooted(&ctx.state.fun0, setter);
   4422          ReservedRooted<JSObject*> receiverRooted(&ctx.state.obj0, receiver);
   4423          ReservedRooted<Value> rhsRooted(&ctx.state.value1, rhs);
   4424          if (!CallNativeSetter(cx, setterRooted, receiverRooted, rhsRooted)) {
   4425            ctx.error = PBIResult::Error;
   4426            return IC_ERROR_SENTINEL();
   4427          }
   4428        }
   4429        PREDICT_RETURN();
   4430        DISPATCH_CACHEOP();
   4431      }
   4432 
   4433      CACHEOP_CASE(LoadInstanceOfObjectResult) {
   4434        ValOperandId lhsId = cacheIRReader.valOperandId();
   4435        ObjOperandId protoId = cacheIRReader.objOperandId();
   4436        Value lhs = READ_VALUE_REG(lhsId.id());
   4437        JSObject* rhsProto =
   4438            reinterpret_cast<JSObject*>(READ_REG(protoId.id()));
   4439        if (!lhs.isObject()) {
   4440          retValue = BooleanValue(false).asRawBits();
   4441          PREDICT_RETURN();
   4442          DISPATCH_CACHEOP();
   4443        }
   4444 
   4445        JSObject* lhsObj = &lhs.toObject();
   4446        bool result = false;
   4447        while (true) {
   4448          TaggedProto proto = lhsObj->taggedProto();
   4449          if (proto.isDynamic()) {
   4450            FAIL_IC();
   4451          }
   4452          JSObject* protoObj = proto.toObjectOrNull();
   4453          if (!protoObj) {
   4454            result = false;
   4455            break;
   4456          }
   4457          if (protoObj == rhsProto) {
   4458            result = true;
   4459            break;
   4460          }
   4461          lhsObj = protoObj;
   4462        }
   4463        retValue = BooleanValue(result).asRawBits();
   4464        PREDICT_RETURN();
   4465        DISPATCH_CACHEOP();
   4466      }
   4467 
   4468      CACHEOP_CASE(StringFromCharCodeResult) {
   4469        Int32OperandId codeId = cacheIRReader.int32OperandId();
   4470        uint32_t code = uint32_t(READ_REG(codeId.id()));
   4471        StaticStrings& sstr = ctx.frameMgr.cxForLocalUseOnly()->staticStrings();
   4472        if (sstr.hasUnit(code)) {
   4473          retValue = StringValue(sstr.getUnit(code)).asRawBits();
   4474        } else {
   4475          PUSH_IC_FRAME();
   4476          auto* result = StringFromCharCode(cx, code);
   4477          if (!result) {
   4478            FAIL_IC();
   4479          }
   4480          retValue = StringValue(result).asRawBits();
   4481        }
   4482        PREDICT_RETURN();
   4483        DISPATCH_CACHEOP();
   4484      }
   4485 
   4486      CACHEOP_CASE(StringFromCodePointResult) {
   4487        Int32OperandId codeId = cacheIRReader.int32OperandId();
   4488        uint32_t code = uint32_t(READ_REG(codeId.id()));
   4489        if (code > unicode::NonBMPMax) {
   4490          FAIL_IC();
   4491        }
   4492        StaticStrings& sstr = ctx.frameMgr.cxForLocalUseOnly()->staticStrings();
   4493        if (sstr.hasUnit(code)) {
   4494          retValue = StringValue(sstr.getUnit(code)).asRawBits();
   4495        } else {
   4496          PUSH_IC_FRAME();
   4497          auto* result = StringFromCodePoint(cx, code);
   4498          if (!result) {
   4499            FAIL_IC();
   4500          }
   4501          retValue = StringValue(result).asRawBits();
   4502        }
   4503        PREDICT_RETURN();
   4504        DISPATCH_CACHEOP();
   4505      }
   4506 
   4507      CACHEOP_CASE(StringIncludesResult) {
   4508        StringOperandId strId = cacheIRReader.stringOperandId();
   4509        StringOperandId searchStrId = cacheIRReader.stringOperandId();
   4510        JSString* str = reinterpret_cast<JSString*>(READ_REG(strId.id()));
   4511        JSString* searchStr =
   4512            reinterpret_cast<JSString*>(READ_REG(searchStrId.id()));
   4513        {
   4514          PUSH_IC_FRAME();
   4515          ReservedRooted<JSString*> str0(&ctx.state.str0, str);
   4516          ReservedRooted<JSString*> str1(&ctx.state.str1, searchStr);
   4517          bool result = false;
   4518          if (!StringIncludes(cx, str0, str1, &result)) {
   4519            ctx.error = PBIResult::Error;
   4520            return IC_ERROR_SENTINEL();
   4521          }
   4522          retValue = BooleanValue(result).asRawBits();
   4523        }
   4524        PREDICT_RETURN();
   4525        DISPATCH_CACHEOP();
   4526      }
   4527 
   4528      CACHEOP_CASE(StringIndexOfResult) {
   4529        StringOperandId strId = cacheIRReader.stringOperandId();
   4530        StringOperandId searchStrId = cacheIRReader.stringOperandId();
   4531        JSString* str = reinterpret_cast<JSString*>(READ_REG(strId.id()));
   4532        JSString* searchStr =
   4533            reinterpret_cast<JSString*>(READ_REG(searchStrId.id()));
   4534        {
   4535          PUSH_IC_FRAME();
   4536          ReservedRooted<JSString*> str0(&ctx.state.str0, str);
   4537          ReservedRooted<JSString*> str1(&ctx.state.str1, searchStr);
   4538          int32_t result = 0;
   4539          if (!StringIndexOf(cx, str0, str1, &result)) {
   4540            ctx.error = PBIResult::Error;
   4541            return IC_ERROR_SENTINEL();
   4542          }
   4543          retValue = Int32Value(result).asRawBits();
   4544        }
   4545        PREDICT_RETURN();
   4546        DISPATCH_CACHEOP();
   4547      }
   4548 
   4549      CACHEOP_CASE(StringLastIndexOfResult) {
   4550        StringOperandId strId = cacheIRReader.stringOperandId();
   4551        StringOperandId searchStrId = cacheIRReader.stringOperandId();
   4552        JSString* str = reinterpret_cast<JSString*>(READ_REG(strId.id()));
   4553        JSString* searchStr =
   4554            reinterpret_cast<JSString*>(READ_REG(searchStrId.id()));
   4555        {
   4556          PUSH_IC_FRAME();
   4557          ReservedRooted<JSString*> str0(&ctx.state.str0, str);
   4558          ReservedRooted<JSString*> str1(&ctx.state.str1, searchStr);
   4559          int32_t result = 0;
   4560          if (!StringLastIndexOf(cx, str0, str1, &result)) {
   4561            ctx.error = PBIResult::Error;
   4562            return IC_ERROR_SENTINEL();
   4563          }
   4564          retValue = Int32Value(result).asRawBits();
   4565        }
   4566        PREDICT_RETURN();
   4567        DISPATCH_CACHEOP();
   4568      }
   4569 
   4570      CACHEOP_CASE(StringStartsWithResult) {
   4571        StringOperandId strId = cacheIRReader.stringOperandId();
   4572        StringOperandId searchStrId = cacheIRReader.stringOperandId();
   4573        JSString* str = reinterpret_cast<JSString*>(READ_REG(strId.id()));
   4574        JSString* searchStr =
   4575            reinterpret_cast<JSString*>(READ_REG(searchStrId.id()));
   4576        {
   4577          PUSH_IC_FRAME();
   4578          ReservedRooted<JSString*> str0(&ctx.state.str0, str);
   4579          ReservedRooted<JSString*> str1(&ctx.state.str1, searchStr);
   4580          bool result = false;
   4581          if (!StringStartsWith(cx, str0, str1, &result)) {
   4582            ctx.error = PBIResult::Error;
   4583            return IC_ERROR_SENTINEL();
   4584          }
   4585          retValue = BooleanValue(result).asRawBits();
   4586        }
   4587        PREDICT_RETURN();
   4588        DISPATCH_CACHEOP();
   4589      }
   4590 
   4591      CACHEOP_CASE(StringEndsWithResult) {
   4592        StringOperandId strId = cacheIRReader.stringOperandId();
   4593        StringOperandId searchStrId = cacheIRReader.stringOperandId();
   4594        JSString* str = reinterpret_cast<JSString*>(READ_REG(strId.id()));
   4595        JSString* searchStr =
   4596            reinterpret_cast<JSString*>(READ_REG(searchStrId.id()));
   4597        {
   4598          PUSH_IC_FRAME();
   4599          ReservedRooted<JSString*> str0(&ctx.state.str0, str);
   4600          ReservedRooted<JSString*> str1(&ctx.state.str1, searchStr);
   4601          bool result = false;
   4602          if (!StringEndsWith(cx, str0, str1, &result)) {
   4603            ctx.error = PBIResult::Error;
   4604            return IC_ERROR_SENTINEL();
   4605          }
   4606          retValue = BooleanValue(result).asRawBits();
   4607        }
   4608        PREDICT_RETURN();
   4609        DISPATCH_CACHEOP();
   4610      }
   4611 
   4612      CACHEOP_CASE(StringToLowerCaseResult) {
   4613        StringOperandId strId = cacheIRReader.stringOperandId();
   4614        JSString* str = reinterpret_cast<JSString*>(READ_REG(strId.id()));
   4615        {
   4616          PUSH_IC_FRAME();
   4617          auto* result = StringToLowerCase(cx, str);
   4618          if (!result) {
   4619            ctx.error = PBIResult::Error;
   4620            return IC_ERROR_SENTINEL();
   4621          }
   4622          retValue = StringValue(result).asRawBits();
   4623        }
   4624        PREDICT_RETURN();
   4625        DISPATCH_CACHEOP();
   4626      }
   4627 
   4628      CACHEOP_CASE(StringToUpperCaseResult) {
   4629        StringOperandId strId = cacheIRReader.stringOperandId();
   4630        JSString* str = reinterpret_cast<JSString*>(READ_REG(strId.id()));
   4631        {
   4632          PUSH_IC_FRAME();
   4633          auto* result = StringToUpperCase(cx, str);
   4634          if (!result) {
   4635            ctx.error = PBIResult::Error;
   4636            return IC_ERROR_SENTINEL();
   4637          }
   4638          retValue = StringValue(result).asRawBits();
   4639        }
   4640        PREDICT_RETURN();
   4641        DISPATCH_CACHEOP();
   4642      }
   4643 
   4644      CACHEOP_CASE(StringTrimResult) {
   4645        StringOperandId strId = cacheIRReader.stringOperandId();
   4646        JSString* str = reinterpret_cast<JSString*>(READ_REG(strId.id()));
   4647        {
   4648          PUSH_IC_FRAME();
   4649          ReservedRooted<JSString*> str0(&ctx.state.str0, str);
   4650          auto* result = StringTrim(cx, str0);
   4651          if (!result) {
   4652            ctx.error = PBIResult::Error;
   4653            return IC_ERROR_SENTINEL();
   4654          }
   4655          retValue = StringValue(result).asRawBits();
   4656        }
   4657        PREDICT_RETURN();
   4658        DISPATCH_CACHEOP();
   4659      }
   4660 
   4661      CACHEOP_CASE(StringTrimStartResult) {
   4662        StringOperandId strId = cacheIRReader.stringOperandId();
   4663        JSString* str = reinterpret_cast<JSString*>(READ_REG(strId.id()));
   4664        {
   4665          PUSH_IC_FRAME();
   4666          ReservedRooted<JSString*> str0(&ctx.state.str0, str);
   4667          auto* result = StringTrimStart(cx, str0);
   4668          if (!result) {
   4669            ctx.error = PBIResult::Error;
   4670            return IC_ERROR_SENTINEL();
   4671          }
   4672          retValue = StringValue(result).asRawBits();
   4673        }
   4674        PREDICT_RETURN();
   4675        DISPATCH_CACHEOP();
   4676      }
   4677 
   4678      CACHEOP_CASE(StringTrimEndResult) {
   4679        StringOperandId strId = cacheIRReader.stringOperandId();
   4680        JSString* str = reinterpret_cast<JSString*>(READ_REG(strId.id()));
   4681        {
   4682          PUSH_IC_FRAME();
   4683          ReservedRooted<JSString*> str0(&ctx.state.str0, str);
   4684          auto* result = StringTrimEnd(cx, str0);
   4685          if (!result) {
   4686            ctx.error = PBIResult::Error;
   4687            return IC_ERROR_SENTINEL();
   4688          }
   4689          retValue = StringValue(result).asRawBits();
   4690        }
   4691        PREDICT_RETURN();
   4692        DISPATCH_CACHEOP();
   4693      }
   4694 
   4695      CACHEOP_CASE(CallSubstringKernelResult) {
   4696        StringOperandId strId = cacheIRReader.stringOperandId();
   4697        Int32OperandId beginId = cacheIRReader.int32OperandId();
   4698        Int32OperandId lengthId = cacheIRReader.int32OperandId();
   4699        JSString* str = reinterpret_cast<JSString*>(READ_REG(strId.id()));
   4700        int32_t begin = int32_t(READ_REG(beginId.id()));
   4701        int32_t length = int32_t(READ_REG(lengthId.id()));
   4702        {
   4703          PUSH_IC_FRAME();
   4704          ReservedRooted<JSString*> str0(&ctx.state.str0, str);
   4705          auto* result = SubstringKernel(cx, str0, begin, length);
   4706          if (!result) {
   4707            ctx.error = PBIResult::Error;
   4708            return IC_ERROR_SENTINEL();
   4709          }
   4710          retValue = StringValue(result).asRawBits();
   4711        }
   4712        PREDICT_RETURN();
   4713        DISPATCH_CACHEOP();
   4714      }
   4715 
   4716      CACHEOP_CASE(StringReplaceStringResult) {
   4717        StringOperandId strId = cacheIRReader.stringOperandId();
   4718        StringOperandId patternId = cacheIRReader.stringOperandId();
   4719        StringOperandId replacementId = cacheIRReader.stringOperandId();
   4720        JSString* str = reinterpret_cast<JSString*>(READ_REG(strId.id()));
   4721        JSString* pattern =
   4722            reinterpret_cast<JSString*>(READ_REG(patternId.id()));
   4723        JSString* replacement =
   4724            reinterpret_cast<JSString*>(READ_REG(replacementId.id()));
   4725        {
   4726          PUSH_IC_FRAME();
   4727          ReservedRooted<JSString*> str0(&ctx.state.str0, str);
   4728          ReservedRooted<JSString*> str1(&ctx.state.str1, pattern);
   4729          ReservedRooted<JSString*> str2(&ctx.state.str2, replacement);
   4730          auto* result = StringReplace(cx, str0, str1, str2);
   4731          if (!result) {
   4732            ctx.error = PBIResult::Error;
   4733            return IC_ERROR_SENTINEL();
   4734          }
   4735          retValue = StringValue(result).asRawBits();
   4736        }
   4737        PREDICT_RETURN();
   4738        DISPATCH_CACHEOP();
   4739      }
   4740 
   4741      CACHEOP_CASE(StringSplitStringResult) {
   4742        StringOperandId strId = cacheIRReader.stringOperandId();
   4743        StringOperandId separatorId = cacheIRReader.stringOperandId();
   4744        JSString* str = reinterpret_cast<JSString*>(READ_REG(strId.id()));
   4745        JSString* separator =
   4746            reinterpret_cast<JSString*>(READ_REG(separatorId.id()));
   4747        {
   4748          PUSH_IC_FRAME();
   4749          ReservedRooted<JSString*> str0(&ctx.state.str0, str);
   4750          ReservedRooted<JSString*> str1(&ctx.state.str1, separator);
   4751          auto* result = StringSplitString(cx, str0, str1, INT32_MAX);
   4752          if (!result) {
   4753            ctx.error = PBIResult::Error;
   4754            return IC_ERROR_SENTINEL();
   4755          }
   4756          retValue = ObjectValue(*result).asRawBits();
   4757        }
   4758        PREDICT_RETURN();
   4759        DISPATCH_CACHEOP();
   4760      }
   4761 
   4762      CACHEOP_CASE(StringToAtom) {
   4763        StringOperandId strId = cacheIRReader.stringOperandId();
   4764        JSString* str = reinterpret_cast<JSString*>(READ_REG(strId.id()));
   4765        JSAtom* result =
   4766            AtomizeStringNoGC(ctx.frameMgr.cxForLocalUseOnly(), str);
   4767        if (!result) {
   4768          FAIL_IC();
   4769        }
   4770        WRITE_REG(strId.id(), reinterpret_cast<uint64_t>(result), STRING);
   4771        DISPATCH_CACHEOP();
   4772      }
   4773 
   4774      CACHEOP_CASE(IdToStringOrSymbol) {
   4775        ValOperandId resultId = cacheIRReader.valOperandId();
   4776        ValOperandId idId = cacheIRReader.valOperandId();
   4777        BOUNDSCHECK(resultId);
   4778        Value id = READ_VALUE_REG(idId.id());
   4779        if (id.isString() || id.isSymbol()) {
   4780          WRITE_VALUE_REG(resultId.id(), id);
   4781        } else if (id.isInt32()) {
   4782          int32_t idInt = id.toInt32();
   4783          StaticStrings& sstr =
   4784              ctx.frameMgr.cxForLocalUseOnly()->staticStrings();
   4785          if (sstr.hasInt(idInt)) {
   4786            WRITE_VALUE_REG(resultId.id(), StringValue(sstr.getInt(idInt)));
   4787          } else {
   4788            PUSH_IC_FRAME();
   4789            auto* result = Int32ToStringPure(cx, idInt);
   4790            if (!result) {
   4791              ctx.error = PBIResult::Error;
   4792              return IC_ERROR_SENTINEL();
   4793            }
   4794            WRITE_VALUE_REG(resultId.id(), StringValue(result));
   4795          }
   4796        } else {
   4797          FAIL_IC();
   4798        }
   4799        DISPATCH_CACHEOP();
   4800      }
   4801 
   4802      CACHEOP_CASE(NewStringIteratorResult) {
   4803        uint32_t templateObjectOffset = cacheIRReader.stubOffset();
   4804        (void)templateObjectOffset;
   4805        {
   4806          PUSH_IC_FRAME();
   4807          auto* result = NewStringIterator(cx);
   4808          if (!result) {
   4809            ctx.error = PBIResult::Error;
   4810            return IC_ERROR_SENTINEL();
   4811          }
   4812          retValue = ObjectValue(*result).asRawBits();
   4813        }
   4814        PREDICT_RETURN();
   4815        DISPATCH_CACHEOP();
   4816      }
   4817 
   4818      CACHEOP_CASE(IsArrayResult) {
   4819        ValOperandId valId = cacheIRReader.valOperandId();
   4820        Value val = READ_VALUE_REG(valId.id());
   4821        if (!val.isObject()) {
   4822          retValue = BooleanValue(false).asRawBits();
   4823        } else {
   4824          JSObject* obj = &val.toObject();
   4825          if (obj->getClass()->isProxyObject()) {
   4826            FAIL_IC();
   4827          }
   4828          retValue = BooleanValue(obj->is<ArrayObject>()).asRawBits();
   4829        }
   4830        PREDICT_RETURN();
   4831        DISPATCH_CACHEOP();
   4832      }
   4833 
   4834      CACHEOP_CASE(IsCallableResult) {
   4835        ValOperandId valId = cacheIRReader.valOperandId();
   4836        Value val = READ_VALUE_REG(valId.id());
   4837        if (!val.isObject()) {
   4838          retValue = BooleanValue(false).asRawBits();
   4839        } else {
   4840          JSObject* obj = &val.toObject();
   4841          if (obj->getClass()->isProxyObject()) {
   4842            FAIL_IC();
   4843          }
   4844          bool callable =
   4845              obj->is<JSFunction>() || obj->getClass()->getCall() != nullptr;
   4846          retValue = BooleanValue(callable).asRawBits();
   4847        }
   4848        PREDICT_RETURN();
   4849        DISPATCH_CACHEOP();
   4850      }
   4851 
   4852      CACHEOP_CASE(IsConstructorResult) {
   4853        ObjOperandId objId = cacheIRReader.objOperandId();
   4854        JSObject* obj = reinterpret_cast<JSObject*>(READ_REG(objId.id()));
   4855        bool ctor = obj->isConstructor();
   4856        retValue = BooleanValue(ctor).asRawBits();
   4857        PREDICT_RETURN();
   4858        DISPATCH_CACHEOP();
   4859      }
   4860 
   4861      CACHEOP_CASE(IsCrossRealmArrayConstructorResult) {
   4862        ObjOperandId objId = cacheIRReader.objOperandId();
   4863        JSObject* obj = reinterpret_cast<JSObject*>(READ_REG(objId.id()));
   4864        bool result =
   4865            obj->shape()->realm() !=
   4866                ctx.frameMgr.cxForLocalUseOnly()->realm() &&
   4867            obj->is<JSFunction>() && obj->as<JSFunction>().isNativeFun() &&
   4868            obj->as<JSFunction>().nativeUnchecked() == &js::ArrayConstructor;
   4869        retValue = BooleanValue(result).asRawBits();
   4870        PREDICT_RETURN();
   4871        DISPATCH_CACHEOP();
   4872      }
   4873 
   4874      CACHEOP_CASE(IsTypedArrayResult) {
   4875        ObjOperandId objId = cacheIRReader.objOperandId();
   4876        bool isPossiblyWrapped = cacheIRReader.readBool();
   4877        JSObject* obj = reinterpret_cast<JSObject*>(READ_REG(objId.id()));
   4878        if (IsTypedArrayClass(obj->getClass())) {
   4879          retValue = BooleanValue(true).asRawBits();
   4880        } else if (isPossiblyWrapped && obj->is<WrapperObject>()) {
   4881          PUSH_IC_FRAME();
   4882          bool result;
   4883          if (!IsPossiblyWrappedTypedArray(cx, obj, &result)) {
   4884            ctx.error = PBIResult::Error;
   4885            return IC_ERROR_SENTINEL();
   4886          }
   4887          retValue = BooleanValue(result).asRawBits();
   4888        } else {
   4889          retValue = BooleanValue(false).asRawBits();
   4890        }
   4891        PREDICT_RETURN();
   4892        DISPATCH_CACHEOP();
   4893      }
   4894 
   4895      CACHEOP_CASE(IsTypedArrayConstructorResult) {
   4896        ObjOperandId objId = cacheIRReader.objOperandId();
   4897        JSObject* obj = reinterpret_cast<JSObject*>(READ_REG(objId.id()));
   4898        retValue = BooleanValue(IsTypedArrayConstructor(obj)).asRawBits();
   4899        PREDICT_RETURN();
   4900        DISPATCH_CACHEOP();
   4901      }
   4902 
   4903      CACHEOP_CASE(ArrayBufferViewByteOffsetInt32Result) {
   4904        ObjOperandId objId = cacheIRReader.objOperandId();
   4905        ArrayBufferViewObject* abvo =
   4906            reinterpret_cast<ArrayBufferViewObject*>(READ_REG(objId.id()));
   4907        size_t byteOffset =
   4908            size_t(abvo->getFixedSlot(ArrayBufferViewObject::BYTEOFFSET_SLOT)
   4909                       .toPrivate());
   4910        if (byteOffset > size_t(INT32_MAX)) {
   4911          FAIL_IC();
   4912        }
   4913        retValue = Int32Value(int32_t(byteOffset)).asRawBits();
   4914        PREDICT_RETURN();
   4915        DISPATCH_CACHEOP();
   4916      }
   4917 
   4918      CACHEOP_CASE(ArrayBufferViewByteOffsetDoubleResult) {
   4919        ObjOperandId objId = cacheIRReader.objOperandId();
   4920        ArrayBufferViewObject* abvo =
   4921            reinterpret_cast<ArrayBufferViewObject*>(READ_REG(objId.id()));
   4922        size_t byteOffset =
   4923            size_t(abvo->getFixedSlot(ArrayBufferViewObject::BYTEOFFSET_SLOT)
   4924                       .toPrivate());
   4925        retValue = DoubleValue(double(byteOffset)).asRawBits();
   4926        PREDICT_RETURN();
   4927        DISPATCH_CACHEOP();
   4928      }
   4929 
   4930      CACHEOP_CASE(TypedArrayByteLengthInt32Result) {
   4931        ObjOperandId objId = cacheIRReader.objOperandId();
   4932        TypedArrayObject* tao =
   4933            reinterpret_cast<TypedArrayObject*>(READ_REG(objId.id()));
   4934        if (!tao->length()) {
   4935          FAIL_IC();
   4936        }
   4937        size_t length = *tao->length() * tao->bytesPerElement();
   4938        if (length > size_t(INT32_MAX)) {
   4939          FAIL_IC();
   4940        }
   4941        retValue = Int32Value(int32_t(length)).asRawBits();
   4942        PREDICT_RETURN();
   4943        DISPATCH_CACHEOP();
   4944      }
   4945 
   4946      CACHEOP_CASE(TypedArrayByteLengthDoubleResult) {
   4947        ObjOperandId objId = cacheIRReader.objOperandId();
   4948        TypedArrayObject* tao =
   4949            reinterpret_cast<TypedArrayObject*>(READ_REG(objId.id()));
   4950        if (!tao->length()) {
   4951          FAIL_IC();
   4952        }
   4953        size_t length = *tao->length() * tao->bytesPerElement();
   4954        retValue = DoubleValue(double(length)).asRawBits();
   4955        PREDICT_RETURN();
   4956        DISPATCH_CACHEOP();
   4957      }
   4958 
   4959      CACHEOP_CASE(MegamorphicStoreSlot) {
   4960        ObjOperandId objId = cacheIRReader.objOperandId();
   4961        uint32_t nameOffset = cacheIRReader.stubOffset();
   4962        ValOperandId valId = cacheIRReader.valOperandId();
   4963        bool strict = cacheIRReader.readBool();
   4964 
   4965        JSObject* obj = reinterpret_cast<JSObject*>(READ_REG(objId.id()));
   4966        jsid id =
   4967            jsid::fromRawBits(stubInfo->getStubRawWord(cstub, nameOffset));
   4968        Value val = READ_VALUE_REG(valId.id());
   4969 
   4970        {
   4971          PUSH_IC_FRAME();
   4972          ReservedRooted<JSObject*> objRooted(&ctx.state.obj0, obj);
   4973          ReservedRooted<jsid> idRooted(&ctx.state.id0, id);
   4974          ReservedRooted<Value> valRooted(&ctx.state.value0, val);
   4975          if (!SetPropertyMegamorphic<false>(cx, objRooted, idRooted, valRooted,
   4976                                             strict)) {
   4977            ctx.error = PBIResult::Error;
   4978            return IC_ERROR_SENTINEL();
   4979          }
   4980        }
   4981 
   4982        PREDICT_RETURN();
   4983        DISPATCH_CACHEOP();
   4984      }
   4985 
   4986      CACHEOP_CASE(MegamorphicHasPropResult) {
   4987        ObjOperandId objId = cacheIRReader.objOperandId();
   4988        ValOperandId valId = cacheIRReader.valOperandId();
   4989        bool hasOwn = cacheIRReader.readBool();
   4990        JSObject* obj = reinterpret_cast<JSObject*>(READ_REG(objId.id()));
   4991        if (!obj->is<NativeObject>()) {
   4992          FAIL_IC();
   4993        }
   4994        Value val[2] = {READ_VALUE_REG(valId.id()), UndefinedValue()};
   4995        {
   4996          PUSH_IC_FRAME();
   4997          bool ok =
   4998              hasOwn
   4999                  ? HasNativeDataPropertyPure<true>(cx, obj, nullptr, &val[0])
   5000                  : HasNativeDataPropertyPure<false>(cx, obj, nullptr, &val[0]);
   5001          if (!ok) {
   5002            FAIL_IC();
   5003          }
   5004          retValue = val[1].asRawBits();
   5005        }
   5006        PREDICT_RETURN();
   5007        DISPATCH_CACHEOP();
   5008      }
   5009 
   5010      CACHEOP_CASE(ArrayJoinResult) {
   5011        ObjOperandId objId = cacheIRReader.objOperandId();
   5012        StringOperandId sepId = cacheIRReader.stringOperandId();
   5013        JSObject* obj = reinterpret_cast<JSObject*>(READ_REG(objId.id()));
   5014        JSString* sep = reinterpret_cast<JSString*>(READ_REG(sepId.id()));
   5015        {
   5016          PUSH_IC_FRAME();
   5017          ReservedRooted<JSObject*> obj0(&ctx.state.obj0, obj);
   5018          ReservedRooted<JSString*> str0(&ctx.state.str0, sep);
   5019          auto* result = ArrayJoin(cx, obj0, str0);
   5020          if (!result) {
   5021            ctx.error = PBIResult::Error;
   5022            return IC_ERROR_SENTINEL();
   5023          }
   5024          retValue = StringValue(result).asRawBits();
   5025        }
   5026        PREDICT_RETURN();
   5027        DISPATCH_CACHEOP();
   5028      }
   5029 
   5030      CACHEOP_CASE(CallSetArrayLength) {
   5031        ObjOperandId objId = cacheIRReader.objOperandId();
   5032        bool strict = cacheIRReader.readBool();
   5033        ValOperandId rhsId = cacheIRReader.valOperandId();
   5034        JSObject* obj = reinterpret_cast<JSObject*>(READ_REG(objId.id()));
   5035        Value rhs = READ_VALUE_REG(rhsId.id());
   5036        {
   5037          PUSH_IC_FRAME();
   5038          ReservedRooted<JSObject*> obj0(&ctx.state.obj0, obj);
   5039          ReservedRooted<Value> value0(&ctx.state.value0, rhs);
   5040          if (!SetArrayLength(cx, obj0, value0, strict)) {
   5041            ctx.error = PBIResult::Error;
   5042            return IC_ERROR_SENTINEL();
   5043          }
   5044        }
   5045        PREDICT_RETURN();
   5046        DISPATCH_CACHEOP();
   5047      }
   5048 
   5049      CACHEOP_CASE(ObjectKeysResult) {
   5050        ObjOperandId objId = cacheIRReader.objOperandId();
   5051        JSObject* obj = reinterpret_cast<JSObject*>(READ_REG(objId.id()));
   5052        {
   5053          PUSH_IC_FRAME();
   5054          ReservedRooted<JSObject*> obj0(&ctx.state.obj0, obj);
   5055          auto* result = ObjectKeys(cx, obj0);
   5056          if (!result) {
   5057            ctx.error = PBIResult::Error;
   5058            return IC_ERROR_SENTINEL();
   5059          }
   5060          retValue = ObjectValue(*result).asRawBits();
   5061        }
   5062        PREDICT_RETURN();
   5063        DISPATCH_CACHEOP();
   5064      }
   5065 
   5066      CACHEOP_CASE(ObjectCreateResult) {
   5067        uint32_t templateOffset = cacheIRReader.stubOffset();
   5068        PlainObject* templateObj = reinterpret_cast<PlainObject*>(
   5069            stubInfo->getStubRawWord(cstub, templateOffset));
   5070        {
   5071          PUSH_IC_FRAME();
   5072          Rooted<PlainObject*> templateRooted(cx, templateObj);
   5073          auto* result = ObjectCreateWithTemplate(cx, templateRooted);
   5074          if (!result) {
   5075            ctx.error = PBIResult::Error;
   5076            return IC_ERROR_SENTINEL();
   5077          }
   5078          retValue = ObjectValue(*result).asRawBits();
   5079        }
   5080        PREDICT_RETURN();
   5081        DISPATCH_CACHEOP();
   5082      }
   5083 
   5084      CACHEOP_CASE(CallNumberToString) {
   5085        NumberOperandId inputId = cacheIRReader.numberOperandId();
   5086        StringOperandId resultId = cacheIRReader.stringOperandId();
   5087        BOUNDSCHECK(resultId);
   5088        double input = READ_VALUE_REG(inputId.id()).toNumber();
   5089        {
   5090          PUSH_IC_FRAME();
   5091          auto* result = NumberToStringPure(cx, input);
   5092          if (!result) {
   5093            FAIL_IC();
   5094          }
   5095          WRITE_REG(resultId.id(), reinterpret_cast<uint64_t>(result), STRING);
   5096        }
   5097        PREDICT_RETURN();
   5098        DISPATCH_CACHEOP();
   5099      }
   5100 
   5101      CACHEOP_CASE(Int32ToStringWithBaseResult) {
   5102        Int32OperandId inputId = cacheIRReader.int32OperandId();
   5103        Int32OperandId baseId = cacheIRReader.int32OperandId();
   5104        int32_t input = int32_t(READ_REG(inputId.id()));
   5105        int32_t base = int32_t(READ_REG(baseId.id()));
   5106        if (base < 2 || base > 36) {
   5107          FAIL_IC();
   5108        }
   5109        {
   5110          PUSH_IC_FRAME();
   5111          auto* result = Int32ToStringWithBase<CanGC>(cx, input, base, true);
   5112          if (!result) {
   5113            ctx.error = PBIResult::Error;
   5114            return IC_ERROR_SENTINEL();
   5115          }
   5116          retValue = StringValue(result).asRawBits();
   5117        }
   5118        PREDICT_RETURN();
   5119        DISPATCH_CACHEOP();
   5120      }
   5121 
   5122      CACHEOP_CASE(BooleanToString) {
   5123        BooleanOperandId inputId = cacheIRReader.booleanOperandId();
   5124        StringOperandId resultId = cacheIRReader.stringOperandId();
   5125        BOUNDSCHECK(resultId);
   5126        bool input = READ_REG(inputId.id()) != 0;
   5127        auto& names = ctx.frameMgr.cxForLocalUseOnly()->names();
   5128        JSString* result = input ? names.true_ : names.false_;
   5129        WRITE_REG(resultId.id(), reinterpret_cast<uint64_t>(result), STRING);
   5130        DISPATCH_CACHEOP();
   5131      }
   5132 
   5133      CACHEOP_CASE(IndirectTruncateInt32Result) {
   5134        Int32OperandId valId = cacheIRReader.int32OperandId();
   5135        int32_t value = int32_t(READ_REG(valId.id()));
   5136        retValue = Int32Value(value).asRawBits();
   5137        PREDICT_RETURN();
   5138        DISPATCH_CACHEOP();
   5139      }
   5140 
   5141      CACHEOP_CASE(GetFirstDollarIndexResult) {
   5142        StringOperandId strId = cacheIRReader.stringOperandId();
   5143        JSString* str = reinterpret_cast<JSString*>(READ_REG(strId.id()));
   5144        int32_t result = 0;
   5145        {
   5146          PUSH_IC_FRAME();
   5147          if (!GetFirstDollarIndexRaw(cx, str, &result)) {
   5148            ctx.error = PBIResult::Error;
   5149            return IC_ERROR_SENTINEL();
   5150          }
   5151          retValue = Int32Value(result).asRawBits();
   5152        }
   5153        PREDICT_RETURN();
   5154        DISPATCH_CACHEOP();
   5155      }
   5156 
   5157      CACHEOP_CASE(LoadBoundFunctionNumArgs) {
   5158        ObjOperandId objId = cacheIRReader.objOperandId();
   5159        Int32OperandId resultId = cacheIRReader.int32OperandId();
   5160        BOUNDSCHECK(resultId);
   5161        BoundFunctionObject* obj =
   5162            reinterpret_cast<BoundFunctionObject*>(READ_REG(objId.id()));
   5163        WRITE_REG(resultId.id(), obj->numBoundArgs(), INT32);
   5164        DISPATCH_CACHEOP();
   5165      }
   5166 
   5167      CACHEOP_CASE(LoadBoundFunctionTarget) {
   5168        ObjOperandId objId = cacheIRReader.objOperandId();
   5169        ObjOperandId resultId = cacheIRReader.objOperandId();
   5170        BOUNDSCHECK(resultId);
   5171        BoundFunctionObject* obj =
   5172            reinterpret_cast<BoundFunctionObject*>(READ_REG(objId.id()));
   5173        WRITE_REG(resultId.id(), reinterpret_cast<uint64_t>(obj->getTarget()),
   5174                  OBJECT);
   5175        DISPATCH_CACHEOP();
   5176      }
   5177 
   5178      CACHEOP_CASE(BindFunctionResult)
   5179      CACHEOP_CASE_FALLTHROUGH(SpecializedBindFunctionResult) {
   5180        ObjOperandId targetId = cacheIRReader.objOperandId();
   5181        uint32_t argc = cacheIRReader.uint32Immediate();
   5182        uint32_t templateObjectOffset = cacheIRReader.stubOffset();
   5183 
   5184        JSObject* target = reinterpret_cast<JSObject*>(READ_REG(targetId.id()));
   5185        BoundFunctionObject* templateObject =
   5186            (cacheop == CacheOp::SpecializedBindFunctionResult)
   5187                ? reinterpret_cast<BoundFunctionObject*>(
   5188                      stubInfo->getStubRawWord(cstub, templateObjectOffset))
   5189                : nullptr;
   5190 
   5191        StackVal* origArgs = ctx.sp();
   5192        {
   5193          PUSH_IC_FRAME();
   5194 
   5195          for (uint32_t i = 0; i < argc; i++) {
   5196            PUSH(origArgs[i]);
   5197          }
   5198          Value* args = reinterpret_cast<Value*>(sp);
   5199 
   5200          ReservedRooted<JSObject*> targetRooted(&ctx.state.obj0, target);
   5201          BoundFunctionObject* result;
   5202          if (cacheop == CacheOp::BindFunctionResult) {
   5203            result = BoundFunctionObject::functionBindImpl(cx, targetRooted,
   5204                                                           args, argc, nullptr);
   5205          } else {
   5206            Rooted<BoundFunctionObject*> templateObjectRooted(cx,
   5207                                                              templateObject);
   5208            result = BoundFunctionObject::functionBindSpecializedBaseline(
   5209                cx, targetRooted, args, argc, templateObjectRooted);
   5210          }
   5211          if (!result) {
   5212            ctx.error = PBIResult::Error;
   5213            return IC_ERROR_SENTINEL();
   5214          }
   5215 
   5216          retValue = ObjectValue(*result).asRawBits();
   5217        }
   5218        PREDICT_RETURN();
   5219        DISPATCH_CACHEOP();
   5220      }
   5221 
   5222      CACHEOP_CASE(CallRegExpMatcherResult)
   5223      CACHEOP_CASE_FALLTHROUGH(CallRegExpSearcherResult) {
   5224        ObjOperandId regexpId = cacheIRReader.objOperandId();
   5225        StringOperandId inputId = cacheIRReader.stringOperandId();
   5226        Int32OperandId lastIndexId = cacheIRReader.int32OperandId();
   5227        uint32_t stubOffset = cacheIRReader.stubOffset();
   5228 
   5229        JSObject* regexp = reinterpret_cast<JSObject*>(READ_REG(regexpId.id()));
   5230        JSString* input = reinterpret_cast<JSString*>(READ_REG(inputId.id()));
   5231        int32_t lastIndex = int32_t(READ_REG(lastIndexId.id()));
   5232        (void)stubOffset;
   5233 
   5234        {
   5235          PUSH_IC_FRAME();
   5236          ReservedRooted<JSObject*> regexpRooted(&ctx.state.obj0, regexp);
   5237          ReservedRooted<JSString*> inputRooted(&ctx.state.str0, input);
   5238 
   5239          if (cacheop == CacheOp::CallRegExpMatcherResult) {
   5240            ReservedRooted<Value> result(&ctx.state.value0, UndefinedValue());
   5241            if (!RegExpMatcherRaw(cx, regexpRooted, inputRooted, lastIndex,
   5242                                  nullptr, &result)) {
   5243              ctx.error = PBIResult::Error;
   5244              return IC_ERROR_SENTINEL();
   5245            }
   5246            retValue = result.asRawBits();
   5247          } else {
   5248            int32_t result = 0;
   5249            if (!RegExpSearcherRaw(cx, regexpRooted, inputRooted, lastIndex,
   5250                                   nullptr, &result)) {
   5251              ctx.error = PBIResult::Error;
   5252              return IC_ERROR_SENTINEL();
   5253            }
   5254            retValue = Int32Value(result).asRawBits();
   5255          }
   5256        }
   5257        PREDICT_RETURN();
   5258        DISPATCH_CACHEOP();
   5259      }
   5260 
   5261      CACHEOP_CASE(RegExpSearcherLastLimitResult) {
   5262        uint32_t lastLimit =
   5263            ctx.frameMgr.cxForLocalUseOnly()->regExpSearcherLastLimit;
   5264        retValue = Int32Value(lastLimit).asRawBits();
   5265        PREDICT_RETURN();
   5266        DISPATCH_CACHEOP();
   5267      }
   5268 
   5269      CACHEOP_CASE(RegExpHasCaptureGroupsResult) {
   5270        ObjOperandId regexpId = cacheIRReader.objOperandId();
   5271        StringOperandId inputId = cacheIRReader.stringOperandId();
   5272        RegExpObject* regexp =
   5273            reinterpret_cast<RegExpObject*>(READ_REG(regexpId.id()));
   5274        JSString* input = reinterpret_cast<JSString*>(READ_REG(inputId.id()));
   5275        {
   5276          PUSH_IC_FRAME();
   5277          Rooted<RegExpObject*> regexpRooted(cx, regexp);
   5278          ReservedRooted<JSString*> inputRooted(&ctx.state.str0, input);
   5279          bool result = false;
   5280          if (!RegExpHasCaptureGroups(cx, regexpRooted, inputRooted, &result)) {
   5281            ctx.error = PBIResult::Error;
   5282            return IC_ERROR_SENTINEL();
   5283          }
   5284          retValue = BooleanValue(result).asRawBits();
   5285        }
   5286        PREDICT_RETURN();
   5287        DISPATCH_CACHEOP();
   5288      }
   5289 
   5290      CACHEOP_CASE(RegExpBuiltinExecMatchResult) {
   5291        ObjOperandId regexpId = cacheIRReader.objOperandId();
   5292        StringOperandId inputId = cacheIRReader.stringOperandId();
   5293        uint32_t stubOffset = cacheIRReader.stubOffset();
   5294 
   5295        RegExpObject* regexp =
   5296            reinterpret_cast<RegExpObject*>(READ_REG(regexpId.id()));
   5297        JSString* input = reinterpret_cast<JSString*>(READ_REG(inputId.id()));
   5298        (void)stubOffset;
   5299 
   5300        {
   5301          PUSH_IC_FRAME();
   5302          Rooted<RegExpObject*> regexpRooted(cx, regexp);
   5303          ReservedRooted<JSString*> inputRooted(&ctx.state.str0, input);
   5304          ReservedRooted<Value> output(&ctx.state.value0, UndefinedValue());
   5305          if (!RegExpBuiltinExecMatchFromJit(cx, regexpRooted, inputRooted,
   5306                                             nullptr, &output)) {
   5307            ctx.error = PBIResult::Error;
   5308            return IC_ERROR_SENTINEL();
   5309          }
   5310          retValue = output.asRawBits();
   5311        }
   5312        PREDICT_RETURN();
   5313        DISPATCH_CACHEOP();
   5314      }
   5315 
   5316      CACHEOP_CASE(RegExpBuiltinExecTestResult) {
   5317        ObjOperandId regexpId = cacheIRReader.objOperandId();
   5318        StringOperandId inputId = cacheIRReader.stringOperandId();
   5319        uint32_t stubOffset = cacheIRReader.stubOffset();
   5320 
   5321        RegExpObject* regexp =
   5322            reinterpret_cast<RegExpObject*>(READ_REG(regexpId.id()));
   5323        JSString* input = reinterpret_cast<JSString*>(READ_REG(inputId.id()));
   5324        (void)stubOffset;
   5325 
   5326        {
   5327          PUSH_IC_FRAME();
   5328          Rooted<RegExpObject*> regexpRooted(cx, regexp);
   5329          ReservedRooted<JSString*> inputRooted(&ctx.state.str0, input);
   5330          bool result = false;
   5331          if (!RegExpBuiltinExecTestFromJit(cx, regexpRooted, inputRooted,
   5332                                            &result)) {
   5333            ctx.error = PBIResult::Error;
   5334            return IC_ERROR_SENTINEL();
   5335          }
   5336          retValue = BooleanValue(result).asRawBits();
   5337        }
   5338        PREDICT_RETURN();
   5339        DISPATCH_CACHEOP();
   5340      }
   5341 
   5342      CACHEOP_CASE(RegExpFlagResult) {
   5343        ObjOperandId regexpId = cacheIRReader.objOperandId();
   5344        uint32_t flagsMask = cacheIRReader.uint32Immediate();
   5345        RegExpObject* regexp =
   5346            reinterpret_cast<RegExpObject*>(READ_REG(regexpId.id()));
   5347        JS::RegExpFlags flags = regexp->getFlags();
   5348        retValue = BooleanValue((uint32_t(flags.value()) & flagsMask) != 0)
   5349                       .asRawBits();
   5350        PREDICT_RETURN();
   5351        DISPATCH_CACHEOP();
   5352      }
   5353 
   5354      CACHEOP_CASE(NewRegExpStringIteratorResult) {
   5355        uint32_t templateObjectOffset = cacheIRReader.stubOffset();
   5356        (void)templateObjectOffset;
   5357        {
   5358          PUSH_IC_FRAME();
   5359          auto* result = NewRegExpStringIterator(cx);
   5360          if (!result) {
   5361            ctx.error = PBIResult::Error;
   5362            return IC_ERROR_SENTINEL();
   5363          }
   5364          retValue = ObjectValue(*result).asRawBits();
   5365        }
   5366        PREDICT_RETURN();
   5367        DISPATCH_CACHEOP();
   5368      }
   5369 
   5370      CACHEOP_CASE(CallGetSparseElementResult) {
   5371        ObjOperandId objId = cacheIRReader.objOperandId();
   5372        Int32OperandId indexId = cacheIRReader.int32OperandId();
   5373        NativeObject* nobj =
   5374            reinterpret_cast<NativeObject*>(READ_REG(objId.id()));
   5375        int32_t index = int32_t(READ_REG(indexId.id()));
   5376        {
   5377          PUSH_IC_FRAME();
   5378          Rooted<NativeObject*> nobjRooted(cx, nobj);
   5379          ReservedRooted<Value> result(&ctx.state.value0, UndefinedValue());
   5380          if (!GetSparseElementHelper(cx, nobjRooted, index, &result)) {
   5381            ctx.error = PBIResult::Error;
   5382            return IC_ERROR_SENTINEL();
   5383          }
   5384          retValue = result.asRawBits();
   5385        }
   5386        PREDICT_RETURN();
   5387        DISPATCH_CACHEOP();
   5388      }
   5389 
   5390 #undef PREDICT_NEXT
   5391 
   5392 #ifndef ENABLE_COMPUTED_GOTO_DISPATCH
   5393      default:
   5394        TRACE_PRINTF("unknown CacheOp\n");
   5395        FAIL_IC();
   5396 #endif
   5397    }
   5398  }
   5399 
   5400 #define CACHEOP_UNIMPL(name, ...)               \
   5401  cacheop_##name : __attribute__((unused));     \
   5402  TRACE_PRINTF("unknown CacheOp: " #name "\n"); \
   5403  FAIL_IC();
   5404  CACHE_IR_OPS(CACHEOP_UNIMPL)
   5405 #undef CACHEOP_UNIMPL
   5406 
   5407 next_ic:
   5408  TRACE_PRINTF("IC failed; next IC\n");
   5409  return CallNextIC(arg0, arg1, stub, ctx);
   5410 }
   5411 
   5412 static MOZ_NEVER_INLINE uint64_t CallNextIC(uint64_t arg0, uint64_t arg1,
   5413                                            ICStub* stub, ICCtx& ctx) {
   5414  stub = stub->maybeNext();
   5415  MOZ_ASSERT(stub);
   5416  uint64_t result;
   5417  PBL_CALL_IC(stub->rawJitCode(), ctx, stub, result, arg0, arg1, ctx.arg2,
   5418              true);
   5419  return result;
   5420 }
   5421 
   5422 /*
   5423 * -----------------------------------------------
   5424 * IC callsite logic, and fallback stubs
   5425 * -----------------------------------------------
   5426 */
   5427 
   5428 #define DEFINE_IC(kind, arity, fallback_body)                   \
   5429  static uint64_t MOZ_NEVER_INLINE IC##kind##Fallback(          \
   5430      uint64_t arg0, uint64_t arg1, ICStub* stub, ICCtx& ctx) { \
   5431    uint64_t retValue = 0;                                      \
   5432    uint64_t arg2 = ctx.arg2;                                   \
   5433    (void)arg2;                                                 \
   5434    ICFallbackStub* fallback = stub->toFallbackStub();          \
   5435    StackVal* sp = ctx.sp();                                    \
   5436    fallback_body;                                              \
   5437    retValue = ctx.state.res.asRawBits();                       \
   5438    ctx.state.res = UndefinedValue();                           \
   5439    return retValue;                                            \
   5440  error:                                                        \
   5441    ctx.error = PBIResult::Error;                               \
   5442    return IC_ERROR_SENTINEL();                                 \
   5443  }
   5444 
   5445 #define DEFINE_IC_ALIAS(kind, target)                           \
   5446  static uint64_t MOZ_NEVER_INLINE IC##kind##Fallback(          \
   5447      uint64_t arg0, uint64_t arg1, ICStub* stub, ICCtx& ctx) { \
   5448    return IC##target##Fallback(arg0, arg1, stub, ctx);         \
   5449  }
   5450 
   5451 #define IC_LOAD_VAL(state_elem, index)                    \
   5452  ReservedRooted<Value> state_elem(&ctx.state.state_elem, \
   5453                                   Value::fromRawBits(arg##index))
   5454 #define IC_LOAD_OBJ(state_elem, index)  \
   5455  ReservedRooted<JSObject*> state_elem( \
   5456      &ctx.state.state_elem, reinterpret_cast<JSObject*>(arg##index))
   5457 
   5458 DEFINE_IC(TypeOf, 1, {
   5459  IC_LOAD_VAL(value0, 0);
   5460  PUSH_FALLBACK_IC_FRAME();
   5461  if (!DoTypeOfFallback(cx, ctx.frame, fallback, value0, &ctx.state.res)) {
   5462    goto error;
   5463  }
   5464 });
   5465 
   5466 DEFINE_IC(TypeOfEq, 1, {
   5467  IC_LOAD_VAL(value0, 0);
   5468  PUSH_FALLBACK_IC_FRAME();
   5469  if (!DoTypeOfEqFallback(cx, ctx.frame, fallback, value0, &ctx.state.res)) {
   5470    goto error;
   5471  }
   5472 });
   5473 
   5474 DEFINE_IC(GetName, 1, {
   5475  IC_LOAD_OBJ(obj0, 0);
   5476  PUSH_FALLBACK_IC_FRAME();
   5477  if (!DoGetNameFallback(cx, ctx.frame, fallback, obj0, &ctx.state.res)) {
   5478    goto error;
   5479  }
   5480 });
   5481 
   5482 DEFINE_IC(Call, 1, {
   5483  uint32_t argc = uint32_t(arg0);
   5484  uint32_t totalArgs =
   5485      argc + ctx.icregs.extraArgs;  // this, callee, (constructing?), func args
   5486  Value* args = reinterpret_cast<Value*>(&sp[0]);
   5487  TRACE_PRINTF("Call fallback: argc %d totalArgs %d args %p\n", argc, totalArgs,
   5488               args);
   5489  // Reverse values on the stack.
   5490  std::reverse(args, args + totalArgs);
   5491  {
   5492    PUSH_FALLBACK_IC_FRAME();
   5493    if (!DoCallFallback(cx, ctx.frame, fallback, argc, args, &ctx.state.res)) {
   5494      std::reverse(args, args + totalArgs);
   5495      goto error;
   5496    }
   5497  }
   5498 });
   5499 
   5500 DEFINE_IC_ALIAS(CallConstructing, Call);
   5501 
   5502 DEFINE_IC(SpreadCall, 1, {
   5503  uint32_t argc = uint32_t(arg0);
   5504  uint32_t totalArgs =
   5505      argc + ctx.icregs.extraArgs;  // this, callee, (constructing?), func args
   5506  Value* args = reinterpret_cast<Value*>(&sp[0]);
   5507  TRACE_PRINTF("Call fallback: argc %d totalArgs %d args %p\n", argc, totalArgs,
   5508               args);
   5509  // Reverse values on the stack.
   5510  std::reverse(args, args + totalArgs);
   5511  {
   5512    PUSH_FALLBACK_IC_FRAME();
   5513    if (!DoSpreadCallFallback(cx, ctx.frame, fallback, args, &ctx.state.res)) {
   5514      std::reverse(args, args + totalArgs);
   5515      goto error;
   5516    }
   5517  }
   5518 });
   5519 
   5520 DEFINE_IC_ALIAS(SpreadCallConstructing, SpreadCall);
   5521 
   5522 DEFINE_IC(UnaryArith, 1, {
   5523  IC_LOAD_VAL(value0, 0);
   5524  PUSH_FALLBACK_IC_FRAME();
   5525  if (!DoUnaryArithFallback(cx, ctx.frame, fallback, value0, &ctx.state.res)) {
   5526    goto error;
   5527  }
   5528 });
   5529 
   5530 DEFINE_IC(BinaryArith, 2, {
   5531  IC_LOAD_VAL(value0, 0);
   5532  IC_LOAD_VAL(value1, 1);
   5533  PUSH_FALLBACK_IC_FRAME();
   5534  if (!DoBinaryArithFallback(cx, ctx.frame, fallback, value0, value1,
   5535                             &ctx.state.res)) {
   5536    goto error;
   5537  }
   5538 });
   5539 
   5540 DEFINE_IC(ToBool, 1, {
   5541  IC_LOAD_VAL(value0, 0);
   5542  PUSH_FALLBACK_IC_FRAME();
   5543  if (!DoToBoolFallback(cx, ctx.frame, fallback, value0, &ctx.state.res)) {
   5544    goto error;
   5545  }
   5546 });
   5547 
   5548 DEFINE_IC(Compare, 2, {
   5549  IC_LOAD_VAL(value0, 0);
   5550  IC_LOAD_VAL(value1, 1);
   5551  PUSH_FALLBACK_IC_FRAME();
   5552  if (!DoCompareFallback(cx, ctx.frame, fallback, value0, value1,
   5553                         &ctx.state.res)) {
   5554    goto error;
   5555  }
   5556 });
   5557 
   5558 DEFINE_IC(InstanceOf, 2, {
   5559  IC_LOAD_VAL(value0, 0);
   5560  IC_LOAD_VAL(value1, 1);
   5561  PUSH_FALLBACK_IC_FRAME();
   5562  if (!DoInstanceOfFallback(cx, ctx.frame, fallback, value0, value1,
   5563                            &ctx.state.res)) {
   5564    goto error;
   5565  }
   5566 });
   5567 
   5568 DEFINE_IC(In, 2, {
   5569  IC_LOAD_VAL(value0, 0);
   5570  IC_LOAD_VAL(value1, 1);
   5571  PUSH_FALLBACK_IC_FRAME();
   5572  if (!DoInFallback(cx, ctx.frame, fallback, value0, value1, &ctx.state.res)) {
   5573    goto error;
   5574  }
   5575 });
   5576 
   5577 DEFINE_IC(BindName, 1, {
   5578  IC_LOAD_OBJ(obj0, 0);
   5579  PUSH_FALLBACK_IC_FRAME();
   5580  if (!DoBindNameFallback(cx, ctx.frame, fallback, obj0, &ctx.state.res)) {
   5581    goto error;
   5582  }
   5583 });
   5584 
   5585 DEFINE_IC(SetProp, 2, {
   5586  IC_LOAD_VAL(value0, 0);
   5587  IC_LOAD_VAL(value1, 1);
   5588  PUSH_FALLBACK_IC_FRAME();
   5589  if (!DoSetPropFallback(cx, ctx.frame, fallback, nullptr, value0, value1)) {
   5590    goto error;
   5591  }
   5592 });
   5593 
   5594 DEFINE_IC(NewObject, 0, {
   5595  PUSH_FALLBACK_IC_FRAME();
   5596  if (!DoNewObjectFallback(cx, ctx.frame, fallback, &ctx.state.res)) {
   5597    goto error;
   5598  }
   5599 });
   5600 
   5601 DEFINE_IC(GetProp, 1, {
   5602  IC_LOAD_VAL(value0, 0);
   5603  PUSH_FALLBACK_IC_FRAME();
   5604  if (!DoGetPropFallback(cx, ctx.frame, fallback, value0, &ctx.state.res)) {
   5605    goto error;
   5606  }
   5607 });
   5608 
   5609 DEFINE_IC(GetPropSuper, 2, {
   5610  IC_LOAD_VAL(value0, 1);
   5611  IC_LOAD_VAL(value1, 0);
   5612  PUSH_FALLBACK_IC_FRAME();
   5613  if (!DoGetPropSuperFallback(cx, ctx.frame, fallback, value0, value1,
   5614                              &ctx.state.res)) {
   5615    goto error;
   5616  }
   5617 });
   5618 
   5619 DEFINE_IC(GetElem, 2, {
   5620  IC_LOAD_VAL(value0, 0);
   5621  IC_LOAD_VAL(value1, 1);
   5622  PUSH_FALLBACK_IC_FRAME();
   5623  if (!DoGetElemFallback(cx, ctx.frame, fallback, value0, value1,
   5624                         &ctx.state.res)) {
   5625    goto error;
   5626  }
   5627 });
   5628 
   5629 DEFINE_IC(GetElemSuper, 3, {
   5630  IC_LOAD_VAL(value0, 0);  // receiver
   5631  IC_LOAD_VAL(value1, 1);  // obj (lhs)
   5632  IC_LOAD_VAL(value2, 2);  // key (rhs)
   5633  PUSH_FALLBACK_IC_FRAME();
   5634  if (!DoGetElemSuperFallback(cx, ctx.frame, fallback, value1, value2, value0,
   5635                              &ctx.state.res)) {
   5636    goto error;
   5637  }
   5638 });
   5639 
   5640 DEFINE_IC(GetImport, 0, {
   5641  PUSH_FALLBACK_IC_FRAME();
   5642  if (!DoGetImportFallback(cx, ctx.frame, fallback, &ctx.state.res)) {
   5643    goto error;
   5644  }
   5645 });
   5646 
   5647 DEFINE_IC(NewArray, 0, {
   5648  PUSH_FALLBACK_IC_FRAME();
   5649  if (!DoNewArrayFallback(cx, ctx.frame, fallback, &ctx.state.res)) {
   5650    goto error;
   5651  }
   5652 });
   5653 
   5654 DEFINE_IC(Lambda, 0, {
   5655  PUSH_FALLBACK_IC_FRAME();
   5656  if (!DoLambdaFallback(cx, ctx.frame, fallback, &ctx.state.res)) {
   5657    goto error;
   5658  }
   5659 });
   5660 
   5661 DEFINE_IC(LazyConstant, 0, {
   5662  PUSH_FALLBACK_IC_FRAME();
   5663  if (!DoLazyConstantFallback(cx, ctx.frame, fallback, &ctx.state.res)) {
   5664    goto error;
   5665  }
   5666 });
   5667 
   5668 DEFINE_IC(SetElem, 3, {
   5669  IC_LOAD_VAL(value0, 0);
   5670  IC_LOAD_VAL(value1, 1);
   5671  IC_LOAD_VAL(value2, 2);
   5672  PUSH_FALLBACK_IC_FRAME();
   5673  if (!DoSetElemFallback(cx, ctx.frame, fallback, nullptr, value0, value1,
   5674                         value2)) {
   5675    goto error;
   5676  }
   5677 });
   5678 
   5679 DEFINE_IC(HasOwn, 2, {
   5680  IC_LOAD_VAL(value0, 0);
   5681  IC_LOAD_VAL(value1, 1);
   5682  PUSH_FALLBACK_IC_FRAME();
   5683  if (!DoHasOwnFallback(cx, ctx.frame, fallback, value0, value1,
   5684                        &ctx.state.res)) {
   5685    goto error;
   5686  }
   5687 });
   5688 
   5689 DEFINE_IC(CheckPrivateField, 2, {
   5690  IC_LOAD_VAL(value0, 0);
   5691  IC_LOAD_VAL(value1, 1);
   5692  PUSH_FALLBACK_IC_FRAME();
   5693  if (!DoCheckPrivateFieldFallback(cx, ctx.frame, fallback, value0, value1,
   5694                                   &ctx.state.res)) {
   5695    goto error;
   5696  }
   5697 });
   5698 
   5699 DEFINE_IC(GetIterator, 1, {
   5700  IC_LOAD_VAL(value0, 0);
   5701  PUSH_FALLBACK_IC_FRAME();
   5702  if (!DoGetIteratorFallback(cx, ctx.frame, fallback, value0, &ctx.state.res)) {
   5703    goto error;
   5704  }
   5705 });
   5706 
   5707 DEFINE_IC(ToPropertyKey, 1, {
   5708  IC_LOAD_VAL(value0, 0);
   5709  PUSH_FALLBACK_IC_FRAME();
   5710  if (!DoToPropertyKeyFallback(cx, ctx.frame, fallback, value0,
   5711                               &ctx.state.res)) {
   5712    goto error;
   5713  }
   5714 });
   5715 
   5716 DEFINE_IC(OptimizeSpreadCall, 1, {
   5717  IC_LOAD_VAL(value0, 0);
   5718  PUSH_FALLBACK_IC_FRAME();
   5719  if (!DoOptimizeSpreadCallFallback(cx, ctx.frame, fallback, value0,
   5720                                    &ctx.state.res)) {
   5721    goto error;
   5722  }
   5723 });
   5724 
   5725 DEFINE_IC(OptimizeGetIterator, 1, {
   5726  IC_LOAD_VAL(value0, 0);
   5727  PUSH_FALLBACK_IC_FRAME();
   5728  if (!DoOptimizeGetIteratorFallback(cx, ctx.frame, fallback, value0,
   5729                                     &ctx.state.res)) {
   5730    goto error;
   5731  }
   5732 });
   5733 
   5734 DEFINE_IC(Rest, 0, {
   5735  PUSH_FALLBACK_IC_FRAME();
   5736  if (!DoRestFallback(cx, ctx.frame, fallback, &ctx.state.res)) {
   5737    goto error;
   5738  }
   5739 });
   5740 
   5741 DEFINE_IC(CloseIter, 1, {
   5742  IC_LOAD_OBJ(obj0, 0);
   5743  PUSH_FALLBACK_IC_FRAME();
   5744  if (!DoCloseIterFallback(cx, ctx.frame, fallback, obj0)) {
   5745    goto error;
   5746  }
   5747 });
   5748 
   5749 uint8_t* GetPortableFallbackStub(BaselineICFallbackKind kind) {
   5750  switch (kind) {
   5751 #define _(ty)                      \
   5752  case BaselineICFallbackKind::ty: \
   5753    return reinterpret_cast<uint8_t*>(&IC##ty##Fallback);
   5754    IC_BASELINE_FALLBACK_CODE_KIND_LIST(_)
   5755 #undef _
   5756    case BaselineICFallbackKind::Count:
   5757      MOZ_CRASH("Invalid kind");
   5758  }
   5759 }
   5760 
   5761 uint8_t* GetICInterpreter() {
   5762  return reinterpret_cast<uint8_t*>(&ICInterpretOps);
   5763 }
   5764 
   5765 /*
   5766 * -----------------------------------------------
   5767 * Main JSOp interpreter
   5768 * -----------------------------------------------
   5769 */
   5770 
   5771 static EnvironmentObject& getEnvironmentFromCoordinate(
   5772    BaselineFrame* frame, EnvironmentCoordinate ec) {
   5773  JSObject* env = frame->environmentChain();
   5774  for (unsigned i = ec.hops(); i; i--) {
   5775    if (env->is<EnvironmentObject>()) {
   5776      env = &env->as<EnvironmentObject>().enclosingEnvironment();
   5777    } else {
   5778      MOZ_ASSERT(env->is<DebugEnvironmentProxy>());
   5779      env = &env->as<DebugEnvironmentProxy>().enclosingEnvironment();
   5780    }
   5781  }
   5782  return env->is<EnvironmentObject>()
   5783             ? env->as<EnvironmentObject>()
   5784             : env->as<DebugEnvironmentProxy>().environment();
   5785 }
   5786 
   5787 #ifndef __wasi__
   5788 #  define DEBUG_CHECK()                                                   \
   5789    if (frame->isDebuggee()) {                                            \
   5790      TRACE_PRINTF(                                                       \
   5791          "Debug check: frame is debuggee, checking for debug script\n"); \
   5792      if (frame->script()->hasDebugScript()) {                            \
   5793        goto debug;                                                       \
   5794      }                                                                   \
   5795    }
   5796 #else
   5797 #  define DEBUG_CHECK()
   5798 #endif
   5799 
   5800 #define LABEL(op) (&&label_##op)
   5801 #ifdef ENABLE_COMPUTED_GOTO_DISPATCH
   5802 #  define CASE(op) label_##op:
   5803 #  define DISPATCH() \
   5804    DEBUG_CHECK();   \
   5805    goto* addresses[*pc]
   5806 #else
   5807 #  define CASE(op) label_##op : case JSOp::op:
   5808 #  define DISPATCH() \
   5809    DEBUG_CHECK();   \
   5810    goto dispatch
   5811 #endif
   5812 
   5813 #define ADVANCE(delta) pc += (delta);
   5814 #define ADVANCE_AND_DISPATCH(delta) \
   5815  ADVANCE(delta);                   \
   5816  DISPATCH();
   5817 
   5818 #define END_OP(op) ADVANCE_AND_DISPATCH(JSOpLength_##op);
   5819 
   5820 #define VIRTPUSH(value) PUSH(value)
   5821 #define VIRTPOP() POP()
   5822 #define VIRTSP(index) sp[(index)]
   5823 #define VIRTSPWRITE(index, value) sp[(index)] = (value)
   5824 #define SYNCSP()
   5825 #define SETLOCAL(i, value) frame->unaliasedLocal(i) = value
   5826 #define GETLOCAL(i) frame->unaliasedLocal(i)
   5827 
   5828 #define IC_SET_ARG_FROM_STACK(index, stack_index) \
   5829  ic_arg##index = sp[(stack_index)].asUInt64();
   5830 #define IC_POP_ARG(index) ic_arg##index = (*sp++).asUInt64();
   5831 #define IC_SET_VAL_ARG(index, expr) ic_arg##index = (expr).asRawBits();
   5832 #define IC_SET_OBJ_ARG(index, expr) \
   5833  ic_arg##index = reinterpret_cast<uint64_t>(expr);
   5834 #define IC_ZERO_ARG(index) ic_arg##index = 0;
   5835 #define IC_PUSH_RESULT() VIRTPUSH(StackVal(ic_ret));
   5836 
   5837 #if !defined(TRACE_INTERP)
   5838 #  define PREDICT_NEXT(op)       \
   5839    if (JSOp(*pc) == JSOp::op) { \
   5840      DEBUG_CHECK();             \
   5841      goto label_##op;           \
   5842    }
   5843 #else
   5844 #  define PREDICT_NEXT(op)
   5845 #endif
   5846 
   5847 #ifdef ENABLE_COVERAGE
   5848 #  define COUNT_COVERAGE_PC(PC)                                 \
   5849    if (frame->script()->hasScriptCounts()) {                   \
   5850      PCCounts* counts = frame->script()->maybeGetPCCounts(PC); \
   5851      MOZ_ASSERT(counts);                                       \
   5852      counts->numExec()++;                                      \
   5853    }
   5854 #  define COUNT_COVERAGE_MAIN()                                        \
   5855    {                                                                  \
   5856      jsbytecode* main = frame->script()->main();                      \
   5857      if (!BytecodeIsJumpTarget(JSOp(*main))) COUNT_COVERAGE_PC(main); \
   5858    }
   5859 #else
   5860 #  define COUNT_COVERAGE_PC(PC) ;
   5861 #  define COUNT_COVERAGE_MAIN() ;
   5862 #endif
   5863 
   5864 #define NEXT_IC() icEntry++
   5865 
   5866 #define INVOKE_IC(kind, hasarg2)                                             \
   5867  ctx.sp_ = sp;                                                              \
   5868  frame->interpreterPC() = pc;                                               \
   5869  frame->interpreterICEntry() = icEntry;                                     \
   5870  SYNCSP();                                                                  \
   5871  PBL_CALL_IC(icEntry->firstStub()->rawJitCode(), ctx, icEntry->firstStub(), \
   5872              ic_ret, ic_arg0, ic_arg1, ic_arg2, hasarg2);                   \
   5873  if (ic_ret == IC_ERROR_SENTINEL()) {                                       \
   5874    ic_result = ctx.error;                                                   \
   5875    goto ic_fail;                                                            \
   5876  }                                                                          \
   5877  NEXT_IC();
   5878 
   5879 #define INVOKE_IC_AND_PUSH(kind, hasarg2) \
   5880  INVOKE_IC(kind, hasarg2);               \
   5881  VIRTPUSH(StackVal(ic_ret));
   5882 
   5883 #define VIRTPOPN(n) \
   5884  SYNCSP();         \
   5885  POPN(n);
   5886 
   5887 #define SPHANDLE(index)          \
   5888  ({                             \
   5889    SYNCSP();                    \
   5890    Stack::handle(&sp[(index)]); \
   5891  })
   5892 #define SPHANDLEMUT(index)          \
   5893  ({                                \
   5894    SYNCSP();                       \
   5895    Stack::handleMut(&sp[(index)]); \
   5896  })
   5897 
   5898 template <bool IsRestart, bool HybridICs>
   5899 PBIResult PortableBaselineInterpret(
   5900    JSContext* cx_, State& state, Stack& stack, StackVal* sp,
   5901    JSObject* envChain, Value* ret, jsbytecode* pc, ImmutableScriptData* isd,
   5902    jsbytecode* restartEntryPC, BaselineFrame* restartFrame,
   5903    StackVal* restartEntryFrame, PBIResult restartCode) {
   5904 #define RESTART(code)                                                 \
   5905  if (!IsRestart) {                                                   \
   5906    TRACE_PRINTF("Restarting (code %d sp %p fp %p)\n", int(code), sp, \
   5907                 ctx.stack.fp);                                       \
   5908    SYNCSP();                                                         \
   5909    restartCode = code;                                               \
   5910    goto restart;                                                     \
   5911  }
   5912 
   5913 #define GOTO_ERROR()           \
   5914  do {                         \
   5915    SYNCSP();                  \
   5916    RESTART(PBIResult::Error); \
   5917    goto error;                \
   5918  } while (0)
   5919 
   5920  // Update local state when we switch to a new script with a new PC.
   5921 #define RESET_PC(new_pc, new_script)                                \
   5922  pc = new_pc;                                                      \
   5923  entryPC = new_script->code();                                     \
   5924  isd = new_script->immutableScriptData();                          \
   5925  icEntries = frame->icScript()->icEntries();                       \
   5926  icEntry = frame->interpreterICEntry();                            \
   5927  argsObjAliasesFormals = frame->script()->argsObjAliasesFormals(); \
   5928  resumeOffsets = isd->resumeOffsets().data();
   5929 
   5930 #define OPCODE_LABEL(op, ...) LABEL(op),
   5931 #define TRAILING_LABEL(v) LABEL(default),
   5932 
   5933  static const void* const addresses[EnableInterruptsPseudoOpcode + 1] = {
   5934      FOR_EACH_OPCODE(OPCODE_LABEL)
   5935          FOR_EACH_TRAILING_UNUSED_OPCODE(TRAILING_LABEL)};
   5936 
   5937 #undef OPCODE_LABEL
   5938 #undef TRAILING_LABEL
   5939 
   5940  BaselineFrame* frame = restartFrame;
   5941  StackVal* entryFrame = restartEntryFrame;
   5942  jsbytecode* entryPC = restartEntryPC;
   5943 
   5944  if (!IsRestart) {
   5945    PUSHNATIVE(StackValNative(nullptr));  // Fake return address.
   5946    frame = stack.pushFrame(sp, cx_, envChain);
   5947    MOZ_ASSERT(frame);  // safety: stack margin.
   5948    sp = reinterpret_cast<StackVal*>(frame);
   5949    // Save the entry frame so that when unwinding, we know when to
   5950    // return from this C++ frame.
   5951    entryFrame = sp;
   5952    // Save the entry PC so that we can compute offsets locally.
   5953    entryPC = pc;
   5954  }
   5955 
   5956  bool from_unwind = false;
   5957  uint32_t nfixed = frame->script()->nfixed();
   5958  bool argsObjAliasesFormals = frame->script()->argsObjAliasesFormals();
   5959 
   5960  PBIResult ic_result = PBIResult::Ok;
   5961  uint64_t ic_arg0 = 0, ic_arg1 = 0, ic_arg2 = 0, ic_ret = 0;
   5962 
   5963  ICCtx ctx(cx_, frame, state, stack);
   5964  auto* icEntries = frame->icScript()->icEntries();
   5965  auto* icEntry = icEntries;
   5966  const uint32_t* resumeOffsets = isd->resumeOffsets().data();
   5967 
   5968  if (IsRestart) {
   5969    ic_result = restartCode;
   5970    TRACE_PRINTF(
   5971        "Enter from restart: sp = %p ctx.stack.fp = %p ctx.frame = %p\n", sp,
   5972        ctx.stack.fp, ctx.frame);
   5973    goto ic_fail;
   5974  } else {
   5975    AutoCheckRecursionLimit recursion(ctx.frameMgr.cxForLocalUseOnly());
   5976    if (!recursion.checkDontReport(ctx.frameMgr.cxForLocalUseOnly())) {
   5977      PUSH_EXIT_FRAME();
   5978      ReportOverRecursed(ctx.frameMgr.cxForLocalUseOnly());
   5979      return PBIResult::Error;
   5980    }
   5981  }
   5982 
   5983  // Check max stack depth once, so we don't need to check it
   5984  // otherwise below for ordinary stack-manipulation opcodes (just for
   5985  // exit frames).
   5986  if (!ctx.stack.check(sp, sizeof(StackVal) * frame->script()->nslots())) {
   5987    PUSH_EXIT_FRAME();
   5988    ReportOverRecursed(ctx.frameMgr.cxForLocalUseOnly());
   5989    return PBIResult::Error;
   5990  }
   5991 
   5992  SYNCSP();
   5993  sp -= nfixed;
   5994  for (uint32_t i = 0; i < nfixed; i++) {
   5995    sp[i] = StackVal(UndefinedValue());
   5996  }
   5997  ret->setUndefined();
   5998 
   5999  // Check if we are being debugged, and set a flag in the frame if so. This
   6000  // flag must be set before calling InitFunctionEnvironmentObjects.
   6001  if (frame->script()->isDebuggee()) {
   6002    TRACE_PRINTF("Script is debuggee\n");
   6003    frame->setIsDebuggee();
   6004  }
   6005 
   6006  if (CalleeTokenIsFunction(frame->calleeToken())) {
   6007    JSFunction* func = CalleeTokenToFunction(frame->calleeToken());
   6008    frame->setEnvironmentChain(func->environment());
   6009    if (func->needsFunctionEnvironmentObjects()) {
   6010      PUSH_EXIT_FRAME();
   6011      if (!js::InitFunctionEnvironmentObjects(cx, frame)) {
   6012        GOTO_ERROR();
   6013      }
   6014      TRACE_PRINTF("callee is func %p; created environment object: %p\n", func,
   6015                   frame->environmentChain());
   6016    }
   6017  }
   6018 
   6019  // The debug prologue can't run until the function environment is set up.
   6020  if (frame->script()->isDebuggee()) {
   6021    PUSH_EXIT_FRAME();
   6022    if (!DebugPrologue(cx, frame)) {
   6023      GOTO_ERROR();
   6024    }
   6025  }
   6026 
   6027  if (!frame->script()->hasScriptCounts()) {
   6028    if (ctx.frameMgr.cxForLocalUseOnly()->realm()->collectCoverageForDebug()) {
   6029      PUSH_EXIT_FRAME();
   6030      if (!frame->script()->initScriptCounts(cx)) {
   6031        GOTO_ERROR();
   6032      }
   6033    }
   6034  }
   6035  COUNT_COVERAGE_MAIN();
   6036 
   6037 #ifdef ENABLE_INTERRUPT_CHECKS
   6038  if (ctx.frameMgr.cxForLocalUseOnly()->hasAnyPendingInterrupt()) {
   6039    PUSH_EXIT_FRAME();
   6040    if (!InterruptCheck(cx)) {
   6041      GOTO_ERROR();
   6042    }
   6043  }
   6044 #endif
   6045 
   6046  TRACE_PRINTF("Entering: sp = %p fp = %p frame = %p, script = %p, pc = %p\n",
   6047               sp, ctx.stack.fp, frame, frame->script(), pc);
   6048  TRACE_PRINTF("nslots = %d nfixed = %d\n", int(frame->script()->nslots()),
   6049               int(frame->script()->nfixed()));
   6050 
   6051  while (true) {
   6052    DEBUG_CHECK();
   6053 
   6054 #if !defined(ENABLE_COMPUTED_GOTO_DISPATCH) || !defined(__wasi__)
   6055  dispatch:
   6056 #endif
   6057 
   6058 #ifdef TRACE_INTERP
   6059  {
   6060    JSOp op = JSOp(*pc);
   6061    printf("sp[0] = %" PRIx64 " sp[1] = %" PRIx64 " sp[2] = %" PRIx64 "\n",
   6062           sp[0].asUInt64(), sp[1].asUInt64(), sp[2].asUInt64());
   6063    printf("script = %p pc = %p: %s (ic %d entry %p) pending = %d\n",
   6064           frame->script(), pc, CodeName(op), (int)(icEntry - icEntries),
   6065           icEntry, ctx.frameMgr.cxForLocalUseOnly()->isExceptionPending());
   6066    printf("sp = %p fp = %p\n", sp, ctx.stack.fp);
   6067    printf("TOS tag: %d\n", int(sp[0].asValue().asRawBits() >> 47));
   6068    fflush(stdout);
   6069  }
   6070 #endif
   6071 
   6072 #ifdef ENABLE_COMPUTED_GOTO_DISPATCH
   6073    goto* addresses[*pc];
   6074 #else
   6075    (void)addresses;  // Avoid unused-local error. We keep the table
   6076                      // itself to avoid warnings (see note in IC
   6077                      // interpreter above).
   6078    switch (JSOp(*pc))
   6079 #endif
   6080    {
   6081      CASE(Nop) { END_OP(Nop); }
   6082      CASE(NopIsAssignOp) { END_OP(NopIsAssignOp); }
   6083      CASE(Undefined) {
   6084        VIRTPUSH(StackVal(UndefinedValue()));
   6085        END_OP(Undefined);
   6086      }
   6087      CASE(Null) {
   6088        VIRTPUSH(StackVal(NullValue()));
   6089        END_OP(Null);
   6090      }
   6091      CASE(False) {
   6092        VIRTPUSH(StackVal(BooleanValue(false)));
   6093        END_OP(False);
   6094      }
   6095      CASE(True) {
   6096        VIRTPUSH(StackVal(BooleanValue(true)));
   6097        END_OP(True);
   6098      }
   6099      CASE(Int32) {
   6100        VIRTPUSH(StackVal(Int32Value(GET_INT32(pc))));
   6101        END_OP(Int32);
   6102      }
   6103      CASE(Zero) {
   6104        VIRTPUSH(StackVal(Int32Value(0)));
   6105        END_OP(Zero);
   6106      }
   6107      CASE(One) {
   6108        VIRTPUSH(StackVal(Int32Value(1)));
   6109        END_OP(One);
   6110      }
   6111      CASE(Int8) {
   6112        VIRTPUSH(StackVal(Int32Value(GET_INT8(pc))));
   6113        END_OP(Int8);
   6114      }
   6115      CASE(Uint16) {
   6116        VIRTPUSH(StackVal(Int32Value(GET_UINT16(pc))));
   6117        END_OP(Uint16);
   6118      }
   6119      CASE(Uint24) {
   6120        VIRTPUSH(StackVal(Int32Value(GET_UINT24(pc))));
   6121        END_OP(Uint24);
   6122      }
   6123      CASE(Double) {
   6124        VIRTPUSH(StackVal(GET_INLINE_VALUE(pc)));
   6125        END_OP(Double);
   6126      }
   6127      CASE(BigInt) {
   6128        VIRTPUSH(StackVal(JS::BigIntValue(frame->script()->getBigInt(pc))));
   6129        END_OP(BigInt);
   6130      }
   6131      CASE(String) {
   6132        VIRTPUSH(StackVal(StringValue(frame->script()->getString(pc))));
   6133        END_OP(String);
   6134      }
   6135      CASE(Symbol) {
   6136        VIRTPUSH(StackVal(SymbolValue(
   6137            ctx.frameMgr.cxForLocalUseOnly()->wellKnownSymbols().get(
   6138                GET_UINT8(pc)))));
   6139        END_OP(Symbol);
   6140      }
   6141      CASE(Void) {
   6142        VIRTSPWRITE(0, StackVal(JS::UndefinedValue()));
   6143        END_OP(Void);
   6144      }
   6145 
   6146      CASE(Typeof)
   6147      CASE(TypeofExpr) {
   6148        static_assert(JSOpLength_Typeof == JSOpLength_TypeofExpr);
   6149        if (HybridICs) {
   6150          SYNCSP();
   6151          VIRTSPWRITE(
   6152              0,
   6153              StackVal(StringValue(TypeOfOperation(
   6154                  SPHANDLE(0), ctx.frameMgr.cxForLocalUseOnly()->runtime()))));
   6155          NEXT_IC();
   6156        } else {
   6157          IC_POP_ARG(0);
   6158          IC_ZERO_ARG(1);
   6159          IC_ZERO_ARG(2);
   6160          INVOKE_IC_AND_PUSH(TypeOf, false);
   6161        }
   6162        END_OP(Typeof);
   6163      }
   6164 
   6165      CASE(TypeofEq) {
   6166        if (HybridICs) {
   6167          TypeofEqOperand operand =
   6168              TypeofEqOperand::fromRawValue(GET_UINT8(pc));
   6169          bool result = js::TypeOfValue(SPHANDLE(0)) == operand.type();
   6170          if (operand.compareOp() == JSOp::Ne) {
   6171            result = !result;
   6172          }
   6173          VIRTSPWRITE(0, StackVal(BooleanValue(result)));
   6174          NEXT_IC();
   6175        } else {
   6176          IC_POP_ARG(0);
   6177          IC_ZERO_ARG(1);
   6178          IC_ZERO_ARG(2);
   6179          INVOKE_IC_AND_PUSH(TypeOfEq, false);
   6180        }
   6181        END_OP(TypeofEq);
   6182      }
   6183 
   6184      CASE(Pos) {
   6185        if (VIRTSP(0).asValue().isNumber()) {
   6186          // Nothing!
   6187          NEXT_IC();
   6188          END_OP(Pos);
   6189        } else {
   6190          goto generic_unary;
   6191        }
   6192      }
   6193      CASE(Neg) {
   6194        Value v = VIRTSP(0).asValue();
   6195        if (v.isInt32()) {
   6196          int32_t i = v.toInt32();
   6197          if (i != 0 && i != INT32_MIN) {
   6198            VIRTSPWRITE(0, StackVal(Int32Value(-i)));
   6199            NEXT_IC();
   6200            END_OP(Neg);
   6201          }
   6202        }
   6203        if (v.isNumber()) {
   6204          VIRTSPWRITE(0, StackVal(NumberValue(-v.toNumber())));
   6205          NEXT_IC();
   6206          END_OP(Neg);
   6207        }
   6208        goto generic_unary;
   6209      }
   6210 
   6211      CASE(Inc) {
   6212        Value v = VIRTSP(0).asValue();
   6213        if (v.isInt32()) {
   6214          int32_t i = v.toInt32();
   6215          if (i != INT32_MAX) {
   6216            VIRTSPWRITE(0, StackVal(Int32Value(i + 1)));
   6217            NEXT_IC();
   6218            END_OP(Inc);
   6219          }
   6220        }
   6221        if (v.isNumber()) {
   6222          VIRTSPWRITE(0, StackVal(NumberValue(v.toNumber() + 1)));
   6223          NEXT_IC();
   6224          END_OP(Inc);
   6225        }
   6226        goto generic_unary;
   6227      }
   6228      CASE(Dec) {
   6229        Value v = VIRTSP(0).asValue();
   6230        if (v.isInt32()) {
   6231          int32_t i = v.toInt32();
   6232          if (i != INT32_MIN) {
   6233            VIRTSPWRITE(0, StackVal(Int32Value(i - 1)));
   6234            NEXT_IC();
   6235            END_OP(Dec);
   6236          }
   6237        }
   6238        if (v.isNumber()) {
   6239          VIRTSPWRITE(0, StackVal(NumberValue(v.toNumber() - 1)));
   6240          NEXT_IC();
   6241          END_OP(Dec);
   6242        }
   6243        goto generic_unary;
   6244      }
   6245 
   6246      CASE(BitNot) {
   6247        Value v = VIRTSP(0).asValue();
   6248        if (v.isInt32()) {
   6249          int32_t i = v.toInt32();
   6250          VIRTSPWRITE(0, StackVal(Int32Value(~i)));
   6251          NEXT_IC();
   6252          END_OP(Inc);
   6253        }
   6254        goto generic_unary;
   6255      }
   6256 
   6257      CASE(ToNumeric) {
   6258        if (VIRTSP(0).asValue().isNumeric()) {
   6259          NEXT_IC();
   6260        } else if (HybridICs) {
   6261          SYNCSP();
   6262          MutableHandleValue val = SPHANDLEMUT(0);
   6263          PUSH_EXIT_FRAME();
   6264          if (!ToNumeric(cx, val)) {
   6265            GOTO_ERROR();
   6266          }
   6267          NEXT_IC();
   6268        } else {
   6269          goto generic_unary;
   6270        }
   6271        END_OP(ToNumeric);
   6272      }
   6273 
   6274    generic_unary:;
   6275      {
   6276        static_assert(JSOpLength_Pos == JSOpLength_Neg);
   6277        static_assert(JSOpLength_Pos == JSOpLength_BitNot);
   6278        static_assert(JSOpLength_Pos == JSOpLength_Inc);
   6279        static_assert(JSOpLength_Pos == JSOpLength_Dec);
   6280        static_assert(JSOpLength_Pos == JSOpLength_ToNumeric);
   6281        IC_POP_ARG(0);
   6282        IC_ZERO_ARG(1);
   6283        IC_ZERO_ARG(2);
   6284        INVOKE_IC_AND_PUSH(UnaryArith, false);
   6285        END_OP(Pos);
   6286      }
   6287 
   6288      CASE(Not) {
   6289        Value v = VIRTSP(0).asValue();
   6290        if (v.isBoolean()) {
   6291          VIRTSPWRITE(0, StackVal(BooleanValue(!v.toBoolean())));
   6292          NEXT_IC();
   6293        } else if (HybridICs) {
   6294          SYNCSP();
   6295          VIRTSPWRITE(0, StackVal(BooleanValue(!ToBoolean(SPHANDLE(0)))));
   6296          NEXT_IC();
   6297        } else {
   6298          IC_POP_ARG(0);
   6299          IC_ZERO_ARG(1);
   6300          IC_ZERO_ARG(2);
   6301          INVOKE_IC(ToBool, false);
   6302          VIRTPUSH(
   6303              StackVal(BooleanValue(!Value::fromRawBits(ic_ret).toBoolean())));
   6304        }
   6305        END_OP(Not);
   6306      }
   6307 
   6308      CASE(And) {
   6309        bool result;
   6310        Value v = VIRTSP(0).asValue();
   6311        if (v.isBoolean()) {
   6312          result = v.toBoolean();
   6313          NEXT_IC();
   6314        } else if (HybridICs) {
   6315          result = ToBoolean(SPHANDLE(0));
   6316          NEXT_IC();
   6317        } else {
   6318          IC_SET_ARG_FROM_STACK(0, 0);
   6319          IC_ZERO_ARG(1);
   6320          IC_ZERO_ARG(2);
   6321          INVOKE_IC(ToBool, false);
   6322          result = Value::fromRawBits(ic_ret).toBoolean();
   6323        }
   6324        int32_t jumpOffset = GET_JUMP_OFFSET(pc);
   6325        if (!result) {
   6326          ADVANCE(jumpOffset);
   6327          PREDICT_NEXT(JumpTarget);
   6328          PREDICT_NEXT(LoopHead);
   6329        } else {
   6330          ADVANCE(JSOpLength_And);
   6331        }
   6332        DISPATCH();
   6333      }
   6334      CASE(Or) {
   6335        bool result;
   6336        Value v = VIRTSP(0).asValue();
   6337        if (v.isBoolean()) {
   6338          result = v.toBoolean();
   6339          NEXT_IC();
   6340        } else if (HybridICs) {
   6341          result = ToBoolean(SPHANDLE(0));
   6342          NEXT_IC();
   6343        } else {
   6344          IC_SET_ARG_FROM_STACK(0, 0);
   6345          IC_ZERO_ARG(1);
   6346          IC_ZERO_ARG(2);
   6347          INVOKE_IC(ToBool, false);
   6348          result = Value::fromRawBits(ic_ret).toBoolean();
   6349        }
   6350        int32_t jumpOffset = GET_JUMP_OFFSET(pc);
   6351        if (result) {
   6352          ADVANCE(jumpOffset);
   6353          PREDICT_NEXT(JumpTarget);
   6354          PREDICT_NEXT(LoopHead);
   6355        } else {
   6356          ADVANCE(JSOpLength_Or);
   6357        }
   6358        DISPATCH();
   6359      }
   6360      CASE(JumpIfTrue) {
   6361        bool result;
   6362        Value v = VIRTSP(0).asValue();
   6363        if (v.isBoolean()) {
   6364          result = v.toBoolean();
   6365          VIRTPOP();
   6366          NEXT_IC();
   6367        } else if (HybridICs) {
   6368          result = ToBoolean(SPHANDLE(0));
   6369          VIRTPOP();
   6370          NEXT_IC();
   6371        } else {
   6372          IC_POP_ARG(0);
   6373          IC_ZERO_ARG(1);
   6374          IC_ZERO_ARG(2);
   6375          INVOKE_IC(ToBool, false);
   6376          result = Value::fromRawBits(ic_ret).toBoolean();
   6377        }
   6378        int32_t jumpOffset = GET_JUMP_OFFSET(pc);
   6379        if (result) {
   6380          ADVANCE(jumpOffset);
   6381          PREDICT_NEXT(JumpTarget);
   6382          PREDICT_NEXT(LoopHead);
   6383        } else {
   6384          ADVANCE(JSOpLength_JumpIfTrue);
   6385        }
   6386        DISPATCH();
   6387      }
   6388      CASE(JumpIfFalse) {
   6389        bool result;
   6390        Value v = VIRTSP(0).asValue();
   6391        if (v.isBoolean()) {
   6392          result = v.toBoolean();
   6393          VIRTPOP();
   6394          NEXT_IC();
   6395        } else if (HybridICs) {
   6396          result = ToBoolean(SPHANDLE(0));
   6397          VIRTPOP();
   6398          NEXT_IC();
   6399        } else {
   6400          IC_POP_ARG(0);
   6401          IC_ZERO_ARG(1);
   6402          IC_ZERO_ARG(2);
   6403          INVOKE_IC(ToBool, false);
   6404          result = Value::fromRawBits(ic_ret).toBoolean();
   6405        }
   6406        int32_t jumpOffset = GET_JUMP_OFFSET(pc);
   6407        if (!result) {
   6408          ADVANCE(jumpOffset);
   6409          PREDICT_NEXT(JumpTarget);
   6410          PREDICT_NEXT(LoopHead);
   6411        } else {
   6412          ADVANCE(JSOpLength_JumpIfFalse);
   6413        }
   6414        DISPATCH();
   6415      }
   6416 
   6417      CASE(Add) {
   6418        if (HybridICs) {
   6419          Value v0 = VIRTSP(0).asValue();
   6420          Value v1 = VIRTSP(1).asValue();
   6421          if (v0.isInt32() && v1.isInt32()) {
   6422            int64_t lhs = v1.toInt32();
   6423            int64_t rhs = v0.toInt32();
   6424            int64_t result = lhs + rhs;
   6425            if (result >= int64_t(INT32_MIN) && result <= int64_t(INT32_MAX)) {
   6426              VIRTPOP();
   6427              VIRTSPWRITE(0, StackVal(Int32Value(int32_t(result))));
   6428              NEXT_IC();
   6429              END_OP(Add);
   6430            }
   6431          }
   6432          if (v0.isNumber() && v1.isNumber()) {
   6433            double lhs = v1.toNumber();
   6434            double rhs = v0.toNumber();
   6435            VIRTPOP();
   6436            VIRTSPWRITE(0, StackVal(NumberValue(lhs + rhs)));
   6437            NEXT_IC();
   6438            END_OP(Add);
   6439          }
   6440 
   6441          MutableHandleValue lhs = SPHANDLEMUT(1);
   6442          MutableHandleValue rhs = SPHANDLEMUT(0);
   6443          MutableHandleValue result = SPHANDLEMUT(1);
   6444          {
   6445            PUSH_EXIT_FRAME();
   6446            if (!AddOperation(cx, lhs, rhs, result)) {
   6447              GOTO_ERROR();
   6448            }
   6449          }
   6450          VIRTPOP();
   6451          NEXT_IC();
   6452          END_OP(Add);
   6453        }
   6454        goto generic_binary;
   6455      }
   6456 
   6457      CASE(Sub) {
   6458        if (HybridICs) {
   6459          Value v0 = VIRTSP(0).asValue();
   6460          Value v1 = VIRTSP(1).asValue();
   6461          if (v0.isInt32() && v1.isInt32()) {
   6462            int64_t lhs = v1.toInt32();
   6463            int64_t rhs = v0.toInt32();
   6464            int64_t result = lhs - rhs;
   6465            if (result >= int64_t(INT32_MIN) && result <= int64_t(INT32_MAX)) {
   6466              VIRTPOP();
   6467              VIRTSPWRITE(0, StackVal(Int32Value(int32_t(result))));
   6468              NEXT_IC();
   6469              END_OP(Sub);
   6470            }
   6471          }
   6472          if (v0.isNumber() && v1.isNumber()) {
   6473            double lhs = v1.toNumber();
   6474            double rhs = v0.toNumber();
   6475            VIRTPOP();
   6476            VIRTSPWRITE(0, StackVal(NumberValue(lhs - rhs)));
   6477            NEXT_IC();
   6478            END_OP(Add);
   6479          }
   6480 
   6481          MutableHandleValue lhs = SPHANDLEMUT(1);
   6482          MutableHandleValue rhs = SPHANDLEMUT(0);
   6483          MutableHandleValue result = SPHANDLEMUT(1);
   6484          {
   6485            PUSH_EXIT_FRAME();
   6486            if (!SubOperation(cx, lhs, rhs, result)) {
   6487              GOTO_ERROR();
   6488            }
   6489          }
   6490          VIRTPOP();
   6491          NEXT_IC();
   6492          END_OP(Sub);
   6493        }
   6494        goto generic_binary;
   6495      }
   6496 
   6497      CASE(Mul) {
   6498        if (HybridICs) {
   6499          Value v0 = VIRTSP(0).asValue();
   6500          Value v1 = VIRTSP(1).asValue();
   6501          if (v0.isInt32() && v1.isInt32()) {
   6502            int64_t lhs = v1.toInt32();
   6503            int64_t rhs = v0.toInt32();
   6504            int64_t product = lhs * rhs;
   6505            if (product >= int64_t(INT32_MIN) &&
   6506                product <= int64_t(INT32_MAX) &&
   6507                (product != 0 || !((lhs < 0) ^ (rhs < 0)))) {
   6508              VIRTPOP();
   6509              VIRTSPWRITE(0, StackVal(Int32Value(int32_t(product))));
   6510              NEXT_IC();
   6511              END_OP(Mul);
   6512            }
   6513          }
   6514          if (v0.isNumber() && v1.isNumber()) {
   6515            double lhs = v1.toNumber();
   6516            double rhs = v0.toNumber();
   6517            VIRTPOP();
   6518            VIRTSPWRITE(0, StackVal(NumberValue(lhs * rhs)));
   6519            NEXT_IC();
   6520            END_OP(Mul);
   6521          }
   6522 
   6523          MutableHandleValue lhs = SPHANDLEMUT(1);
   6524          MutableHandleValue rhs = SPHANDLEMUT(0);
   6525          MutableHandleValue result = SPHANDLEMUT(1);
   6526          {
   6527            PUSH_EXIT_FRAME();
   6528            if (!MulOperation(cx, lhs, rhs, result)) {
   6529              GOTO_ERROR();
   6530            }
   6531          }
   6532          VIRTPOP();
   6533          NEXT_IC();
   6534          END_OP(Mul);
   6535        }
   6536        goto generic_binary;
   6537      }
   6538      CASE(Div) {
   6539        if (HybridICs) {
   6540          Value v0 = VIRTSP(0).asValue();
   6541          Value v1 = VIRTSP(1).asValue();
   6542          if (v0.isNumber() && v1.isNumber()) {
   6543            double lhs = v1.toNumber();
   6544            double rhs = v0.toNumber();
   6545            VIRTPOP();
   6546            VIRTSPWRITE(0, StackVal(NumberValue(NumberDiv(lhs, rhs))));
   6547            NEXT_IC();
   6548            END_OP(Div);
   6549          }
   6550 
   6551          MutableHandleValue lhs = SPHANDLEMUT(1);
   6552          MutableHandleValue rhs = SPHANDLEMUT(0);
   6553          MutableHandleValue result = SPHANDLEMUT(1);
   6554          {
   6555            PUSH_EXIT_FRAME();
   6556            if (!DivOperation(cx, lhs, rhs, result)) {
   6557              GOTO_ERROR();
   6558            }
   6559          }
   6560          VIRTPOP();
   6561          NEXT_IC();
   6562          END_OP(Div);
   6563        }
   6564        goto generic_binary;
   6565      }
   6566      CASE(Mod) {
   6567        if (HybridICs) {
   6568          Value v0 = VIRTSP(0).asValue();
   6569          Value v1 = VIRTSP(1).asValue();
   6570          if (v0.isInt32() && v1.isInt32()) {
   6571            int64_t lhs = v1.toInt32();
   6572            int64_t rhs = v0.toInt32();
   6573            if (lhs > 0 && rhs > 0) {
   6574              int64_t mod = lhs % rhs;
   6575              VIRTPOP();
   6576              VIRTSPWRITE(0, StackVal(Int32Value(int32_t(mod))));
   6577              NEXT_IC();
   6578              END_OP(Mod);
   6579            }
   6580          }
   6581          if (v0.isNumber() && v1.isNumber()) {
   6582            double lhs = v1.toNumber();
   6583            double rhs = v0.toNumber();
   6584            VIRTPOP();
   6585            VIRTSPWRITE(0, StackVal(DoubleValue(NumberMod(lhs, rhs))));
   6586            NEXT_IC();
   6587            END_OP(Mod);
   6588          }
   6589 
   6590          MutableHandleValue lhs = SPHANDLEMUT(1);
   6591          MutableHandleValue rhs = SPHANDLEMUT(0);
   6592          MutableHandleValue result = SPHANDLEMUT(1);
   6593          {
   6594            PUSH_EXIT_FRAME();
   6595            if (!ModOperation(cx, lhs, rhs, result)) {
   6596              GOTO_ERROR();
   6597            }
   6598          }
   6599          VIRTPOP();
   6600          NEXT_IC();
   6601          END_OP(Mod);
   6602        }
   6603        goto generic_binary;
   6604      }
   6605      CASE(Pow) {
   6606        if (HybridICs) {
   6607          Value v0 = VIRTSP(0).asValue();
   6608          Value v1 = VIRTSP(1).asValue();
   6609          if (v0.isNumber() && v1.isNumber()) {
   6610            double lhs = v1.toNumber();
   6611            double rhs = v0.toNumber();
   6612            VIRTPOP();
   6613            VIRTSPWRITE(0, StackVal(NumberValue(ecmaPow(lhs, rhs))));
   6614            NEXT_IC();
   6615            END_OP(Pow);
   6616          }
   6617 
   6618          MutableHandleValue lhs = SPHANDLEMUT(1);
   6619          MutableHandleValue rhs = SPHANDLEMUT(0);
   6620          MutableHandleValue result = SPHANDLEMUT(1);
   6621          {
   6622            PUSH_EXIT_FRAME();
   6623            if (!PowOperation(cx, lhs, rhs, result)) {
   6624              GOTO_ERROR();
   6625            }
   6626          }
   6627          VIRTPOP();
   6628          NEXT_IC();
   6629          END_OP(Pow);
   6630        }
   6631        goto generic_binary;
   6632      }
   6633      CASE(BitOr) {
   6634        if (HybridICs) {
   6635          Value v0 = VIRTSP(0).asValue();
   6636          Value v1 = VIRTSP(1).asValue();
   6637          if (v0.isInt32() && v1.isInt32()) {
   6638            int32_t lhs = v1.toInt32();
   6639            int32_t rhs = v0.toInt32();
   6640            VIRTPOP();
   6641            VIRTSPWRITE(0, StackVal(Int32Value(lhs | rhs)));
   6642            NEXT_IC();
   6643            END_OP(BitOr);
   6644          }
   6645        }
   6646        goto generic_binary;
   6647      }
   6648      CASE(BitAnd) {
   6649        if (HybridICs) {
   6650          Value v0 = VIRTSP(0).asValue();
   6651          Value v1 = VIRTSP(1).asValue();
   6652          if (v0.isInt32() && v1.isInt32()) {
   6653            int32_t lhs = v1.toInt32();
   6654            int32_t rhs = v0.toInt32();
   6655            VIRTPOP();
   6656            VIRTSPWRITE(0, StackVal(Int32Value(lhs & rhs)));
   6657            NEXT_IC();
   6658            END_OP(BitAnd);
   6659          }
   6660        }
   6661        goto generic_binary;
   6662      }
   6663      CASE(BitXor) {
   6664        if (HybridICs) {
   6665          Value v0 = VIRTSP(0).asValue();
   6666          Value v1 = VIRTSP(1).asValue();
   6667          if (v0.isInt32() && v1.isInt32()) {
   6668            int32_t lhs = v1.toInt32();
   6669            int32_t rhs = v0.toInt32();
   6670            VIRTPOP();
   6671            VIRTSPWRITE(0, StackVal(Int32Value(lhs ^ rhs)));
   6672            NEXT_IC();
   6673            END_OP(BitXor);
   6674          }
   6675        }
   6676        goto generic_binary;
   6677      }
   6678      CASE(Lsh) {
   6679        if (HybridICs) {
   6680          Value v0 = VIRTSP(0).asValue();
   6681          Value v1 = VIRTSP(1).asValue();
   6682          if (v0.isInt32() && v1.isInt32()) {
   6683            // Unsigned to avoid undefined behavior on left-shift overflow
   6684            // (see comment in BitLshOperation in Interpreter.cpp).
   6685            uint32_t lhs = uint32_t(v1.toInt32());
   6686            uint32_t rhs = uint32_t(v0.toInt32());
   6687            VIRTPOP();
   6688            rhs &= 31;
   6689            VIRTSPWRITE(0, StackVal(Int32Value(int32_t(lhs << rhs))));
   6690            NEXT_IC();
   6691            END_OP(Lsh);
   6692          }
   6693        }
   6694        goto generic_binary;
   6695      }
   6696      CASE(Rsh) {
   6697        if (HybridICs) {
   6698          Value v0 = VIRTSP(0).asValue();
   6699          Value v1 = VIRTSP(1).asValue();
   6700          if (v0.isInt32() && v1.isInt32()) {
   6701            int32_t lhs = v1.toInt32();
   6702            int32_t rhs = v0.toInt32();
   6703            VIRTPOP();
   6704            rhs &= 31;
   6705            VIRTSPWRITE(0, StackVal(Int32Value(lhs >> rhs)));
   6706            NEXT_IC();
   6707            END_OP(Rsh);
   6708          }
   6709        }
   6710        goto generic_binary;
   6711      }
   6712      CASE(Ursh) {
   6713        if (HybridICs) {
   6714          Value v0 = VIRTSP(0).asValue();
   6715          Value v1 = VIRTSP(1).asValue();
   6716          if (v0.isInt32() && v1.isInt32()) {
   6717            uint32_t lhs = uint32_t(v1.toInt32());
   6718            int32_t rhs = v0.toInt32();
   6719            VIRTPOP();
   6720            rhs &= 31;
   6721            uint32_t result = lhs >> rhs;
   6722            StackVal stackResult(0);
   6723            if (result <= uint32_t(INT32_MAX)) {
   6724              stackResult = StackVal(Int32Value(int32_t(result)));
   6725            } else {
   6726              stackResult = StackVal(NumberValue(double(result)));
   6727            }
   6728            VIRTSPWRITE(0, stackResult);
   6729            NEXT_IC();
   6730            END_OP(Ursh);
   6731          }
   6732        }
   6733        goto generic_binary;
   6734      }
   6735 
   6736    generic_binary:;
   6737      {
   6738        static_assert(JSOpLength_BitOr == JSOpLength_BitXor);
   6739        static_assert(JSOpLength_BitOr == JSOpLength_BitAnd);
   6740        static_assert(JSOpLength_BitOr == JSOpLength_Lsh);
   6741        static_assert(JSOpLength_BitOr == JSOpLength_Rsh);
   6742        static_assert(JSOpLength_BitOr == JSOpLength_Ursh);
   6743        static_assert(JSOpLength_BitOr == JSOpLength_Add);
   6744        static_assert(JSOpLength_BitOr == JSOpLength_Sub);
   6745        static_assert(JSOpLength_BitOr == JSOpLength_Mul);
   6746        static_assert(JSOpLength_BitOr == JSOpLength_Div);
   6747        static_assert(JSOpLength_BitOr == JSOpLength_Mod);
   6748        static_assert(JSOpLength_BitOr == JSOpLength_Pow);
   6749        IC_POP_ARG(1);
   6750        IC_POP_ARG(0);
   6751        IC_ZERO_ARG(2);
   6752        INVOKE_IC_AND_PUSH(BinaryArith, false);
   6753        END_OP(Div);
   6754      }
   6755 
   6756      CASE(Eq) {
   6757        if (HybridICs) {
   6758          Value v0 = VIRTSP(0).asValue();
   6759          Value v1 = VIRTSP(1).asValue();
   6760          if (v0.isInt32() && v1.isInt32()) {
   6761            bool result = v0.toInt32() == v1.toInt32();
   6762            VIRTPOP();
   6763            VIRTSPWRITE(0, StackVal(BooleanValue(result)));
   6764            NEXT_IC();
   6765            END_OP(Eq);
   6766          }
   6767          if (v0.isNumber() && v1.isNumber()) {
   6768            double lhs = v1.toNumber();
   6769            double rhs = v0.toNumber();
   6770            bool result = lhs == rhs;
   6771            VIRTPOP();
   6772            VIRTSPWRITE(0, StackVal(BooleanValue(result)));
   6773            NEXT_IC();
   6774            END_OP(Eq);
   6775          }
   6776          if (v0.isNumber() && v1.isNumber()) {
   6777            bool result = v0.toNumber() == v1.toNumber();
   6778            VIRTPOP();
   6779            VIRTSPWRITE(0, StackVal(BooleanValue(result)));
   6780            NEXT_IC();
   6781            END_OP(Eq);
   6782          }
   6783        }
   6784        goto generic_cmp;
   6785      }
   6786 
   6787      CASE(Ne) {
   6788        if (HybridICs) {
   6789          Value v0 = VIRTSP(0).asValue();
   6790          Value v1 = VIRTSP(1).asValue();
   6791          if (v0.isInt32() && v1.isInt32()) {
   6792            bool result = v0.toInt32() != v1.toInt32();
   6793            VIRTPOP();
   6794            VIRTSPWRITE(0, StackVal(BooleanValue(result)));
   6795            NEXT_IC();
   6796            END_OP(Ne);
   6797          }
   6798          if (v0.isNumber() && v1.isNumber()) {
   6799            double lhs = v1.toNumber();
   6800            double rhs = v0.toNumber();
   6801            bool result = lhs != rhs;
   6802            VIRTPOP();
   6803            VIRTSPWRITE(0, StackVal(BooleanValue(result)));
   6804            NEXT_IC();
   6805            END_OP(Ne);
   6806          }
   6807          if (v0.isNumber() && v1.isNumber()) {
   6808            bool result = v0.toNumber() != v1.toNumber();
   6809            VIRTPOP();
   6810            VIRTSPWRITE(0, StackVal(BooleanValue(result)));
   6811            NEXT_IC();
   6812            END_OP(Eq);
   6813          }
   6814        }
   6815        goto generic_cmp;
   6816      }
   6817 
   6818      CASE(Lt) {
   6819        if (HybridICs) {
   6820          Value v0 = VIRTSP(0).asValue();
   6821          Value v1 = VIRTSP(1).asValue();
   6822          if (v0.isInt32() && v1.isInt32()) {
   6823            bool result = v1.toInt32() < v0.toInt32();
   6824            VIRTPOP();
   6825            VIRTSPWRITE(0, StackVal(BooleanValue(result)));
   6826            NEXT_IC();
   6827            END_OP(Lt);
   6828          }
   6829          if (v0.isNumber() && v1.isNumber()) {
   6830            double lhs = v1.toNumber();
   6831            double rhs = v0.toNumber();
   6832            bool result = lhs < rhs;
   6833            if (std::isnan(lhs) || std::isnan(rhs)) {
   6834              result = false;
   6835            }
   6836            VIRTPOP();
   6837            VIRTSPWRITE(0, StackVal(BooleanValue(result)));
   6838            NEXT_IC();
   6839            END_OP(Lt);
   6840          }
   6841        }
   6842        goto generic_cmp;
   6843      }
   6844      CASE(Le) {
   6845        if (HybridICs) {
   6846          Value v0 = VIRTSP(0).asValue();
   6847          Value v1 = VIRTSP(1).asValue();
   6848          if (v0.isInt32() && v1.isInt32()) {
   6849            bool result = v1.toInt32() <= v0.toInt32();
   6850            VIRTPOP();
   6851            VIRTSPWRITE(0, StackVal(BooleanValue(result)));
   6852            NEXT_IC();
   6853            END_OP(Le);
   6854          }
   6855          if (v0.isNumber() && v1.isNumber()) {
   6856            double lhs = v1.toNumber();
   6857            double rhs = v0.toNumber();
   6858            bool result = lhs <= rhs;
   6859            if (std::isnan(lhs) || std::isnan(rhs)) {
   6860              result = false;
   6861            }
   6862            VIRTPOP();
   6863            VIRTSPWRITE(0, StackVal(BooleanValue(result)));
   6864            NEXT_IC();
   6865            END_OP(Le);
   6866          }
   6867        }
   6868        goto generic_cmp;
   6869      }
   6870      CASE(Gt) {
   6871        if (HybridICs) {
   6872          Value v0 = VIRTSP(0).asValue();
   6873          Value v1 = VIRTSP(1).asValue();
   6874          if (v0.isInt32() && v1.isInt32()) {
   6875            bool result = v1.toInt32() > v0.toInt32();
   6876            VIRTPOP();
   6877            VIRTSPWRITE(0, StackVal(BooleanValue(result)));
   6878            NEXT_IC();
   6879            END_OP(Gt);
   6880          }
   6881          if (v0.isNumber() && v1.isNumber()) {
   6882            double lhs = v1.toNumber();
   6883            double rhs = v0.toNumber();
   6884            bool result = lhs > rhs;
   6885            if (std::isnan(lhs) || std::isnan(rhs)) {
   6886              result = false;
   6887            }
   6888            VIRTPOP();
   6889            VIRTSPWRITE(0, StackVal(BooleanValue(result)));
   6890            NEXT_IC();
   6891            END_OP(Gt);
   6892          }
   6893        }
   6894        goto generic_cmp;
   6895      }
   6896      CASE(Ge) {
   6897        if (HybridICs) {
   6898          Value v0 = VIRTSP(0).asValue();
   6899          Value v1 = VIRTSP(1).asValue();
   6900          if (v0.isInt32() && v1.isInt32()) {
   6901            bool result = v1.toInt32() >= v0.toInt32();
   6902            VIRTPOP();
   6903            VIRTSPWRITE(0, StackVal(BooleanValue(result)));
   6904            NEXT_IC();
   6905            END_OP(Ge);
   6906          }
   6907          if (v0.isNumber() && v1.isNumber()) {
   6908            double lhs = v1.toNumber();
   6909            double rhs = v0.toNumber();
   6910            bool result = lhs >= rhs;
   6911            if (std::isnan(lhs) || std::isnan(rhs)) {
   6912              result = false;
   6913            }
   6914            VIRTPOP();
   6915            VIRTSPWRITE(0, StackVal(BooleanValue(result)));
   6916            NEXT_IC();
   6917            END_OP(Ge);
   6918          }
   6919        }
   6920        goto generic_cmp;
   6921      }
   6922 
   6923      CASE(StrictEq)
   6924      CASE(StrictNe) {
   6925        if (HybridICs) {
   6926          Value v0 = VIRTSP(0).asValue();
   6927          Value v1 = VIRTSP(1).asValue();
   6928          bool result;
   6929          HandleValue lval = SPHANDLE(1);
   6930          HandleValue rval = SPHANDLE(0);
   6931          if (v0.isString() && v1.isString()) {
   6932            PUSH_EXIT_FRAME();
   6933            if (!js::StrictlyEqual(cx, lval, rval, &result)) {
   6934              GOTO_ERROR();
   6935            }
   6936          } else {
   6937            if (!js::StrictlyEqual(nullptr, lval, rval, &result)) {
   6938              GOTO_ERROR();
   6939            }
   6940          }
   6941          VIRTPOP();
   6942          VIRTSPWRITE(0,
   6943                      StackVal(BooleanValue(
   6944                          (JSOp(*pc) == JSOp::StrictEq) ? result : !result)));
   6945          NEXT_IC();
   6946          END_OP(StrictEq);
   6947        } else {
   6948          goto generic_cmp;
   6949        }
   6950      }
   6951 
   6952    generic_cmp:;
   6953      {
   6954        static_assert(JSOpLength_Eq == JSOpLength_Ne);
   6955        static_assert(JSOpLength_Eq == JSOpLength_StrictEq);
   6956        static_assert(JSOpLength_Eq == JSOpLength_StrictNe);
   6957        static_assert(JSOpLength_Eq == JSOpLength_Lt);
   6958        static_assert(JSOpLength_Eq == JSOpLength_Gt);
   6959        static_assert(JSOpLength_Eq == JSOpLength_Le);
   6960        static_assert(JSOpLength_Eq == JSOpLength_Ge);
   6961        IC_POP_ARG(1);
   6962        IC_POP_ARG(0);
   6963        IC_ZERO_ARG(2);
   6964        INVOKE_IC_AND_PUSH(Compare, false);
   6965        END_OP(Eq);
   6966      }
   6967 
   6968      CASE(StrictConstantNe)
   6969      CASE(StrictConstantEq) {
   6970        JSOp op = JSOp(*pc);
   6971        uint16_t operand = GET_UINT16(pc);
   6972        {
   6973          bool result = js::ConstantStrictEqual(VIRTPOP().asValue(), operand);
   6974          VIRTPUSH(StackVal(
   6975              BooleanValue(op == JSOp::StrictConstantEq ? result : !result)));
   6976        }
   6977        END_OP(StrictConstantEq);
   6978      }
   6979 
   6980      CASE(Instanceof) {
   6981        IC_POP_ARG(1);
   6982        IC_POP_ARG(0);
   6983        IC_ZERO_ARG(2);
   6984        INVOKE_IC_AND_PUSH(InstanceOf, false);
   6985        END_OP(Instanceof);
   6986      }
   6987 
   6988      CASE(In) {
   6989        IC_POP_ARG(1);
   6990        IC_POP_ARG(0);
   6991        IC_ZERO_ARG(2);
   6992        INVOKE_IC_AND_PUSH(In, false);
   6993        END_OP(In);
   6994      }
   6995 
   6996      CASE(ToPropertyKey) {
   6997        IC_POP_ARG(0);
   6998        IC_ZERO_ARG(1);
   6999        IC_ZERO_ARG(2);
   7000        INVOKE_IC_AND_PUSH(ToPropertyKey, false);
   7001        END_OP(ToPropertyKey);
   7002      }
   7003 
   7004      CASE(ToString) {
   7005        if (VIRTSP(0).asValue().isString()) {
   7006          END_OP(ToString);
   7007        }
   7008        {
   7009          ReservedRooted<Value> value0(&state.value0, VIRTPOP().asValue());
   7010          if (JSString* result = ToStringSlow<NoGC>(
   7011                  ctx.frameMgr.cxForLocalUseOnly(), value0)) {
   7012            VIRTPUSH(StackVal(StringValue(result)));
   7013          } else {
   7014            {
   7015              PUSH_EXIT_FRAME();
   7016              result = ToString<CanGC>(cx, value0);
   7017              if (!result) {
   7018                GOTO_ERROR();
   7019              }
   7020            }
   7021            VIRTPUSH(StackVal(StringValue(result)));
   7022          }
   7023        }
   7024        END_OP(ToString);
   7025      }
   7026 
   7027      CASE(IsNullOrUndefined) {
   7028        Value v = VIRTSP(0).asValue();
   7029        bool result = v.isNull() || v.isUndefined();
   7030        VIRTPUSH(StackVal(BooleanValue(result)));
   7031        END_OP(IsNullOrUndefined);
   7032      }
   7033 
   7034      CASE(GlobalThis) {
   7035        VIRTPUSH(StackVal(ObjectValue(*ctx.frameMgr.cxForLocalUseOnly()
   7036                                           ->global()
   7037                                           ->lexicalEnvironment()
   7038                                           .thisObject())));
   7039        END_OP(GlobalThis);
   7040      }
   7041 
   7042      CASE(NonSyntacticGlobalThis) {
   7043        {
   7044          ReservedRooted<JSObject*> obj0(&state.obj0,
   7045                                         frame->environmentChain());
   7046          ReservedRooted<Value> value0(&state.value0);
   7047          {
   7048            PUSH_EXIT_FRAME();
   7049            js::GetNonSyntacticGlobalThis(cx, obj0, &value0);
   7050          }
   7051          VIRTPUSH(StackVal(value0));
   7052        }
   7053        END_OP(NonSyntacticGlobalThis);
   7054      }
   7055 
   7056      CASE(NewTarget) {
   7057        VIRTPUSH(StackVal(frame->newTarget()));
   7058        END_OP(NewTarget);
   7059      }
   7060 
   7061      CASE(DynamicImport) {
   7062        {
   7063          ReservedRooted<Value> value0(&state.value0,
   7064                                       VIRTPOP().asValue());  // options
   7065          ReservedRooted<Value> value1(&state.value1,
   7066                                       VIRTPOP().asValue());  // specifier
   7067          JSObject* promise;
   7068          {
   7069            PUSH_EXIT_FRAME();
   7070            ReservedRooted<JSScript*> script0(&state.script0, frame->script());
   7071            promise = StartDynamicModuleImport(cx, script0, value1, value0);
   7072            if (!promise) {
   7073              GOTO_ERROR();
   7074            }
   7075          }
   7076          VIRTPUSH(StackVal(ObjectValue(*promise)));
   7077        }
   7078        END_OP(DynamicImport);
   7079      }
   7080 
   7081      CASE(ImportMeta) {
   7082        IC_ZERO_ARG(0);
   7083        IC_ZERO_ARG(1);
   7084        IC_ZERO_ARG(2);
   7085        INVOKE_IC_AND_PUSH(LazyConstant, false);
   7086        END_OP(ImportMeta);
   7087      }
   7088 
   7089      CASE(NewInit) {
   7090        if (HybridICs) {
   7091          JSObject* obj;
   7092          {
   7093            PUSH_EXIT_FRAME();
   7094            ReservedRooted<JSScript*> script0(&state.script0, frame->script());
   7095            obj = NewObjectOperation(cx, script0, pc);
   7096            if (!obj) {
   7097              GOTO_ERROR();
   7098            }
   7099          }
   7100          VIRTPUSH(StackVal(ObjectValue(*obj)));
   7101          NEXT_IC();
   7102          END_OP(NewInit);
   7103        } else {
   7104          IC_ZERO_ARG(0);
   7105          IC_ZERO_ARG(1);
   7106          IC_ZERO_ARG(2);
   7107          INVOKE_IC_AND_PUSH(NewObject, false);
   7108          END_OP(NewInit);
   7109        }
   7110      }
   7111      CASE(NewObject) {
   7112        if (HybridICs) {
   7113          JSObject* obj;
   7114          {
   7115            PUSH_EXIT_FRAME();
   7116            ReservedRooted<JSScript*> script0(&state.script0, frame->script());
   7117            obj = NewObjectOperation(cx, script0, pc);
   7118            if (!obj) {
   7119              GOTO_ERROR();
   7120            }
   7121          }
   7122          VIRTPUSH(StackVal(ObjectValue(*obj)));
   7123          NEXT_IC();
   7124          END_OP(NewObject);
   7125        } else {
   7126          IC_ZERO_ARG(0);
   7127          IC_ZERO_ARG(1);
   7128          IC_ZERO_ARG(2);
   7129          INVOKE_IC_AND_PUSH(NewObject, false);
   7130          END_OP(NewObject);
   7131        }
   7132      }
   7133      CASE(Object) {
   7134        VIRTPUSH(StackVal(ObjectValue(*frame->script()->getObject(pc))));
   7135        END_OP(Object);
   7136      }
   7137      CASE(ObjWithProto) {
   7138        {
   7139          ReservedRooted<Value> value0(&state.value0, VIRTSP(0).asValue());
   7140          JSObject* obj;
   7141          {
   7142            PUSH_EXIT_FRAME();
   7143            obj = ObjectWithProtoOperation(cx, value0);
   7144            if (!obj) {
   7145              GOTO_ERROR();
   7146            }
   7147          }
   7148          VIRTSPWRITE(0, StackVal(ObjectValue(*obj)));
   7149        }
   7150        END_OP(ObjWithProto);
   7151      }
   7152 
   7153      CASE(InitElem)
   7154      CASE(InitHiddenElem)
   7155      CASE(InitLockedElem)
   7156      CASE(InitElemInc)
   7157      CASE(SetElem)
   7158      CASE(StrictSetElem) {
   7159        static_assert(JSOpLength_InitElem == JSOpLength_InitHiddenElem);
   7160        static_assert(JSOpLength_InitElem == JSOpLength_InitLockedElem);
   7161        static_assert(JSOpLength_InitElem == JSOpLength_InitElemInc);
   7162        static_assert(JSOpLength_InitElem == JSOpLength_SetElem);
   7163        static_assert(JSOpLength_InitElem == JSOpLength_StrictSetElem);
   7164        StackVal val = VIRTSP(0);
   7165        IC_POP_ARG(2);
   7166        IC_POP_ARG(1);
   7167        IC_SET_ARG_FROM_STACK(0, 0);
   7168        if (JSOp(*pc) == JSOp::SetElem || JSOp(*pc) == JSOp::StrictSetElem) {
   7169          VIRTSPWRITE(0, val);
   7170        }
   7171        INVOKE_IC(SetElem, true);
   7172        if (JSOp(*pc) == JSOp::InitElemInc) {
   7173          VIRTPUSH(
   7174              StackVal(Int32Value(Value::fromRawBits(ic_arg1).toInt32() + 1)));
   7175        }
   7176        END_OP(InitElem);
   7177      }
   7178 
   7179      CASE(InitPropGetter)
   7180      CASE(InitHiddenPropGetter)
   7181      CASE(InitPropSetter)
   7182      CASE(InitHiddenPropSetter) {
   7183        static_assert(JSOpLength_InitPropGetter ==
   7184                      JSOpLength_InitHiddenPropGetter);
   7185        static_assert(JSOpLength_InitPropGetter == JSOpLength_InitPropSetter);
   7186        static_assert(JSOpLength_InitPropGetter ==
   7187                      JSOpLength_InitHiddenPropSetter);
   7188        {
   7189          ReservedRooted<JSObject*> obj1(
   7190              &state.obj1,
   7191              &VIRTPOP().asValue().toObject());  // val
   7192          ReservedRooted<JSObject*> obj0(
   7193              &state.obj0,
   7194              &VIRTSP(0).asValue().toObject());  // obj; leave on stack
   7195          ReservedRooted<PropertyName*> name0(&state.name0,
   7196                                              frame->script()->getName(pc));
   7197          {
   7198            PUSH_EXIT_FRAME();
   7199            if (!InitPropGetterSetterOperation(cx, pc, obj0, name0, obj1)) {
   7200              GOTO_ERROR();
   7201            }
   7202          }
   7203        }
   7204        END_OP(InitPropGetter);
   7205      }
   7206 
   7207      CASE(InitElemGetter)
   7208      CASE(InitHiddenElemGetter)
   7209      CASE(InitElemSetter)
   7210      CASE(InitHiddenElemSetter) {
   7211        static_assert(JSOpLength_InitElemGetter ==
   7212                      JSOpLength_InitHiddenElemGetter);
   7213        static_assert(JSOpLength_InitElemGetter == JSOpLength_InitElemSetter);
   7214        static_assert(JSOpLength_InitElemGetter ==
   7215                      JSOpLength_InitHiddenElemSetter);
   7216        {
   7217          ReservedRooted<JSObject*> obj1(
   7218              &state.obj1,
   7219              &VIRTPOP().asValue().toObject());  // val
   7220          ReservedRooted<Value> value0(&state.value0,
   7221                                       VIRTPOP().asValue());  // idval
   7222          ReservedRooted<JSObject*> obj0(
   7223              &state.obj0,
   7224              &VIRTSP(0).asValue().toObject());  // obj; leave on stack
   7225          {
   7226            PUSH_EXIT_FRAME();
   7227            if (!InitElemGetterSetterOperation(cx, pc, obj0, value0, obj1)) {
   7228              GOTO_ERROR();
   7229            }
   7230          }
   7231        }
   7232        END_OP(InitElemGetter);
   7233      }
   7234 
   7235      CASE(GetProp)
   7236      CASE(GetBoundName) {
   7237        static_assert(JSOpLength_GetProp == JSOpLength_GetBoundName);
   7238        IC_POP_ARG(0);
   7239        IC_ZERO_ARG(1);
   7240        IC_ZERO_ARG(2);
   7241        INVOKE_IC_AND_PUSH(GetProp, false);
   7242        END_OP(GetProp);
   7243      }
   7244      CASE(GetPropSuper) {
   7245        IC_POP_ARG(0);
   7246        IC_POP_ARG(1);
   7247        IC_ZERO_ARG(2);
   7248        INVOKE_IC_AND_PUSH(GetPropSuper, false);
   7249        END_OP(GetPropSuper);
   7250      }
   7251 
   7252      CASE(GetElem) {
   7253        if (HybridICs && VIRTSP(1).asValue().isString()) {
   7254          HandleValue lhs = SPHANDLE(1);
   7255          HandleValue rhs = SPHANDLE(0);
   7256          uint32_t index;
   7257          if (IsDefinitelyIndex(rhs, &index)) {
   7258            JSString* str = lhs.toString();
   7259            if (index < str->length() && str->isLinear()) {
   7260              JSLinearString* linear = &str->asLinear();
   7261              char16_t c = linear->latin1OrTwoByteChar(index);
   7262              StaticStrings& sstr =
   7263                  ctx.frameMgr.cxForLocalUseOnly()->staticStrings();
   7264              if (sstr.hasUnit(c)) {
   7265                VIRTPOP();
   7266                VIRTSPWRITE(0, StackVal(StringValue(sstr.getUnit(c))));
   7267                NEXT_IC();
   7268                END_OP(GetElem);
   7269              }
   7270            }
   7271          }
   7272        }
   7273 
   7274        IC_POP_ARG(1);
   7275        IC_POP_ARG(0);
   7276        IC_ZERO_ARG(2);
   7277        INVOKE_IC_AND_PUSH(GetElem, false);
   7278        END_OP(GetElem);
   7279      }
   7280 
   7281      CASE(GetElemSuper) {
   7282        // N.B.: second and third args are out of order! See the saga at
   7283        // https://bugzilla.mozilla.org/show_bug.cgi?id=1709328; this is
   7284        // an echo of that issue.
   7285        IC_POP_ARG(1);
   7286        IC_POP_ARG(2);
   7287        IC_POP_ARG(0);
   7288        INVOKE_IC_AND_PUSH(GetElemSuper, true);
   7289        END_OP(GetElemSuper);
   7290      }
   7291 
   7292      CASE(DelProp) {
   7293        {
   7294          ReservedRooted<Value> value0(&state.value0, VIRTPOP().asValue());
   7295          ReservedRooted<PropertyName*> name0(&state.name0,
   7296                                              frame->script()->getName(pc));
   7297          bool res = false;
   7298          {
   7299            PUSH_EXIT_FRAME();
   7300            if (!DelPropOperation<false>(cx, value0, name0, &res)) {
   7301              GOTO_ERROR();
   7302            }
   7303          }
   7304          VIRTPUSH(StackVal(BooleanValue(res)));
   7305        }
   7306        END_OP(DelProp);
   7307      }
   7308      CASE(StrictDelProp) {
   7309        {
   7310          ReservedRooted<Value> value0(&state.value0, VIRTPOP().asValue());
   7311          ReservedRooted<PropertyName*> name0(&state.name0,
   7312                                              frame->script()->getName(pc));
   7313          bool res = false;
   7314          {
   7315            PUSH_EXIT_FRAME();
   7316            if (!DelPropOperation<true>(cx, value0, name0, &res)) {
   7317              GOTO_ERROR();
   7318            }
   7319          }
   7320          VIRTPUSH(StackVal(BooleanValue(res)));
   7321        }
   7322        END_OP(StrictDelProp);
   7323      }
   7324      CASE(DelElem) {
   7325        {
   7326          ReservedRooted<Value> value1(&state.value1, VIRTPOP().asValue());
   7327          ReservedRooted<Value> value0(&state.value0, VIRTPOP().asValue());
   7328          bool res = false;
   7329          {
   7330            PUSH_EXIT_FRAME();
   7331            if (!DelElemOperation<false>(cx, value0, value1, &res)) {
   7332              GOTO_ERROR();
   7333            }
   7334          }
   7335          VIRTPUSH(StackVal(BooleanValue(res)));
   7336        }
   7337        END_OP(DelElem);
   7338      }
   7339      CASE(StrictDelElem) {
   7340        {
   7341          ReservedRooted<Value> value1(&state.value1, VIRTPOP().asValue());
   7342          ReservedRooted<Value> value0(&state.value0, VIRTPOP().asValue());
   7343          bool res = false;
   7344          {
   7345            PUSH_EXIT_FRAME();
   7346            if (!DelElemOperation<true>(cx, value0, value1, &res)) {
   7347              GOTO_ERROR();
   7348            }
   7349          }
   7350          VIRTPUSH(StackVal(BooleanValue(res)));
   7351        }
   7352        END_OP(StrictDelElem);
   7353      }
   7354 
   7355      CASE(HasOwn) {
   7356        IC_POP_ARG(1);
   7357        IC_POP_ARG(0);
   7358        IC_ZERO_ARG(2);
   7359        INVOKE_IC_AND_PUSH(HasOwn, false);
   7360        END_OP(HasOwn);
   7361      }
   7362 
   7363      CASE(CheckPrivateField) {
   7364        IC_SET_ARG_FROM_STACK(1, 0);
   7365        IC_SET_ARG_FROM_STACK(0, 1);
   7366        IC_ZERO_ARG(2);
   7367        INVOKE_IC_AND_PUSH(CheckPrivateField, false);
   7368        END_OP(CheckPrivateField);
   7369      }
   7370 
   7371      CASE(NewPrivateName) {
   7372        {
   7373          ReservedRooted<JSAtom*> atom0(&state.atom0,
   7374                                        frame->script()->getAtom(pc));
   7375          JS::Symbol* symbol;
   7376          {
   7377            PUSH_EXIT_FRAME();
   7378            symbol = NewPrivateName(cx, atom0);
   7379            if (!symbol) {
   7380              GOTO_ERROR();
   7381            }
   7382          }
   7383          VIRTPUSH(StackVal(SymbolValue(symbol)));
   7384        }
   7385        END_OP(NewPrivateName);
   7386      }
   7387 
   7388      CASE(SuperBase) {
   7389        JSFunction& superEnvFunc =
   7390            VIRTPOP().asValue().toObject().as<JSFunction>();
   7391        MOZ_ASSERT(superEnvFunc.allowSuperProperty());
   7392        MOZ_ASSERT(superEnvFunc.baseScript()->needsHomeObject());
   7393        const Value& homeObjVal = superEnvFunc.getExtendedSlot(
   7394            FunctionExtended::METHOD_HOMEOBJECT_SLOT);
   7395 
   7396        JSObject* homeObj = &homeObjVal.toObject();
   7397        JSObject* superBase = HomeObjectSuperBase(homeObj);
   7398 
   7399        VIRTPUSH(StackVal(ObjectOrNullValue(superBase)));
   7400        END_OP(SuperBase);
   7401      }
   7402 
   7403      CASE(SetPropSuper)
   7404      CASE(StrictSetPropSuper) {
   7405        // stack signature: receiver, lval, rval => rval
   7406        static_assert(JSOpLength_SetPropSuper == JSOpLength_StrictSetPropSuper);
   7407        bool strict = JSOp(*pc) == JSOp::StrictSetPropSuper;
   7408        {
   7409          ReservedRooted<Value> value2(&state.value2,
   7410                                       VIRTPOP().asValue());  // rval
   7411          ReservedRooted<Value> value1(&state.value1,
   7412                                       VIRTPOP().asValue());  // lval
   7413          ReservedRooted<Value> value0(&state.value0,
   7414                                       VIRTPOP().asValue());  // recevier
   7415          ReservedRooted<PropertyName*> name0(&state.name0,
   7416                                              frame->script()->getName(pc));
   7417          {
   7418            PUSH_EXIT_FRAME();
   7419            // SetPropertySuper(cx, lval, receiver, name, rval, strict)
   7420            // (N.B.: lval and receiver are transposed!)
   7421            if (!SetPropertySuper(cx, value1, value0, name0, value2, strict)) {
   7422              GOTO_ERROR();
   7423            }
   7424          }
   7425          VIRTPUSH(StackVal(value2));
   7426        }
   7427        END_OP(SetPropSuper);
   7428      }
   7429 
   7430      CASE(SetElemSuper)
   7431      CASE(StrictSetElemSuper) {
   7432        // stack signature: receiver, key, lval, rval => rval
   7433        static_assert(JSOpLength_SetElemSuper == JSOpLength_StrictSetElemSuper);
   7434        bool strict = JSOp(*pc) == JSOp::StrictSetElemSuper;
   7435        {
   7436          ReservedRooted<Value> value3(&state.value3,
   7437                                       VIRTPOP().asValue());  // rval
   7438          ReservedRooted<Value> value2(&state.value2,
   7439                                       VIRTPOP().asValue());  // lval
   7440          ReservedRooted<Value> value1(&state.value1,
   7441                                       VIRTPOP().asValue());  // index
   7442          ReservedRooted<Value> value0(&state.value0,
   7443                                       VIRTPOP().asValue());  // receiver
   7444          {
   7445            PUSH_EXIT_FRAME();
   7446            // SetElementSuper(cx, lval, receiver, index, rval, strict)
   7447            // (N.B.: lval, receiver and index are rotated!)
   7448            if (!SetElementSuper(cx, value2, value0, value1, value3, strict)) {
   7449              GOTO_ERROR();
   7450            }
   7451          }
   7452          VIRTPUSH(StackVal(value3));  // value
   7453        }
   7454        END_OP(SetElemSuper);
   7455      }
   7456 
   7457      CASE(Iter) {
   7458        IC_POP_ARG(0);
   7459        IC_ZERO_ARG(1);
   7460        IC_ZERO_ARG(2);
   7461        INVOKE_IC_AND_PUSH(GetIterator, false);
   7462        END_OP(Iter);
   7463      }
   7464 
   7465      CASE(MoreIter) {
   7466        // iter => iter, name
   7467        Value v = IteratorMore(&VIRTSP(0).asValue().toObject());
   7468        VIRTPUSH(StackVal(v));
   7469        END_OP(MoreIter);
   7470      }
   7471 
   7472      CASE(IsNoIter) {
   7473        // iter => iter, bool
   7474        bool result = VIRTSP(0).asValue().isMagic(JS_NO_ITER_VALUE);
   7475        VIRTPUSH(StackVal(BooleanValue(result)));
   7476        END_OP(IsNoIter);
   7477      }
   7478 
   7479      CASE(EndIter) {
   7480        // iter, interval =>
   7481        VIRTPOP();
   7482        CloseIterator(&VIRTPOP().asValue().toObject());
   7483        END_OP(EndIter);
   7484      }
   7485 
   7486      CASE(CloseIter) {
   7487        IC_SET_OBJ_ARG(0, &VIRTPOP().asValue().toObject());
   7488        IC_ZERO_ARG(1);
   7489        IC_ZERO_ARG(2);
   7490        INVOKE_IC(CloseIter, false);
   7491        END_OP(CloseIter);
   7492      }
   7493 
   7494      CASE(CheckIsObj) {
   7495        if (!VIRTSP(0).asValue().isObject()) {
   7496          PUSH_EXIT_FRAME();
   7497          MOZ_ALWAYS_FALSE(
   7498              js::ThrowCheckIsObject(cx, js::CheckIsObjectKind(GET_UINT8(pc))));
   7499          /* abandon frame; error handler will re-establish sp */
   7500          GOTO_ERROR();
   7501        }
   7502        END_OP(CheckIsObj);
   7503      }
   7504 
   7505      CASE(CheckObjCoercible) {
   7506        {
   7507          ReservedRooted<Value> value0(&state.value0, VIRTSP(0).asValue());
   7508          if (value0.isNullOrUndefined()) {
   7509            PUSH_EXIT_FRAME();
   7510            MOZ_ALWAYS_FALSE(ThrowObjectCoercible(cx, value0));
   7511            /* abandon frame; error handler will re-establish sp */
   7512            GOTO_ERROR();
   7513          }
   7514        }
   7515        END_OP(CheckObjCoercible);
   7516      }
   7517 
   7518      CASE(ToAsyncIter) {
   7519        // iter, next => asynciter
   7520        {
   7521          ReservedRooted<Value> value0(&state.value0,
   7522                                       VIRTPOP().asValue());  // next
   7523          ReservedRooted<JSObject*> obj0(
   7524              &state.obj0,
   7525              &VIRTPOP().asValue().toObject());  // iter
   7526          JSObject* result;
   7527          {
   7528            PUSH_EXIT_FRAME();
   7529            result = CreateAsyncFromSyncIterator(cx, obj0, value0);
   7530            if (!result) {
   7531              GOTO_ERROR();
   7532            }
   7533          }
   7534          VIRTPUSH(StackVal(ObjectValue(*result)));
   7535        }
   7536        END_OP(ToAsyncIter);
   7537      }
   7538 
   7539      CASE(MutateProto) {
   7540        // obj, protoVal => obj
   7541        {
   7542          ReservedRooted<Value> value0(&state.value0, VIRTPOP().asValue());
   7543          ReservedRooted<JSObject*> obj0(&state.obj0,
   7544                                         &VIRTSP(0).asValue().toObject());
   7545          {
   7546            PUSH_EXIT_FRAME();
   7547            if (!MutatePrototype(cx, obj0.as<PlainObject>(), value0)) {
   7548              GOTO_ERROR();
   7549            }
   7550          }
   7551        }
   7552        END_OP(MutateProto);
   7553      }
   7554 
   7555      CASE(NewArray) {
   7556        if (HybridICs) {
   7557          ArrayObject* obj;
   7558          {
   7559            PUSH_EXIT_FRAME();
   7560            uint32_t length = GET_UINT32(pc);
   7561            obj = NewArrayOperation(cx, length);
   7562            if (!obj) {
   7563              GOTO_ERROR();
   7564            }
   7565          }
   7566          VIRTPUSH(StackVal(ObjectValue(*obj)));
   7567          NEXT_IC();
   7568          END_OP(NewArray);
   7569        } else {
   7570          IC_ZERO_ARG(0);
   7571          IC_ZERO_ARG(1);
   7572          IC_ZERO_ARG(2);
   7573          INVOKE_IC_AND_PUSH(NewArray, false);
   7574          END_OP(NewArray);
   7575        }
   7576      }
   7577 
   7578      CASE(InitElemArray) {
   7579        // array, val => array
   7580        {
   7581          ReservedRooted<Value> value0(&state.value0, VIRTPOP().asValue());
   7582          ReservedRooted<JSObject*> obj0(&state.obj0,
   7583                                         &VIRTSP(0).asValue().toObject());
   7584          {
   7585            PUSH_EXIT_FRAME();
   7586            InitElemArrayOperation(cx, pc, obj0.as<ArrayObject>(), value0);
   7587          }
   7588        }
   7589        END_OP(InitElemArray);
   7590      }
   7591 
   7592      CASE(Hole) {
   7593        VIRTPUSH(StackVal(MagicValue(JS_ELEMENTS_HOLE)));
   7594        END_OP(Hole);
   7595      }
   7596 
   7597      CASE(RegExp) {
   7598        JSObject* obj;
   7599        {
   7600          PUSH_EXIT_FRAME();
   7601          ReservedRooted<JSObject*> obj0(&state.obj0,
   7602                                         frame->script()->getRegExp(pc));
   7603          obj = CloneRegExpObject(cx, obj0.as<RegExpObject>());
   7604          if (!obj) {
   7605            GOTO_ERROR();
   7606          }
   7607        }
   7608        VIRTPUSH(StackVal(ObjectValue(*obj)));
   7609        END_OP(RegExp);
   7610      }
   7611 
   7612      CASE(Lambda) {
   7613        if (HybridICs) {
   7614          JSObject* clone;
   7615          {
   7616            PUSH_EXIT_FRAME();
   7617            ReservedRooted<JSFunction*> fun0(&state.fun0,
   7618                                             frame->script()->getFunction(pc));
   7619            ReservedRooted<JSObject*> obj0(&state.obj0,
   7620                                           frame->environmentChain());
   7621            clone = Lambda(cx, fun0, obj0);
   7622            if (!clone) {
   7623              GOTO_ERROR();
   7624            }
   7625          }
   7626          VIRTPUSH(StackVal(ObjectValue(*clone)));
   7627          NEXT_IC();
   7628          END_OP(Lambda);
   7629        } else {
   7630          IC_ZERO_ARG(0);
   7631          IC_ZERO_ARG(1);
   7632          IC_ZERO_ARG(2);
   7633          INVOKE_IC_AND_PUSH(Lambda, false);
   7634          END_OP(Lambda);
   7635        }
   7636      }
   7637 
   7638      CASE(SetFunName) {
   7639        // fun, name => fun
   7640        {
   7641          ReservedRooted<Value> value0(&state.value0,
   7642                                       VIRTPOP().asValue());  // name
   7643          ReservedRooted<JSFunction*> fun0(
   7644              &state.fun0, &VIRTSP(0).asValue().toObject().as<JSFunction>());
   7645          FunctionPrefixKind prefixKind = FunctionPrefixKind(GET_UINT8(pc));
   7646          {
   7647            PUSH_EXIT_FRAME();
   7648            if (!SetFunctionName(cx, fun0, value0, prefixKind)) {
   7649              GOTO_ERROR();
   7650            }
   7651          }
   7652        }
   7653        END_OP(SetFunName);
   7654      }
   7655 
   7656      CASE(InitHomeObject) {
   7657        // fun, homeObject => fun
   7658        {
   7659          ReservedRooted<JSObject*> obj0(
   7660              &state.obj0, &VIRTPOP().asValue().toObject());  // homeObject
   7661          ReservedRooted<JSFunction*> fun0(
   7662              &state.fun0, &VIRTSP(0).asValue().toObject().as<JSFunction>());
   7663          MOZ_ASSERT(fun0->allowSuperProperty());
   7664          MOZ_ASSERT(obj0->is<PlainObject>() || obj0->is<JSFunction>());
   7665          fun0->setExtendedSlot(FunctionExtended::METHOD_HOMEOBJECT_SLOT,
   7666                                ObjectValue(*obj0));
   7667        }
   7668        END_OP(InitHomeObject);
   7669      }
   7670 
   7671      CASE(CheckClassHeritage) {
   7672        {
   7673          ReservedRooted<Value> value0(&state.value0, VIRTSP(0).asValue());
   7674          {
   7675            PUSH_EXIT_FRAME();
   7676            if (!CheckClassHeritageOperation(cx, value0)) {
   7677              GOTO_ERROR();
   7678            }
   7679          }
   7680        }
   7681        END_OP(CheckClassHeritage);
   7682      }
   7683 
   7684      CASE(FunWithProto) {
   7685        // proto => obj
   7686        {
   7687          ReservedRooted<JSObject*> obj0(
   7688              &state.obj0,
   7689              &VIRTPOP().asValue().toObject());  // proto
   7690          ReservedRooted<JSObject*> obj1(&state.obj1,
   7691                                         frame->environmentChain());
   7692          ReservedRooted<JSFunction*> fun0(&state.fun0,
   7693                                           frame->script()->getFunction(pc));
   7694          JSObject* obj;
   7695          {
   7696            PUSH_EXIT_FRAME();
   7697            obj = FunWithProtoOperation(cx, fun0, obj1, obj0);
   7698            if (!obj) {
   7699              GOTO_ERROR();
   7700            }
   7701          }
   7702          VIRTPUSH(StackVal(ObjectValue(*obj)));
   7703        }
   7704        END_OP(FunWithProto);
   7705      }
   7706 
   7707      CASE(BuiltinObject) {
   7708        IC_ZERO_ARG(0);
   7709        IC_ZERO_ARG(1);
   7710        IC_ZERO_ARG(2);
   7711        INVOKE_IC_AND_PUSH(LazyConstant, false);
   7712        END_OP(BuiltinObject);
   7713      }
   7714 
   7715      CASE(Call)
   7716      CASE(CallIgnoresRv)
   7717      CASE(CallContent)
   7718      CASE(CallIter)
   7719      CASE(CallContentIter)
   7720      CASE(Eval)
   7721      CASE(StrictEval)
   7722      CASE(SuperCall)
   7723      CASE(New)
   7724      CASE(NewContent) {
   7725        static_assert(JSOpLength_Call == JSOpLength_CallIgnoresRv);
   7726        static_assert(JSOpLength_Call == JSOpLength_CallContent);
   7727        static_assert(JSOpLength_Call == JSOpLength_CallIter);
   7728        static_assert(JSOpLength_Call == JSOpLength_CallContentIter);
   7729        static_assert(JSOpLength_Call == JSOpLength_Eval);
   7730        static_assert(JSOpLength_Call == JSOpLength_StrictEval);
   7731        static_assert(JSOpLength_Call == JSOpLength_SuperCall);
   7732        static_assert(JSOpLength_Call == JSOpLength_New);
   7733        static_assert(JSOpLength_Call == JSOpLength_NewContent);
   7734        JSOp op = JSOp(*pc);
   7735        bool constructing = (op == JSOp::New || op == JSOp::NewContent ||
   7736                             op == JSOp::SuperCall);
   7737        uint32_t argc = GET_ARGC(pc);
   7738        do {
   7739          {
   7740            // CallArgsFromSp would be called with
   7741            // - numValues = argc + 2 + constructing
   7742            // - stackSlots = argc + constructing
   7743            // - sp = vp + numValues
   7744            // CallArgs::create then gets
   7745            // - argc_ = stackSlots - constructing = argc
   7746            // - argv_ = sp - stackSlots = vp + 2
   7747            // our arguments are in reverse order compared to what CallArgs
   7748            // expects so we should subtract any array subscripts from (sp +
   7749            // stackSlots - 1)
   7750            StackVal* firstArg = sp + argc + constructing - 1;
   7751 
   7752            // callee is argv_[-2] -> sp + argc + constructing + 1
   7753            // this is   argv_[-1] -> sp + argc + constructing
   7754            // newTarget is argv_[argc_] -> sp + constructing - 1
   7755            // but this/newTarget are only used when constructing is 1 so we can
   7756            // simplify this is   argv_[-1] -> sp + argc + 1 newTarget is
   7757            // argv_[argc_] -> sp
   7758 
   7759            HandleValue callee = Stack::handle(firstArg + 2);
   7760            if (!callee.isObject() || !callee.toObject().is<JSFunction>()) {
   7761              TRACE_PRINTF("missed fastpath: not a function\n");
   7762              break;
   7763            }
   7764            ReservedRooted<JSFunction*> func(
   7765                &state.fun0, &callee.toObject().as<JSFunction>());
   7766            if (!func->hasBaseScript() || !func->isInterpreted()) {
   7767              TRACE_PRINTF("missed fastpath: not an interpreted script\n");
   7768              break;
   7769            }
   7770            if (!constructing && func->isClassConstructor()) {
   7771              TRACE_PRINTF(
   7772                  "missed fastpath: constructor called without `new`\n");
   7773              break;
   7774            }
   7775            if (constructing && !func->isConstructor()) {
   7776              TRACE_PRINTF(
   7777                  "missed fastpath: constructing with a non-constructor\n");
   7778              break;
   7779            }
   7780            if (!func->baseScript()->hasBytecode()) {
   7781              TRACE_PRINTF("missed fastpath: no bytecode\n");
   7782              break;
   7783            }
   7784            ReservedRooted<JSScript*> calleeScript(
   7785                &state.script0, func->baseScript()->asJSScript());
   7786            if (!calleeScript->hasJitScript()) {
   7787              TRACE_PRINTF("missed fastpath: no jit-script\n");
   7788              break;
   7789            }
   7790            if (ctx.frameMgr.cxForLocalUseOnly()->realm() !=
   7791                calleeScript->realm()) {
   7792              TRACE_PRINTF("missed fastpath: mismatched realm\n");
   7793              break;
   7794            }
   7795            if (argc < func->nargs()) {
   7796              TRACE_PRINTF("missed fastpath: not enough arguments\n");
   7797              break;
   7798            }
   7799 
   7800            // Fast-path: function, interpreted, has JitScript, same realm, no
   7801            // argument underflow.
   7802 
   7803            // Include newTarget in the args if it exists; exclude callee
   7804            uint32_t totalArgs = argc + 1 + constructing;
   7805            StackVal* origArgs = sp;
   7806 
   7807            TRACE_PRINTF(
   7808                "Call fastpath: argc = %d origArgs = %p callee = %" PRIx64 "\n",
   7809                argc, origArgs, callee.get().asRawBits());
   7810 
   7811            if (!ctx.stack.check(sp, sizeof(StackVal) * (totalArgs + 3))) {
   7812              TRACE_PRINTF("missed fastpath: would cause stack overrun\n");
   7813              break;
   7814            }
   7815 
   7816            if (constructing) {
   7817              MutableHandleValue thisv = Stack::handleMut(firstArg + 1);
   7818              if (!thisv.isObject()) {
   7819                HandleValue newTarget = Stack::handle(firstArg - argc);
   7820                ReservedRooted<JSObject*> obj0(&state.obj0,
   7821                                               &newTarget.toObject());
   7822 
   7823                PUSH_EXIT_FRAME();
   7824                // CreateThis might discard the JitScript but we're counting on
   7825                // it continuing to exist while we evaluate the fastpath.
   7826                AutoKeepJitScripts keepJitScript(cx);
   7827                if (!CreateThis(cx, func, obj0, GenericObject, thisv)) {
   7828                  GOTO_ERROR();
   7829                }
   7830 
   7831                TRACE_PRINTF("created %" PRIx64 "\n", thisv.get().asRawBits());
   7832              }
   7833            }
   7834 
   7835            // 0. Save current PC and interpreter IC pointer in
   7836            // current frame, so we can retrieve them later.
   7837            frame->interpreterPC() = pc;
   7838            frame->interpreterICEntry() = icEntry;
   7839 
   7840            // 1. Push a baseline stub frame. Don't use the frame manager
   7841            // -- we don't want the frame to be auto-freed when we leave
   7842            // this scope, and we don't want to shadow `sp`.
   7843            StackVal* exitFP = ctx.stack.pushExitFrame(sp, frame);
   7844            MOZ_ASSERT(exitFP);  // safety: stack margin.
   7845            sp = exitFP;
   7846            TRACE_PRINTF("exit frame at %p\n", exitFP);
   7847 
   7848            // 2. Modify exit code to nullptr (this is where ICStubReg is
   7849            // normally saved; the tracing code can skip if null).
   7850            PUSHNATIVE(StackValNative(nullptr));
   7851 
   7852            // 3. Push args in proper order (they are reversed in our
   7853            // downward-growth stack compared to what the calling
   7854            // convention expects).
   7855            for (uint32_t i = 0; i < totalArgs; i++) {
   7856              VIRTPUSH(origArgs[i]);
   7857            }
   7858 
   7859            // 4. Push inter-frame content: callee token, descriptor for
   7860            // above.
   7861            PUSHNATIVE(StackValNative(CalleeToToken(func, constructing)));
   7862            PUSHNATIVE(StackValNative(
   7863                MakeFrameDescriptorForJitCall(FrameType::BaselineStub, argc)));
   7864 
   7865            // 5. Push fake return address, set script, push baseline frame.
   7866            PUSHNATIVE(StackValNative(nullptr));
   7867            BaselineFrame* newFrame =
   7868                ctx.stack.pushFrame(sp, ctx.frameMgr.cxForLocalUseOnly(),
   7869                                    /* envChain = */ func->environment());
   7870            MOZ_ASSERT(newFrame);  // safety: stack margin.
   7871            TRACE_PRINTF("callee frame at %p\n", newFrame);
   7872            frame = newFrame;
   7873            ctx.frameMgr.switchToFrame(frame);
   7874            ctx.frame = frame;
   7875            // 6. Set up PC and SP for callee.
   7876            sp = reinterpret_cast<StackVal*>(frame);
   7877            RESET_PC(calleeScript->code(), calleeScript);
   7878            // 7. Check callee stack space for max stack depth.
   7879            if (!stack.check(sp, sizeof(StackVal) * calleeScript->nslots())) {
   7880              PUSH_EXIT_FRAME();
   7881              ReportOverRecursed(ctx.frameMgr.cxForLocalUseOnly());
   7882              GOTO_ERROR();
   7883            }
   7884            // 8. Push local slots, and set return value to `undefined` by
   7885            // default.
   7886            uint32_t nfixed = calleeScript->nfixed();
   7887            for (uint32_t i = 0; i < nfixed; i++) {
   7888              VIRTPUSH(StackVal(UndefinedValue()));
   7889            }
   7890            ret->setUndefined();
   7891            // 9. Initialize environment objects.
   7892            if (func->needsFunctionEnvironmentObjects()) {
   7893              PUSH_EXIT_FRAME();
   7894              if (!js::InitFunctionEnvironmentObjects(cx, frame)) {
   7895                GOTO_ERROR();
   7896              }
   7897            }
   7898            // 10. Set debug flag, if appropriate.
   7899            if (frame->script()->isDebuggee()) {
   7900              TRACE_PRINTF("Script is debuggee\n");
   7901              frame->setIsDebuggee();
   7902 
   7903              PUSH_EXIT_FRAME();
   7904              if (!DebugPrologue(cx, frame)) {
   7905                GOTO_ERROR();
   7906              }
   7907            }
   7908            // 11. Check for interrupts.
   7909 #ifdef ENABLE_INTERRUPT_CHECKS
   7910            if (ctx.frameMgr.cxForLocalUseOnly()->hasAnyPendingInterrupt()) {
   7911              PUSH_EXIT_FRAME();
   7912              if (!InterruptCheck(cx)) {
   7913                GOTO_ERROR();
   7914              }
   7915            }
   7916 #endif
   7917            // 12. Initialize coverage tables, if needed.
   7918            if (!frame->script()->hasScriptCounts()) {
   7919              if (ctx.frameMgr.cxForLocalUseOnly()
   7920                      ->realm()
   7921                      ->collectCoverageForDebug()) {
   7922                PUSH_EXIT_FRAME();
   7923                if (!frame->script()->initScriptCounts(cx)) {
   7924                  GOTO_ERROR();
   7925                }
   7926              }
   7927            }
   7928            COUNT_COVERAGE_MAIN();
   7929          }
   7930 
   7931          // Everything is switched to callee context now -- dispatch!
   7932          DISPATCH();
   7933        } while (0);
   7934 
   7935        // Slow path: use the IC!
   7936        ic_arg0 = argc;
   7937        ctx.icregs.extraArgs = 2 + constructing;
   7938        INVOKE_IC(Call, false);
   7939        VIRTPOPN(argc + 2 + constructing);
   7940        VIRTPUSH(StackVal(Value::fromRawBits(ic_ret)));
   7941        END_OP(Call);
   7942      }
   7943 
   7944      CASE(SpreadCall)
   7945      CASE(SpreadEval)
   7946      CASE(StrictSpreadEval) {
   7947        static_assert(JSOpLength_SpreadCall == JSOpLength_SpreadEval);
   7948        static_assert(JSOpLength_SpreadCall == JSOpLength_StrictSpreadEval);
   7949        ic_arg0 = 1;
   7950        IC_ZERO_ARG(1);
   7951        IC_ZERO_ARG(2);
   7952        ctx.icregs.extraArgs = 2;
   7953        INVOKE_IC(SpreadCall, false);
   7954        VIRTPOPN(3);
   7955        VIRTPUSH(StackVal(Value::fromRawBits(ic_ret)));
   7956        END_OP(SpreadCall);
   7957      }
   7958 
   7959      CASE(SpreadSuperCall)
   7960      CASE(SpreadNew) {
   7961        static_assert(JSOpLength_SpreadSuperCall == JSOpLength_SpreadNew);
   7962        ic_arg0 = 1;
   7963        ctx.icregs.extraArgs = 3;
   7964        INVOKE_IC(SpreadCall, false);
   7965        VIRTPOPN(4);
   7966        VIRTPUSH(StackVal(Value::fromRawBits(ic_ret)));
   7967        END_OP(SpreadSuperCall);
   7968      }
   7969 
   7970      CASE(OptimizeSpreadCall) {
   7971        IC_POP_ARG(0);
   7972        IC_ZERO_ARG(1);
   7973        IC_ZERO_ARG(2);
   7974        INVOKE_IC_AND_PUSH(OptimizeSpreadCall, false);
   7975        END_OP(OptimizeSpreadCall);
   7976      }
   7977 
   7978      CASE(OptimizeGetIterator) {
   7979        IC_POP_ARG(0);
   7980        IC_ZERO_ARG(1);
   7981        IC_ZERO_ARG(2);
   7982        INVOKE_IC_AND_PUSH(OptimizeGetIterator, false);
   7983        END_OP(OptimizeGetIterator);
   7984      }
   7985 
   7986      CASE(ImplicitThis) {
   7987        {
   7988          ReservedRooted<JSObject*> env(&state.obj0,
   7989                                        &VIRTSP(0).asValue().toObject());
   7990          VIRTPOP();
   7991          PUSH_EXIT_FRAME();
   7992          ImplicitThisOperation(cx, env, &state.res);
   7993        }
   7994        VIRTPUSH(StackVal(state.res));
   7995        state.res.setUndefined();
   7996        END_OP(ImplicitThis);
   7997      }
   7998 
   7999      CASE(CallSiteObj) {
   8000        JSObject* cso = frame->script()->getObject(pc);
   8001        MOZ_ASSERT(!cso->as<ArrayObject>().isExtensible());
   8002        MOZ_ASSERT(cso->as<ArrayObject>().containsPure(
   8003            ctx.frameMgr.cxForLocalUseOnly()->names().raw));
   8004        VIRTPUSH(StackVal(ObjectValue(*cso)));
   8005        END_OP(CallSiteObj);
   8006      }
   8007 
   8008      CASE(IsConstructing) {
   8009        VIRTPUSH(StackVal(MagicValue(JS_IS_CONSTRUCTING)));
   8010        END_OP(IsConstructing);
   8011      }
   8012 
   8013      CASE(SuperFun) {
   8014        JSObject* superEnvFunc = &VIRTPOP().asValue().toObject();
   8015        JSObject* superFun = SuperFunOperation(superEnvFunc);
   8016        VIRTPUSH(StackVal(ObjectOrNullValue(superFun)));
   8017        END_OP(SuperFun);
   8018      }
   8019 
   8020      CASE(CheckThis) {
   8021        if (VIRTSP(0).asValue().isMagic(JS_UNINITIALIZED_LEXICAL)) {
   8022          PUSH_EXIT_FRAME();
   8023          MOZ_ALWAYS_FALSE(ThrowUninitializedThis(cx));
   8024          GOTO_ERROR();
   8025        }
   8026        END_OP(CheckThis);
   8027      }
   8028 
   8029      CASE(CheckThisReinit) {
   8030        if (!VIRTSP(0).asValue().isMagic(JS_UNINITIALIZED_LEXICAL)) {
   8031          PUSH_EXIT_FRAME();
   8032          MOZ_ALWAYS_FALSE(ThrowInitializedThis(cx));
   8033          GOTO_ERROR();
   8034        }
   8035        END_OP(CheckThisReinit);
   8036      }
   8037 
   8038      CASE(Generator) {
   8039        JSObject* generator;
   8040        {
   8041          PUSH_EXIT_FRAME();
   8042          generator = CreateGeneratorFromFrame(cx, frame);
   8043          if (!generator) {
   8044            GOTO_ERROR();
   8045          }
   8046        }
   8047        VIRTPUSH(StackVal(ObjectValue(*generator)));
   8048        END_OP(Generator);
   8049      }
   8050 
   8051      CASE(InitialYield) {
   8052        // gen => rval, gen, resumeKind
   8053        ReservedRooted<JSObject*> obj0(&state.obj0,
   8054                                       &VIRTSP(0).asValue().toObject());
   8055        uint32_t frameSize = ctx.stack.frameSize(sp, frame);
   8056        {
   8057          PUSH_EXIT_FRAME();
   8058          if (!NormalSuspend(cx, obj0, frame, frameSize, pc)) {
   8059            GOTO_ERROR();
   8060          }
   8061        }
   8062        frame->setReturnValue(VIRTSP(0).asValue());
   8063        goto do_return;
   8064      }
   8065 
   8066      CASE(Await)
   8067      CASE(Yield) {
   8068        // rval1, gen => rval2, gen, resumeKind
   8069        ReservedRooted<JSObject*> obj0(&state.obj0,
   8070                                       &VIRTPOP().asValue().toObject());
   8071        uint32_t frameSize = ctx.stack.frameSize(sp, frame);
   8072        {
   8073          PUSH_EXIT_FRAME();
   8074          if (!NormalSuspend(cx, obj0, frame, frameSize, pc)) {
   8075            GOTO_ERROR();
   8076          }
   8077        }
   8078        frame->setReturnValue(VIRTSP(0).asValue());
   8079        goto do_return;
   8080      }
   8081 
   8082      CASE(FinalYieldRval) {
   8083        // gen =>
   8084        ReservedRooted<JSObject*> obj0(&state.obj0,
   8085                                       &VIRTPOP().asValue().toObject());
   8086        {
   8087          PUSH_EXIT_FRAME();
   8088          if (!FinalSuspend(cx, obj0, pc)) {
   8089            GOTO_ERROR();
   8090          }
   8091        }
   8092        goto do_return;
   8093      }
   8094 
   8095      CASE(IsGenClosing) {
   8096        bool result = VIRTSP(0).asValue() == MagicValue(JS_GENERATOR_CLOSING);
   8097        VIRTPUSH(StackVal(BooleanValue(result)));
   8098        END_OP(IsGenClosing);
   8099      }
   8100 
   8101      CASE(AsyncAwait) {
   8102        // value, gen => promise
   8103        JSObject* promise;
   8104        {
   8105          ReservedRooted<JSObject*> obj0(
   8106              &state.obj0,
   8107              &VIRTPOP().asValue().toObject());  // gen
   8108          ReservedRooted<Value> value0(&state.value0,
   8109                                       VIRTPOP().asValue());  // value
   8110          PUSH_EXIT_FRAME();
   8111          promise = AsyncFunctionAwait(
   8112              cx, obj0.as<AsyncFunctionGeneratorObject>(), value0);
   8113          if (!promise) {
   8114            GOTO_ERROR();
   8115          }
   8116        }
   8117        VIRTPUSH(StackVal(ObjectValue(*promise)));
   8118        END_OP(AsyncAwait);
   8119      }
   8120 
   8121      CASE(AsyncResolve) {
   8122        // value, gen => promise
   8123        JSObject* promise;
   8124        {
   8125          ReservedRooted<JSObject*> obj0(
   8126              &state.obj0,
   8127              &VIRTPOP().asValue().toObject());  // gen
   8128          ReservedRooted<Value> value0(&state.value0,
   8129                                       VIRTPOP().asValue());  // value
   8130          PUSH_EXIT_FRAME();
   8131          promise = AsyncFunctionResolve(
   8132              cx, obj0.as<AsyncFunctionGeneratorObject>(), value0);
   8133          if (!promise) {
   8134            GOTO_ERROR();
   8135          }
   8136        }
   8137        VIRTPUSH(StackVal(ObjectValue(*promise)));
   8138        END_OP(AsyncResolve);
   8139      }
   8140 
   8141      CASE(AsyncReject) {
   8142        // reason, gen => promise
   8143        JSObject* promise;
   8144        {
   8145          ReservedRooted<JSObject*> obj0(
   8146              &state.obj0,
   8147              &VIRTPOP().asValue().toObject());  // gen
   8148          ReservedRooted<Value> value0(&state.value0,
   8149                                       VIRTPOP().asValue());  // stack
   8150          ReservedRooted<Value> value1(&state.value1,
   8151                                       VIRTPOP().asValue());  // reason
   8152          PUSH_EXIT_FRAME();
   8153          promise = AsyncFunctionReject(
   8154              cx, obj0.as<AsyncFunctionGeneratorObject>(), value1, value0);
   8155          if (!promise) {
   8156            GOTO_ERROR();
   8157          }
   8158        }
   8159        VIRTPUSH(StackVal(ObjectValue(*promise)));
   8160        END_OP(AsyncReject);
   8161      }
   8162 
   8163      CASE(CanSkipAwait) {
   8164        // value => value, can_skip
   8165        bool result = false;
   8166        {
   8167          ReservedRooted<Value> value0(&state.value0, VIRTSP(0).asValue());
   8168          PUSH_EXIT_FRAME();
   8169          if (!CanSkipAwait(cx, value0, &result)) {
   8170            GOTO_ERROR();
   8171          }
   8172        }
   8173        VIRTPUSH(StackVal(BooleanValue(result)));
   8174        END_OP(CanSkipAwait);
   8175      }
   8176 
   8177      CASE(MaybeExtractAwaitValue) {
   8178        // value, can_skip => value_or_resolved, can_skip
   8179        {
   8180          Value can_skip = VIRTPOP().asValue();
   8181          ReservedRooted<Value> value0(&state.value0,
   8182                                       VIRTPOP().asValue());  // value
   8183          if (can_skip.toBoolean()) {
   8184            PUSH_EXIT_FRAME();
   8185            if (!ExtractAwaitValue(cx, value0, &value0)) {
   8186              GOTO_ERROR();
   8187            }
   8188          }
   8189          VIRTPUSH(StackVal(value0));
   8190          VIRTPUSH(StackVal(can_skip));
   8191        }
   8192        END_OP(MaybeExtractAwaitValue);
   8193      }
   8194 
   8195      CASE(ResumeKind) {
   8196        GeneratorResumeKind resumeKind = ResumeKindFromPC(pc);
   8197        VIRTPUSH(StackVal(Int32Value(int32_t(resumeKind))));
   8198        END_OP(ResumeKind);
   8199      }
   8200 
   8201      CASE(CheckResumeKind) {
   8202        // rval, gen, resumeKind => rval
   8203        {
   8204          GeneratorResumeKind resumeKind =
   8205              IntToResumeKind(VIRTPOP().asValue().toInt32());
   8206          ReservedRooted<JSObject*> obj0(
   8207              &state.obj0,
   8208              &VIRTPOP().asValue().toObject());  // gen
   8209          ReservedRooted<Value> value0(&state.value0,
   8210                                       VIRTSP(0).asValue());  // rval
   8211          if (resumeKind != GeneratorResumeKind::Next) {
   8212            PUSH_EXIT_FRAME();
   8213            MOZ_ALWAYS_FALSE(GeneratorThrowOrReturn(
   8214                cx, frame, obj0.as<AbstractGeneratorObject>(), value0,
   8215                resumeKind));
   8216            GOTO_ERROR();
   8217          }
   8218        }
   8219        END_OP(CheckResumeKind);
   8220      }
   8221 
   8222      CASE(Resume) {
   8223        SYNCSP();
   8224        Value gen = VIRTSP(2).asValue();
   8225        Value* callerSP = reinterpret_cast<Value*>(sp);
   8226        {
   8227          ReservedRooted<Value> value0(&state.value0);
   8228          ReservedRooted<JSObject*> obj0(&state.obj0, &gen.toObject());
   8229          {
   8230            PUSH_EXIT_FRAME();
   8231            TRACE_PRINTF("Going to C++ interp for Resume\n");
   8232            if (!InterpretResume(cx, obj0, callerSP, &value0)) {
   8233              GOTO_ERROR();
   8234            }
   8235          }
   8236          VIRTPOPN(2);
   8237          VIRTSPWRITE(0, StackVal(value0));
   8238        }
   8239        END_OP(Resume);
   8240      }
   8241 
   8242      CASE(JumpTarget) {
   8243        int32_t icIndex = GET_INT32(pc);
   8244        icEntry = icEntries + icIndex;
   8245        COUNT_COVERAGE_PC(pc);
   8246        END_OP(JumpTarget);
   8247      }
   8248      CASE(LoopHead) {
   8249        int32_t icIndex = GET_INT32(pc);
   8250        icEntry = icEntries + icIndex;
   8251 #ifdef ENABLE_INTERRUPT_CHECKS
   8252        if (ctx.frameMgr.cxForLocalUseOnly()->hasAnyPendingInterrupt()) {
   8253          PUSH_EXIT_FRAME();
   8254          if (!InterruptCheck(cx)) {
   8255            GOTO_ERROR();
   8256          }
   8257        }
   8258 #endif
   8259        COUNT_COVERAGE_PC(pc);
   8260        END_OP(LoopHead);
   8261      }
   8262      CASE(AfterYield) {
   8263        int32_t icIndex = GET_INT32(pc);
   8264        icEntry = icEntries + icIndex;
   8265        if (frame->script()->isDebuggee()) {
   8266          TRACE_PRINTF("doing DebugAfterYield\n");
   8267          PUSH_EXIT_FRAME();
   8268          ReservedRooted<JSScript*> script0(&state.script0, frame->script());
   8269          if (DebugAPI::hasAnyBreakpointsOrStepMode(script0) &&
   8270              !HandleDebugTrap(cx, frame, pc)) {
   8271            TRACE_PRINTF("HandleDebugTrap returned error\n");
   8272            GOTO_ERROR();
   8273          }
   8274          if (!DebugAfterYield(cx, frame)) {
   8275            TRACE_PRINTF("DebugAfterYield returned error\n");
   8276            GOTO_ERROR();
   8277          }
   8278        }
   8279        COUNT_COVERAGE_PC(pc);
   8280        END_OP(AfterYield);
   8281      }
   8282 
   8283      CASE(Goto) {
   8284        ADVANCE(GET_JUMP_OFFSET(pc));
   8285        PREDICT_NEXT(JumpTarget);
   8286        PREDICT_NEXT(LoopHead);
   8287        DISPATCH();
   8288      }
   8289 
   8290      CASE(Coalesce) {
   8291        if (!VIRTSP(0).asValue().isNullOrUndefined()) {
   8292          ADVANCE(GET_JUMP_OFFSET(pc));
   8293          DISPATCH();
   8294        } else {
   8295          END_OP(Coalesce);
   8296        }
   8297      }
   8298 
   8299      CASE(Case) {
   8300        bool cond = VIRTPOP().asValue().toBoolean();
   8301        if (cond) {
   8302          VIRTPOP();
   8303          ADVANCE(GET_JUMP_OFFSET(pc));
   8304          DISPATCH();
   8305        } else {
   8306          END_OP(Case);
   8307        }
   8308      }
   8309 
   8310      CASE(Default) {
   8311        VIRTPOP();
   8312        ADVANCE(GET_JUMP_OFFSET(pc));
   8313        DISPATCH();
   8314      }
   8315 
   8316      CASE(TableSwitch) {
   8317        int32_t len = GET_JUMP_OFFSET(pc);
   8318        int32_t low = GET_JUMP_OFFSET(pc + 1 * JUMP_OFFSET_LEN);
   8319        int32_t high = GET_JUMP_OFFSET(pc + 2 * JUMP_OFFSET_LEN);
   8320        Value v = VIRTPOP().asValue();
   8321        int32_t i = 0;
   8322        if (v.isInt32()) {
   8323          i = v.toInt32();
   8324        } else if (!v.isDouble() ||
   8325                   !mozilla::NumberEqualsInt32(v.toDouble(), &i)) {
   8326          ADVANCE(len);
   8327          DISPATCH();
   8328        }
   8329 
   8330        if (i >= low && i <= high) {
   8331          uint32_t idx = uint32_t(i) - uint32_t(low);
   8332          uint32_t firstResumeIndex = GET_RESUMEINDEX(pc + 3 * JUMP_OFFSET_LEN);
   8333          pc = entryPC + resumeOffsets[firstResumeIndex + idx];
   8334          DISPATCH();
   8335        }
   8336        ADVANCE(len);
   8337        DISPATCH();
   8338      }
   8339 
   8340      CASE(Return) {
   8341        frame->setReturnValue(VIRTPOP().asValue());
   8342        goto do_return;
   8343      }
   8344 
   8345      CASE(GetRval) {
   8346        VIRTPUSH(StackVal(frame->returnValue()));
   8347        END_OP(GetRval);
   8348      }
   8349 
   8350      CASE(SetRval) {
   8351        frame->setReturnValue(VIRTPOP().asValue());
   8352        END_OP(SetRval);
   8353      }
   8354 
   8355    do_return:
   8356      CASE(RetRval) {
   8357        SYNCSP();
   8358        bool ok = true;
   8359        if (frame->isDebuggee() && !from_unwind) {
   8360          TRACE_PRINTF("doing DebugEpilogueOnBaselineReturn\n");
   8361          PUSH_EXIT_FRAME();
   8362          ok = DebugEpilogueOnBaselineReturn(cx, frame, pc);
   8363        }
   8364        from_unwind = false;
   8365 
   8366        uint32_t argc = frame->numActualArgs();
   8367        sp = ctx.stack.popFrame();
   8368 
   8369        // If FP is higher than the entry frame now, return; otherwise,
   8370        // do an inline state update.
   8371        if (stack.fp > entryFrame) {
   8372          *ret = frame->returnValue();
   8373          TRACE_PRINTF("ret = %" PRIx64 "\n", ret->asRawBits());
   8374          return ok ? PBIResult::Ok : PBIResult::Error;
   8375        } else {
   8376          TRACE_PRINTF("Return fastpath\n");
   8377          Value ret = frame->returnValue();
   8378          TRACE_PRINTF("ret = %" PRIx64 "\n", ret.asRawBits());
   8379 
   8380          // Pop exit frame as well.
   8381          sp = ctx.stack.popFrame();
   8382          // Pop fake return address and descriptor.
   8383          POPNNATIVE(2);
   8384 
   8385          // Set PC, frame, and current script.
   8386          frame = reinterpret_cast<BaselineFrame*>(
   8387              reinterpret_cast<uintptr_t>(stack.fp) - BaselineFrame::Size());
   8388          TRACE_PRINTF(" sp -> %p, fp -> %p, frame -> %p\n", sp, ctx.stack.fp,
   8389                       frame);
   8390          ctx.frameMgr.switchToFrame(frame);
   8391          ctx.frame = frame;
   8392          RESET_PC(frame->interpreterPC(), frame->script());
   8393 
   8394          // Adjust caller's stack to complete the call op that PC still points
   8395          // to in that frame (pop args, push return value).
   8396          JSOp op = JSOp(*pc);
   8397          bool constructing = (op == JSOp::New || op == JSOp::NewContent ||
   8398                               op == JSOp::SuperCall);
   8399          // Fix-up return value; EnterJit would do this if we hadn't bypassed
   8400          // it.
   8401          if (constructing && ret.isPrimitive()) {
   8402            ret = sp[argc + constructing].asValue();
   8403            TRACE_PRINTF("updated ret = %" PRIx64 "\n", ret.asRawBits());
   8404          }
   8405          // Pop args -- this is 1 more than how many are pushed in the
   8406          // `totalArgs` count during the call fastpath because it includes
   8407          // the callee.
   8408          VIRTPOPN(argc + 2 + constructing);
   8409          // Push return value.
   8410          VIRTPUSH(StackVal(ret));
   8411 
   8412          if (!ok) {
   8413            GOTO_ERROR();
   8414          }
   8415 
   8416          // Advance past call instruction, and advance past IC.
   8417          NEXT_IC();
   8418          ADVANCE(JSOpLength_Call);
   8419 
   8420          DISPATCH();
   8421        }
   8422      }
   8423 
   8424      CASE(CheckReturn) {
   8425        Value thisval = VIRTPOP().asValue();
   8426        // inlined version of frame->checkReturn(thisval, result)
   8427        // (js/src/vm/Stack.cpp).
   8428        HandleValue retVal = frame->returnValue();
   8429        if (retVal.isObject()) {
   8430          VIRTPUSH(StackVal(retVal));
   8431        } else if (!retVal.isUndefined()) {
   8432          PUSH_EXIT_FRAME();
   8433          MOZ_ALWAYS_FALSE(ReportValueError(cx, JSMSG_BAD_DERIVED_RETURN,
   8434                                            JSDVG_IGNORE_STACK, retVal,
   8435                                            nullptr));
   8436          GOTO_ERROR();
   8437        } else if (thisval.isMagic(JS_UNINITIALIZED_LEXICAL)) {
   8438          PUSH_EXIT_FRAME();
   8439          MOZ_ALWAYS_FALSE(ThrowUninitializedThis(cx));
   8440          GOTO_ERROR();
   8441        } else {
   8442          VIRTPUSH(StackVal(thisval));
   8443        }
   8444        END_OP(CheckReturn);
   8445      }
   8446 
   8447      CASE(Throw) {
   8448        {
   8449          ReservedRooted<Value> value0(&state.value0, VIRTPOP().asValue());
   8450          PUSH_EXIT_FRAME();
   8451          MOZ_ALWAYS_FALSE(ThrowOperation(cx, value0));
   8452          GOTO_ERROR();
   8453        }
   8454        END_OP(Throw);
   8455      }
   8456 
   8457      CASE(ThrowWithStack) {
   8458        {
   8459          ReservedRooted<Value> value0(&state.value0, VIRTPOP().asValue());
   8460          ReservedRooted<Value> value1(&state.value1, VIRTPOP().asValue());
   8461          PUSH_EXIT_FRAME();
   8462          MOZ_ALWAYS_FALSE(ThrowWithStackOperation(cx, value1, value0));
   8463          GOTO_ERROR();
   8464        }
   8465        END_OP(ThrowWithStack);
   8466      }
   8467 
   8468      CASE(ThrowMsg) {
   8469        {
   8470          PUSH_EXIT_FRAME();
   8471          MOZ_ALWAYS_FALSE(ThrowMsgOperation(cx, GET_UINT8(pc)));
   8472          GOTO_ERROR();
   8473        }
   8474        END_OP(ThrowMsg);
   8475      }
   8476 
   8477      CASE(ThrowSetConst) {
   8478        {
   8479          PUSH_EXIT_FRAME();
   8480          ReservedRooted<JSScript*> script0(&state.script0, frame->script());
   8481          ReportRuntimeLexicalError(cx, JSMSG_BAD_CONST_ASSIGN, script0, pc);
   8482          GOTO_ERROR();
   8483        }
   8484        END_OP(ThrowSetConst);
   8485      }
   8486 
   8487      CASE(Try)
   8488      CASE(TryDestructuring) {
   8489        static_assert(JSOpLength_Try == JSOpLength_TryDestructuring);
   8490        END_OP(Try);
   8491      }
   8492 
   8493      CASE(Exception) {
   8494        {
   8495          PUSH_EXIT_FRAME();
   8496          if (!GetAndClearException(cx, &state.res)) {
   8497            GOTO_ERROR();
   8498          }
   8499        }
   8500        VIRTPUSH(StackVal(state.res));
   8501        state.res.setUndefined();
   8502        END_OP(Exception);
   8503      }
   8504 
   8505      CASE(ExceptionAndStack) {
   8506        {
   8507          ReservedRooted<Value> value0(&state.value0);
   8508          {
   8509            PUSH_EXIT_FRAME();
   8510            if (!cx.getCx()->getPendingExceptionStack(&value0)) {
   8511              GOTO_ERROR();
   8512            }
   8513            if (!GetAndClearException(cx, &state.res)) {
   8514              GOTO_ERROR();
   8515            }
   8516          }
   8517          VIRTPUSH(StackVal(state.res));
   8518          VIRTPUSH(StackVal(value0));
   8519          state.res.setUndefined();
   8520        }
   8521        END_OP(ExceptionAndStack);
   8522      }
   8523 
   8524      CASE(Finally) {
   8525 #ifdef ENABLE_INTERRUPT_CHECKS
   8526        if (ctx.frameMgr.cxForLocalUseOnly()->hasAnyPendingInterrupt()) {
   8527          PUSH_EXIT_FRAME();
   8528          if (!InterruptCheck(cx)) {
   8529            GOTO_ERROR();
   8530          }
   8531        }
   8532 #endif
   8533        END_OP(Finally);
   8534      }
   8535 
   8536      CASE(Uninitialized) {
   8537        VIRTPUSH(StackVal(MagicValue(JS_UNINITIALIZED_LEXICAL)));
   8538        END_OP(Uninitialized);
   8539      }
   8540      CASE(InitLexical) {
   8541        uint32_t i = GET_LOCALNO(pc);
   8542        frame->unaliasedLocal(i) = VIRTSP(0).asValue();
   8543        END_OP(InitLexical);
   8544      }
   8545 
   8546      CASE(InitAliasedLexical) {
   8547        EnvironmentCoordinate ec = EnvironmentCoordinate(pc);
   8548        EnvironmentObject& obj = getEnvironmentFromCoordinate(frame, ec);
   8549        obj.setAliasedBinding(ec, VIRTSP(0).asValue());
   8550        END_OP(InitAliasedLexical);
   8551      }
   8552      CASE(CheckLexical) {
   8553        if (VIRTSP(0).asValue().isMagic(JS_UNINITIALIZED_LEXICAL)) {
   8554          PUSH_EXIT_FRAME();
   8555          ReservedRooted<JSScript*> script0(&state.script0, frame->script());
   8556          ReportRuntimeLexicalError(cx, JSMSG_UNINITIALIZED_LEXICAL, script0,
   8557                                    pc);
   8558          GOTO_ERROR();
   8559        }
   8560        END_OP(CheckLexical);
   8561      }
   8562      CASE(CheckAliasedLexical) {
   8563        if (VIRTSP(0).asValue().isMagic(JS_UNINITIALIZED_LEXICAL)) {
   8564          PUSH_EXIT_FRAME();
   8565          ReservedRooted<JSScript*> script0(&state.script0, frame->script());
   8566          ReportRuntimeLexicalError(cx, JSMSG_UNINITIALIZED_LEXICAL, script0,
   8567                                    pc);
   8568          GOTO_ERROR();
   8569        }
   8570        END_OP(CheckAliasedLexical);
   8571      }
   8572 
   8573      CASE(BindUnqualifiedGName) {
   8574        IC_SET_OBJ_ARG(
   8575            0,
   8576            &ctx.frameMgr.cxForLocalUseOnly()->global()->lexicalEnvironment());
   8577        IC_ZERO_ARG(1);
   8578        IC_ZERO_ARG(2);
   8579        INVOKE_IC_AND_PUSH(BindName, false);
   8580        END_OP(BindUnqualifiedGName);
   8581      }
   8582      CASE(BindName) {
   8583        IC_SET_OBJ_ARG(0, frame->environmentChain());
   8584        IC_ZERO_ARG(1);
   8585        IC_ZERO_ARG(2);
   8586        INVOKE_IC_AND_PUSH(BindName, false);
   8587        END_OP(BindName);
   8588      }
   8589      CASE(BindUnqualifiedName) {
   8590        IC_SET_OBJ_ARG(0, frame->environmentChain());
   8591        IC_ZERO_ARG(1);
   8592        IC_ZERO_ARG(2);
   8593        INVOKE_IC_AND_PUSH(BindName, false);
   8594        END_OP(BindUnqualifiedName);
   8595      }
   8596      CASE(GetGName) {
   8597        IC_SET_OBJ_ARG(
   8598            0,
   8599            &ctx.frameMgr.cxForLocalUseOnly()->global()->lexicalEnvironment());
   8600        IC_ZERO_ARG(1);
   8601        IC_ZERO_ARG(2);
   8602        INVOKE_IC_AND_PUSH(GetName, false);
   8603        END_OP(GetGName);
   8604      }
   8605      CASE(GetName) {
   8606        IC_SET_OBJ_ARG(0, frame->environmentChain());
   8607        IC_ZERO_ARG(1);
   8608        IC_ZERO_ARG(2);
   8609        INVOKE_IC_AND_PUSH(GetName, false);
   8610        END_OP(GetName);
   8611      }
   8612 
   8613      CASE(GetArg) {
   8614        unsigned i = GET_ARGNO(pc);
   8615        if (argsObjAliasesFormals) {
   8616          VIRTPUSH(StackVal(frame->argsObj().arg(i)));
   8617        } else {
   8618          VIRTPUSH(StackVal(frame->argv()[i]));
   8619        }
   8620        END_OP(GetArg);
   8621      }
   8622 
   8623      CASE(GetFrameArg) {
   8624        uint32_t i = GET_ARGNO(pc);
   8625        VIRTPUSH(StackVal(frame->argv()[i]));
   8626        END_OP(GetFrameArg);
   8627      }
   8628 
   8629      CASE(GetLocal) {
   8630        uint32_t i = GET_LOCALNO(pc);
   8631        TRACE_PRINTF(" -> local: %d\n", int(i));
   8632        VIRTPUSH(StackVal(GETLOCAL(i)));
   8633        END_OP(GetLocal);
   8634      }
   8635 
   8636      CASE(ArgumentsLength) {
   8637        VIRTPUSH(StackVal(Int32Value(frame->numActualArgs())));
   8638        END_OP(ArgumentsLength);
   8639      }
   8640 
   8641      CASE(GetActualArg) {
   8642        MOZ_ASSERT(!frame->script()->needsArgsObj());
   8643        uint32_t index = VIRTSP(0).asValue().toInt32();
   8644        VIRTSPWRITE(0, StackVal(frame->unaliasedActual(index)));
   8645        END_OP(GetActualArg);
   8646      }
   8647 
   8648      CASE(GetAliasedVar)
   8649      CASE(GetAliasedDebugVar) {
   8650        static_assert(JSOpLength_GetAliasedVar ==
   8651                      JSOpLength_GetAliasedDebugVar);
   8652        EnvironmentCoordinate ec = EnvironmentCoordinate(pc);
   8653        EnvironmentObject& obj = getEnvironmentFromCoordinate(frame, ec);
   8654        VIRTPUSH(StackVal(obj.aliasedBinding(ec)));
   8655        END_OP(GetAliasedVar);
   8656      }
   8657 
   8658      CASE(GetImport) {
   8659        IC_ZERO_ARG(0);
   8660        IC_ZERO_ARG(1);
   8661        IC_ZERO_ARG(2);
   8662        INVOKE_IC_AND_PUSH(GetImport, false);
   8663        END_OP(GetImport);
   8664      }
   8665 
   8666      CASE(GetIntrinsic) {
   8667        IC_ZERO_ARG(0);
   8668        IC_ZERO_ARG(1);
   8669        IC_ZERO_ARG(2);
   8670        INVOKE_IC_AND_PUSH(LazyConstant, false);
   8671        END_OP(GetIntrinsic);
   8672      }
   8673 
   8674      CASE(Callee) {
   8675        VIRTPUSH(StackVal(frame->calleev()));
   8676        END_OP(Callee);
   8677      }
   8678 
   8679      CASE(EnvCallee) {
   8680        uint16_t numHops = GET_ENVCOORD_HOPS(pc);
   8681        JSObject* env = &frame->environmentChain()->as<EnvironmentObject>();
   8682        for (unsigned i = 0; i < numHops; i++) {
   8683          env = &env->as<EnvironmentObject>().enclosingEnvironment();
   8684        }
   8685        VIRTPUSH(StackVal(ObjectValue(env->as<CallObject>().callee())));
   8686        END_OP(EnvCallee);
   8687      }
   8688 
   8689      CASE(SetProp)
   8690      CASE(StrictSetProp)
   8691      CASE(SetName)
   8692      CASE(StrictSetName)
   8693      CASE(SetGName)
   8694      CASE(StrictSetGName) {
   8695        static_assert(JSOpLength_SetProp == JSOpLength_StrictSetProp);
   8696        static_assert(JSOpLength_SetProp == JSOpLength_SetName);
   8697        static_assert(JSOpLength_SetProp == JSOpLength_StrictSetName);
   8698        static_assert(JSOpLength_SetProp == JSOpLength_SetGName);
   8699        static_assert(JSOpLength_SetProp == JSOpLength_StrictSetGName);
   8700        IC_POP_ARG(1);
   8701        IC_POP_ARG(0);
   8702        IC_ZERO_ARG(2);
   8703        VIRTPUSH(StackVal(ic_arg1));
   8704        INVOKE_IC(SetProp, false);
   8705        END_OP(SetProp);
   8706      }
   8707 
   8708      CASE(InitProp)
   8709      CASE(InitHiddenProp)
   8710      CASE(InitLockedProp) {
   8711        static_assert(JSOpLength_InitProp == JSOpLength_InitHiddenProp);
   8712        static_assert(JSOpLength_InitProp == JSOpLength_InitLockedProp);
   8713        IC_POP_ARG(1);
   8714        IC_SET_ARG_FROM_STACK(0, 0);
   8715        IC_ZERO_ARG(2);
   8716        INVOKE_IC(SetProp, false);
   8717        END_OP(InitProp);
   8718      }
   8719      CASE(InitGLexical) {
   8720        IC_SET_ARG_FROM_STACK(1, 0);
   8721        IC_SET_OBJ_ARG(
   8722            0,
   8723            &ctx.frameMgr.cxForLocalUseOnly()->global()->lexicalEnvironment());
   8724        IC_ZERO_ARG(2);
   8725        INVOKE_IC(SetProp, false);
   8726        END_OP(InitGLexical);
   8727      }
   8728 
   8729      CASE(SetArg) {
   8730        unsigned i = GET_ARGNO(pc);
   8731        if (argsObjAliasesFormals) {
   8732          frame->argsObj().setArg(i, VIRTSP(0).asValue());
   8733        } else {
   8734          frame->argv()[i] = VIRTSP(0).asValue();
   8735        }
   8736        END_OP(SetArg);
   8737      }
   8738 
   8739      CASE(SetLocal) {
   8740        uint32_t i = GET_LOCALNO(pc);
   8741        TRACE_PRINTF(" -> local: %d\n", int(i));
   8742        SETLOCAL(i, VIRTSP(0).asValue());
   8743        END_OP(SetLocal);
   8744      }
   8745 
   8746      CASE(SetAliasedVar) {
   8747        EnvironmentCoordinate ec = EnvironmentCoordinate(pc);
   8748        EnvironmentObject& obj = getEnvironmentFromCoordinate(frame, ec);
   8749        MOZ_ASSERT(!IsUninitializedLexical(obj.aliasedBinding(ec)));
   8750        obj.setAliasedBinding(ec, VIRTSP(0).asValue());
   8751        END_OP(SetAliasedVar);
   8752      }
   8753 
   8754      CASE(SetIntrinsic) {
   8755        {
   8756          ReservedRooted<Value> value0(&state.value0, VIRTSP(0).asValue());
   8757          ReservedRooted<JSScript*> script0(&state.script0, frame->script());
   8758          {
   8759            PUSH_EXIT_FRAME();
   8760            if (!SetIntrinsicOperation(cx, script0, pc, value0)) {
   8761              GOTO_ERROR();
   8762            }
   8763          }
   8764        }
   8765        END_OP(SetIntrinsic);
   8766      }
   8767 
   8768      CASE(PushLexicalEnv) {
   8769        {
   8770          ReservedRooted<Scope*> scope0(&state.scope0,
   8771                                        frame->script()->getScope(pc));
   8772          {
   8773            PUSH_EXIT_FRAME();
   8774            if (!frame->pushLexicalEnvironment(cx, scope0.as<LexicalScope>())) {
   8775              GOTO_ERROR();
   8776            }
   8777          }
   8778        }
   8779        END_OP(PushLexicalEnv);
   8780      }
   8781      CASE(PopLexicalEnv) {
   8782        if (frame->isDebuggee()) {
   8783          TRACE_PRINTF("doing DebugLeaveThenPopLexicalEnv\n");
   8784          PUSH_EXIT_FRAME();
   8785          if (!DebugLeaveThenPopLexicalEnv(cx, frame, pc)) {
   8786            GOTO_ERROR();
   8787          }
   8788        } else {
   8789          frame->popOffEnvironmentChain<LexicalEnvironmentObject>();
   8790        }
   8791        END_OP(PopLexicalEnv);
   8792      }
   8793      CASE(DebugLeaveLexicalEnv) {
   8794        if (frame->isDebuggee()) {
   8795          TRACE_PRINTF("doing DebugLeaveLexicalEnv\n");
   8796          PUSH_EXIT_FRAME();
   8797          if (!DebugLeaveLexicalEnv(cx, frame, pc)) {
   8798            GOTO_ERROR();
   8799          }
   8800        }
   8801        END_OP(DebugLeaveLexicalEnv);
   8802      }
   8803 
   8804      CASE(RecreateLexicalEnv) {
   8805        {
   8806          PUSH_EXIT_FRAME();
   8807          if (frame->isDebuggee()) {
   8808            TRACE_PRINTF("doing DebuggeeRecreateLexicalEnv\n");
   8809            if (!DebuggeeRecreateLexicalEnv(cx, frame, pc)) {
   8810              GOTO_ERROR();
   8811            }
   8812          } else {
   8813            if (!frame->recreateLexicalEnvironment<false>(cx)) {
   8814              GOTO_ERROR();
   8815            }
   8816          }
   8817        }
   8818        END_OP(RecreateLexicalEnv);
   8819      }
   8820 
   8821      CASE(FreshenLexicalEnv) {
   8822        {
   8823          PUSH_EXIT_FRAME();
   8824          if (frame->isDebuggee()) {
   8825            TRACE_PRINTF("doing DebuggeeFreshenLexicalEnv\n");
   8826            if (!DebuggeeFreshenLexicalEnv(cx, frame, pc)) {
   8827              GOTO_ERROR();
   8828            }
   8829          } else {
   8830            if (!frame->freshenLexicalEnvironment<false>(cx)) {
   8831              GOTO_ERROR();
   8832            }
   8833          }
   8834        }
   8835        END_OP(FreshenLexicalEnv);
   8836      }
   8837      CASE(PushClassBodyEnv) {
   8838        {
   8839          ReservedRooted<Scope*> scope0(&state.scope0,
   8840                                        frame->script()->getScope(pc));
   8841          PUSH_EXIT_FRAME();
   8842          if (!frame->pushClassBodyEnvironment(cx,
   8843                                               scope0.as<ClassBodyScope>())) {
   8844            GOTO_ERROR();
   8845          }
   8846        }
   8847        END_OP(PushClassBodyEnv);
   8848      }
   8849      CASE(PushVarEnv) {
   8850        {
   8851          ReservedRooted<Scope*> scope0(&state.scope0,
   8852                                        frame->script()->getScope(pc));
   8853          PUSH_EXIT_FRAME();
   8854          if (!frame->pushVarEnvironment(cx, scope0)) {
   8855            GOTO_ERROR();
   8856          }
   8857        }
   8858        END_OP(PushVarEnv);
   8859      }
   8860      CASE(EnterWith) {
   8861        {
   8862          ReservedRooted<Scope*> scope0(&state.scope0,
   8863                                        frame->script()->getScope(pc));
   8864          ReservedRooted<Value> value0(&state.value0, VIRTPOP().asValue());
   8865          PUSH_EXIT_FRAME();
   8866          if (!EnterWithOperation(cx, frame, value0, scope0.as<WithScope>())) {
   8867            GOTO_ERROR();
   8868          }
   8869        }
   8870        END_OP(EnterWith);
   8871      }
   8872      CASE(LeaveWith) {
   8873        frame->popOffEnvironmentChain<WithEnvironmentObject>();
   8874        END_OP(LeaveWith);
   8875      }
   8876 #ifdef ENABLE_EXPLICIT_RESOURCE_MANAGEMENT
   8877      CASE(AddDisposable) {
   8878        {
   8879          ReservedRooted<JSObject*> env(&state.obj0, frame->environmentChain());
   8880 
   8881          ReservedRooted<JS::Value> needsClosure(&state.value0,
   8882                                                 VIRTPOP().asValue());
   8883          ReservedRooted<JS::Value> method(&state.value1, VIRTPOP().asValue());
   8884          ReservedRooted<JS::Value> val(&state.value2, VIRTPOP().asValue());
   8885          UsingHint hint = UsingHint(GET_UINT8(pc));
   8886          PUSH_EXIT_FRAME();
   8887          if (!AddDisposableResourceToCapability(
   8888                  cx, env, val, method, needsClosure.toBoolean(), hint)) {
   8889            GOTO_ERROR();
   8890          }
   8891        }
   8892        END_OP(AddDisposable);
   8893      }
   8894 
   8895      CASE(TakeDisposeCapability) {
   8896        {
   8897          ReservedRooted<JSObject*> env(&state.obj0, frame->environmentChain());
   8898          JS::Value maybeDisposables =
   8899              env->as<DisposableEnvironmentObject>().getDisposables();
   8900 
   8901          MOZ_ASSERT(maybeDisposables.isObject() ||
   8902                     maybeDisposables.isUndefined());
   8903 
   8904          if (maybeDisposables.isUndefined()) {
   8905            VIRTPUSH(StackVal(UndefinedValue()));
   8906          } else {
   8907            VIRTPUSH(StackVal(maybeDisposables));
   8908            env->as<DisposableEnvironmentObject>().clearDisposables();
   8909          }
   8910        }
   8911        END_OP(TakeDisposeCapability);
   8912      }
   8913 
   8914      CASE(CreateSuppressedError) {
   8915        ErrorObject* errorObj;
   8916        {
   8917          ReservedRooted<JS::Value> error(&state.value0, VIRTPOP().asValue());
   8918          ReservedRooted<JS::Value> suppressed(&state.value1,
   8919                                               VIRTPOP().asValue());
   8920          PUSH_EXIT_FRAME();
   8921          errorObj = CreateSuppressedError(cx, error, suppressed);
   8922          if (!errorObj) {
   8923            GOTO_ERROR();
   8924          }
   8925        }
   8926        VIRTPUSH(StackVal(ObjectValue(*errorObj)));
   8927        END_OP(CreateSuppressedError);
   8928      }
   8929 #endif
   8930      CASE(BindVar) {
   8931        JSObject* varObj;
   8932        {
   8933          ReservedRooted<JSObject*> obj0(&state.obj0,
   8934                                         frame->environmentChain());
   8935          PUSH_EXIT_FRAME();
   8936          varObj = BindVarOperation(cx, obj0);
   8937        }
   8938        VIRTPUSH(StackVal(ObjectValue(*varObj)));
   8939        END_OP(BindVar);
   8940      }
   8941 
   8942      CASE(GlobalOrEvalDeclInstantiation) {
   8943        GCThingIndex lastFun = GET_GCTHING_INDEX(pc);
   8944        {
   8945          ReservedRooted<JSObject*> obj0(&state.obj0,
   8946                                         frame->environmentChain());
   8947          ReservedRooted<JSScript*> script0(&state.script0, frame->script());
   8948          PUSH_EXIT_FRAME();
   8949          if (!GlobalOrEvalDeclInstantiation(cx, obj0, script0, lastFun)) {
   8950            GOTO_ERROR();
   8951          }
   8952        }
   8953        END_OP(GlobalOrEvalDeclInstantiation);
   8954      }
   8955 
   8956      CASE(DelName) {
   8957        {
   8958          ReservedRooted<PropertyName*> name0(&state.name0,
   8959                                              frame->script()->getName(pc));
   8960          ReservedRooted<JSObject*> obj0(&state.obj0,
   8961                                         frame->environmentChain());
   8962          PUSH_EXIT_FRAME();
   8963          if (!DeleteNameOperation(cx, name0, obj0, &state.res)) {
   8964            GOTO_ERROR();
   8965          }
   8966        }
   8967        VIRTPUSH(StackVal(state.res));
   8968        state.res.setUndefined();
   8969        END_OP(DelName);
   8970      }
   8971 
   8972      CASE(Arguments) {
   8973        {
   8974          PUSH_EXIT_FRAME();
   8975          if (!NewArgumentsObject(cx, frame, &state.res)) {
   8976            GOTO_ERROR();
   8977          }
   8978        }
   8979        VIRTPUSH(StackVal(state.res));
   8980        state.res.setUndefined();
   8981        END_OP(Arguments);
   8982      }
   8983 
   8984      CASE(Rest) {
   8985        IC_ZERO_ARG(0);
   8986        IC_ZERO_ARG(1);
   8987        IC_ZERO_ARG(2);
   8988        INVOKE_IC_AND_PUSH(Rest, false);
   8989        END_OP(Rest);
   8990      }
   8991 
   8992      CASE(FunctionThis) {
   8993        {
   8994          PUSH_EXIT_FRAME();
   8995          if (!js::GetFunctionThis(cx, frame, &state.res)) {
   8996            GOTO_ERROR();
   8997          }
   8998        }
   8999        VIRTPUSH(StackVal(state.res));
   9000        state.res.setUndefined();
   9001        END_OP(FunctionThis);
   9002      }
   9003 
   9004      CASE(Pop) {
   9005        VIRTPOP();
   9006        END_OP(Pop);
   9007      }
   9008      CASE(PopN) {
   9009        SYNCSP();
   9010        uint32_t n = GET_UINT16(pc);
   9011        VIRTPOPN(n);
   9012        END_OP(PopN);
   9013      }
   9014      CASE(Dup) {
   9015        StackVal value = VIRTSP(0);
   9016        VIRTPUSH(value);
   9017        END_OP(Dup);
   9018      }
   9019      CASE(Dup2) {
   9020        StackVal value1 = VIRTSP(0);
   9021        StackVal value2 = VIRTSP(1);
   9022        VIRTPUSH(value2);
   9023        VIRTPUSH(value1);
   9024        END_OP(Dup2);
   9025      }
   9026      CASE(DupAt) {
   9027        unsigned i = GET_UINT24(pc);
   9028        StackVal value = VIRTSP(i);
   9029        VIRTPUSH(value);
   9030        END_OP(DupAt);
   9031      }
   9032      CASE(Swap) {
   9033        StackVal v0 = VIRTSP(0);
   9034        StackVal v1 = VIRTSP(1);
   9035        VIRTSPWRITE(0, v1);
   9036        VIRTSPWRITE(1, v0);
   9037        END_OP(Swap);
   9038      }
   9039      CASE(Pick) {
   9040        unsigned i = GET_UINT8(pc);
   9041        SYNCSP();
   9042        StackVal tmp = sp[i];
   9043        memmove(&sp[1], &sp[0], sizeof(StackVal) * i);
   9044        VIRTSPWRITE(0, tmp);
   9045        END_OP(Pick);
   9046      }
   9047      CASE(Unpick) {
   9048        unsigned i = GET_UINT8(pc);
   9049        StackVal tmp = VIRTSP(0);
   9050        SYNCSP();
   9051        memmove(&sp[0], &sp[1], sizeof(StackVal) * i);
   9052        sp[i] = tmp;
   9053        END_OP(Unpick);
   9054      }
   9055      CASE(DebugCheckSelfHosted) {
   9056        HandleValue val = SPHANDLE(0);
   9057        {
   9058          PUSH_EXIT_FRAME();
   9059          if (!Debug_CheckSelfHosted(cx, val)) {
   9060            GOTO_ERROR();
   9061          }
   9062        }
   9063        END_OP(DebugCheckSelfHosted);
   9064      }
   9065      CASE(Lineno) { END_OP(Lineno); }
   9066      CASE(NopDestructuring) { END_OP(NopDestructuring); }
   9067      CASE(ForceInterpreter) { END_OP(ForceInterpreter); }
   9068      CASE(Debugger) {
   9069        {
   9070          PUSH_EXIT_FRAME();
   9071          if (!OnDebuggerStatement(cx, frame)) {
   9072            GOTO_ERROR();
   9073          }
   9074        }
   9075        END_OP(Debugger);
   9076      }
   9077 
   9078    label_default:
   9079 #ifndef ENABLE_COMPUTED_GOTO_DISPATCH
   9080    default:
   9081 #endif
   9082      MOZ_CRASH("Bad opcode");
   9083    }
   9084  }
   9085 
   9086 restart:
   9087  // This is a `goto` target so that we exit any on-stack exit frames
   9088  // before restarting, to match previous behavior.
   9089  return PortableBaselineInterpret<true, HybridICs>(
   9090      ctx.frameMgr.cxForLocalUseOnly(), ctx.state, ctx.stack, sp, envChain, ret,
   9091      pc, isd, entryPC, frame, entryFrame, restartCode);
   9092 
   9093 error:
   9094  TRACE_PRINTF("HandleException: frame %p\n", frame);
   9095  {
   9096    ResumeFromException rfe;
   9097    {
   9098      PUSH_EXIT_FRAME();
   9099      HandleException(&rfe);
   9100    }
   9101 
   9102    switch (rfe.kind) {
   9103      case ExceptionResumeKind::EntryFrame:
   9104        TRACE_PRINTF(" -> Return from entry frame\n");
   9105        frame->setReturnValue(MagicValue(JS_ION_ERROR));
   9106        ctx.stack.fp = reinterpret_cast<StackVal*>(rfe.framePointer);
   9107        ctx.stack.unwindingSP = reinterpret_cast<StackVal*>(rfe.stackPointer);
   9108        ctx.stack.unwindingFP = reinterpret_cast<StackVal*>(rfe.framePointer);
   9109        goto unwind_error;
   9110      case ExceptionResumeKind::Catch:
   9111        RESET_PC(frame->interpreterPC(), frame->script());
   9112        ctx.stack.fp = reinterpret_cast<StackVal*>(rfe.framePointer);
   9113        ctx.stack.unwindingSP = reinterpret_cast<StackVal*>(rfe.stackPointer);
   9114        ctx.stack.unwindingFP = reinterpret_cast<StackVal*>(rfe.framePointer);
   9115        TRACE_PRINTF(" -> catch to pc %p\n", pc);
   9116        goto unwind;
   9117      case ExceptionResumeKind::Finally:
   9118        RESET_PC(frame->interpreterPC(), frame->script());
   9119        ctx.stack.fp = reinterpret_cast<StackVal*>(rfe.framePointer);
   9120        sp = reinterpret_cast<StackVal*>(rfe.stackPointer);
   9121        TRACE_PRINTF(" -> finally to pc %p\n", pc);
   9122        VIRTPUSH(StackVal(rfe.exception));
   9123        VIRTPUSH(StackVal(rfe.exceptionStack));
   9124        VIRTPUSH(StackVal(BooleanValue(true)));
   9125        ctx.stack.unwindingSP = sp;
   9126        ctx.stack.unwindingFP = ctx.stack.fp;
   9127        goto unwind;
   9128      case ExceptionResumeKind::ForcedReturnBaseline:
   9129        RESET_PC(frame->interpreterPC(), frame->script());
   9130        ctx.stack.fp = reinterpret_cast<StackVal*>(rfe.framePointer);
   9131        ctx.stack.unwindingSP = reinterpret_cast<StackVal*>(rfe.stackPointer);
   9132        ctx.stack.unwindingFP = reinterpret_cast<StackVal*>(rfe.framePointer);
   9133        TRACE_PRINTF(" -> forced return\n");
   9134        goto unwind_ret;
   9135      case ExceptionResumeKind::ForcedReturnIon:
   9136        MOZ_CRASH(
   9137            "Unexpected ForcedReturnIon exception-resume kind in Portable "
   9138            "Baseline");
   9139      case ExceptionResumeKind::Bailout:
   9140        MOZ_CRASH(
   9141            "Unexpected Bailout exception-resume kind in Portable Baseline");
   9142      case ExceptionResumeKind::WasmInterpEntry:
   9143        MOZ_CRASH(
   9144            "Unexpected WasmInterpEntry exception-resume kind in Portable "
   9145            "Baseline");
   9146      case ExceptionResumeKind::WasmCatch:
   9147        MOZ_CRASH(
   9148            "Unexpected WasmCatch exception-resume kind in Portable "
   9149            "Baseline");
   9150    }
   9151  }
   9152 
   9153  DISPATCH();
   9154 
   9155 ic_fail:
   9156  RESTART(ic_result);
   9157  switch (ic_result) {
   9158    case PBIResult::Ok:
   9159      MOZ_CRASH("Unreachable: ic_result must be an error if we reach ic_fail");
   9160    case PBIResult::Error:
   9161      goto error;
   9162    case PBIResult::Unwind:
   9163      goto unwind;
   9164    case PBIResult::UnwindError:
   9165      goto unwind_error;
   9166    case PBIResult::UnwindRet:
   9167      goto unwind_ret;
   9168  }
   9169 
   9170 unwind:
   9171  TRACE_PRINTF("unwind: fp = %p entryFrame = %p\n", ctx.stack.fp, entryFrame);
   9172  if (reinterpret_cast<uintptr_t>(ctx.stack.unwindingFP) >
   9173      reinterpret_cast<uintptr_t>(entryFrame) + BaselineFrame::Size()) {
   9174    TRACE_PRINTF(" -> returning\n");
   9175    return PBIResult::Unwind;
   9176  }
   9177  sp = ctx.stack.unwindingSP;
   9178  ctx.stack.fp = ctx.stack.unwindingFP;
   9179  frame = reinterpret_cast<BaselineFrame*>(
   9180      reinterpret_cast<uintptr_t>(ctx.stack.fp) - BaselineFrame::Size());
   9181  TRACE_PRINTF(" -> setting sp to %p, frame to %p\n", sp, frame);
   9182  ctx.frameMgr.switchToFrame(frame);
   9183  ctx.frame = frame;
   9184  RESET_PC(frame->interpreterPC(), frame->script());
   9185  DISPATCH();
   9186 unwind_error:
   9187  TRACE_PRINTF("unwind_error: fp = %p entryFrame = %p\n", ctx.stack.fp,
   9188               entryFrame);
   9189  if (reinterpret_cast<uintptr_t>(ctx.stack.unwindingFP) >
   9190      reinterpret_cast<uintptr_t>(entryFrame) + BaselineFrame::Size()) {
   9191    return PBIResult::UnwindError;
   9192  }
   9193  if (reinterpret_cast<uintptr_t>(ctx.stack.unwindingFP) ==
   9194      reinterpret_cast<uintptr_t>(entryFrame) + BaselineFrame::Size()) {
   9195    return PBIResult::Error;
   9196  }
   9197  sp = ctx.stack.unwindingSP;
   9198  ctx.stack.fp = ctx.stack.unwindingFP;
   9199  frame = reinterpret_cast<BaselineFrame*>(
   9200      reinterpret_cast<uintptr_t>(ctx.stack.fp) - BaselineFrame::Size());
   9201  TRACE_PRINTF(" -> setting sp to %p, frame to %p\n", sp, frame);
   9202  ctx.frameMgr.switchToFrame(frame);
   9203  ctx.frame = frame;
   9204  RESET_PC(frame->interpreterPC(), frame->script());
   9205  goto error;
   9206 unwind_ret:
   9207  TRACE_PRINTF("unwind_ret: fp = %p entryFrame = %p\n", ctx.stack.fp,
   9208               entryFrame);
   9209  if (reinterpret_cast<uintptr_t>(ctx.stack.unwindingFP) >
   9210      reinterpret_cast<uintptr_t>(entryFrame) + BaselineFrame::Size()) {
   9211    return PBIResult::UnwindRet;
   9212  }
   9213  if (reinterpret_cast<uintptr_t>(ctx.stack.unwindingFP) ==
   9214      reinterpret_cast<uintptr_t>(entryFrame) + BaselineFrame::Size()) {
   9215    *ret = frame->returnValue();
   9216    return PBIResult::Ok;
   9217  }
   9218  sp = ctx.stack.unwindingSP;
   9219  ctx.stack.fp = ctx.stack.unwindingFP;
   9220  frame = reinterpret_cast<BaselineFrame*>(
   9221      reinterpret_cast<uintptr_t>(ctx.stack.fp) - BaselineFrame::Size());
   9222  TRACE_PRINTF(" -> setting sp to %p, frame to %p\n", sp, frame);
   9223  ctx.frameMgr.switchToFrame(frame);
   9224  ctx.frame = frame;
   9225  RESET_PC(frame->interpreterPC(), frame->script());
   9226  from_unwind = true;
   9227  goto do_return;
   9228 
   9229 #ifndef __wasi__
   9230 debug:;
   9231  {
   9232    TRACE_PRINTF("hit debug point\n");
   9233    PUSH_EXIT_FRAME();
   9234    if (!HandleDebugTrap(cx, frame, pc)) {
   9235      TRACE_PRINTF("HandleDebugTrap returned error\n");
   9236      goto error;
   9237    }
   9238    RESET_PC(frame->interpreterPC(), frame->script());
   9239    TRACE_PRINTF("HandleDebugTrap done\n");
   9240  }
   9241  goto dispatch;
   9242 #endif
   9243 }
   9244 
   9245 /*
   9246 * -----------------------------------------------
   9247 * Entry point
   9248 * -----------------------------------------------
   9249 */
   9250 
   9251 bool PortableBaselineTrampoline(JSContext* cx, size_t argc, Value* argv,
   9252                                size_t numFormals, CalleeToken calleeToken,
   9253                                JSObject* envChain, Value* result) {
   9254  State state(cx);
   9255  Stack stack(cx->portableBaselineStack());
   9256  StackVal* sp = stack.top;
   9257 
   9258  TRACE_PRINTF("Trampoline: calleeToken %p env %p\n", calleeToken, envChain);
   9259 
   9260  // Expected stack frame:
   9261  // - argN
   9262  // - ...
   9263  // - arg1
   9264  // - this
   9265  // - calleeToken
   9266  // - descriptor
   9267  // - "return address" (nullptr for top frame)
   9268 
   9269  // `argc` is the number of args *excluding* `this` (`N` above).
   9270  // `numFormals` is the minimum `N`; if less, we need to push
   9271  // `UndefinedValue`s above. The argc in the frame descriptor does
   9272  // not include `this` or any undefs.
   9273  //
   9274  // If constructing, there is an additional `newTarget` at the end.
   9275  //
   9276  // Note that `callee`, which is in the stack signature for a `Call`
   9277  // JSOp, does *not* appear in this count: it is separately passed in
   9278  // the `calleeToken`.
   9279 
   9280  if (CalleeTokenIsFunction(calleeToken)) {
   9281    bool constructing = CalleeTokenIsConstructing(calleeToken);
   9282    size_t numCalleeActuals = std::max(argc, numFormals);
   9283    size_t numUndefs = numCalleeActuals - argc;
   9284 
   9285    // N.B.: we already checked the stack in
   9286    // PortableBaselineInterpreterStackCheck; we don't do it here
   9287    // because we can't push an exit frame if we don't have an entry
   9288    // frame, and we need a full activation to produce the backtrace
   9289    // from ReportOverRecursed.
   9290 
   9291    if (constructing) {
   9292      PUSH(StackVal(argv[argc]));
   9293    }
   9294    for (size_t i = 0; i < numUndefs; i++) {
   9295      PUSH(StackVal(UndefinedValue()));
   9296    }
   9297    for (size_t i = 0; i < argc + 1; i++) {
   9298      PUSH(StackVal(argv[argc - 1 - i]));
   9299    }
   9300  }
   9301  PUSHNATIVE(StackValNative(calleeToken));
   9302  PUSHNATIVE(StackValNative(
   9303      MakeFrameDescriptorForJitCall(FrameType::CppToJSJit, argc)));
   9304 
   9305  JSScript* script = ScriptFromCalleeToken(calleeToken);
   9306  jsbytecode* pc = script->code();
   9307  ImmutableScriptData* isd = script->immutableScriptData();
   9308  PBIResult ret;
   9309  ret = PortableBaselineInterpret<false, kHybridICsInterp>(
   9310      cx, state, stack, sp, envChain, result, pc, isd, nullptr, nullptr,
   9311      nullptr, PBIResult::Ok);
   9312  switch (ret) {
   9313    case PBIResult::Ok:
   9314    case PBIResult::UnwindRet:
   9315      TRACE_PRINTF("PBI returned Ok/UnwindRet with result %" PRIx64 "\n",
   9316                   result->asRawBits());
   9317      break;
   9318    case PBIResult::Error:
   9319    case PBIResult::UnwindError:
   9320      TRACE_PRINTF("PBI returned Error/UnwindError\n");
   9321      return false;
   9322    case PBIResult::Unwind:
   9323      MOZ_CRASH("Should not unwind out of top / entry frame");
   9324  }
   9325 
   9326  return true;
   9327 }
   9328 
   9329 MethodStatus CanEnterPortableBaselineInterpreter(JSContext* cx,
   9330                                                 RunState& state) {
   9331  if (!JitOptions.portableBaselineInterpreter) {
   9332    return MethodStatus::Method_CantCompile;
   9333  }
   9334  if (state.script()->hasJitScript()) {
   9335    return MethodStatus::Method_Compiled;
   9336  }
   9337  if (state.script()->hasForceInterpreterOp()) {
   9338    return MethodStatus::Method_CantCompile;
   9339  }
   9340  if (state.script()->isAsync() || state.script()->isGenerator()) {
   9341    return MethodStatus::Method_CantCompile;
   9342  }
   9343  if (cx->runtime()->geckoProfiler().enabled()) {
   9344    return MethodStatus::Method_CantCompile;
   9345  }
   9346 
   9347  if (state.isInvoke()) {
   9348    InvokeState& invoke = *state.asInvoke();
   9349    if (TooManyActualArguments(invoke.args().length())) {
   9350      return MethodStatus::Method_CantCompile;
   9351    }
   9352  } else {
   9353    if (state.asExecute()->isDebuggerEval()) {
   9354      return MethodStatus::Method_CantCompile;
   9355    }
   9356  }
   9357  if (state.script()->getWarmUpCount() <=
   9358      JitOptions.portableBaselineInterpreterWarmUpThreshold) {
   9359    return MethodStatus::Method_Skipped;
   9360  }
   9361  if (!cx->zone()->ensureJitZoneExists(cx)) {
   9362    return MethodStatus::Method_Error;
   9363  }
   9364 
   9365  AutoKeepJitScripts keepJitScript(cx);
   9366  if (!state.script()->ensureHasJitScript(cx, keepJitScript)) {
   9367    return MethodStatus::Method_Error;
   9368  }
   9369  state.script()->updateJitCodeRaw(cx->runtime());
   9370  return MethodStatus::Method_Compiled;
   9371 }
   9372 
   9373 bool PortablebaselineInterpreterStackCheck(JSContext* cx, RunState& state,
   9374                                           size_t numActualArgs) {
   9375  auto& pbs = cx->portableBaselineStack();
   9376  StackVal* base = reinterpret_cast<StackVal*>(pbs.base);
   9377  StackVal* top = reinterpret_cast<StackVal*>(pbs.top);
   9378  ssize_t margin = kStackMargin / sizeof(StackVal);
   9379  ssize_t needed = numActualArgs + state.script()->nslots() + margin;
   9380  return (top - base) >= needed;
   9381 }
   9382 
   9383 }  // namespace pbl
   9384 }  // namespace js