tor-browser

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

Lowering.cpp (295216B)


      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 #include "jit/Lowering.h"
      8 
      9 #include "mozilla/DebugOnly.h"
     10 #include "mozilla/EndianUtils.h"
     11 #include "mozilla/FloatingPoint.h"
     12 #include "mozilla/MathAlgorithms.h"
     13 
     14 #include <type_traits>
     15 
     16 #include "jit/ABIArgGenerator.h"
     17 #include "jit/IonGenericCallStub.h"
     18 #include "jit/IonOptimizationLevels.h"
     19 #include "jit/JitSpewer.h"
     20 #include "jit/LIR.h"
     21 #include "jit/MacroAssembler.h"
     22 #include "jit/MIR-wasm.h"
     23 #include "jit/MIR.h"
     24 #include "jit/MIRGraph.h"
     25 #include "jit/SharedICRegisters.h"
     26 #include "js/experimental/JitInfo.h"  // JSJitInfo
     27 #include "util/Memory.h"
     28 #include "wasm/WasmCodegenTypes.h"
     29 #include "wasm/WasmFeatures.h"  // for wasm::ReportSimdAnalysis
     30 #include "wasm/WasmInstanceData.h"
     31 
     32 #include "jit/shared/Lowering-shared-inl.h"
     33 #include "vm/BytecodeUtil-inl.h"
     34 
     35 using namespace js;
     36 using namespace jit;
     37 
     38 using JS::GenericNaN;
     39 using mozilla::DebugOnly;
     40 
     41 LBoxAllocation LIRGenerator::useBoxFixedAtStart(MDefinition* mir,
     42                                                ValueOperand op) {
     43 #if defined(JS_NUNBOX32)
     44  return useBoxFixed(mir, op.typeReg(), op.payloadReg(), true);
     45 #elif defined(JS_PUNBOX64)
     46  return useBoxFixed(mir, op.valueReg(), op.scratchReg(), true);
     47 #endif
     48 }
     49 
     50 LBoxAllocation LIRGenerator::useBoxAtStart(MDefinition* mir,
     51                                           LUse::Policy policy) {
     52  return useBox(mir, policy, /* useAtStart = */ true);
     53 }
     54 
     55 void LIRGenerator::visitParameter(MParameter* param) {
     56  ptrdiff_t offset;
     57  if (param->index() == MParameter::THIS_SLOT) {
     58    offset = THIS_FRAME_ARGSLOT;
     59  } else {
     60    offset = 1 + param->index();
     61  }
     62 
     63  LParameter* ins = new (alloc()) LParameter;
     64  defineBox(ins, param, LDefinition::FIXED);
     65 
     66  offset *= sizeof(Value);
     67 #if defined(JS_NUNBOX32)
     68 #  if MOZ_BIG_ENDIAN()
     69  ins->getDef(0)->setOutput(LArgument(offset));
     70  ins->getDef(1)->setOutput(LArgument(offset + 4));
     71 #  else
     72  ins->getDef(0)->setOutput(LArgument(offset + 4));
     73  ins->getDef(1)->setOutput(LArgument(offset));
     74 #  endif
     75 #elif defined(JS_PUNBOX64)
     76  ins->getDef(0)->setOutput(LArgument(offset));
     77 #endif
     78 }
     79 
     80 void LIRGenerator::visitCallee(MCallee* ins) {
     81  define(new (alloc()) LCallee(), ins);
     82 }
     83 
     84 void LIRGenerator::visitIsConstructing(MIsConstructing* ins) {
     85  define(new (alloc()) LIsConstructing(), ins);
     86 }
     87 
     88 void LIRGenerator::visitGoto(MGoto* ins) {
     89  add(new (alloc()) LGoto(ins->target()));
     90 }
     91 
     92 void LIRGenerator::visitTableSwitch(MTableSwitch* tableswitch) {
     93  MDefinition* opd = tableswitch->getOperand(0);
     94 
     95  // There should be at least 1 successor. The default case!
     96  MOZ_ASSERT(tableswitch->numSuccessors() > 0);
     97 
     98  // If there are no cases, the default case is always taken.
     99  if (tableswitch->numSuccessors() == 1) {
    100    add(new (alloc()) LGoto(tableswitch->getDefault()));
    101    return;
    102  }
    103 
    104  // If we don't know the type.
    105  if (opd->type() == MIRType::Value) {
    106    add(newLTableSwitchV(useBox(opd)), tableswitch);
    107    return;
    108  }
    109 
    110  // Case indices are numeric, so other types will always go to the default
    111  // case.
    112  if (opd->type() != MIRType::Int32 && opd->type() != MIRType::Double) {
    113    add(new (alloc()) LGoto(tableswitch->getDefault()));
    114    return;
    115  }
    116 
    117  // Return an LTableSwitch, capable of handling either an integer or
    118  // floating-point index.
    119  LAllocation index;
    120  LDefinition tempInt;
    121  if (opd->type() == MIRType::Int32) {
    122    index = useRegisterAtStart(opd);
    123    tempInt = tempCopy(opd, 0);
    124  } else {
    125    index = useRegister(opd);
    126    tempInt = temp();
    127  }
    128  add(newLTableSwitch(index, tempInt), tableswitch);
    129 }
    130 
    131 void LIRGenerator::visitCheckOverRecursed(MCheckOverRecursed* ins) {
    132  LCheckOverRecursed* lir = new (alloc()) LCheckOverRecursed();
    133  add(lir, ins);
    134  assignSafepoint(lir, ins);
    135 }
    136 
    137 void LIRGenerator::visitNewArray(MNewArray* ins) {
    138  LNewArray* lir = new (alloc()) LNewArray(temp());
    139  define(lir, ins);
    140  assignSafepoint(lir, ins);
    141 }
    142 
    143 void LIRGenerator::visitNewArrayDynamicLength(MNewArrayDynamicLength* ins) {
    144  MDefinition* length = ins->length();
    145  MOZ_ASSERT(length->type() == MIRType::Int32);
    146 
    147  LNewArrayDynamicLength* lir =
    148      new (alloc()) LNewArrayDynamicLength(useRegister(length), temp());
    149  define(lir, ins);
    150  assignSafepoint(lir, ins);
    151 }
    152 
    153 void LIRGenerator::visitNewIterator(MNewIterator* ins) {
    154  LNewIterator* lir = new (alloc()) LNewIterator(temp());
    155  define(lir, ins);
    156  assignSafepoint(lir, ins);
    157 }
    158 
    159 void LIRGenerator::visitNewTypedArray(MNewTypedArray* ins) {
    160  size_t nbytes = ins->templateObject()->byteLength();
    161  if (nbytes <= FixedLengthTypedArrayObject::INLINE_BUFFER_LIMIT) {
    162    auto* lir = new (alloc()) LNewTypedArrayInline(temp());
    163    define(lir, ins);
    164    assignSafepoint(lir, ins);
    165  } else {
    166    auto* lir = new (alloc())
    167        LNewTypedArray(tempFixed(CallTempReg0), tempFixed(CallTempReg1),
    168                       tempFixed(CallTempReg2), tempFixed(CallTempReg3));
    169    defineReturn(lir, ins);
    170    assignSafepoint(lir, ins);
    171  }
    172 }
    173 
    174 void LIRGenerator::visitNewTypedArrayDynamicLength(
    175    MNewTypedArrayDynamicLength* ins) {
    176  MDefinition* length = ins->length();
    177  MOZ_ASSERT(length->type() == MIRType::Int32);
    178 
    179  auto* lir = new (alloc()) LNewTypedArrayDynamicLength(
    180      useFixedAtStart(length, CallTempReg0), tempFixed(CallTempReg1),
    181      tempFixed(CallTempReg2), tempFixed(CallTempReg3));
    182  defineReturn(lir, ins);
    183  assignSafepoint(lir, ins);
    184 }
    185 
    186 void LIRGenerator::visitNewTypedArrayFromArray(MNewTypedArrayFromArray* ins) {
    187  MDefinition* array = ins->array();
    188  MOZ_ASSERT(array->type() == MIRType::Object);
    189 
    190  auto* lir = new (alloc()) LNewTypedArrayFromArray(useRegisterAtStart(array));
    191  defineReturn(lir, ins);
    192  assignSafepoint(lir, ins);
    193 }
    194 
    195 void LIRGenerator::visitNewTypedArrayFromArrayBuffer(
    196    MNewTypedArrayFromArrayBuffer* ins) {
    197  MDefinition* arrayBuffer = ins->arrayBuffer();
    198  MDefinition* byteOffset = ins->byteOffset();
    199  MDefinition* length = ins->length();
    200  MOZ_ASSERT(arrayBuffer->type() == MIRType::Object);
    201  MOZ_ASSERT(byteOffset->type() == MIRType::Value);
    202  MOZ_ASSERT(length->type() == MIRType::Value);
    203 
    204  auto* lir = new (alloc()) LNewTypedArrayFromArrayBuffer(
    205      useRegisterAtStart(arrayBuffer), useBoxAtStart(byteOffset),
    206      useBoxAtStart(length));
    207  defineReturn(lir, ins);
    208  assignSafepoint(lir, ins);
    209 }
    210 
    211 void LIRGenerator::visitNewObject(MNewObject* ins) {
    212  LNewObject* lir = new (alloc()) LNewObject(temp());
    213  define(lir, ins);
    214  assignSafepoint(lir, ins);
    215 }
    216 
    217 void LIRGenerator::visitBindFunction(MBindFunction* ins) {
    218  MDefinition* target = ins->target();
    219  MOZ_ASSERT(target->type() == MIRType::Object);
    220 
    221  if (!lowerCallArguments(ins)) {
    222    abort(AbortReason::Alloc, "OOM: LIRGenerator::visitBindFunction");
    223    return;
    224  }
    225 
    226  auto* lir = new (alloc())
    227      LBindFunction(useFixedAtStart(target, CallTempReg0),
    228                    tempFixed(CallTempReg1), tempFixed(CallTempReg2));
    229  defineReturn(lir, ins);
    230  assignSafepoint(lir, ins);
    231 }
    232 
    233 void LIRGenerator::visitNewBoundFunction(MNewBoundFunction* ins) {
    234  auto* lir = new (alloc()) LNewBoundFunction(temp());
    235  define(lir, ins);
    236  assignSafepoint(lir, ins);
    237 }
    238 
    239 void LIRGenerator::visitNewPlainObject(MNewPlainObject* ins) {
    240  LNewPlainObject* lir = new (alloc()) LNewPlainObject(temp(), temp(), temp());
    241  define(lir, ins);
    242  assignSafepoint(lir, ins);
    243 }
    244 
    245 void LIRGenerator::visitNewArrayObject(MNewArrayObject* ins) {
    246  LNewArrayObject* lir = new (alloc()) LNewArrayObject(temp(), temp());
    247  define(lir, ins);
    248  assignSafepoint(lir, ins);
    249 }
    250 
    251 void LIRGenerator::visitNewNamedLambdaObject(MNewNamedLambdaObject* ins) {
    252  LNewNamedLambdaObject* lir = new (alloc()) LNewNamedLambdaObject(temp());
    253  define(lir, ins);
    254  assignSafepoint(lir, ins);
    255 }
    256 
    257 void LIRGenerator::visitNewCallObject(MNewCallObject* ins) {
    258  LNewCallObject* lir = new (alloc()) LNewCallObject(temp());
    259  define(lir, ins);
    260  assignSafepoint(lir, ins);
    261 }
    262 
    263 void LIRGenerator::visitNewMapObject(MNewMapObject* ins) {
    264  auto* lir = new (alloc()) LNewMapObject(temp());
    265  define(lir, ins);
    266  assignSafepoint(lir, ins);
    267 }
    268 
    269 void LIRGenerator::visitNewSetObject(MNewSetObject* ins) {
    270  auto* lir = new (alloc()) LNewSetObject(temp());
    271  define(lir, ins);
    272  assignSafepoint(lir, ins);
    273 }
    274 
    275 void LIRGenerator::visitNewMapObjectFromIterable(
    276    MNewMapObjectFromIterable* ins) {
    277  MOZ_ASSERT(ins->iterable()->type() == MIRType::Value);
    278  auto* lir = new (alloc()) LNewMapObjectFromIterable(
    279      useBoxFixedAtStart(ins->iterable(), CallTempReg0, CallTempReg1),
    280      tempFixed(CallTempReg2), tempFixed(CallTempReg3));
    281  defineReturn(lir, ins);
    282  assignSafepoint(lir, ins);
    283 }
    284 
    285 void LIRGenerator::visitNewSetObjectFromIterable(
    286    MNewSetObjectFromIterable* ins) {
    287  MOZ_ASSERT(ins->iterable()->type() == MIRType::Value);
    288  auto* lir = new (alloc()) LNewSetObjectFromIterable(
    289      useBoxFixedAtStart(ins->iterable(), CallTempReg0, CallTempReg1),
    290      tempFixed(CallTempReg2), tempFixed(CallTempReg3));
    291  defineReturn(lir, ins);
    292  assignSafepoint(lir, ins);
    293 }
    294 
    295 void LIRGenerator::visitNewStringObject(MNewStringObject* ins) {
    296  MOZ_ASSERT(ins->input()->type() == MIRType::String);
    297 
    298  LNewStringObject* lir =
    299      new (alloc()) LNewStringObject(useRegister(ins->input()), temp());
    300  define(lir, ins);
    301  assignSafepoint(lir, ins);
    302 }
    303 
    304 void LIRGenerator::visitInitElemGetterSetter(MInitElemGetterSetter* ins) {
    305  LInitElemGetterSetter* lir = new (alloc()) LInitElemGetterSetter(
    306      useRegisterAtStart(ins->object()), useBoxAtStart(ins->id()),
    307      useRegisterAtStart(ins->value()));
    308  add(lir, ins);
    309  assignSafepoint(lir, ins);
    310 }
    311 
    312 void LIRGenerator::visitMutateProto(MMutateProto* ins) {
    313  LMutateProto* lir = new (alloc()) LMutateProto(
    314      useRegisterAtStart(ins->object()), useBoxAtStart(ins->value()));
    315  add(lir, ins);
    316  assignSafepoint(lir, ins);
    317 }
    318 
    319 void LIRGenerator::visitInitPropGetterSetter(MInitPropGetterSetter* ins) {
    320  LInitPropGetterSetter* lir = new (alloc()) LInitPropGetterSetter(
    321      useRegisterAtStart(ins->object()), useRegisterAtStart(ins->value()));
    322  add(lir, ins);
    323  assignSafepoint(lir, ins);
    324 }
    325 
    326 void LIRGenerator::visitCreateThis(MCreateThis* ins) {
    327  LCreateThis* lir =
    328      new (alloc()) LCreateThis(useRegisterOrConstantAtStart(ins->callee()),
    329                                useRegisterOrConstantAtStart(ins->newTarget()));
    330  defineReturn(lir, ins);
    331  assignSafepoint(lir, ins);
    332 }
    333 
    334 void LIRGenerator::visitCreateArgumentsObject(MCreateArgumentsObject* ins) {
    335  LAllocation callObj = useRegisterAtStart(ins->getCallObject());
    336  LCreateArgumentsObject* lir = new (alloc())
    337      LCreateArgumentsObject(callObj, tempFixed(CallTempReg0),
    338                             tempFixed(CallTempReg1), tempFixed(CallTempReg2));
    339  defineReturn(lir, ins);
    340  assignSafepoint(lir, ins);
    341 }
    342 
    343 void LIRGenerator::visitCreateInlinedArgumentsObject(
    344    MCreateInlinedArgumentsObject* ins) {
    345  LAllocation callObj = useRegisterAtStart(ins->getCallObject());
    346  LAllocation callee = useRegisterAtStart(ins->getCallee());
    347  uint32_t numActuals = ins->numActuals();
    348  uint32_t numOperands = numActuals * BOX_PIECES +
    349                         LCreateInlinedArgumentsObject::NumNonArgumentOperands;
    350 
    351  auto* lir = allocateVariadic<LCreateInlinedArgumentsObject>(
    352      numOperands, tempFixed(CallTempReg0), tempFixed(CallTempReg1));
    353  if (!lir) {
    354    abort(AbortReason::Alloc,
    355          "OOM: LIRGenerator::visitCreateInlinedArgumentsObject");
    356    return;
    357  }
    358 
    359  lir->setOperand(LCreateInlinedArgumentsObject::CallObj, callObj);
    360  lir->setOperand(LCreateInlinedArgumentsObject::Callee, callee);
    361  for (uint32_t i = 0; i < numActuals; i++) {
    362    MDefinition* arg = ins->getArg(i);
    363    uint32_t index = LCreateInlinedArgumentsObject::ArgIndex(i);
    364    lir->setBoxOperand(index, useBoxOrTypedOrConstant(arg,
    365                                                      /*useConstant = */ true,
    366                                                      /*useAtStart = */ true));
    367  }
    368 
    369  defineReturn(lir, ins);
    370  assignSafepoint(lir, ins);
    371 }
    372 
    373 void LIRGenerator::visitGetInlinedArgument(MGetInlinedArgument* ins) {
    374  LAllocation index = useRegisterAtStart(ins->index());
    375  uint32_t numActuals = ins->numActuals();
    376  uint32_t numOperands =
    377      numActuals * BOX_PIECES + LGetInlinedArgument::NumNonArgumentOperands;
    378 
    379  auto* lir = allocateVariadic<LGetInlinedArgument>(numOperands);
    380  if (!lir) {
    381    abort(AbortReason::Alloc, "OOM: LIRGenerator::visitGetInlinedArgument");
    382    return;
    383  }
    384 
    385  lir->setOperand(LGetInlinedArgument::Index, index);
    386  for (uint32_t i = 0; i < numActuals; i++) {
    387    MDefinition* arg = ins->getArg(i);
    388    uint32_t index = LGetInlinedArgument::ArgIndex(i);
    389    lir->setBoxOperand(index, useBoxOrTypedOrConstant(arg,
    390                                                      /*useConstant = */ true,
    391                                                      /*useAtStart = */ true));
    392  }
    393  defineBox(lir, ins);
    394 }
    395 
    396 void LIRGenerator::visitGetInlinedArgumentHole(MGetInlinedArgumentHole* ins) {
    397  LAllocation index = useRegisterAtStart(ins->index());
    398  uint32_t numActuals = ins->numActuals();
    399  uint32_t numOperands =
    400      numActuals * BOX_PIECES + LGetInlinedArgumentHole::NumNonArgumentOperands;
    401 
    402  auto* lir = allocateVariadic<LGetInlinedArgumentHole>(numOperands);
    403  if (!lir) {
    404    abort(AbortReason::Alloc, "OOM: LIRGenerator::visitGetInlinedArgumentHole");
    405    return;
    406  }
    407 
    408  lir->setOperand(LGetInlinedArgumentHole::Index, index);
    409  for (uint32_t i = 0; i < numActuals; i++) {
    410    MDefinition* arg = ins->getArg(i);
    411    uint32_t index = LGetInlinedArgumentHole::ArgIndex(i);
    412    lir->setBoxOperand(index, useBoxOrTypedOrConstant(arg,
    413                                                      /*useConstant = */ true,
    414                                                      /*useAtStart = */ true));
    415  }
    416  assignSnapshot(lir, ins->bailoutKind());
    417  defineBox(lir, ins);
    418 }
    419 
    420 void LIRGenerator::visitGetArgumentsObjectArg(MGetArgumentsObjectArg* ins) {
    421  LAllocation argsObj = useRegister(ins->argsObject());
    422  LGetArgumentsObjectArg* lir =
    423      new (alloc()) LGetArgumentsObjectArg(argsObj, temp());
    424  defineBox(lir, ins);
    425 }
    426 
    427 void LIRGenerator::visitSetArgumentsObjectArg(MSetArgumentsObjectArg* ins) {
    428  LAllocation argsObj = useRegister(ins->argsObject());
    429  LSetArgumentsObjectArg* lir = new (alloc())
    430      LSetArgumentsObjectArg(argsObj, useBox(ins->value()), temp());
    431  add(lir, ins);
    432 }
    433 
    434 void LIRGenerator::visitLoadArgumentsObjectArg(MLoadArgumentsObjectArg* ins) {
    435  MDefinition* argsObj = ins->argsObject();
    436  MOZ_ASSERT(argsObj->type() == MIRType::Object);
    437 
    438  MDefinition* index = ins->index();
    439  MOZ_ASSERT(index->type() == MIRType::Int32);
    440 
    441  auto* lir = new (alloc())
    442      LLoadArgumentsObjectArg(useRegister(argsObj), useRegister(index), temp());
    443  assignSnapshot(lir, ins->bailoutKind());
    444  defineBox(lir, ins);
    445 }
    446 
    447 void LIRGenerator::visitLoadArgumentsObjectArgHole(
    448    MLoadArgumentsObjectArgHole* ins) {
    449  MDefinition* argsObj = ins->argsObject();
    450  MOZ_ASSERT(argsObj->type() == MIRType::Object);
    451 
    452  MDefinition* index = ins->index();
    453  MOZ_ASSERT(index->type() == MIRType::Int32);
    454 
    455  auto* lir = new (alloc()) LLoadArgumentsObjectArgHole(
    456      useRegister(argsObj), useRegister(index), temp());
    457  assignSnapshot(lir, ins->bailoutKind());
    458  defineBox(lir, ins);
    459 }
    460 
    461 void LIRGenerator::visitInArgumentsObjectArg(MInArgumentsObjectArg* ins) {
    462  MDefinition* argsObj = ins->argsObject();
    463  MOZ_ASSERT(argsObj->type() == MIRType::Object);
    464 
    465  MDefinition* index = ins->index();
    466  MOZ_ASSERT(index->type() == MIRType::Int32);
    467 
    468  auto* lir = new (alloc())
    469      LInArgumentsObjectArg(useRegister(argsObj), useRegister(index), temp());
    470  assignSnapshot(lir, ins->bailoutKind());
    471  define(lir, ins);
    472 }
    473 
    474 void LIRGenerator::visitArgumentsObjectLength(MArgumentsObjectLength* ins) {
    475  MDefinition* argsObj = ins->argsObject();
    476  MOZ_ASSERT(argsObj->type() == MIRType::Object);
    477 
    478  auto* lir = new (alloc()) LArgumentsObjectLength(useRegister(argsObj));
    479  assignSnapshot(lir, ins->bailoutKind());
    480  define(lir, ins);
    481 }
    482 
    483 void LIRGenerator::visitArrayFromArgumentsObject(
    484    MArrayFromArgumentsObject* ins) {
    485  MDefinition* argsObj = ins->argsObject();
    486  MOZ_ASSERT(argsObj->type() == MIRType::Object);
    487 
    488  auto* lir =
    489      new (alloc()) LArrayFromArgumentsObject(useRegisterAtStart(argsObj));
    490  defineReturn(lir, ins);
    491  assignSafepoint(lir, ins);
    492 }
    493 
    494 void LIRGenerator::visitGuardArgumentsObjectFlags(
    495    MGuardArgumentsObjectFlags* ins) {
    496  MDefinition* argsObj = ins->argsObject();
    497  MOZ_ASSERT(argsObj->type() == MIRType::Object);
    498 
    499  auto* lir =
    500      new (alloc()) LGuardArgumentsObjectFlags(useRegister(argsObj), temp());
    501  assignSnapshot(lir, ins->bailoutKind());
    502  add(lir, ins);
    503  redefine(ins, argsObj);
    504 }
    505 
    506 void LIRGenerator::visitGuardObjectHasSameRealm(MGuardObjectHasSameRealm* ins) {
    507  MDefinition* obj = ins->object();
    508  MOZ_ASSERT(obj->type() == MIRType::Object);
    509 
    510  auto* lir = new (alloc()) LGuardObjectHasSameRealm(useRegister(obj), temp());
    511  assignSnapshot(lir, ins->bailoutKind());
    512  add(lir, ins);
    513  redefine(ins, obj);
    514 }
    515 
    516 void LIRGenerator::visitBoundFunctionNumArgs(MBoundFunctionNumArgs* ins) {
    517  MDefinition* obj = ins->object();
    518  MOZ_ASSERT(obj->type() == MIRType::Object);
    519 
    520  auto* lir = new (alloc()) LBoundFunctionNumArgs(useRegisterAtStart(obj));
    521  define(lir, ins);
    522 }
    523 
    524 void LIRGenerator::visitGuardBoundFunctionIsConstructor(
    525    MGuardBoundFunctionIsConstructor* ins) {
    526  MOZ_ASSERT(ins->object()->type() == MIRType::Object);
    527 
    528  auto* lir = new (alloc())
    529      LGuardBoundFunctionIsConstructor(useRegister(ins->object()));
    530  assignSnapshot(lir, ins->bailoutKind());
    531  add(lir, ins);
    532  redefine(ins, ins->object());
    533 }
    534 
    535 void LIRGenerator::visitReturnFromCtor(MReturnFromCtor* ins) {
    536  LReturnFromCtor* lir = new (alloc())
    537      LReturnFromCtor(useBox(ins->value()), useRegister(ins->object()));
    538  define(lir, ins);
    539 }
    540 
    541 void LIRGenerator::visitBoxNonStrictThis(MBoxNonStrictThis* ins) {
    542  MOZ_ASSERT(ins->type() == MIRType::Object);
    543  MOZ_ASSERT(ins->input()->type() == MIRType::Value);
    544 
    545  auto* lir = new (alloc()) LBoxNonStrictThis(useBox(ins->input()));
    546  define(lir, ins);
    547  assignSafepoint(lir, ins);
    548 }
    549 
    550 void LIRGenerator::visitImplicitThis(MImplicitThis* ins) {
    551  MDefinition* env = ins->env();
    552  MOZ_ASSERT(env->type() == MIRType::Object);
    553 
    554  auto* lir = new (alloc()) LImplicitThis(useRegister(env));
    555  defineBox(lir, ins);
    556  assignSafepoint(lir, ins);
    557 }
    558 
    559 template <typename T>
    560 bool LIRGenerator::lowerCallArguments(T* call) {
    561  uint32_t argc = call->numStackArgs();
    562 
    563  // Align the arguments of a call such that the callee would keep the same
    564  // alignment as the caller.
    565  uint32_t baseSlot = 0;
    566  if (JitStackValueAlignment > 1) {
    567    baseSlot = AlignBytes(argc, JitStackValueAlignment);
    568  } else {
    569    baseSlot = argc;
    570  }
    571 
    572  // Save the maximum number of argument, such that we can have one unique
    573  // frame size.
    574  if (baseSlot > maxargslots_) {
    575    maxargslots_ = baseSlot;
    576  }
    577 
    578  for (size_t i = 0; i < argc; i++) {
    579    MDefinition* arg = call->getArg(i);
    580    uint32_t argslot = baseSlot - i;
    581 
    582    // Values take a slow path.
    583    if (arg->type() == MIRType::Value) {
    584      LStackArgV* stack = new (alloc()) LStackArgV(useBox(arg), argslot);
    585      add(stack);
    586    } else {
    587      // Known types can move constant types and/or payloads.
    588      LStackArgT* stack = new (alloc())
    589          LStackArgT(useRegisterOrConstant(arg), argslot, arg->type());
    590      add(stack);
    591    }
    592 
    593    if (!alloc().ensureBallast()) {
    594      return false;
    595    }
    596  }
    597  return true;
    598 }
    599 
    600 void LIRGenerator::visitCall(MCall* call) {
    601  MOZ_ASSERT(call->getCallee()->type() == MIRType::Object);
    602 
    603  // In case of oom, skip the rest of the allocations.
    604  if (!lowerCallArguments(call)) {
    605    abort(AbortReason::Alloc, "OOM: LIRGenerator::visitCall");
    606    return;
    607  }
    608 
    609  WrappedFunction* target = call->getSingleTarget();
    610 
    611  LInstruction* lir;
    612 
    613  if (call->isCallDOMNative()) {
    614    // Call DOM functions.
    615    MOZ_ASSERT(target && target->isNativeWithoutJitEntry());
    616    Register cxReg, objReg, privReg, argsReg;
    617    GetTempRegForIntArg(0, 0, &cxReg);
    618    GetTempRegForIntArg(1, 0, &objReg);
    619    GetTempRegForIntArg(2, 0, &privReg);
    620    mozilla::DebugOnly<bool> ok = GetTempRegForIntArg(3, 0, &argsReg);
    621    MOZ_ASSERT(ok, "How can we not have four temp registers?");
    622    lir = new (alloc()) LCallDOMNative(tempFixed(cxReg), tempFixed(objReg),
    623                                       tempFixed(privReg), tempFixed(argsReg));
    624  } else if (target) {
    625    // Call known functions.
    626    if (target->isNativeWithoutJitEntry()) {
    627      Register cxReg, numReg, vpReg, tmpReg;
    628      GetTempRegForIntArg(0, 0, &cxReg);
    629      GetTempRegForIntArg(1, 0, &numReg);
    630      GetTempRegForIntArg(2, 0, &vpReg);
    631 
    632      // Even though this is just a temp reg, use the same API to avoid
    633      // register collisions.
    634      mozilla::DebugOnly<bool> ok = GetTempRegForIntArg(3, 0, &tmpReg);
    635      MOZ_ASSERT(ok, "How can we not have four temp registers?");
    636 
    637      lir = new (alloc()) LCallNative(tempFixed(cxReg), tempFixed(numReg),
    638                                      tempFixed(vpReg), tempFixed(tmpReg));
    639    } else {
    640      lir = new (alloc()) LCallKnown(useRegisterAtStart(call->getCallee()),
    641                                     tempFixed(CallTempReg0));
    642    }
    643  } else {
    644    // Call anything, using the most generic code.
    645    lir = new (alloc()) LCallGeneric(
    646        useFixedAtStart(call->getCallee(), IonGenericCallCalleeReg),
    647        tempFixed(IonGenericCallArgcReg));
    648  }
    649  defineReturn(lir, call);
    650  assignSafepoint(lir, call);
    651 }
    652 
    653 void LIRGenerator::visitCallClassHook(MCallClassHook* call) {
    654  MDefinition* callee = call->getCallee();
    655  MOZ_ASSERT(callee->type() == MIRType::Object);
    656 
    657  // In case of oom, skip the rest of the allocations.
    658  if (!lowerCallArguments(call)) {
    659    abort(AbortReason::Alloc, "OOM: LIRGenerator::visitCallClassHook");
    660    return;
    661  }
    662 
    663  Register cxReg, numReg, vpReg, tmpReg;
    664  GetTempRegForIntArg(0, 0, &cxReg);
    665  GetTempRegForIntArg(1, 0, &numReg);
    666  GetTempRegForIntArg(2, 0, &vpReg);
    667 
    668  // Even though this is just a temp reg, use the same API to avoid
    669  // register collisions.
    670  mozilla::DebugOnly<bool> ok = GetTempRegForIntArg(3, 0, &tmpReg);
    671  MOZ_ASSERT(ok, "How can we not have four temp registers?");
    672 
    673  auto* lir = new (alloc())
    674      LCallClassHook(useRegisterAtStart(callee), tempFixed(cxReg),
    675                     tempFixed(numReg), tempFixed(vpReg), tempFixed(tmpReg));
    676  defineReturn(lir, call);
    677  assignSafepoint(lir, call);
    678 }
    679 
    680 void LIRGenerator::visitApplyArgs(MApplyArgs* apply) {
    681  MOZ_ASSERT(apply->getFunction()->type() == MIRType::Object);
    682 
    683  // Assert if the return value is already erased.
    684  static_assert(CallTempReg2 != JSReturnReg_Type);
    685  static_assert(CallTempReg2 != JSReturnReg_Data);
    686 
    687  auto argc = useFixedAtStart(apply->getArgc(), CallTempReg0);
    688  auto thisValue =
    689      useBoxFixedAtStart(apply->getThis(), CallTempReg4, CallTempReg5);
    690  auto tempObj = tempFixed(CallTempReg1);   // object register
    691  auto tempCopy = tempFixed(CallTempReg2);  // copy register
    692 
    693  auto* target = apply->getSingleTarget();
    694 
    695  LInstruction* lir;
    696  if (target && target->isNativeWithoutJitEntry()) {
    697    auto temp = tempFixed(CallTempReg3);
    698 
    699    lir = new (alloc())
    700        LApplyArgsNative(argc, thisValue, tempObj, tempCopy, temp);
    701  } else {
    702    auto function = useFixedAtStart(apply->getFunction(), CallTempReg3);
    703 
    704    lir = new (alloc())
    705        LApplyArgsGeneric(function, argc, thisValue, tempObj, tempCopy);
    706    lirGraph_.addExtraSafepointUses(1);
    707  }
    708 
    709  // Bailout is needed in the case of too many values in the arguments array.
    710  assignSnapshot(lir, apply->bailoutKind());
    711 
    712  defineReturn(lir, apply);
    713  assignSafepoint(lir, apply);
    714 }
    715 
    716 void LIRGenerator::visitApplyArgsObj(MApplyArgsObj* apply) {
    717  MOZ_ASSERT(apply->getFunction()->type() == MIRType::Object);
    718 
    719  // Assert if the return value is already erased.
    720  static_assert(CallTempReg2 != JSReturnReg_Type);
    721  static_assert(CallTempReg2 != JSReturnReg_Data);
    722 
    723  auto argsObj = useFixedAtStart(apply->getArgsObj(), CallTempReg0);
    724  auto thisValue =
    725      useBoxFixedAtStart(apply->getThis(), CallTempReg4, CallTempReg5);
    726  auto tempObj = tempFixed(CallTempReg1);   // object register
    727  auto tempCopy = tempFixed(CallTempReg2);  // copy register
    728 
    729  auto* target = apply->getSingleTarget();
    730 
    731  LInstruction* lir;
    732  if (target && target->isNativeWithoutJitEntry()) {
    733    auto temp = tempFixed(CallTempReg3);
    734 
    735    lir = new (alloc())
    736        LApplyArgsObjNative(argsObj, thisValue, tempObj, tempCopy, temp);
    737  } else {
    738    auto function = useFixedAtStart(apply->getFunction(), CallTempReg3);
    739 
    740    lir = new (alloc())
    741        LApplyArgsObj(function, argsObj, thisValue, tempObj, tempCopy);
    742    lirGraph_.addExtraSafepointUses(1);
    743  }
    744 
    745  // Bailout is needed in the case of too many values in the arguments array.
    746  assignSnapshot(lir, apply->bailoutKind());
    747 
    748  defineReturn(lir, apply);
    749  assignSafepoint(lir, apply);
    750 }
    751 
    752 void LIRGenerator::visitApplyArray(MApplyArray* apply) {
    753  MOZ_ASSERT(apply->getFunction()->type() == MIRType::Object);
    754 
    755  // Assert if the return value is already erased.
    756  static_assert(CallTempReg2 != JSReturnReg_Type);
    757  static_assert(CallTempReg2 != JSReturnReg_Data);
    758 
    759  auto elements = useFixedAtStart(apply->getElements(), CallTempReg0);
    760  auto thisValue =
    761      useBoxFixedAtStart(apply->getThis(), CallTempReg4, CallTempReg5);
    762  auto tempObj = tempFixed(CallTempReg1);   // object register
    763  auto tempCopy = tempFixed(CallTempReg2);  // copy register
    764 
    765  auto* target = apply->getSingleTarget();
    766 
    767  LInstruction* lir;
    768  if (target && target->isNativeWithoutJitEntry()) {
    769    auto temp = tempFixed(CallTempReg3);
    770 
    771    lir = new (alloc())
    772        LApplyArrayNative(elements, thisValue, tempObj, tempCopy, temp);
    773  } else {
    774    auto function = useFixedAtStart(apply->getFunction(), CallTempReg3);
    775 
    776    lir = new (alloc())
    777        LApplyArrayGeneric(function, elements, thisValue, tempObj, tempCopy);
    778    lirGraph_.addExtraSafepointUses(1);
    779  }
    780 
    781  // Bailout is needed in the case of too many values in the array, or empty
    782  // space at the end of the array.
    783  assignSnapshot(lir, apply->bailoutKind());
    784 
    785  defineReturn(lir, apply);
    786  assignSafepoint(lir, apply);
    787 }
    788 
    789 void LIRGenerator::visitConstructArgs(MConstructArgs* mir) {
    790  MOZ_ASSERT(mir->getFunction()->type() == MIRType::Object);
    791  MOZ_ASSERT(mir->getArgc()->type() == MIRType::Int32);
    792  MOZ_ASSERT(mir->getNewTarget()->type() == MIRType::Object);
    793  MOZ_ASSERT(mir->getThis()->type() == MIRType::Value);
    794 
    795  // Assert if the return value is already erased.
    796  static_assert(CallTempReg2 != JSReturnReg_Type);
    797  static_assert(CallTempReg2 != JSReturnReg_Data);
    798 
    799  auto argc = useFixedAtStart(mir->getArgc(), CallTempReg0);
    800  auto newTarget = useFixedAtStart(mir->getNewTarget(), CallTempReg1);
    801  auto temp = tempFixed(CallTempReg2);
    802 
    803  auto* target = mir->getSingleTarget();
    804 
    805  LInstruction* lir;
    806  if (target && target->isNativeWithoutJitEntry()) {
    807    auto temp2 = tempFixed(CallTempReg3);
    808    auto temp3 = tempFixed(CallTempReg4);
    809 
    810    lir =
    811        new (alloc()) LConstructArgsNative(argc, newTarget, temp, temp2, temp3);
    812  } else {
    813    auto function = useFixedAtStart(mir->getFunction(), CallTempReg3);
    814    auto thisValue =
    815        useBoxFixedAtStart(mir->getThis(), CallTempReg4, CallTempReg5);
    816 
    817    lir = new (alloc())
    818        LConstructArgsGeneric(function, argc, newTarget, thisValue, temp);
    819    lirGraph_.addExtraSafepointUses(1);
    820  }
    821 
    822  // Bailout is needed in the case of too many values in the arguments array.
    823  assignSnapshot(lir, mir->bailoutKind());
    824 
    825  defineReturn(lir, mir);
    826  assignSafepoint(lir, mir);
    827 }
    828 
    829 void LIRGenerator::visitConstructArray(MConstructArray* mir) {
    830  MOZ_ASSERT(mir->getFunction()->type() == MIRType::Object);
    831  MOZ_ASSERT(mir->getElements()->type() == MIRType::Elements);
    832  MOZ_ASSERT(mir->getNewTarget()->type() == MIRType::Object);
    833  MOZ_ASSERT(mir->getThis()->type() == MIRType::Value);
    834 
    835  // Assert if the return value is already erased.
    836  static_assert(CallTempReg2 != JSReturnReg_Type);
    837  static_assert(CallTempReg2 != JSReturnReg_Data);
    838 
    839  auto elements = useFixedAtStart(mir->getElements(), CallTempReg0);
    840  auto newTarget = useFixedAtStart(mir->getNewTarget(), CallTempReg1);
    841  auto temp = tempFixed(CallTempReg2);
    842 
    843  auto* target = mir->getSingleTarget();
    844 
    845  LInstruction* lir;
    846  if (target && target->isNativeWithoutJitEntry()) {
    847    auto temp2 = tempFixed(CallTempReg3);
    848    auto temp3 = tempFixed(CallTempReg4);
    849 
    850    lir = new (alloc())
    851        LConstructArrayNative(elements, newTarget, temp, temp2, temp3);
    852  } else {
    853    auto function = useFixedAtStart(mir->getFunction(), CallTempReg3);
    854    auto thisValue =
    855        useBoxFixedAtStart(mir->getThis(), CallTempReg4, CallTempReg5);
    856 
    857    lir = new (alloc())
    858        LConstructArrayGeneric(function, elements, newTarget, thisValue, temp);
    859    lirGraph_.addExtraSafepointUses(1);
    860  }
    861 
    862  // Bailout is needed in the case of too many values in the array, or empty
    863  // space at the end of the array.
    864  assignSnapshot(lir, mir->bailoutKind());
    865 
    866  defineReturn(lir, mir);
    867  assignSafepoint(lir, mir);
    868 }
    869 
    870 void LIRGenerator::visitBail(MBail* bail) {
    871  LBail* lir = new (alloc()) LBail();
    872  assignSnapshot(lir, bail->bailoutKind());
    873  add(lir, bail);
    874 }
    875 
    876 void LIRGenerator::visitUnreachable(MUnreachable* unreachable) {
    877  LUnreachable* lir = new (alloc()) LUnreachable();
    878  add(lir, unreachable);
    879 }
    880 
    881 void LIRGenerator::visitEncodeSnapshot(MEncodeSnapshot* mir) {
    882  LEncodeSnapshot* lir = new (alloc()) LEncodeSnapshot();
    883  assignSnapshot(lir, mir->bailoutKind());
    884  add(lir, mir);
    885 }
    886 
    887 void LIRGenerator::visitUnreachableResult(MUnreachableResult* mir) {
    888  if (mir->type() == MIRType::Value) {
    889    auto* lir = new (alloc()) LUnreachableResultV();
    890    defineBox(lir, mir);
    891  } else {
    892    auto* lir = new (alloc()) LUnreachableResultT();
    893    define(lir, mir);
    894  }
    895 }
    896 
    897 void LIRGenerator::visitAssertFloat32(MAssertFloat32* assertion) {
    898  MIRType type = assertion->input()->type();
    899  DebugOnly<bool> checkIsFloat32 = assertion->mustBeFloat32();
    900 
    901  if (type != MIRType::Value && !JitOptions.eagerIonCompilation()) {
    902    MOZ_ASSERT_IF(checkIsFloat32, type == MIRType::Float32);
    903    MOZ_ASSERT_IF(!checkIsFloat32, type != MIRType::Float32);
    904  }
    905 }
    906 
    907 void LIRGenerator::visitAssertRecoveredOnBailout(
    908    MAssertRecoveredOnBailout* assertion) {
    909  MOZ_CRASH("AssertRecoveredOnBailout nodes are always recovered on bailouts.");
    910 }
    911 
    912 [[nodiscard]] static JSOp ReorderComparison(JSOp op, MDefinition** lhsp,
    913                                            MDefinition** rhsp) {
    914  MDefinition* lhs = *lhsp;
    915  MDefinition* rhs = *rhsp;
    916 
    917  if (lhs->maybeConstantValue()) {
    918    *rhsp = lhs;
    919    *lhsp = rhs;
    920    return ReverseCompareOp(op);
    921  }
    922  return op;
    923 }
    924 
    925 void LIRGenerator::visitTest(MTest* test) {
    926  MDefinition* opd = test->getOperand(0);
    927  MBasicBlock* ifTrue = test->ifTrue();
    928  MBasicBlock* ifFalse = test->ifFalse();
    929 
    930  // String is converted to length of string in the type analysis phase (see
    931  // TestPolicy).
    932  MOZ_ASSERT(opd->type() != MIRType::String);
    933 
    934  // Testing a constant.
    935  if (MConstant* constant = opd->maybeConstantValue()) {
    936    bool b;
    937    if (constant->valueToBoolean(&b)) {
    938      add(new (alloc()) LGoto(b ? ifTrue : ifFalse));
    939      return;
    940    }
    941  }
    942 
    943  if (opd->type() == MIRType::Value) {
    944    auto* lir = new (alloc()) LTestVAndBranch(
    945        ifTrue, ifFalse, useBox(opd), tempDouble(), tempToUnbox(), temp());
    946    add(lir, test);
    947    return;
    948  }
    949 
    950  // Objects are truthy, except if it might emulate undefined.
    951  if (opd->type() == MIRType::Object) {
    952    add(new (alloc())
    953            LTestOAndBranch(ifTrue, ifFalse, useRegister(opd), temp()),
    954        test);
    955    return;
    956  }
    957 
    958  // These must be explicitly sniffed out since they are constants and have
    959  // no payload.
    960  if (opd->type() == MIRType::Undefined || opd->type() == MIRType::Null) {
    961    add(new (alloc()) LGoto(ifFalse));
    962    return;
    963  }
    964 
    965  // All symbols are truthy.
    966  if (opd->type() == MIRType::Symbol) {
    967    add(new (alloc()) LGoto(ifTrue));
    968    return;
    969  }
    970 
    971  // Try to match the pattern
    972  //   test=MTest(
    973  //          comp=MCompare(
    974  //                 {EQ,NE} for {Int,UInt}{32,64},
    975  //                 bitAnd={MBitAnd,MWasmBinaryBitwise(And{32,64})}(x, y),
    976  //                 MConstant(0)
    977  //               )
    978  //        )
    979  // and produce a single LBitAnd{,64}AndBranch node. This requires both `comp`
    980  // and `bitAnd` to be marked emit-at-uses.
    981  if (opd->isCompare() && opd->isEmittedAtUses()) {
    982    MCompare* comp = opd->toCompare();
    983    Assembler::Condition compCond =
    984        JSOpToCondition(comp->compareType(), comp->jsop());
    985    MDefinition* compL = comp->lhs();
    986    MDefinition* compR = comp->rhs();
    987    if ((comp->compareType() == MCompare::Compare_Int32 ||
    988         comp->compareType() == MCompare::Compare_UInt32 ||
    989         (comp->compareType() == MCompare::Compare_Int64) ||
    990         (comp->compareType() == MCompare::Compare_UInt64)) &&
    991        (compCond == Assembler::Equal || compCond == Assembler::NotEqual) &&
    992        compR->isConstant() &&
    993        (compR->toConstant()->isInt32(0) ||
    994         (compR->toConstant()->isInt64(0))) &&
    995        (compL->isBitAnd() || (compL->isWasmBinaryBitwise() &&
    996                               compL->toWasmBinaryBitwise()->subOpcode() ==
    997                                   MWasmBinaryBitwise::SubOpcode::And))) {
    998      // The MCompare is OK; now check its first operand (the and-ish node).
    999      MDefinition* bitAnd = compL;
   1000      MDefinition* bitAndL = bitAnd->getOperand(0);
   1001      MDefinition* bitAndR = bitAnd->getOperand(1);
   1002      MIRType bitAndLTy = bitAndL->type();
   1003      MIRType bitAndRTy = bitAndR->type();
   1004      if (bitAnd->isEmittedAtUses() && bitAndLTy == bitAndRTy &&
   1005          (bitAndLTy == MIRType::Int32 || (bitAndLTy == MIRType::Int64))) {
   1006        // Pattern match succeeded.
   1007        ReorderCommutative(&bitAndL, &bitAndR, test);
   1008        if (compCond == Assembler::Equal) {
   1009          compCond = Assembler::Zero;
   1010        } else if (compCond == Assembler::NotEqual) {
   1011          compCond = Assembler::NonZero;
   1012        } else {
   1013          MOZ_ASSERT_UNREACHABLE("inequality operators cannot be folded");
   1014        }
   1015 
   1016        if (bitAndLTy == MIRType::Int64) {
   1017          auto lhs = useInt64RegisterAtStart(bitAndL);
   1018          auto rhs = useInt64RegisterOrConstantAtStart(bitAndR);
   1019          auto* lir = new (alloc())
   1020              LBitAnd64AndBranch(ifTrue, ifFalse, lhs, rhs, compCond);
   1021          add(lir, test);
   1022          return;
   1023        }
   1024 
   1025        LAllocation lhs = useRegisterAtStart(bitAndL);
   1026        LAllocation rhs = useRegisterOrConstantAtStart(bitAndR);
   1027        auto* lir =
   1028            new (alloc()) LBitAndAndBranch(ifTrue, ifFalse, lhs, rhs, compCond);
   1029        add(lir, test);
   1030        return;
   1031      }
   1032    }
   1033  }
   1034 
   1035  // Check if the operand for this test is a compare operation. If it is, we
   1036  // want to emit an LCompare*AndBranch rather than an LTest*AndBranch, to fuse
   1037  // the compare and jump instructions.
   1038  if (opd->isCompare() && opd->isEmittedAtUses()) {
   1039    MCompare* comp = opd->toCompare();
   1040    MDefinition* left = comp->lhs();
   1041    MDefinition* right = comp->rhs();
   1042 
   1043    // Try to fold the comparison so that we don't have to handle all cases.
   1044    bool result;
   1045    if (comp->tryFold(&result)) {
   1046      add(new (alloc()) LGoto(result ? ifTrue : ifFalse));
   1047      return;
   1048    }
   1049 
   1050    // Emit LCompare*AndBranch.
   1051 
   1052    // Compare and branch null/undefined.
   1053    // The second operand has known null/undefined type,
   1054    // so just test the first operand.
   1055    if (comp->compareType() == MCompare::Compare_Null ||
   1056        comp->compareType() == MCompare::Compare_Undefined) {
   1057      if (left->type() == MIRType::Object) {
   1058        auto* lir = new (alloc()) LIsNullOrLikeUndefinedAndBranchT(
   1059            ifTrue, ifFalse, useRegister(left), temp(), comp);
   1060        add(lir, test);
   1061        return;
   1062      }
   1063 
   1064      if (IsLooseEqualityOp(comp->jsop())) {
   1065        auto* lir = new (alloc()) LIsNullOrLikeUndefinedAndBranchV(
   1066            ifTrue, ifFalse, useBox(left), temp(), tempToUnbox(), comp);
   1067        add(lir, test);
   1068        return;
   1069      }
   1070 
   1071      if (comp->compareType() == MCompare::Compare_Null) {
   1072        auto* lir =
   1073            new (alloc()) LIsNullAndBranch(ifTrue, ifFalse, useBox(left), comp);
   1074        add(lir, test);
   1075        return;
   1076      }
   1077 
   1078      auto* lir = new (alloc())
   1079          LIsUndefinedAndBranch(ifTrue, ifFalse, useBox(left), comp);
   1080      add(lir, test);
   1081      return;
   1082    }
   1083 
   1084    // Compare and branch Int32, Symbol, Object, or WasmAnyRef pointers.
   1085    if (comp->isInt32Comparison() ||
   1086        comp->compareType() == MCompare::Compare_UInt32 ||
   1087        comp->compareType() == MCompare::Compare_IntPtr ||
   1088        comp->compareType() == MCompare::Compare_UIntPtr ||
   1089        comp->compareType() == MCompare::Compare_Object ||
   1090        comp->compareType() == MCompare::Compare_Symbol ||
   1091        comp->compareType() == MCompare::Compare_WasmAnyRef) {
   1092      JSOp op = ReorderComparison(comp->jsop(), &left, &right);
   1093      LAllocation lhs = useRegister(left);
   1094      LAllocation rhs;
   1095      if (comp->isInt32Comparison() ||
   1096          comp->compareType() == MCompare::Compare_UInt32 ||
   1097          comp->compareType() == MCompare::Compare_IntPtr ||
   1098          comp->compareType() == MCompare::Compare_UIntPtr) {
   1099        rhs = useAnyOrInt32Constant(right);
   1100      } else {
   1101        rhs = useAny(right);
   1102      }
   1103      auto* lir =
   1104          new (alloc()) LCompareAndBranch(ifTrue, ifFalse, lhs, rhs, comp, op);
   1105      add(lir, test);
   1106      return;
   1107    }
   1108 
   1109    // Compare and branch Int64.
   1110    if (comp->compareType() == MCompare::Compare_Int64 ||
   1111        comp->compareType() == MCompare::Compare_UInt64) {
   1112      JSOp op = ReorderComparison(comp->jsop(), &left, &right);
   1113      LInt64Allocation lhs = useInt64Register(left);
   1114      LInt64Allocation rhs = useInt64OrConstant(right);
   1115      auto* lir = new (alloc())
   1116          LCompareI64AndBranch(ifTrue, ifFalse, lhs, rhs, comp, op);
   1117      add(lir, test);
   1118      return;
   1119    }
   1120 
   1121    // Compare and branch doubles.
   1122    if (comp->isDoubleComparison()) {
   1123      LAllocation lhs = useRegister(left);
   1124      LAllocation rhs = useRegister(right);
   1125      auto* lir =
   1126          new (alloc()) LCompareDAndBranch(ifTrue, ifFalse, lhs, rhs, comp);
   1127      add(lir, test);
   1128      return;
   1129    }
   1130 
   1131    // Compare and branch floats.
   1132    if (comp->isFloat32Comparison()) {
   1133      LAllocation lhs = useRegister(left);
   1134      LAllocation rhs = useRegister(right);
   1135      auto* lir =
   1136          new (alloc()) LCompareFAndBranch(ifTrue, ifFalse, lhs, rhs, comp);
   1137      add(lir, test);
   1138      return;
   1139    }
   1140 
   1141    // Compare and branch BigInt with Int32.
   1142    if (comp->compareType() == MCompare::Compare_BigInt_Int32) {
   1143      LAllocation lhs = useRegister(left);
   1144      LAllocation rhs = useRegisterOrInt32Constant(right);
   1145      LDefinition temp1 = temp();
   1146      LDefinition temp2 = !rhs.isConstant() ? temp() : LDefinition::BogusTemp();
   1147      auto* lir = new (alloc()) LCompareBigIntInt32AndBranch(
   1148          ifTrue, ifFalse, lhs, rhs, temp1, temp2, comp);
   1149      add(lir, test);
   1150      return;
   1151    }
   1152  }
   1153 
   1154  // Check if the operand for this test is a bitand operation. If it is, we want
   1155  // to emit an LBitAndAndBranch rather than an LTest*AndBranch.
   1156  if (opd->isBitAnd() && opd->isEmittedAtUses()) {
   1157    MBitAnd* bitAnd = opd->toBitAnd();
   1158    MDefinition* left = bitAnd->lhs();
   1159    MDefinition* right = bitAnd->rhs();
   1160    if (left->type() == MIRType::Int32 && right->type() == MIRType::Int32) {
   1161      ReorderCommutative(&left, &right, test);
   1162      LAllocation lhs = useRegisterAtStart(left);
   1163      LAllocation rhs = useRegisterOrConstantAtStart(right);
   1164      auto* lir = new (alloc())
   1165          LBitAndAndBranch(ifTrue, ifFalse, lhs, rhs, Assembler::NonZero);
   1166      add(lir, test);
   1167      return;
   1168    }
   1169  }
   1170 
   1171 #if defined(ENABLE_WASM_SIMD) &&                           \
   1172    (defined(JS_CODEGEN_X86) || defined(JS_CODEGEN_X64) || \
   1173     defined(JS_CODEGEN_ARM64))
   1174  // Check if the operand for this test is an any_true/all_true SIMD operation.
   1175  // If it is, we want to emit an LWasmReduceAndBranchSimd128 node to avoid
   1176  // generating an intermediate boolean result.
   1177  if (opd->isWasmReduceSimd128() && opd->isEmittedAtUses()) {
   1178    MWasmReduceSimd128* node = opd->toWasmReduceSimd128();
   1179    if (canFoldReduceSimd128AndBranch(node->simdOp())) {
   1180 #  ifdef DEBUG
   1181      js::wasm::ReportSimdAnalysis("simd128-to-scalar-and-branch -> folded");
   1182 #  endif
   1183      auto* lir = new (alloc()) LWasmReduceAndBranchSimd128(
   1184          ifTrue, ifFalse, useRegister(node->input()), node->simdOp());
   1185      add(lir, test);
   1186      return;
   1187    }
   1188  }
   1189 #endif
   1190 
   1191  if (opd->isIsObject() && opd->isEmittedAtUses()) {
   1192    MDefinition* input = opd->toIsObject()->input();
   1193    MOZ_ASSERT(input->type() == MIRType::Value);
   1194 
   1195    LIsObjectAndBranch* lir =
   1196        new (alloc()) LIsObjectAndBranch(ifTrue, ifFalse, useBoxAtStart(input));
   1197    add(lir, test);
   1198    return;
   1199  }
   1200 
   1201  if (opd->isWasmRefTestAbstract() && opd->isEmittedAtUses()) {
   1202    MWasmRefTestAbstract* refTest = opd->toWasmRefTestAbstract();
   1203 
   1204    LAllocation ref = useRegister(refTest->ref());
   1205    WasmRefIsSubtypeDefs regs =
   1206        useWasmRefIsSubtype(refTest->destType(), /*superSTV=*/nullptr);
   1207    add(new (alloc()) LWasmRefTestAbstractAndBranch(
   1208            ifTrue, ifFalse, ref, regs.scratch1, refTest->ref()->wasmRefType(),
   1209            refTest->destType()),
   1210        test);
   1211    return;
   1212  }
   1213 
   1214  if (opd->isWasmRefTestConcrete() && opd->isEmittedAtUses()) {
   1215    MWasmRefTestConcrete* refTest = opd->toWasmRefTestConcrete();
   1216 
   1217    LAllocation ref = useRegister(refTest->ref());
   1218    WasmRefIsSubtypeDefs regs =
   1219        useWasmRefIsSubtype(refTest->destType(), refTest->superSTV());
   1220    add(new (alloc()) LWasmRefTestConcreteAndBranch(
   1221            ifTrue, ifFalse, ref, regs.superSTV, regs.scratch1, regs.scratch2,
   1222            refTest->ref()->wasmRefType(), refTest->destType()),
   1223        test);
   1224    return;
   1225  }
   1226 
   1227  if (opd->isIsNullOrUndefined() && opd->isEmittedAtUses()) {
   1228    MIsNullOrUndefined* isNullOrUndefined = opd->toIsNullOrUndefined();
   1229    MDefinition* input = isNullOrUndefined->value();
   1230 
   1231    if (input->type() == MIRType::Value) {
   1232      auto* lir = new (alloc())
   1233          LIsNullOrUndefinedAndBranch(ifTrue, ifFalse, useBoxAtStart(input));
   1234      add(lir, test);
   1235    } else {
   1236      auto* target = IsNullOrUndefined(input->type()) ? ifTrue : ifFalse;
   1237      add(new (alloc()) LGoto(target));
   1238    }
   1239    return;
   1240  }
   1241 
   1242  if (opd->isStrictConstantCompareInt32() && opd->isEmittedAtUses()) {
   1243    auto* comp = opd->toStrictConstantCompareInt32();
   1244    auto* value = comp->value();
   1245 
   1246    auto* lir = new (alloc()) LStrictConstantCompareInt32AndBranch(
   1247        ifTrue, ifFalse, useBoxAtStart(value), comp);
   1248    add(lir, test);
   1249    return;
   1250  }
   1251 
   1252  if (opd->isStrictConstantCompareBoolean() && opd->isEmittedAtUses()) {
   1253    auto* comp = opd->toStrictConstantCompareBoolean();
   1254    auto* value = comp->value();
   1255 
   1256    auto* lir = new (alloc()) LStrictConstantCompareBooleanAndBranch(
   1257        ifTrue, ifFalse, useBoxAtStart(value), comp);
   1258    add(lir, test);
   1259    return;
   1260  }
   1261 
   1262  if (opd->isIsNoIter()) {
   1263    MOZ_ASSERT(opd->isEmittedAtUses());
   1264 
   1265    MDefinition* input = opd->toIsNoIter()->input();
   1266    MOZ_ASSERT(input->type() == MIRType::Value);
   1267 
   1268    LIsNoIterAndBranch* lir =
   1269        new (alloc()) LIsNoIterAndBranch(ifTrue, ifFalse, useBox(input));
   1270    add(lir, test);
   1271    return;
   1272  }
   1273 
   1274  if (opd->isIteratorHasIndices()) {
   1275    MOZ_ASSERT(opd->isEmittedAtUses());
   1276 
   1277    MDefinition* object = opd->toIteratorHasIndices()->object();
   1278    MDefinition* iterator = opd->toIteratorHasIndices()->iterator();
   1279    LIteratorHasIndicesAndBranch* lir = new (alloc())
   1280        LIteratorHasIndicesAndBranch(ifTrue, ifFalse, useRegister(object),
   1281                                     useRegister(iterator), temp(), temp());
   1282    add(lir, test);
   1283    return;
   1284  }
   1285 
   1286  if (opd->isIteratorsMatchAndHaveIndices()) {
   1287    MOZ_ASSERT(opd->isEmittedAtUses());
   1288 
   1289    MDefinition* object = opd->toIteratorsMatchAndHaveIndices()->object();
   1290    MDefinition* iterator = opd->toIteratorsMatchAndHaveIndices()->iterator();
   1291    MDefinition* otherIterator =
   1292        opd->toIteratorsMatchAndHaveIndices()->otherIterator();
   1293    LIteratorsMatchAndHaveIndicesAndBranch* lir =
   1294        new (alloc()) LIteratorsMatchAndHaveIndicesAndBranch(
   1295            ifTrue, ifFalse, useRegister(object), useRegister(iterator),
   1296            useRegister(otherIterator), temp(), temp());
   1297    add(lir, test);
   1298    return;
   1299  }
   1300 
   1301  switch (opd->type()) {
   1302    case MIRType::Double:
   1303      add(new (alloc()) LTestDAndBranch(ifTrue, ifFalse, useRegister(opd)));
   1304      break;
   1305    case MIRType::Float32:
   1306      add(new (alloc()) LTestFAndBranch(ifTrue, ifFalse, useRegister(opd)));
   1307      break;
   1308    case MIRType::Int32:
   1309    case MIRType::Boolean:
   1310      add(new (alloc()) LTestIAndBranch(ifTrue, ifFalse, useRegister(opd)));
   1311      break;
   1312    case MIRType::IntPtr:
   1313      add(new (alloc()) LTestIPtrAndBranch(ifTrue, ifFalse, useRegister(opd)));
   1314      break;
   1315    case MIRType::Int64:
   1316      add(new (alloc())
   1317              LTestI64AndBranch(ifTrue, ifFalse, useInt64Register(opd)));
   1318      break;
   1319    case MIRType::BigInt:
   1320      add(new (alloc()) LTestBIAndBranch(ifTrue, ifFalse, useRegister(opd)));
   1321      break;
   1322    default:
   1323      MOZ_CRASH("Bad type");
   1324  }
   1325 }
   1326 
   1327 static inline bool CanEmitCompareAtUses(MInstruction* ins) {
   1328  if (!ins->canEmitAtUses()) {
   1329    return false;
   1330  }
   1331 
   1332  // If the result is never used, we can usefully defer emission to the use
   1333  // point, since that will never happen.
   1334  MUseIterator iter(ins->usesBegin());
   1335  if (iter == ins->usesEnd()) {
   1336    return true;
   1337  }
   1338 
   1339  // If the first use isn't of the expected form, the answer is No.
   1340  MNode* node = iter->consumer();
   1341  if (!node->isDefinition()) {
   1342    return false;
   1343  }
   1344 
   1345  MDefinition* use = node->toDefinition();
   1346  if (!use->isTest() && !use->isWasmSelect()) {
   1347    return false;
   1348  }
   1349 
   1350  // Emission can be deferred to the first use point, but only if there are no
   1351  // other use points.
   1352  iter++;
   1353  return iter == ins->usesEnd();
   1354 }
   1355 
   1356 void LIRGenerator::visitCompare(MCompare* comp) {
   1357  MDefinition* left = comp->lhs();
   1358  MDefinition* right = comp->rhs();
   1359 
   1360  // Try to fold the comparison so that we don't have to handle all cases.
   1361  bool result;
   1362  if (comp->tryFold(&result)) {
   1363    define(new (alloc()) LInteger(result), comp);
   1364    return;
   1365  }
   1366 
   1367  // Move below the emitAtUses call if we ever implement
   1368  // LCompareSAndBranch. Doing this now wouldn't be wrong, but doesn't
   1369  // make sense and avoids confusion.
   1370  if (comp->compareType() == MCompare::Compare_String) {
   1371    MConstant* constant = nullptr;
   1372    MDefinition* input = nullptr;
   1373    if (left->isConstant()) {
   1374      constant = left->toConstant();
   1375      input = right;
   1376    } else if (right->isConstant()) {
   1377      constant = right->toConstant();
   1378      input = left;
   1379    }
   1380 
   1381    if (constant) {
   1382      JSOffThreadAtom* str = constant->toString();
   1383 
   1384      if (IsEqualityOp(comp->jsop())) {
   1385        if (MacroAssembler::canCompareStringCharsInline(str)) {
   1386          auto* lir = new (alloc()) LCompareSInline(useRegister(input), str);
   1387          define(lir, comp);
   1388          assignSafepoint(lir, comp);
   1389          return;
   1390        }
   1391      } else {
   1392        MOZ_ASSERT(IsRelationalOp(comp->jsop()));
   1393 
   1394        if (str->length() == 1) {
   1395          // Move the constant value into the right-hand side operand.
   1396          JSOp op = comp->jsop();
   1397          if (left == constant) {
   1398            op = ReverseCompareOp(op);
   1399          }
   1400 
   1401          auto* lir = new (alloc())
   1402              LCompareSSingle(useRegister(input), temp(), op, str);
   1403          define(lir, comp);
   1404          return;
   1405        }
   1406      }
   1407    }
   1408 
   1409    LCompareS* lir =
   1410        new (alloc()) LCompareS(useRegister(left), useRegister(right));
   1411    define(lir, comp);
   1412    assignSafepoint(lir, comp);
   1413    return;
   1414  }
   1415 
   1416  // Compare two BigInts.
   1417  if (comp->compareType() == MCompare::Compare_BigInt) {
   1418    auto* lir = new (alloc()) LCompareBigInt(
   1419        useRegister(left), useRegister(right), temp(), temp(), temp());
   1420    define(lir, comp);
   1421    return;
   1422  }
   1423 
   1424  // Compare BigInt with Double.
   1425  if (comp->compareType() == MCompare::Compare_BigInt_Double) {
   1426    auto* lir = new (alloc()) LCompareBigIntDouble(useRegisterAtStart(left),
   1427                                                   useRegisterAtStart(right));
   1428    defineReturn(lir, comp);
   1429    return;
   1430  }
   1431 
   1432  // Compare BigInt with String.
   1433  if (comp->compareType() == MCompare::Compare_BigInt_String) {
   1434    auto* lir = new (alloc()) LCompareBigIntString(useRegisterAtStart(left),
   1435                                                   useRegisterAtStart(right));
   1436    defineReturn(lir, comp);
   1437    assignSafepoint(lir, comp);
   1438    return;
   1439  }
   1440 
   1441  // Sniff out if the output of this compare is used only for a branching.
   1442  // If it is, then we will emit an LCompare*AndBranch instruction in place
   1443  // of this compare and any test that uses this compare. Thus, we can
   1444  // ignore this Compare.
   1445  if (CanEmitCompareAtUses(comp)) {
   1446    emitAtUses(comp);
   1447    return;
   1448  }
   1449 
   1450  // Compare Null and Undefined.
   1451  if (comp->compareType() == MCompare::Compare_Null ||
   1452      comp->compareType() == MCompare::Compare_Undefined) {
   1453    if (left->type() == MIRType::Object) {
   1454      define(new (alloc()) LIsNullOrLikeUndefinedT(useRegister(left)), comp);
   1455      return;
   1456    }
   1457 
   1458    if (IsLooseEqualityOp(comp->jsop())) {
   1459      auto* lir =
   1460          new (alloc()) LIsNullOrLikeUndefinedV(useBox(left), tempToUnbox());
   1461      define(lir, comp);
   1462      return;
   1463    }
   1464 
   1465    if (comp->compareType() == MCompare::Compare_Null) {
   1466      auto* lir = new (alloc()) LIsNull(useBox(left));
   1467      define(lir, comp);
   1468      return;
   1469    }
   1470 
   1471    auto* lir = new (alloc()) LIsUndefined(useBox(left));
   1472    define(lir, comp);
   1473    return;
   1474  }
   1475 
   1476  // Compare Int32, Symbol, Object or Wasm pointers.
   1477  if (comp->isInt32Comparison() ||
   1478      comp->compareType() == MCompare::Compare_UInt32 ||
   1479      comp->compareType() == MCompare::Compare_IntPtr ||
   1480      comp->compareType() == MCompare::Compare_UIntPtr ||
   1481      comp->compareType() == MCompare::Compare_Object ||
   1482      comp->compareType() == MCompare::Compare_Symbol ||
   1483      comp->compareType() == MCompare::Compare_WasmAnyRef) {
   1484    JSOp op = ReorderComparison(comp->jsop(), &left, &right);
   1485    LAllocation lhs = useRegister(left);
   1486    LAllocation rhs;
   1487    if (comp->isInt32Comparison() ||
   1488        comp->compareType() == MCompare::Compare_UInt32 ||
   1489        comp->compareType() == MCompare::Compare_IntPtr ||
   1490        comp->compareType() == MCompare::Compare_UIntPtr) {
   1491      rhs = useAnyOrInt32Constant(right);
   1492    } else {
   1493      rhs = useAny(right);
   1494    }
   1495    define(new (alloc()) LCompare(lhs, rhs, op), comp);
   1496    return;
   1497  }
   1498 
   1499  // Compare Int64.
   1500  if (comp->compareType() == MCompare::Compare_Int64 ||
   1501      comp->compareType() == MCompare::Compare_UInt64) {
   1502    JSOp op = ReorderComparison(comp->jsop(), &left, &right);
   1503    define(new (alloc()) LCompareI64(useInt64Register(left),
   1504                                     useInt64OrConstant(right), op),
   1505           comp);
   1506    return;
   1507  }
   1508 
   1509  // Compare doubles.
   1510  if (comp->isDoubleComparison()) {
   1511    define(new (alloc()) LCompareD(useRegister(left), useRegister(right)),
   1512           comp);
   1513    return;
   1514  }
   1515 
   1516  // Compare float32.
   1517  if (comp->isFloat32Comparison()) {
   1518    define(new (alloc()) LCompareF(useRegister(left), useRegister(right)),
   1519           comp);
   1520    return;
   1521  }
   1522 
   1523  // Compare BigInt with Int32.
   1524  if (comp->compareType() == MCompare::Compare_BigInt_Int32) {
   1525    LAllocation lhs = useRegister(left);
   1526    LAllocation rhs = useRegisterOrInt32Constant(right);
   1527    LDefinition temp1 = temp();
   1528    LDefinition temp2 = !rhs.isConstant() ? temp() : LDefinition::BogusTemp();
   1529    auto* lir = new (alloc()) LCompareBigIntInt32(lhs, rhs, temp1, temp2);
   1530    define(lir, comp);
   1531    return;
   1532  }
   1533 
   1534  MOZ_CRASH("Unrecognized compare type.");
   1535 }
   1536 
   1537 void LIRGenerator::visitStrictConstantCompareInt32(
   1538    MStrictConstantCompareInt32* ins) {
   1539  // Prefer to emit fused compare-and-branch if possible.
   1540  if (CanEmitCompareAtUses(ins)) {
   1541    emitAtUses(ins);
   1542    return;
   1543  }
   1544 
   1545  MDefinition* value = ins->value();
   1546 
   1547  auto* lir = new (alloc()) LStrictConstantCompareInt32(useBox(value), temp());
   1548  define(lir, ins);
   1549 }
   1550 
   1551 void LIRGenerator::visitStrictConstantCompareBoolean(
   1552    MStrictConstantCompareBoolean* ins) {
   1553  // Prefer to emit fused compare-and-branch if possible.
   1554  if (CanEmitCompareAtUses(ins)) {
   1555    emitAtUses(ins);
   1556    return;
   1557  }
   1558 
   1559  MDefinition* value = ins->value();
   1560 
   1561  auto* lir = new (alloc()) LStrictConstantCompareBoolean(useBox(value));
   1562  define(lir, ins);
   1563 }
   1564 
   1565 void LIRGenerator::visitSameValueDouble(MSameValueDouble* ins) {
   1566  MDefinition* lhs = ins->lhs();
   1567  MDefinition* rhs = ins->rhs();
   1568 
   1569  MOZ_ASSERT(lhs->type() == MIRType::Double);
   1570  MOZ_ASSERT(rhs->type() == MIRType::Double);
   1571 
   1572  auto* lir = new (alloc())
   1573      LSameValueDouble(useRegister(lhs), useRegister(rhs), tempDouble());
   1574  define(lir, ins);
   1575 }
   1576 
   1577 void LIRGenerator::visitSameValue(MSameValue* ins) {
   1578  MDefinition* lhs = ins->lhs();
   1579  MDefinition* rhs = ins->rhs();
   1580 
   1581  MOZ_ASSERT(lhs->type() == MIRType::Value);
   1582  MOZ_ASSERT(rhs->type() == MIRType::Value);
   1583 
   1584  auto* lir = new (alloc()) LSameValue(useBox(lhs), useBox(rhs));
   1585  define(lir, ins);
   1586  assignSafepoint(lir, ins);
   1587 }
   1588 
   1589 void LIRGenerator::lowerBitOp(JSOp op, MBinaryInstruction* ins) {
   1590  MDefinition* lhs = ins->getOperand(0);
   1591  MDefinition* rhs = ins->getOperand(1);
   1592  MOZ_ASSERT(IsIntType(ins->type()));
   1593 
   1594  if (ins->type() == MIRType::Int32) {
   1595    MOZ_ASSERT(lhs->type() == MIRType::Int32);
   1596    MOZ_ASSERT(rhs->type() == MIRType::Int32);
   1597    ReorderCommutative(&lhs, &rhs, ins);
   1598    lowerForALU(new (alloc()) LBitOpI(op), ins, lhs, rhs);
   1599    return;
   1600  }
   1601 
   1602  if (ins->type() == MIRType::Int64) {
   1603    MOZ_ASSERT(lhs->type() == MIRType::Int64);
   1604    MOZ_ASSERT(rhs->type() == MIRType::Int64);
   1605    ReorderCommutative(&lhs, &rhs, ins);
   1606    lowerForALUInt64(new (alloc()) LBitOpI64(op), ins, lhs, rhs);
   1607    return;
   1608  }
   1609 
   1610  MOZ_CRASH("Unhandled integer specialization");
   1611 }
   1612 
   1613 void LIRGenerator::visitTypeOf(MTypeOf* ins) {
   1614  MDefinition* opd = ins->input();
   1615 
   1616  if (opd->type() == MIRType::Object) {
   1617    auto* lir = new (alloc()) LTypeOfO(useRegister(opd));
   1618    define(lir, ins);
   1619    return;
   1620  }
   1621 
   1622  MOZ_ASSERT(opd->type() == MIRType::Value);
   1623 
   1624  LTypeOfV* lir = new (alloc()) LTypeOfV(useBox(opd), tempToUnbox());
   1625  define(lir, ins);
   1626 }
   1627 
   1628 void LIRGenerator::visitTypeOfName(MTypeOfName* ins) {
   1629  MDefinition* input = ins->input();
   1630  MOZ_ASSERT(input->type() == MIRType::Int32);
   1631 
   1632  auto* lir = new (alloc()) LTypeOfName(useRegister(input));
   1633  define(lir, ins);
   1634 }
   1635 
   1636 void LIRGenerator::visitTypeOfIs(MTypeOfIs* ins) {
   1637  MDefinition* input = ins->input();
   1638 
   1639  MOZ_ASSERT(input->type() == MIRType::Object ||
   1640             input->type() == MIRType::Value);
   1641 
   1642  switch (ins->jstype()) {
   1643    case JSTYPE_UNDEFINED:
   1644    case JSTYPE_OBJECT:
   1645    case JSTYPE_FUNCTION: {
   1646      if (input->type() == MIRType::Object) {
   1647        auto* lir = new (alloc()) LTypeOfIsNonPrimitiveO(useRegister(input));
   1648        define(lir, ins);
   1649      } else {
   1650        auto* lir =
   1651            new (alloc()) LTypeOfIsNonPrimitiveV(useBox(input), tempToUnbox());
   1652        define(lir, ins);
   1653      }
   1654      return;
   1655    }
   1656 
   1657    case JSTYPE_STRING:
   1658    case JSTYPE_NUMBER:
   1659    case JSTYPE_BOOLEAN:
   1660    case JSTYPE_SYMBOL:
   1661    case JSTYPE_BIGINT: {
   1662      MOZ_ASSERT(input->type() == MIRType::Value);
   1663 
   1664      auto* lir = new (alloc()) LTypeOfIsPrimitive(useBoxAtStart(input));
   1665      define(lir, ins);
   1666      return;
   1667    }
   1668 
   1669    case JSTYPE_LIMIT:
   1670      break;
   1671  }
   1672  MOZ_CRASH("Unhandled JSType");
   1673 }
   1674 
   1675 void LIRGenerator::visitToAsyncIter(MToAsyncIter* ins) {
   1676  LToAsyncIter* lir = new (alloc()) LToAsyncIter(
   1677      useRegisterAtStart(ins->iterator()), useBoxAtStart(ins->nextMethod()));
   1678  defineReturn(lir, ins);
   1679  assignSafepoint(lir, ins);
   1680 }
   1681 
   1682 void LIRGenerator::visitToPropertyKeyCache(MToPropertyKeyCache* ins) {
   1683  MDefinition* input = ins->getOperand(0);
   1684  MOZ_ASSERT(ins->type() == MIRType::Value);
   1685 
   1686  auto* lir = new (alloc()) LToPropertyKeyCache(useBox(input));
   1687  defineBox(lir, ins);
   1688  assignSafepoint(lir, ins);
   1689 }
   1690 
   1691 void LIRGenerator::visitBitNot(MBitNot* ins) {
   1692  MDefinition* input = ins->getOperand(0);
   1693 
   1694  if (ins->type() == MIRType::Int32) {
   1695    MOZ_ASSERT(input->type() == MIRType::Int32);
   1696    lowerForALU(new (alloc()) LBitNotI(), ins, input);
   1697    return;
   1698  }
   1699 
   1700  if (ins->type() == MIRType::Int64) {
   1701    MOZ_ASSERT(input->type() == MIRType::Int64);
   1702    lowerForALUInt64(new (alloc()) LBitNotI64(), ins, input);
   1703    return;
   1704  }
   1705 
   1706  MOZ_CRASH("Unhandled integer specialization");
   1707 }
   1708 
   1709 static bool CanEmitBitAndAtUses(MInstruction* ins) {
   1710  if (!ins->canEmitAtUses()) {
   1711    return false;
   1712  }
   1713 
   1714  MIRType tyL = ins->getOperand(0)->type();
   1715  MIRType tyR = ins->getOperand(1)->type();
   1716  if (tyL != tyR || (tyL != MIRType::Int32 && tyL != MIRType::Int64)) {
   1717    return false;
   1718  }
   1719 
   1720  MUseIterator iter(ins->usesBegin());
   1721  if (iter == ins->usesEnd()) {
   1722    return false;
   1723  }
   1724 
   1725  MNode* node = iter->consumer();
   1726  if (!node->isDefinition() || !node->toDefinition()->isInstruction()) {
   1727    return false;
   1728  }
   1729 
   1730  MInstruction* use = node->toDefinition()->toInstruction();
   1731  if (!use->isTest() && !(use->isCompare() && CanEmitCompareAtUses(use))) {
   1732    return false;
   1733  }
   1734 
   1735  iter++;
   1736  return iter == ins->usesEnd();
   1737 }
   1738 
   1739 void LIRGenerator::visitBitAnd(MBitAnd* ins) {
   1740  // Sniff out if the output of this bitand is used only for a branching.
   1741  // If it is, then we will emit an LBitAndAndBranch instruction in place
   1742  // of this bitand and any test that uses this bitand. Thus, we can
   1743  // ignore this BitAnd.
   1744  if (CanEmitBitAndAtUses(ins)) {
   1745    emitAtUses(ins);
   1746  } else {
   1747    lowerBitOp(JSOp::BitAnd, ins);
   1748  }
   1749 }
   1750 
   1751 void LIRGenerator::visitBitOr(MBitOr* ins) { lowerBitOp(JSOp::BitOr, ins); }
   1752 
   1753 void LIRGenerator::visitBitXor(MBitXor* ins) { lowerBitOp(JSOp::BitXor, ins); }
   1754 
   1755 void LIRGenerator::visitWasmBinaryBitwise(MWasmBinaryBitwise* ins) {
   1756  switch (ins->subOpcode()) {
   1757    case MWasmBinaryBitwise::SubOpcode::And:
   1758      if (CanEmitBitAndAtUses(ins)) {
   1759        emitAtUses(ins);
   1760      } else {
   1761        lowerBitOp(JSOp::BitAnd, ins);
   1762      }
   1763      break;
   1764    case MWasmBinaryBitwise::SubOpcode::Or:
   1765      lowerBitOp(JSOp::BitOr, ins);
   1766      break;
   1767    case MWasmBinaryBitwise::SubOpcode::Xor:
   1768      lowerBitOp(JSOp::BitXor, ins);
   1769      break;
   1770    default:
   1771      MOZ_CRASH();
   1772  }
   1773 }
   1774 
   1775 void LIRGenerator::lowerShiftOp(JSOp op, MShiftInstruction* ins) {
   1776  MDefinition* lhs = ins->getOperand(0);
   1777  MDefinition* rhs = ins->getOperand(1);
   1778 
   1779  if (op == JSOp::Ursh && ins->type() == MIRType::Double) {
   1780    MOZ_ASSERT(lhs->type() == MIRType::Int32);
   1781    MOZ_ASSERT(rhs->type() == MIRType::Int32);
   1782    lowerUrshD(ins->toUrsh());
   1783    return;
   1784  }
   1785 
   1786  MOZ_ASSERT(IsIntType(ins->type()));
   1787 
   1788  if (ins->type() == MIRType::Int32) {
   1789    MOZ_ASSERT(lhs->type() == MIRType::Int32);
   1790    MOZ_ASSERT(rhs->type() == MIRType::Int32);
   1791 
   1792    LShiftI* lir = new (alloc()) LShiftI(op);
   1793    if (op == JSOp::Ursh) {
   1794      if (ins->toUrsh()->fallible()) {
   1795        assignSnapshot(lir, ins->bailoutKind());
   1796      }
   1797    }
   1798    lowerForShift(lir, ins, lhs, rhs);
   1799    return;
   1800  }
   1801 
   1802  if (ins->type() == MIRType::Int64) {
   1803    MOZ_ASSERT(lhs->type() == MIRType::Int64);
   1804    MOZ_ASSERT(rhs->type() == MIRType::Int64);
   1805    lowerForShiftInt64(new (alloc()) LShiftI64(op), ins, lhs, rhs);
   1806    return;
   1807  }
   1808 
   1809  if (ins->type() == MIRType::IntPtr) {
   1810    MOZ_ASSERT(lhs->type() == MIRType::IntPtr);
   1811    MOZ_ASSERT(rhs->type() == MIRType::IntPtr);
   1812    lowerForShift(new (alloc()) LShiftIntPtr(op), ins, lhs, rhs);
   1813    return;
   1814  }
   1815 
   1816  MOZ_CRASH("Unhandled integer specialization");
   1817 }
   1818 
   1819 void LIRGenerator::visitLsh(MLsh* ins) { lowerShiftOp(JSOp::Lsh, ins); }
   1820 
   1821 void LIRGenerator::visitRsh(MRsh* ins) { lowerShiftOp(JSOp::Rsh, ins); }
   1822 
   1823 void LIRGenerator::visitUrsh(MUrsh* ins) { lowerShiftOp(JSOp::Ursh, ins); }
   1824 
   1825 void LIRGenerator::visitSignExtendInt32(MSignExtendInt32* ins) {
   1826  LInstructionHelper<1, 1, 0>* lir;
   1827 
   1828  if (ins->mode() == MSignExtendInt32::Byte) {
   1829    lir =
   1830        new (alloc()) LSignExtendInt32(useByteOpRegisterAtStart(ins->input()));
   1831  } else {
   1832    lir = new (alloc()) LSignExtendInt32(useRegisterAtStart(ins->input()));
   1833  }
   1834 
   1835  define(lir, ins);
   1836 }
   1837 
   1838 void LIRGenerator::visitSignExtendIntPtr(MSignExtendIntPtr* ins) {
   1839  LInstructionHelper<1, 1, 0>* lir;
   1840 
   1841  if (ins->mode() == MSignExtendIntPtr::Byte) {
   1842    lir =
   1843        new (alloc()) LSignExtendIntPtr(useByteOpRegisterAtStart(ins->input()));
   1844  } else {
   1845    lir = new (alloc()) LSignExtendIntPtr(useRegisterAtStart(ins->input()));
   1846  }
   1847 
   1848  define(lir, ins);
   1849 }
   1850 
   1851 void LIRGenerator::visitRotate(MRotate* ins) {
   1852  MDefinition* input = ins->input();
   1853  MDefinition* count = ins->count();
   1854 
   1855  if (ins->type() == MIRType::Int32) {
   1856    auto* lir = new (alloc()) LRotate();
   1857    lowerForShift(lir, ins, input, count);
   1858  } else if (ins->type() == MIRType::Int64) {
   1859    auto* lir = new (alloc()) LRotateI64();
   1860    lowerForShiftInt64(lir, ins, input, count);
   1861  } else {
   1862    MOZ_CRASH("unexpected type in visitRotate");
   1863  }
   1864 }
   1865 
   1866 void LIRGenerator::visitFloor(MFloor* ins) {
   1867  MIRType type = ins->input()->type();
   1868  MOZ_ASSERT(IsFloatingPointType(type));
   1869 
   1870  LInstructionHelper<1, 1, 0>* lir;
   1871  if (type == MIRType::Double) {
   1872    lir = new (alloc()) LFloor(useRegister(ins->input()));
   1873  } else {
   1874    lir = new (alloc()) LFloorF(useRegister(ins->input()));
   1875  }
   1876 
   1877  assignSnapshot(lir, ins->bailoutKind());
   1878  define(lir, ins);
   1879 }
   1880 
   1881 void LIRGenerator::visitCeil(MCeil* ins) {
   1882  MIRType type = ins->input()->type();
   1883  MOZ_ASSERT(IsFloatingPointType(type));
   1884 
   1885  LInstructionHelper<1, 1, 0>* lir;
   1886  if (type == MIRType::Double) {
   1887    lir = new (alloc()) LCeil(useRegister(ins->input()));
   1888  } else {
   1889    lir = new (alloc()) LCeilF(useRegister(ins->input()));
   1890  }
   1891 
   1892  assignSnapshot(lir, ins->bailoutKind());
   1893  define(lir, ins);
   1894 }
   1895 
   1896 void LIRGenerator::visitRound(MRound* ins) {
   1897  MIRType type = ins->input()->type();
   1898  MOZ_ASSERT(IsFloatingPointType(type));
   1899 
   1900  LInstructionHelper<1, 1, 1>* lir;
   1901  if (type == MIRType::Double) {
   1902    lir = new (alloc()) LRound(useRegister(ins->input()), tempDouble());
   1903  } else {
   1904    lir = new (alloc()) LRoundF(useRegister(ins->input()), tempFloat32());
   1905  }
   1906 
   1907  assignSnapshot(lir, ins->bailoutKind());
   1908  define(lir, ins);
   1909 }
   1910 
   1911 void LIRGenerator::visitTrunc(MTrunc* ins) {
   1912  MIRType type = ins->input()->type();
   1913  MOZ_ASSERT(IsFloatingPointType(type));
   1914 
   1915  LInstructionHelper<1, 1, 0>* lir;
   1916  if (type == MIRType::Double) {
   1917    lir = new (alloc()) LTrunc(useRegister(ins->input()));
   1918  } else {
   1919    lir = new (alloc()) LTruncF(useRegister(ins->input()));
   1920  }
   1921 
   1922  assignSnapshot(lir, ins->bailoutKind());
   1923  define(lir, ins);
   1924 }
   1925 
   1926 void LIRGenerator::visitNearbyInt(MNearbyInt* ins) {
   1927  MIRType inputType = ins->input()->type();
   1928  MOZ_ASSERT(IsFloatingPointType(inputType));
   1929  MOZ_ASSERT(ins->type() == inputType);
   1930 
   1931  LInstructionHelper<1, 1, 0>* lir;
   1932  if (inputType == MIRType::Double) {
   1933    lir = new (alloc()) LNearbyInt(useRegisterAtStart(ins->input()));
   1934  } else {
   1935    lir = new (alloc()) LNearbyIntF(useRegisterAtStart(ins->input()));
   1936  }
   1937 
   1938  define(lir, ins);
   1939 }
   1940 
   1941 void LIRGenerator::visitRoundToDouble(MRoundToDouble* ins) {
   1942  MIRType inputType = ins->input()->type();
   1943  MOZ_ASSERT(IsFloatingPointType(inputType));
   1944  MOZ_ASSERT(ins->type() == inputType);
   1945 
   1946  LInstructionHelper<1, 1, 0>* lir;
   1947  if (inputType == MIRType::Double) {
   1948    lir = new (alloc()) LRoundToDouble(useRegister(ins->input()));
   1949  } else {
   1950    lir = new (alloc()) LRoundToFloat32(useRegister(ins->input()));
   1951  }
   1952 
   1953  define(lir, ins);
   1954 }
   1955 
   1956 void LIRGenerator::visitMinMax(MMinMax* ins) {
   1957  MDefinition* first = ins->getOperand(0);
   1958  MDefinition* second = ins->getOperand(1);
   1959 
   1960  ReorderCommutative(&first, &second, ins);
   1961 
   1962  LInstructionHelper<1, 2, 0>* lir;
   1963  switch (ins->type()) {
   1964    case MIRType::Int32:
   1965      lir = new (alloc())
   1966          LMinMaxI(useRegisterAtStart(first), useRegisterOrConstant(second));
   1967      break;
   1968    case MIRType::IntPtr:
   1969      lir = new (alloc()) LMinMaxIntPtr(useRegisterAtStart(first),
   1970                                        useRegisterOrConstant(second));
   1971      break;
   1972    case MIRType::Float32:
   1973      lir = new (alloc())
   1974          LMinMaxF(useRegisterAtStart(first), useRegister(second));
   1975      break;
   1976    case MIRType::Double:
   1977      lir = new (alloc())
   1978          LMinMaxD(useRegisterAtStart(first), useRegister(second));
   1979      break;
   1980    default:
   1981      MOZ_CRASH();
   1982  }
   1983 
   1984  // Input reuse is OK (for now) even on ARM64: floating min/max are fairly
   1985  // expensive due to SNaN -> QNaN conversion, and int min/max is for asm.js.
   1986  defineReuseInput(lir, ins, 0);
   1987 }
   1988 
   1989 void LIRGenerator::visitMinMaxArray(MMinMaxArray* ins) {
   1990  LInstructionHelper<1, 1, 3>* lir;
   1991  if (ins->type() == MIRType::Int32) {
   1992    lir = new (alloc())
   1993        LMinMaxArrayI(useRegisterAtStart(ins->array()), temp(), temp(), temp());
   1994  } else {
   1995    MOZ_ASSERT(ins->type() == MIRType::Double);
   1996    lir = new (alloc()) LMinMaxArrayD(useRegisterAtStart(ins->array()),
   1997                                      tempDouble(), temp(), temp());
   1998  }
   1999  assignSnapshot(lir, ins->bailoutKind());
   2000  define(lir, ins);
   2001 }
   2002 
   2003 void LIRGenerator::visitAbs(MAbs* ins) {
   2004  MDefinition* num = ins->input();
   2005  MOZ_ASSERT(IsNumberType(num->type()));
   2006 
   2007  switch (num->type()) {
   2008    case MIRType::Int32: {
   2009      auto* lir = new (alloc()) LAbsI;
   2010      // needed to handle abs(INT32_MIN)
   2011      if (ins->fallible()) {
   2012        assignSnapshot(lir, ins->bailoutKind());
   2013      }
   2014      lowerForALU(lir, ins, num);
   2015      break;
   2016    }
   2017    case MIRType::Float32:
   2018      lowerForFPU(new (alloc()) LAbsF, ins, num);
   2019      break;
   2020    case MIRType::Double:
   2021      lowerForFPU(new (alloc()) LAbsD, ins, num);
   2022      break;
   2023    default:
   2024      MOZ_CRASH();
   2025  }
   2026 }
   2027 
   2028 void LIRGenerator::visitClz(MClz* ins) {
   2029  MDefinition* num = ins->num();
   2030 
   2031  MOZ_ASSERT(IsIntType(ins->type()));
   2032 
   2033  if (ins->type() == MIRType::Int32) {
   2034    LClzI* lir = new (alloc()) LClzI(useRegisterAtStart(num));
   2035    define(lir, ins);
   2036    return;
   2037  }
   2038 
   2039  auto* lir = new (alloc()) LClzI64(useInt64RegisterAtStart(num));
   2040  defineInt64(lir, ins);
   2041 }
   2042 
   2043 void LIRGenerator::visitCtz(MCtz* ins) {
   2044  MDefinition* num = ins->num();
   2045 
   2046  MOZ_ASSERT(IsIntType(ins->type()));
   2047 
   2048  if (ins->type() == MIRType::Int32) {
   2049    LCtzI* lir = new (alloc()) LCtzI(useRegisterAtStart(num));
   2050    define(lir, ins);
   2051    return;
   2052  }
   2053 
   2054  auto* lir = new (alloc()) LCtzI64(useInt64RegisterAtStart(num));
   2055  defineInt64(lir, ins);
   2056 }
   2057 
   2058 void LIRGenerator::visitPopcnt(MPopcnt* ins) {
   2059  MDefinition* num = ins->num();
   2060 
   2061  MOZ_ASSERT(IsIntType(ins->type()));
   2062 
   2063  if (ins->type() == MIRType::Int32) {
   2064    LPopcntI* lir = new (alloc()) LPopcntI(useRegisterAtStart(num), temp());
   2065    define(lir, ins);
   2066    return;
   2067  }
   2068 
   2069  auto* lir = new (alloc()) LPopcntI64(useInt64RegisterAtStart(num), temp());
   2070  defineInt64(lir, ins);
   2071 }
   2072 
   2073 void LIRGenerator::visitSqrt(MSqrt* ins) {
   2074  MDefinition* num = ins->input();
   2075  MOZ_ASSERT(IsFloatingPointType(num->type()));
   2076 
   2077  LInstructionHelper<1, 1, 0>* lir;
   2078  if (num->type() == MIRType::Double) {
   2079    lir = new (alloc()) LSqrtD(useRegisterAtStart(num));
   2080  } else {
   2081    lir = new (alloc()) LSqrtF(useRegisterAtStart(num));
   2082  }
   2083  define(lir, ins);
   2084 }
   2085 
   2086 void LIRGenerator::visitAtan2(MAtan2* ins) {
   2087  MDefinition* y = ins->y();
   2088  MOZ_ASSERT(y->type() == MIRType::Double);
   2089 
   2090  MDefinition* x = ins->x();
   2091  MOZ_ASSERT(x->type() == MIRType::Double);
   2092 
   2093  LAtan2D* lir =
   2094      new (alloc()) LAtan2D(useRegisterAtStart(y), useRegisterAtStart(x));
   2095  defineReturn(lir, ins);
   2096 }
   2097 
   2098 void LIRGenerator::visitHypot(MHypot* ins) {
   2099  LHypot* lir = nullptr;
   2100  uint32_t length = ins->numOperands();
   2101  for (uint32_t i = 0; i < length; ++i) {
   2102    MOZ_ASSERT(ins->getOperand(i)->type() == MIRType::Double);
   2103  }
   2104 
   2105  switch (length) {
   2106    case 2:
   2107      lir = new (alloc()) LHypot(useRegisterAtStart(ins->getOperand(0)),
   2108                                 useRegisterAtStart(ins->getOperand(1)));
   2109      break;
   2110    case 3:
   2111      lir = new (alloc()) LHypot(useRegisterAtStart(ins->getOperand(0)),
   2112                                 useRegisterAtStart(ins->getOperand(1)),
   2113                                 useRegisterAtStart(ins->getOperand(2)));
   2114      break;
   2115    case 4:
   2116      lir = new (alloc()) LHypot(useRegisterAtStart(ins->getOperand(0)),
   2117                                 useRegisterAtStart(ins->getOperand(1)),
   2118                                 useRegisterAtStart(ins->getOperand(2)),
   2119                                 useRegisterAtStart(ins->getOperand(3)));
   2120      break;
   2121    default:
   2122      MOZ_CRASH("Unexpected number of arguments to LHypot.");
   2123  }
   2124 
   2125  defineReturn(lir, ins);
   2126 }
   2127 
   2128 void LIRGenerator::visitPow(MPow* ins) {
   2129  MDefinition* input = ins->input();
   2130  MDefinition* power = ins->power();
   2131 
   2132  if (ins->type() == MIRType::Int32) {
   2133    MOZ_ASSERT(input->type() == MIRType::Int32);
   2134    MOZ_ASSERT(power->type() == MIRType::Int32);
   2135 
   2136    if (input->isConstant()) {
   2137      // Restrict this optimization to |base <= 256| to avoid generating too
   2138      // many consecutive shift instructions.
   2139      int32_t base = input->toConstant()->toInt32();
   2140      if (2 <= base && base <= 256 && mozilla::IsPowerOfTwo(uint32_t(base))) {
   2141        lowerPowOfTwoI(ins);
   2142        return;
   2143      }
   2144    }
   2145 
   2146    auto* lir = new (alloc())
   2147        LPowII(useRegister(input), useRegister(power), temp(), temp());
   2148    assignSnapshot(lir, ins->bailoutKind());
   2149    define(lir, ins);
   2150    return;
   2151  }
   2152 
   2153  MOZ_ASSERT(ins->type() == MIRType::Double);
   2154  MOZ_ASSERT(input->type() == MIRType::Double);
   2155  MOZ_ASSERT(power->type() == MIRType::Int32 ||
   2156             power->type() == MIRType::Double);
   2157 
   2158  LInstruction* lir;
   2159  if (power->type() == MIRType::Int32) {
   2160    lir = new (alloc())
   2161        LPowI(useRegisterAtStart(input), useRegisterAtStart(power));
   2162  } else {
   2163    lir = new (alloc())
   2164        LPowD(useRegisterAtStart(input), useRegisterAtStart(power));
   2165  }
   2166  defineReturn(lir, ins);
   2167 }
   2168 
   2169 void LIRGenerator::visitPowHalf(MPowHalf* ins) {
   2170  MDefinition* input = ins->input();
   2171  MOZ_ASSERT(input->type() == MIRType::Double);
   2172  auto* lir = new (alloc()) LPowHalfD(useRegisterAtStart(input));
   2173  define(lir, ins);
   2174 }
   2175 
   2176 void LIRGenerator::visitSign(MSign* ins) {
   2177  MOZ_ASSERT(ins->type() == MIRType::Int32 || ins->type() == MIRType::Double);
   2178  MOZ_ASSERT(ins->input()->type() == MIRType::Int32 ||
   2179             ins->input()->type() == MIRType::Double);
   2180 
   2181  if (ins->type() == ins->input()->type()) {
   2182    if (ins->type() == MIRType::Int32) {
   2183      define(new (alloc()) LSignI(useRegister(ins->input())), ins);
   2184    } else {
   2185      define(new (alloc()) LSignD(useRegister(ins->input())), ins);
   2186    }
   2187  } else {
   2188    if (ins->type() == MIRType::Int32) {
   2189      auto* lir =
   2190          new (alloc()) LSignDI(useRegister(ins->input()), tempDouble());
   2191      assignSnapshot(lir, ins->bailoutKind());
   2192      define(lir, ins);
   2193    } else {
   2194      define(new (alloc()) LSignID(useRegister(ins->input()), temp()), ins);
   2195    }
   2196  }
   2197 }
   2198 
   2199 void LIRGenerator::visitMathFunction(MMathFunction* ins) {
   2200  MOZ_ASSERT(IsFloatingPointType(ins->type()));
   2201  MOZ_ASSERT(ins->type() == ins->input()->type());
   2202 
   2203  LInstruction* lir;
   2204  if (ins->type() == MIRType::Double) {
   2205    lir = new (alloc()) LMathFunctionD(useRegisterAtStart(ins->input()));
   2206  } else {
   2207    lir = new (alloc()) LMathFunctionF(useRegisterAtStart(ins->input()));
   2208  }
   2209  defineReturn(lir, ins);
   2210 }
   2211 
   2212 void LIRGenerator::visitRandom(MRandom* ins) {
   2213  auto* lir = new (alloc()) LRandom(temp(), tempInt64(), tempInt64());
   2214  define(lir, ins);
   2215 }
   2216 
   2217 // Try to mark an add or sub instruction as able to recover its input when
   2218 // bailing out.
   2219 template <typename S, typename T>
   2220 static void MaybeSetRecoversInput(S* mir, T* lir) {
   2221  MOZ_ASSERT(lir->mirRaw() == mir);
   2222  if (!mir->fallible() || !lir->snapshot()) {
   2223    return;
   2224  }
   2225 
   2226  if (lir->output()->policy() != LDefinition::MUST_REUSE_INPUT) {
   2227    return;
   2228  }
   2229 
   2230  // The original operands to an add or sub can't be recovered if they both
   2231  // use the same register.
   2232  if (lir->lhs()->isUse() && lir->rhs()->isUse() &&
   2233      lir->lhs()->toUse()->virtualRegister() ==
   2234          lir->rhs()->toUse()->virtualRegister()) {
   2235    return;
   2236  }
   2237 
   2238  // Add instructions that are on two different values can recover
   2239  // the input they clobbered via MUST_REUSE_INPUT. Thus, a copy
   2240  // of that input does not need to be kept alive in the snapshot
   2241  // for the instruction.
   2242 
   2243  lir->setRecoversInput();
   2244 
   2245  const LUse* input = lir->getOperand(lir->output()->getReusedInput())->toUse();
   2246  lir->snapshot()->rewriteRecoveredInput(*input);
   2247 }
   2248 
   2249 void LIRGenerator::visitAdd(MAdd* ins) {
   2250  MDefinition* lhs = ins->getOperand(0);
   2251  MDefinition* rhs = ins->getOperand(1);
   2252 
   2253  MOZ_ASSERT(lhs->type() == rhs->type());
   2254  MOZ_ASSERT(IsNumberType(ins->type()));
   2255 
   2256  if (ins->type() == MIRType::Int32) {
   2257    MOZ_ASSERT(lhs->type() == MIRType::Int32);
   2258    ReorderCommutative(&lhs, &rhs, ins);
   2259    LAddI* lir = new (alloc()) LAddI;
   2260 
   2261    if (ins->fallible()) {
   2262      assignSnapshot(lir, ins->bailoutKind());
   2263    }
   2264 
   2265    lowerForALU(lir, ins, lhs, rhs);
   2266    MaybeSetRecoversInput(ins, lir);
   2267    return;
   2268  }
   2269 
   2270  if (ins->type() == MIRType::Int64) {
   2271    MOZ_ASSERT(lhs->type() == MIRType::Int64);
   2272    ReorderCommutative(&lhs, &rhs, ins);
   2273    LAddI64* lir = new (alloc()) LAddI64;
   2274    lowerForALUInt64(lir, ins, lhs, rhs);
   2275    return;
   2276  }
   2277 
   2278  if (ins->type() == MIRType::IntPtr) {
   2279    MOZ_ASSERT(lhs->type() == MIRType::IntPtr);
   2280    ReorderCommutative(&lhs, &rhs, ins);
   2281 
   2282    auto* lir = new (alloc()) LAddIntPtr;
   2283    lowerForALU(lir, ins, lhs, rhs);
   2284    return;
   2285  }
   2286 
   2287  if (ins->type() == MIRType::Double) {
   2288    MOZ_ASSERT(lhs->type() == MIRType::Double);
   2289    ReorderCommutative(&lhs, &rhs, ins);
   2290    lowerForFPU(new (alloc()) LMathD(JSOp::Add), ins, lhs, rhs);
   2291    return;
   2292  }
   2293 
   2294  if (ins->type() == MIRType::Float32) {
   2295    MOZ_ASSERT(lhs->type() == MIRType::Float32);
   2296    ReorderCommutative(&lhs, &rhs, ins);
   2297    lowerForFPU(new (alloc()) LMathF(JSOp::Add), ins, lhs, rhs);
   2298    return;
   2299  }
   2300 
   2301  MOZ_CRASH("Unhandled number specialization");
   2302 }
   2303 
   2304 void LIRGenerator::visitSub(MSub* ins) {
   2305  MDefinition* lhs = ins->lhs();
   2306  MDefinition* rhs = ins->rhs();
   2307 
   2308  MOZ_ASSERT(lhs->type() == rhs->type());
   2309  MOZ_ASSERT(IsNumberType(ins->type()));
   2310 
   2311  if (ins->type() == MIRType::Int32) {
   2312    MOZ_ASSERT(lhs->type() == MIRType::Int32);
   2313 
   2314    // If our LHS is a constant 0 and we don't have to worry about results that
   2315    // can't be represented as an int32, we can optimize to an LNegI.
   2316    if (!ins->fallible() && lhs->isConstant() &&
   2317        lhs->toConstant()->toInt32() == 0) {
   2318      lowerForALU(new (alloc()) LNegI, ins, rhs);
   2319      return;
   2320    }
   2321 
   2322    LSubI* lir = new (alloc()) LSubI;
   2323    if (ins->fallible()) {
   2324      assignSnapshot(lir, ins->bailoutKind());
   2325    }
   2326 
   2327    lowerForALU(lir, ins, lhs, rhs);
   2328    MaybeSetRecoversInput(ins, lir);
   2329    return;
   2330  }
   2331 
   2332  if (ins->type() == MIRType::Int64) {
   2333    MOZ_ASSERT(lhs->type() == MIRType::Int64);
   2334 
   2335    // If our LHS is a constant 0, we can optimize to an LNegI64.
   2336    if (lhs->isConstant() && lhs->toConstant()->toInt64() == 0) {
   2337      lowerForALUInt64(new (alloc()) LNegI64, ins, rhs);
   2338      return;
   2339    }
   2340 
   2341    LSubI64* lir = new (alloc()) LSubI64;
   2342    lowerForALUInt64(lir, ins, lhs, rhs);
   2343    return;
   2344  }
   2345 
   2346  if (ins->type() == MIRType::IntPtr) {
   2347    MOZ_ASSERT(lhs->type() == MIRType::IntPtr);
   2348 
   2349    auto* lir = new (alloc()) LSubIntPtr;
   2350    lowerForALU(lir, ins, lhs, rhs);
   2351    return;
   2352  }
   2353 
   2354  if (ins->type() == MIRType::Double) {
   2355    MOZ_ASSERT(lhs->type() == MIRType::Double);
   2356    lowerForFPU(new (alloc()) LMathD(JSOp::Sub), ins, lhs, rhs);
   2357    return;
   2358  }
   2359 
   2360  if (ins->type() == MIRType::Float32) {
   2361    MOZ_ASSERT(lhs->type() == MIRType::Float32);
   2362    lowerForFPU(new (alloc()) LMathF(JSOp::Sub), ins, lhs, rhs);
   2363    return;
   2364  }
   2365 
   2366  MOZ_CRASH("Unhandled number specialization");
   2367 }
   2368 
   2369 void LIRGenerator::visitMul(MMul* ins) {
   2370  MDefinition* lhs = ins->lhs();
   2371  MDefinition* rhs = ins->rhs();
   2372  MOZ_ASSERT(lhs->type() == rhs->type());
   2373  MOZ_ASSERT(IsNumberType(ins->type()));
   2374 
   2375  if (ins->type() == MIRType::Int32) {
   2376    MOZ_ASSERT(lhs->type() == MIRType::Int32);
   2377    ReorderCommutative(&lhs, &rhs, ins);
   2378 
   2379    // If our RHS is a constant -1 and we don't have to worry about results that
   2380    // can't be represented as an int32, we can optimize to an LNegI.
   2381    if (!ins->fallible() && rhs->isConstant() &&
   2382        rhs->toConstant()->toInt32() == -1) {
   2383      lowerForALU(new (alloc()) LNegI, ins, lhs);
   2384      return;
   2385    }
   2386 
   2387    lowerMulI(ins, lhs, rhs);
   2388    return;
   2389  }
   2390 
   2391  if (ins->type() == MIRType::Int64) {
   2392    MOZ_ASSERT(lhs->type() == MIRType::Int64);
   2393    ReorderCommutative(&lhs, &rhs, ins);
   2394 
   2395    // If our RHS is a constant -1, we can optimize to an LNegI64.
   2396    if (rhs->isConstant() && rhs->toConstant()->toInt64() == -1) {
   2397      lowerForALUInt64(new (alloc()) LNegI64, ins, lhs);
   2398      return;
   2399    }
   2400 
   2401    LMulI64* lir = new (alloc()) LMulI64;
   2402    lowerForMulInt64(lir, ins, lhs, rhs);
   2403    return;
   2404  }
   2405 
   2406  if (ins->type() == MIRType::IntPtr) {
   2407    MOZ_ASSERT(lhs->type() == MIRType::IntPtr);
   2408    ReorderCommutative(&lhs, &rhs, ins);
   2409 
   2410    auto* lir = new (alloc()) LMulIntPtr;
   2411    lowerForALU(lir, ins, lhs, rhs);
   2412    return;
   2413  }
   2414 
   2415  if (ins->type() == MIRType::Double) {
   2416    MOZ_ASSERT(lhs->type() == MIRType::Double);
   2417    ReorderCommutative(&lhs, &rhs, ins);
   2418 
   2419    // If our RHS is a constant -1.0, we can optimize to an LNegD.
   2420    if (!ins->mustPreserveNaN() && rhs->isConstant() &&
   2421        rhs->toConstant()->toDouble() == -1.0) {
   2422      lowerForFPU(new (alloc()) LNegD, ins, lhs);
   2423      return;
   2424    }
   2425 
   2426    lowerForFPU(new (alloc()) LMathD(JSOp::Mul), ins, lhs, rhs);
   2427    return;
   2428  }
   2429 
   2430  if (ins->type() == MIRType::Float32) {
   2431    MOZ_ASSERT(lhs->type() == MIRType::Float32);
   2432    ReorderCommutative(&lhs, &rhs, ins);
   2433 
   2434    // We apply the same optimizations as for doubles
   2435    if (!ins->mustPreserveNaN() && rhs->isConstant() &&
   2436        rhs->toConstant()->toFloat32() == -1.0f) {
   2437      lowerForFPU(new (alloc()) LNegF, ins, lhs);
   2438      return;
   2439    }
   2440 
   2441    lowerForFPU(new (alloc()) LMathF(JSOp::Mul), ins, lhs, rhs);
   2442    return;
   2443  }
   2444 
   2445  MOZ_CRASH("Unhandled number specialization");
   2446 }
   2447 
   2448 void LIRGenerator::visitWasmNeg(MWasmNeg* ins) {
   2449  switch (ins->type()) {
   2450    case MIRType::Int32:
   2451      lowerForALU(new (alloc()) LNegI, ins, ins->input());
   2452      break;
   2453    case MIRType::Float32:
   2454      lowerForFPU(new (alloc()) LNegF, ins, ins->input());
   2455      break;
   2456    case MIRType::Double:
   2457      lowerForFPU(new (alloc()) LNegD, ins, ins->input());
   2458      break;
   2459    default:
   2460      MOZ_CRASH();
   2461  }
   2462 }
   2463 
   2464 void LIRGenerator::visitDiv(MDiv* ins) {
   2465  MDefinition* lhs = ins->lhs();
   2466  MDefinition* rhs = ins->rhs();
   2467  MOZ_ASSERT(lhs->type() == rhs->type());
   2468  MOZ_ASSERT(IsNumberType(ins->type()));
   2469 
   2470  if (ins->type() == MIRType::Int32) {
   2471    MOZ_ASSERT(lhs->type() == MIRType::Int32);
   2472    if (ins->isUnsigned()) {
   2473      lowerUDiv(ins);
   2474    } else {
   2475      lowerDivI(ins);
   2476    }
   2477    return;
   2478  }
   2479 
   2480  if (ins->type() == MIRType::Int64) {
   2481    MOZ_ASSERT(lhs->type() == MIRType::Int64);
   2482    if (ins->isUnsigned()) {
   2483      lowerUDivI64(ins);
   2484    } else {
   2485      lowerDivI64(ins);
   2486    }
   2487    return;
   2488  }
   2489 
   2490  if (ins->type() == MIRType::Double) {
   2491    MOZ_ASSERT(lhs->type() == MIRType::Double);
   2492    lowerForFPU(new (alloc()) LMathD(JSOp::Div), ins, lhs, rhs);
   2493    return;
   2494  }
   2495 
   2496  if (ins->type() == MIRType::Float32) {
   2497    MOZ_ASSERT(lhs->type() == MIRType::Float32);
   2498    lowerForFPU(new (alloc()) LMathF(JSOp::Div), ins, lhs, rhs);
   2499    return;
   2500  }
   2501 
   2502  MOZ_CRASH("Unhandled number specialization");
   2503 }
   2504 
   2505 void LIRGenerator::visitWasmBuiltinDivI64(MWasmBuiltinDivI64* div) {
   2506  lowerWasmBuiltinDivI64(div);
   2507 }
   2508 
   2509 void LIRGenerator::visitWasmBuiltinModI64(MWasmBuiltinModI64* mod) {
   2510  lowerWasmBuiltinModI64(mod);
   2511 }
   2512 
   2513 void LIRGenerator::visitBuiltinInt64ToFloatingPoint(
   2514    MBuiltinInt64ToFloatingPoint* ins) {
   2515  lowerBuiltinInt64ToFloatingPoint(ins);
   2516 }
   2517 
   2518 void LIRGenerator::visitWasmBuiltinTruncateToInt64(
   2519    MWasmBuiltinTruncateToInt64* ins) {
   2520  lowerWasmBuiltinTruncateToInt64(ins);
   2521 }
   2522 
   2523 void LIRGenerator::visitWasmBuiltinModD(MWasmBuiltinModD* ins) {
   2524  MOZ_ASSERT(gen->compilingWasm());
   2525  LWasmBuiltinModD* lir = new (alloc()) LWasmBuiltinModD(
   2526      useRegisterAtStart(ins->lhs()), useRegisterAtStart(ins->rhs()),
   2527      useFixedAtStart(ins->instance(), InstanceReg));
   2528  defineReturn(lir, ins);
   2529 }
   2530 
   2531 void LIRGenerator::visitMod(MMod* ins) {
   2532  MOZ_ASSERT(ins->lhs()->type() == ins->rhs()->type());
   2533  MOZ_ASSERT(IsNumberType(ins->type()));
   2534 
   2535  if (ins->type() == MIRType::Int32) {
   2536    MOZ_ASSERT(ins->type() == MIRType::Int32);
   2537    MOZ_ASSERT(ins->lhs()->type() == MIRType::Int32);
   2538    if (ins->isUnsigned()) {
   2539      lowerUMod(ins);
   2540    } else {
   2541      lowerModI(ins);
   2542    }
   2543    return;
   2544  }
   2545 
   2546  if (ins->type() == MIRType::Int64) {
   2547    MOZ_ASSERT(ins->type() == MIRType::Int64);
   2548    MOZ_ASSERT(ins->lhs()->type() == MIRType::Int64);
   2549    if (ins->isUnsigned()) {
   2550      lowerUModI64(ins);
   2551    } else {
   2552      lowerModI64(ins);
   2553    }
   2554    return;
   2555  }
   2556 
   2557  if (ins->type() == MIRType::Double) {
   2558    MOZ_ASSERT(ins->lhs()->type() == MIRType::Double);
   2559    MOZ_ASSERT(ins->rhs()->type() == MIRType::Double);
   2560 
   2561    MOZ_ASSERT(!gen->compilingWasm());
   2562 
   2563    if (Assembler::HasRoundInstruction(RoundingMode::TowardsZero)) {
   2564      if (ins->rhs()->isConstant()) {
   2565        double d = ins->rhs()->toConstant()->toDouble();
   2566        int32_t div;
   2567        if (mozilla::NumberIsInt32(d, &div) && div > 0 &&
   2568            mozilla::IsPowerOfTwo(uint32_t(div))) {
   2569          auto* lir = new (alloc()) LModPowTwoD(useRegister(ins->lhs()), div);
   2570          define(lir, ins);
   2571          return;
   2572        }
   2573      }
   2574    }
   2575 
   2576    LModD* lir = new (alloc())
   2577        LModD(useRegisterAtStart(ins->lhs()), useRegisterAtStart(ins->rhs()));
   2578    defineReturn(lir, ins);
   2579    return;
   2580  }
   2581 
   2582  MOZ_CRASH("Unhandled number specialization");
   2583 }
   2584 
   2585 void LIRGenerator::visitBigIntAdd(MBigIntAdd* ins) {
   2586  auto* lir = new (alloc()) LBigIntAdd(useRegisterAtStart(ins->lhs()),
   2587                                       useRegisterAtStart(ins->rhs()));
   2588  defineReturn(lir, ins);
   2589  assignSafepoint(lir, ins);
   2590 }
   2591 
   2592 void LIRGenerator::visitBigIntSub(MBigIntSub* ins) {
   2593  auto* lir = new (alloc()) LBigIntSub(useRegisterAtStart(ins->lhs()),
   2594                                       useRegisterAtStart(ins->rhs()));
   2595  defineReturn(lir, ins);
   2596  assignSafepoint(lir, ins);
   2597 }
   2598 
   2599 void LIRGenerator::visitBigIntMul(MBigIntMul* ins) {
   2600  auto* lir = new (alloc()) LBigIntMul(useRegisterAtStart(ins->lhs()),
   2601                                       useRegisterAtStart(ins->rhs()));
   2602  defineReturn(lir, ins);
   2603  assignSafepoint(lir, ins);
   2604 }
   2605 
   2606 void LIRGenerator::visitBigIntDiv(MBigIntDiv* ins) {
   2607  auto* lir = new (alloc()) LBigIntDiv(useRegisterAtStart(ins->lhs()),
   2608                                       useRegisterAtStart(ins->rhs()));
   2609  defineReturn(lir, ins);
   2610  assignSafepoint(lir, ins);
   2611 }
   2612 
   2613 void LIRGenerator::visitBigIntMod(MBigIntMod* ins) {
   2614  auto* lir = new (alloc()) LBigIntMod(useRegisterAtStart(ins->lhs()),
   2615                                       useRegisterAtStart(ins->rhs()));
   2616  defineReturn(lir, ins);
   2617  assignSafepoint(lir, ins);
   2618 }
   2619 
   2620 void LIRGenerator::visitBigIntPow(MBigIntPow* ins) {
   2621  auto* lir = new (alloc()) LBigIntPow(useRegisterAtStart(ins->lhs()),
   2622                                       useRegisterAtStart(ins->rhs()));
   2623  defineReturn(lir, ins);
   2624  assignSafepoint(lir, ins);
   2625 }
   2626 
   2627 void LIRGenerator::visitBigIntBitAnd(MBigIntBitAnd* ins) {
   2628  auto* lir = new (alloc()) LBigIntBitAnd(useRegisterAtStart(ins->lhs()),
   2629                                          useRegisterAtStart(ins->rhs()));
   2630  defineReturn(lir, ins);
   2631  assignSafepoint(lir, ins);
   2632 }
   2633 
   2634 void LIRGenerator::visitBigIntBitOr(MBigIntBitOr* ins) {
   2635  auto* lir = new (alloc()) LBigIntBitOr(useRegisterAtStart(ins->lhs()),
   2636                                         useRegisterAtStart(ins->rhs()));
   2637  defineReturn(lir, ins);
   2638  assignSafepoint(lir, ins);
   2639 }
   2640 
   2641 void LIRGenerator::visitBigIntBitXor(MBigIntBitXor* ins) {
   2642  auto* lir = new (alloc()) LBigIntBitXor(useRegisterAtStart(ins->lhs()),
   2643                                          useRegisterAtStart(ins->rhs()));
   2644  defineReturn(lir, ins);
   2645  assignSafepoint(lir, ins);
   2646 }
   2647 
   2648 void LIRGenerator::visitBigIntLsh(MBigIntLsh* ins) {
   2649  auto* lir = new (alloc()) LBigIntLsh(useRegisterAtStart(ins->lhs()),
   2650                                       useRegisterAtStart(ins->rhs()));
   2651  defineReturn(lir, ins);
   2652  assignSafepoint(lir, ins);
   2653 }
   2654 
   2655 void LIRGenerator::visitBigIntRsh(MBigIntRsh* ins) {
   2656  auto* lir = new (alloc()) LBigIntRsh(useRegisterAtStart(ins->lhs()),
   2657                                       useRegisterAtStart(ins->rhs()));
   2658  defineReturn(lir, ins);
   2659  assignSafepoint(lir, ins);
   2660 }
   2661 
   2662 void LIRGenerator::visitBigIntIncrement(MBigIntIncrement* ins) {
   2663  auto* lir = new (alloc()) LBigIntIncrement(useRegisterAtStart(ins->input()));
   2664  defineReturn(lir, ins);
   2665  assignSafepoint(lir, ins);
   2666 }
   2667 
   2668 void LIRGenerator::visitBigIntDecrement(MBigIntDecrement* ins) {
   2669  auto* lir = new (alloc()) LBigIntDecrement(useRegisterAtStart(ins->input()));
   2670  defineReturn(lir, ins);
   2671  assignSafepoint(lir, ins);
   2672 }
   2673 
   2674 void LIRGenerator::visitBigIntNegate(MBigIntNegate* ins) {
   2675  auto* lir = new (alloc()) LBigIntNegate(useRegister(ins->input()), temp());
   2676  define(lir, ins);
   2677  assignSafepoint(lir, ins);
   2678 }
   2679 
   2680 void LIRGenerator::visitBigIntBitNot(MBigIntBitNot* ins) {
   2681  auto* lir = new (alloc()) LBigIntBitNot(useRegisterAtStart(ins->input()));
   2682  defineReturn(lir, ins);
   2683  assignSafepoint(lir, ins);
   2684 }
   2685 
   2686 void LIRGenerator::visitBigIntToIntPtr(MBigIntToIntPtr* ins) {
   2687  MOZ_ASSERT(ins->input()->type() == MIRType::BigInt);
   2688 
   2689  auto* lir = new (alloc()) LBigIntToIntPtr(useRegister(ins->input()));
   2690  assignSnapshot(lir, ins->bailoutKind());
   2691  define(lir, ins);
   2692 }
   2693 
   2694 void LIRGenerator::visitIntPtrToBigInt(MIntPtrToBigInt* ins) {
   2695  MOZ_ASSERT(ins->input()->type() == MIRType::IntPtr);
   2696 
   2697  auto* lir = new (alloc()) LIntPtrToBigInt(useRegister(ins->input()), temp());
   2698  define(lir, ins);
   2699  assignSafepoint(lir, ins);
   2700 }
   2701 
   2702 void LIRGenerator::visitBigIntPtrAdd(MBigIntPtrAdd* ins) {
   2703  MOZ_ASSERT(ins->lhs()->type() == MIRType::IntPtr);
   2704  MOZ_ASSERT(ins->rhs()->type() == MIRType::IntPtr);
   2705 
   2706  MDefinition* lhs = ins->lhs();
   2707  MDefinition* rhs = ins->rhs();
   2708  ReorderCommutative(&lhs, &rhs, ins);
   2709 
   2710  auto* lir =
   2711      new (alloc()) LBigIntPtrAdd(useRegister(lhs), useRegisterOrConstant(rhs));
   2712  assignSnapshot(lir, ins->bailoutKind());
   2713  define(lir, ins);
   2714 }
   2715 
   2716 void LIRGenerator::visitBigIntPtrSub(MBigIntPtrSub* ins) {
   2717  MOZ_ASSERT(ins->lhs()->type() == MIRType::IntPtr);
   2718  MOZ_ASSERT(ins->rhs()->type() == MIRType::IntPtr);
   2719 
   2720  auto* lir = new (alloc())
   2721      LBigIntPtrSub(useRegister(ins->lhs()), useRegister(ins->rhs()));
   2722  assignSnapshot(lir, ins->bailoutKind());
   2723  define(lir, ins);
   2724 }
   2725 
   2726 void LIRGenerator::visitBigIntPtrMul(MBigIntPtrMul* ins) {
   2727  MOZ_ASSERT(ins->lhs()->type() == MIRType::IntPtr);
   2728  MOZ_ASSERT(ins->rhs()->type() == MIRType::IntPtr);
   2729 
   2730  MDefinition* lhs = ins->lhs();
   2731  MDefinition* rhs = ins->rhs();
   2732  ReorderCommutative(&lhs, &rhs, ins);
   2733 
   2734  auto* lir =
   2735      new (alloc()) LBigIntPtrMul(useRegister(lhs), useRegisterOrConstant(rhs));
   2736  assignSnapshot(lir, ins->bailoutKind());
   2737  define(lir, ins);
   2738 }
   2739 
   2740 void LIRGenerator::visitBigIntPtrDiv(MBigIntPtrDiv* ins) {
   2741  MOZ_ASSERT(ins->lhs()->type() == MIRType::IntPtr);
   2742  MOZ_ASSERT(ins->rhs()->type() == MIRType::IntPtr);
   2743 
   2744  if (ins->rhs()->isConstant()) {
   2745    intptr_t rhs = ins->rhs()->toConstant()->toIntPtr();
   2746    if (mozilla::IsPowerOfTwo(mozilla::Abs(rhs))) {
   2747      int32_t shift = mozilla::FloorLog2(mozilla::Abs(rhs));
   2748      auto* lir = new (alloc())
   2749          LBigIntPtrDivPowTwo(useRegister(ins->lhs()), shift, rhs < 0);
   2750      if (shift == 0 && rhs < 0) {
   2751        assignSnapshot(lir, ins->bailoutKind());
   2752      }
   2753      define(lir, ins);
   2754      return;
   2755    }
   2756  }
   2757 
   2758  lowerBigIntPtrDiv(ins);
   2759 }
   2760 
   2761 void LIRGenerator::visitBigIntPtrMod(MBigIntPtrMod* ins) {
   2762  MOZ_ASSERT(ins->lhs()->type() == MIRType::IntPtr);
   2763  MOZ_ASSERT(ins->rhs()->type() == MIRType::IntPtr);
   2764 
   2765  if (ins->rhs()->isConstant()) {
   2766    intptr_t rhs = ins->rhs()->toConstant()->toIntPtr();
   2767    if (mozilla::IsPowerOfTwo(mozilla::Abs(rhs))) {
   2768      int32_t shift = mozilla::FloorLog2(mozilla::Abs(rhs));
   2769      auto* lir = new (alloc())
   2770          LBigIntPtrModPowTwo(useRegister(ins->lhs()), temp(), shift);
   2771      define(lir, ins);
   2772      return;
   2773    }
   2774  }
   2775 
   2776  lowerBigIntPtrMod(ins);
   2777 }
   2778 
   2779 void LIRGenerator::visitBigIntPtrPow(MBigIntPtrPow* ins) {
   2780  MOZ_ASSERT(ins->lhs()->type() == MIRType::IntPtr);
   2781  MOZ_ASSERT(ins->rhs()->type() == MIRType::IntPtr);
   2782 
   2783  auto* lir = new (alloc()) LBigIntPtrPow(
   2784      useRegister(ins->lhs()), useRegister(ins->rhs()), temp(), temp());
   2785  assignSnapshot(lir, ins->bailoutKind());
   2786  define(lir, ins);
   2787 }
   2788 
   2789 void LIRGenerator::visitBigIntPtrBitAnd(MBigIntPtrBitAnd* ins) {
   2790  MOZ_ASSERT(ins->lhs()->type() == MIRType::IntPtr);
   2791  MOZ_ASSERT(ins->rhs()->type() == MIRType::IntPtr);
   2792 
   2793  MDefinition* lhs = ins->lhs();
   2794  MDefinition* rhs = ins->rhs();
   2795  ReorderCommutative(&lhs, &rhs, ins);
   2796 
   2797  auto* lir = new (alloc())
   2798      LBigIntPtrBitAnd(useRegister(lhs), useRegisterOrConstant(rhs));
   2799  define(lir, ins);
   2800 }
   2801 
   2802 void LIRGenerator::visitBigIntPtrBitOr(MBigIntPtrBitOr* ins) {
   2803  MOZ_ASSERT(ins->lhs()->type() == MIRType::IntPtr);
   2804  MOZ_ASSERT(ins->rhs()->type() == MIRType::IntPtr);
   2805 
   2806  MDefinition* lhs = ins->lhs();
   2807  MDefinition* rhs = ins->rhs();
   2808  ReorderCommutative(&lhs, &rhs, ins);
   2809 
   2810  auto* lir = new (alloc())
   2811      LBigIntPtrBitOr(useRegister(lhs), useRegisterOrConstant(rhs));
   2812  define(lir, ins);
   2813 }
   2814 
   2815 void LIRGenerator::visitBigIntPtrBitXor(MBigIntPtrBitXor* ins) {
   2816  MOZ_ASSERT(ins->lhs()->type() == MIRType::IntPtr);
   2817  MOZ_ASSERT(ins->rhs()->type() == MIRType::IntPtr);
   2818 
   2819  MDefinition* lhs = ins->lhs();
   2820  MDefinition* rhs = ins->rhs();
   2821  ReorderCommutative(&lhs, &rhs, ins);
   2822 
   2823  auto* lir = new (alloc())
   2824      LBigIntPtrBitXor(useRegister(lhs), useRegisterOrConstant(rhs));
   2825  define(lir, ins);
   2826 }
   2827 
   2828 void LIRGenerator::visitBigIntPtrLsh(MBigIntPtrLsh* ins) {
   2829  MOZ_ASSERT(ins->lhs()->type() == MIRType::IntPtr);
   2830  MOZ_ASSERT(ins->rhs()->type() == MIRType::IntPtr);
   2831 
   2832  if (ins->rhs()->isConstant()) {
   2833    // Need an additional temp when the operation is fallible.
   2834    auto tmp = ins->fallible() ? temp() : LDefinition::BogusTemp();
   2835 
   2836    auto* lir = new (alloc()) LBigIntPtrLsh(useRegister(ins->lhs()),
   2837                                            useRegisterOrConstant(ins->rhs()),
   2838                                            tmp, LDefinition::BogusTemp());
   2839    if (ins->fallible()) {
   2840      assignSnapshot(lir, ins->bailoutKind());
   2841    }
   2842    define(lir, ins);
   2843    return;
   2844  }
   2845 
   2846  lowerBigIntPtrLsh(ins);
   2847 }
   2848 
   2849 void LIRGenerator::visitBigIntPtrRsh(MBigIntPtrRsh* ins) {
   2850  MOZ_ASSERT(ins->lhs()->type() == MIRType::IntPtr);
   2851  MOZ_ASSERT(ins->rhs()->type() == MIRType::IntPtr);
   2852 
   2853  if (ins->rhs()->isConstant()) {
   2854    // Need an additional temp when the operation is fallible.
   2855    auto tmp = ins->fallible() ? temp() : LDefinition::BogusTemp();
   2856 
   2857    auto* lir = new (alloc()) LBigIntPtrRsh(useRegister(ins->lhs()),
   2858                                            useRegisterOrConstant(ins->rhs()),
   2859                                            tmp, LDefinition::BogusTemp());
   2860    if (ins->fallible()) {
   2861      assignSnapshot(lir, ins->bailoutKind());
   2862    }
   2863    define(lir, ins);
   2864    return;
   2865  }
   2866 
   2867  lowerBigIntPtrRsh(ins);
   2868 }
   2869 
   2870 void LIRGenerator::visitBigIntPtrBitNot(MBigIntPtrBitNot* ins) {
   2871  MOZ_ASSERT(ins->input()->type() == MIRType::IntPtr);
   2872 
   2873  auto* lir = new (alloc()) LBigIntPtrBitNot(useRegister(ins->input()));
   2874  define(lir, ins);
   2875 }
   2876 
   2877 void LIRGenerator::visitInt32ToStringWithBase(MInt32ToStringWithBase* ins) {
   2878  MOZ_ASSERT(ins->input()->type() == MIRType::Int32);
   2879  MOZ_ASSERT(ins->base()->type() == MIRType::Int32);
   2880 
   2881  int32_t baseInt =
   2882      ins->base()->isConstant() ? ins->base()->toConstant()->toInt32() : 0;
   2883 
   2884  LAllocation base;
   2885  if (2 <= baseInt && baseInt <= 36) {
   2886    base = useRegisterOrConstant(ins->base());
   2887  } else {
   2888    base = useRegister(ins->base());
   2889  }
   2890 
   2891  auto* lir = new (alloc())
   2892      LInt32ToStringWithBase(useRegister(ins->input()), base, temp(), temp());
   2893  define(lir, ins);
   2894  assignSafepoint(lir, ins);
   2895 }
   2896 
   2897 void LIRGenerator::visitNumberParseInt(MNumberParseInt* ins) {
   2898  MOZ_ASSERT(ins->string()->type() == MIRType::String);
   2899  MOZ_ASSERT(ins->radix()->type() == MIRType::Int32);
   2900 
   2901  auto* lir = new (alloc()) LNumberParseInt(useRegisterAtStart(ins->string()),
   2902                                            useRegisterAtStart(ins->radix()),
   2903                                            tempFixed(CallTempReg0));
   2904  defineReturn(lir, ins);
   2905  assignSafepoint(lir, ins);
   2906 }
   2907 
   2908 void LIRGenerator::visitDoubleParseInt(MDoubleParseInt* ins) {
   2909  MOZ_ASSERT(ins->number()->type() == MIRType::Double);
   2910 
   2911  auto* lir =
   2912      new (alloc()) LDoubleParseInt(useRegister(ins->number()), tempDouble());
   2913  assignSnapshot(lir, ins->bailoutKind());
   2914  define(lir, ins);
   2915 }
   2916 
   2917 void LIRGenerator::visitConcat(MConcat* ins) {
   2918  MDefinition* lhs = ins->getOperand(0);
   2919  MDefinition* rhs = ins->getOperand(1);
   2920 
   2921  MOZ_ASSERT(lhs->type() == MIRType::String);
   2922  MOZ_ASSERT(rhs->type() == MIRType::String);
   2923  MOZ_ASSERT(ins->type() == MIRType::String);
   2924 
   2925  LConcat* lir = new (alloc()) LConcat(
   2926      useFixedAtStart(lhs, CallTempReg0), useFixedAtStart(rhs, CallTempReg1),
   2927      tempFixed(CallTempReg0), tempFixed(CallTempReg1), tempFixed(CallTempReg2),
   2928      tempFixed(CallTempReg3), tempFixed(CallTempReg4));
   2929  defineFixed(lir, ins, LAllocation(AnyRegister(CallTempReg5)));
   2930  assignSafepoint(lir, ins);
   2931 }
   2932 
   2933 void LIRGenerator::visitLinearizeString(MLinearizeString* ins) {
   2934  MDefinition* str = ins->string();
   2935  MOZ_ASSERT(str->type() == MIRType::String);
   2936 
   2937  auto* lir = new (alloc()) LLinearizeString(useRegister(str));
   2938  define(lir, ins);
   2939  assignSafepoint(lir, ins);
   2940 }
   2941 
   2942 void LIRGenerator::visitLinearizeForCharAccess(MLinearizeForCharAccess* ins) {
   2943  MDefinition* str = ins->string();
   2944  MDefinition* idx = ins->index();
   2945 
   2946  MOZ_ASSERT(str->type() == MIRType::String);
   2947  MOZ_ASSERT(idx->type() == MIRType::Int32);
   2948 
   2949  auto* lir =
   2950      new (alloc()) LLinearizeForCharAccess(useRegister(str), useRegister(idx));
   2951  define(lir, ins);
   2952  assignSafepoint(lir, ins);
   2953 }
   2954 
   2955 void LIRGenerator::visitLinearizeForCodePointAccess(
   2956    MLinearizeForCodePointAccess* ins) {
   2957  MDefinition* str = ins->string();
   2958  MDefinition* idx = ins->index();
   2959 
   2960  MOZ_ASSERT(str->type() == MIRType::String);
   2961  MOZ_ASSERT(idx->type() == MIRType::Int32);
   2962 
   2963  auto* lir = new (alloc())
   2964      LLinearizeForCodePointAccess(useRegister(str), useRegister(idx), temp());
   2965  define(lir, ins);
   2966  assignSafepoint(lir, ins);
   2967 }
   2968 
   2969 void LIRGenerator::visitToRelativeStringIndex(MToRelativeStringIndex* ins) {
   2970  MDefinition* index = ins->index();
   2971  MDefinition* length = ins->length();
   2972 
   2973  MOZ_ASSERT(index->type() == MIRType::Int32);
   2974  MOZ_ASSERT(length->type() == MIRType::Int32);
   2975 
   2976  auto* lir = new (alloc())
   2977      LToRelativeStringIndex(useRegister(index), useRegister(length));
   2978  define(lir, ins);
   2979 }
   2980 
   2981 void LIRGenerator::visitCharCodeAt(MCharCodeAt* ins) {
   2982  MDefinition* str = ins->string();
   2983  MDefinition* idx = ins->index();
   2984 
   2985  MOZ_ASSERT(str->type() == MIRType::String);
   2986  MOZ_ASSERT(idx->type() == MIRType::Int32);
   2987 
   2988  auto* lir = new (alloc())
   2989      LCharCodeAt(useRegister(str), useRegisterOrZero(idx), temp(), temp());
   2990  define(lir, ins);
   2991  assignSafepoint(lir, ins);
   2992 }
   2993 
   2994 void LIRGenerator::visitCharCodeAtOrNegative(MCharCodeAtOrNegative* ins) {
   2995  MDefinition* str = ins->string();
   2996  MDefinition* idx = ins->index();
   2997 
   2998  MOZ_ASSERT(str->type() == MIRType::String);
   2999  MOZ_ASSERT(idx->type() == MIRType::Int32);
   3000 
   3001  auto* lir = new (alloc()) LCharCodeAtOrNegative(
   3002      useRegister(str), useRegisterOrZero(idx), temp(), temp());
   3003  define(lir, ins);
   3004  assignSafepoint(lir, ins);
   3005 }
   3006 
   3007 void LIRGenerator::visitCodePointAt(MCodePointAt* ins) {
   3008  MDefinition* str = ins->string();
   3009  MDefinition* idx = ins->index();
   3010 
   3011  MOZ_ASSERT(str->type() == MIRType::String);
   3012  MOZ_ASSERT(idx->type() == MIRType::Int32);
   3013 
   3014  auto* lir = new (alloc())
   3015      LCodePointAt(useRegister(str), useRegister(idx), temp(), temp());
   3016  define(lir, ins);
   3017  assignSafepoint(lir, ins);
   3018 }
   3019 
   3020 void LIRGenerator::visitCodePointAtOrNegative(MCodePointAtOrNegative* ins) {
   3021  MDefinition* str = ins->string();
   3022  MDefinition* idx = ins->index();
   3023 
   3024  MOZ_ASSERT(str->type() == MIRType::String);
   3025  MOZ_ASSERT(idx->type() == MIRType::Int32);
   3026 
   3027  auto* lir = new (alloc()) LCodePointAtOrNegative(
   3028      useRegister(str), useRegister(idx), temp(), temp());
   3029  define(lir, ins);
   3030  assignSafepoint(lir, ins);
   3031 }
   3032 
   3033 void LIRGenerator::visitNegativeToNaN(MNegativeToNaN* ins) {
   3034  MOZ_ASSERT(ins->input()->type() == MIRType::Int32);
   3035 
   3036  auto* lir = new (alloc()) LNegativeToNaN(useRegister(ins->input()));
   3037  defineBox(lir, ins);
   3038 }
   3039 
   3040 void LIRGenerator::visitNegativeToUndefined(MNegativeToUndefined* ins) {
   3041  MOZ_ASSERT(ins->input()->type() == MIRType::Int32);
   3042 
   3043  auto* lir = new (alloc()) LNegativeToUndefined(useRegister(ins->input()));
   3044  defineBox(lir, ins);
   3045 }
   3046 
   3047 void LIRGenerator::visitFromCharCode(MFromCharCode* ins) {
   3048  MDefinition* code = ins->code();
   3049 
   3050  MOZ_ASSERT(code->type() == MIRType::Int32);
   3051 
   3052  LFromCharCode* lir = new (alloc()) LFromCharCode(useRegister(code));
   3053  define(lir, ins);
   3054  assignSafepoint(lir, ins);
   3055 }
   3056 
   3057 void LIRGenerator::visitFromCharCodeEmptyIfNegative(
   3058    MFromCharCodeEmptyIfNegative* ins) {
   3059  MDefinition* code = ins->code();
   3060 
   3061  MOZ_ASSERT(code->type() == MIRType::Int32);
   3062 
   3063  auto* lir = new (alloc()) LFromCharCodeEmptyIfNegative(useRegister(code));
   3064  define(lir, ins);
   3065  assignSafepoint(lir, ins);
   3066 }
   3067 
   3068 void LIRGenerator::visitFromCharCodeUndefinedIfNegative(
   3069    MFromCharCodeUndefinedIfNegative* ins) {
   3070  MDefinition* code = ins->code();
   3071 
   3072  MOZ_ASSERT(code->type() == MIRType::Int32);
   3073 
   3074  auto* lir = new (alloc()) LFromCharCodeUndefinedIfNegative(useRegister(code));
   3075  defineBox(lir, ins);
   3076  assignSafepoint(lir, ins);
   3077 }
   3078 
   3079 void LIRGenerator::visitFromCodePoint(MFromCodePoint* ins) {
   3080  MDefinition* codePoint = ins->codePoint();
   3081 
   3082  MOZ_ASSERT(codePoint->type() == MIRType::Int32);
   3083 
   3084  LFromCodePoint* lir =
   3085      new (alloc()) LFromCodePoint(useRegister(codePoint), temp(), temp());
   3086  assignSnapshot(lir, ins->bailoutKind());
   3087  define(lir, ins);
   3088  assignSafepoint(lir, ins);
   3089 }
   3090 
   3091 void LIRGenerator::visitStringIncludes(MStringIncludes* ins) {
   3092  auto* string = ins->string();
   3093  MOZ_ASSERT(string->type() == MIRType::String);
   3094 
   3095  auto* searchStr = ins->searchString();
   3096  MOZ_ASSERT(searchStr->type() == MIRType::String);
   3097 
   3098  if (searchStr->isConstant()) {
   3099    JSOffThreadAtom* str = searchStr->toConstant()->toString();
   3100    size_t length = str->length();
   3101    if (length == 1 || length == 2) {
   3102      LDefinition tempDef = LDefinition::BogusTemp();
   3103      if (length > 1) {
   3104        tempDef = temp();
   3105      }
   3106 
   3107      auto* lir = new (alloc()) LStringIncludesSIMD(useRegister(string), temp(),
   3108                                                    temp(), tempDef, str);
   3109      define(lir, ins);
   3110      assignSafepoint(lir, ins);
   3111      return;
   3112    }
   3113  }
   3114 
   3115  auto* lir = new (alloc()) LStringIncludes(useRegisterAtStart(string),
   3116                                            useRegisterAtStart(searchStr));
   3117  defineReturn(lir, ins);
   3118  assignSafepoint(lir, ins);
   3119 }
   3120 
   3121 void LIRGenerator::visitStringIndexOf(MStringIndexOf* ins) {
   3122  auto* string = ins->string();
   3123  MOZ_ASSERT(string->type() == MIRType::String);
   3124 
   3125  auto* searchStr = ins->searchString();
   3126  MOZ_ASSERT(searchStr->type() == MIRType::String);
   3127 
   3128  if (searchStr->isConstant()) {
   3129    JSOffThreadAtom* str = searchStr->toConstant()->toString();
   3130    size_t length = str->length();
   3131    if (length == 1 || length == 2) {
   3132      LDefinition tempDef = LDefinition::BogusTemp();
   3133      if (length > 1) {
   3134        tempDef = temp();
   3135      }
   3136 
   3137      auto* lir = new (alloc())
   3138          LStringIndexOfSIMD(useRegister(string), temp(), temp(), tempDef, str);
   3139      define(lir, ins);
   3140      assignSafepoint(lir, ins);
   3141      return;
   3142    }
   3143  }
   3144 
   3145  auto* lir = new (alloc())
   3146      LStringIndexOf(useRegisterAtStart(string), useRegisterAtStart(searchStr));
   3147  defineReturn(lir, ins);
   3148  assignSafepoint(lir, ins);
   3149 }
   3150 
   3151 void LIRGenerator::visitStringLastIndexOf(MStringLastIndexOf* ins) {
   3152  auto* string = ins->string();
   3153  MOZ_ASSERT(string->type() == MIRType::String);
   3154 
   3155  auto* searchStr = ins->searchString();
   3156  MOZ_ASSERT(searchStr->type() == MIRType::String);
   3157 
   3158  auto* lir = new (alloc()) LStringLastIndexOf(useRegisterAtStart(string),
   3159                                               useRegisterAtStart(searchStr));
   3160  defineReturn(lir, ins);
   3161  assignSafepoint(lir, ins);
   3162 }
   3163 
   3164 void LIRGenerator::visitStringStartsWith(MStringStartsWith* ins) {
   3165  auto* string = ins->string();
   3166  MOZ_ASSERT(string->type() == MIRType::String);
   3167 
   3168  auto* searchStr = ins->searchString();
   3169  MOZ_ASSERT(searchStr->type() == MIRType::String);
   3170 
   3171  if (searchStr->isConstant()) {
   3172    JSOffThreadAtom* str = searchStr->toConstant()->toString();
   3173 
   3174    if (MacroAssembler::canCompareStringCharsInline(str)) {
   3175      auto* lir = new (alloc())
   3176          LStringStartsWithInline(useRegister(string), temp(), str);
   3177      define(lir, ins);
   3178      assignSafepoint(lir, ins);
   3179      return;
   3180    }
   3181  }
   3182 
   3183  auto* lir = new (alloc()) LStringStartsWith(useRegisterAtStart(string),
   3184                                              useRegisterAtStart(searchStr));
   3185  defineReturn(lir, ins);
   3186  assignSafepoint(lir, ins);
   3187 }
   3188 
   3189 void LIRGenerator::visitStringEndsWith(MStringEndsWith* ins) {
   3190  auto* string = ins->string();
   3191  MOZ_ASSERT(string->type() == MIRType::String);
   3192 
   3193  auto* searchStr = ins->searchString();
   3194  MOZ_ASSERT(searchStr->type() == MIRType::String);
   3195 
   3196  if (searchStr->isConstant()) {
   3197    JSOffThreadAtom* str = searchStr->toConstant()->toString();
   3198 
   3199    if (MacroAssembler::canCompareStringCharsInline(str)) {
   3200      auto* lir =
   3201          new (alloc()) LStringEndsWithInline(useRegister(string), temp(), str);
   3202      define(lir, ins);
   3203      assignSafepoint(lir, ins);
   3204      return;
   3205    }
   3206  }
   3207 
   3208  auto* lir = new (alloc()) LStringEndsWith(useRegisterAtStart(string),
   3209                                            useRegisterAtStart(searchStr));
   3210  defineReturn(lir, ins);
   3211  assignSafepoint(lir, ins);
   3212 }
   3213 
   3214 void LIRGenerator::visitStringConvertCase(MStringConvertCase* ins) {
   3215  MOZ_ASSERT(ins->string()->type() == MIRType::String);
   3216 
   3217  if (ins->mode() == MStringConvertCase::LowerCase) {
   3218 #ifdef JS_CODEGEN_X86
   3219    // Due to lack of registers on x86, we reuse the string register as
   3220    // temporary. As a result we only need four temporary registers and take a
   3221    // bogus temporary as the fifth argument.
   3222    LDefinition temp4 = LDefinition::BogusTemp();
   3223 #else
   3224    LDefinition temp4 = temp();
   3225 #endif
   3226    auto* lir = new (alloc())
   3227        LStringToLowerCase(useRegister(ins->string()), temp(), temp(), temp(),
   3228                           temp4, tempByteOpRegister());
   3229    define(lir, ins);
   3230    assignSafepoint(lir, ins);
   3231  } else {
   3232    auto* lir =
   3233        new (alloc()) LStringToUpperCase(useRegisterAtStart(ins->string()));
   3234    defineReturn(lir, ins);
   3235    assignSafepoint(lir, ins);
   3236  }
   3237 }
   3238 
   3239 void LIRGenerator::visitCharCodeConvertCase(MCharCodeConvertCase* ins) {
   3240  MOZ_ASSERT(ins->code()->type() == MIRType::Int32);
   3241 
   3242  if (ins->mode() == MCharCodeConvertCase::LowerCase) {
   3243    auto* lir = new (alloc())
   3244        LCharCodeToLowerCase(useRegister(ins->code()), tempByteOpRegister());
   3245    define(lir, ins);
   3246    assignSafepoint(lir, ins);
   3247  } else {
   3248    auto* lir = new (alloc())
   3249        LCharCodeToUpperCase(useRegister(ins->code()), tempByteOpRegister());
   3250    define(lir, ins);
   3251    assignSafepoint(lir, ins);
   3252  }
   3253 }
   3254 
   3255 void LIRGenerator::visitStringTrimStartIndex(MStringTrimStartIndex* ins) {
   3256  auto* string = ins->string();
   3257  MOZ_ASSERT(string->type() == MIRType::String);
   3258 
   3259  auto* lir = new (alloc()) LStringTrimStartIndex(useRegister(string));
   3260  define(lir, ins);
   3261  assignSafepoint(lir, ins);
   3262 }
   3263 
   3264 void LIRGenerator::visitStringTrimEndIndex(MStringTrimEndIndex* ins) {
   3265  auto* string = ins->string();
   3266  MOZ_ASSERT(string->type() == MIRType::String);
   3267 
   3268  auto* start = ins->start();
   3269  MOZ_ASSERT(start->type() == MIRType::Int32);
   3270 
   3271  auto* lir = new (alloc())
   3272      LStringTrimEndIndex(useRegister(string), useRegister(start));
   3273  define(lir, ins);
   3274  assignSafepoint(lir, ins);
   3275 }
   3276 
   3277 void LIRGenerator::visitStart(MStart* start) {}
   3278 
   3279 void LIRGenerator::visitNop(MNop* nop) {}
   3280 
   3281 void LIRGenerator::visitLimitedTruncate(MLimitedTruncate* nop) {
   3282  redefine(nop, nop->input());
   3283 }
   3284 
   3285 void LIRGenerator::visitIntPtrLimitedTruncate(MIntPtrLimitedTruncate* ins) {
   3286  MOZ_ASSERT(ins->input()->type() == MIRType::IntPtr);
   3287 
   3288  // This is a no-op.
   3289  redefine(ins, ins->input());
   3290 }
   3291 
   3292 void LIRGenerator::visitInt64LimitedTruncate(MInt64LimitedTruncate* ins) {
   3293  MOZ_ASSERT(ins->input()->type() == MIRType::Int64);
   3294 
   3295  // This is a no-op.
   3296  redefine(ins, ins->input());
   3297 }
   3298 
   3299 void LIRGenerator::visitOsrEntry(MOsrEntry* entry) {
   3300  LOsrEntry* lir = new (alloc()) LOsrEntry(temp());
   3301  defineFixed(lir, entry, LAllocation(AnyRegister(OsrFrameReg)));
   3302 }
   3303 
   3304 void LIRGenerator::visitOsrValue(MOsrValue* value) {
   3305  LOsrValue* lir = new (alloc()) LOsrValue(useRegister(value->entry()));
   3306  defineBox(lir, value);
   3307 }
   3308 
   3309 void LIRGenerator::visitOsrReturnValue(MOsrReturnValue* value) {
   3310  LOsrReturnValue* lir =
   3311      new (alloc()) LOsrReturnValue(useRegister(value->entry()));
   3312  defineBox(lir, value);
   3313 }
   3314 
   3315 void LIRGenerator::visitOsrEnvironmentChain(MOsrEnvironmentChain* object) {
   3316  LOsrEnvironmentChain* lir =
   3317      new (alloc()) LOsrEnvironmentChain(useRegister(object->entry()));
   3318  define(lir, object);
   3319 }
   3320 
   3321 void LIRGenerator::visitOsrArgumentsObject(MOsrArgumentsObject* object) {
   3322  LOsrArgumentsObject* lir =
   3323      new (alloc()) LOsrArgumentsObject(useRegister(object->entry()));
   3324  define(lir, object);
   3325 }
   3326 
   3327 void LIRGenerator::visitToDouble(MToDouble* convert) {
   3328  MDefinition* opd = convert->input();
   3329 
   3330  switch (opd->type()) {
   3331    case MIRType::Value: {
   3332      LValueToDouble* lir = new (alloc()) LValueToDouble(useBox(opd));
   3333      assignSnapshot(lir, convert->bailoutKind());
   3334      define(lir, convert);
   3335      break;
   3336    }
   3337 
   3338    case MIRType::Null:
   3339      lowerConstantDouble(0, convert);
   3340      break;
   3341 
   3342    case MIRType::Undefined:
   3343      lowerConstantDouble(GenericNaN(), convert);
   3344      break;
   3345 
   3346    case MIRType::Boolean:
   3347    case MIRType::Int32: {
   3348      LInt32ToDouble* lir =
   3349          new (alloc()) LInt32ToDouble(useRegisterAtStart(opd));
   3350      define(lir, convert);
   3351      break;
   3352    }
   3353 
   3354    case MIRType::Float32: {
   3355      LFloat32ToDouble* lir =
   3356          new (alloc()) LFloat32ToDouble(useRegisterAtStart(opd));
   3357      define(lir, convert);
   3358      break;
   3359    }
   3360 
   3361    case MIRType::Double:
   3362      redefine(convert, opd);
   3363      break;
   3364 
   3365    default:
   3366      // Objects might be effectful. Symbols will throw.
   3367      // Strings are complicated - we don't handle them yet.
   3368      MOZ_CRASH("unexpected type");
   3369  }
   3370 }
   3371 
   3372 void LIRGenerator::visitToFloat32(MToFloat32* convert) {
   3373  MDefinition* opd = convert->input();
   3374 
   3375  switch (opd->type()) {
   3376    case MIRType::Value: {
   3377      LValueToFloat32* lir = new (alloc()) LValueToFloat32(useBox(opd));
   3378      assignSnapshot(lir, convert->bailoutKind());
   3379      define(lir, convert);
   3380      break;
   3381    }
   3382 
   3383    case MIRType::Null:
   3384      lowerConstantFloat32(0, convert);
   3385      break;
   3386 
   3387    case MIRType::Undefined:
   3388      lowerConstantFloat32(GenericNaN(), convert);
   3389      break;
   3390 
   3391    case MIRType::Boolean:
   3392    case MIRType::Int32: {
   3393      LInt32ToFloat32* lir =
   3394          new (alloc()) LInt32ToFloat32(useRegisterAtStart(opd));
   3395      define(lir, convert);
   3396      break;
   3397    }
   3398 
   3399    case MIRType::Double: {
   3400      LDoubleToFloat32* lir =
   3401          new (alloc()) LDoubleToFloat32(useRegisterAtStart(opd));
   3402      define(lir, convert);
   3403      break;
   3404    }
   3405 
   3406    case MIRType::Float32:
   3407      redefine(convert, opd);
   3408      break;
   3409 
   3410    default:
   3411      // Objects might be effectful. Symbols will throw.
   3412      // Strings are complicated - we don't handle them yet.
   3413      MOZ_CRASH("unexpected type");
   3414  }
   3415 }
   3416 
   3417 void LIRGenerator::visitToFloat16(MToFloat16* convert) {
   3418  MDefinition* opd = convert->input();
   3419 
   3420  switch (opd->type()) {
   3421    case MIRType::Value: {
   3422      LDefinition tempDef = LDefinition::BogusTemp();
   3423      if (!MacroAssembler::SupportsFloat64To16()) {
   3424        tempDef = temp();
   3425      }
   3426 
   3427      auto* lir = new (alloc()) LValueToFloat16(useBox(opd), tempDef);
   3428      assignSnapshot(lir, convert->bailoutKind());
   3429      define(lir, convert);
   3430 
   3431      if (!MacroAssembler::SupportsFloat64To16()) {
   3432        assignSafepoint(lir, convert);
   3433      }
   3434      break;
   3435    }
   3436 
   3437    case MIRType::Null:
   3438      lowerConstantFloat32(0, convert);
   3439      break;
   3440 
   3441    case MIRType::Undefined:
   3442      lowerConstantFloat32(GenericNaN(), convert);
   3443      break;
   3444 
   3445    case MIRType::Boolean:
   3446    case MIRType::Int32: {
   3447      LDefinition tempDef = LDefinition::BogusTemp();
   3448      if (!MacroAssembler::SupportsFloat32To16()) {
   3449        tempDef = temp();
   3450      }
   3451 
   3452      auto* lir =
   3453          new (alloc()) LInt32ToFloat16(useRegisterAtStart(opd), tempDef);
   3454      define(lir, convert);
   3455 
   3456      if (!MacroAssembler::SupportsFloat32To16()) {
   3457        assignSafepoint(lir, convert);
   3458      }
   3459      break;
   3460    }
   3461 
   3462    case MIRType::Double: {
   3463      if (MacroAssembler::SupportsFloat64To16()) {
   3464        auto* lir = new (alloc())
   3465            LDoubleToFloat16(useRegisterAtStart(opd), LDefinition::BogusTemp());
   3466        define(lir, convert);
   3467      } else if (MacroAssembler::SupportsFloat32To16()) {
   3468        auto* lir = new (alloc())
   3469            LDoubleToFloat32ToFloat16(useRegister(opd), temp(), temp());
   3470        define(lir, convert);
   3471      } else {
   3472        auto* lir =
   3473            new (alloc()) LDoubleToFloat16(useRegisterAtStart(opd), temp());
   3474        define(lir, convert);
   3475        assignSafepoint(lir, convert);
   3476      }
   3477      break;
   3478    }
   3479 
   3480    case MIRType::Float32: {
   3481      LDefinition tempDef = LDefinition::BogusTemp();
   3482      if (!MacroAssembler::SupportsFloat32To16()) {
   3483        tempDef = temp();
   3484      }
   3485 
   3486      auto* lir =
   3487          new (alloc()) LFloat32ToFloat16(useRegisterAtStart(opd), tempDef);
   3488      define(lir, convert);
   3489 
   3490      if (!MacroAssembler::SupportsFloat32To16()) {
   3491        assignSafepoint(lir, convert);
   3492      }
   3493      break;
   3494    }
   3495 
   3496    default:
   3497      // Objects might be effectful. Symbols will throw.
   3498      // Strings are complicated - we don't handle them yet.
   3499      MOZ_CRASH("unexpected type");
   3500  }
   3501 }
   3502 
   3503 void LIRGenerator::visitToNumberInt32(MToNumberInt32* convert) {
   3504  MDefinition* opd = convert->input();
   3505 
   3506  switch (opd->type()) {
   3507    case MIRType::Value: {
   3508      auto* lir = new (alloc()) LValueToNumberInt32(useBox(opd), tempDouble());
   3509      assignSnapshot(lir, convert->bailoutKind());
   3510      define(lir, convert);
   3511      break;
   3512    }
   3513 
   3514    case MIRType::Null:
   3515      MOZ_ASSERT(convert->conversion() == IntConversionInputKind::Any);
   3516      define(new (alloc()) LInteger(0), convert);
   3517      break;
   3518 
   3519    case MIRType::Boolean:
   3520      MOZ_ASSERT(convert->conversion() == IntConversionInputKind::Any);
   3521      redefine(convert, opd);
   3522      break;
   3523 
   3524    case MIRType::Int32:
   3525      redefine(convert, opd);
   3526      break;
   3527 
   3528    case MIRType::Float32: {
   3529      LFloat32ToInt32* lir = new (alloc()) LFloat32ToInt32(useRegister(opd));
   3530      assignSnapshot(lir, convert->bailoutKind());
   3531      define(lir, convert);
   3532      break;
   3533    }
   3534 
   3535    case MIRType::Double: {
   3536      LDoubleToInt32* lir = new (alloc()) LDoubleToInt32(useRegister(opd));
   3537      assignSnapshot(lir, convert->bailoutKind());
   3538      define(lir, convert);
   3539      break;
   3540    }
   3541 
   3542    case MIRType::String:
   3543    case MIRType::Symbol:
   3544    case MIRType::BigInt:
   3545    case MIRType::Object:
   3546    case MIRType::Undefined:
   3547      // Objects might be effectful. Symbols and BigInts throw. Undefined
   3548      // coerces to NaN, not int32.
   3549      MOZ_CRASH("ToInt32 invalid input type");
   3550 
   3551    default:
   3552      MOZ_CRASH("unexpected type");
   3553  }
   3554 }
   3555 
   3556 void LIRGenerator::visitBooleanToInt32(MBooleanToInt32* convert) {
   3557  MDefinition* opd = convert->input();
   3558  MOZ_ASSERT(opd->type() == MIRType::Boolean);
   3559  redefine(convert, opd);
   3560 }
   3561 
   3562 void LIRGenerator::visitTruncateToInt32(MTruncateToInt32* truncate) {
   3563  MDefinition* opd = truncate->input();
   3564 
   3565  switch (opd->type()) {
   3566    case MIRType::Value: {
   3567      auto* lir = new (alloc())
   3568          LValueTruncateToInt32(useBox(opd), tempDouble(), temp());
   3569      assignSnapshot(lir, truncate->bailoutKind());
   3570      define(lir, truncate);
   3571      assignSafepoint(lir, truncate);
   3572      break;
   3573    }
   3574 
   3575    case MIRType::Null:
   3576    case MIRType::Undefined:
   3577      define(new (alloc()) LInteger(0), truncate);
   3578      break;
   3579 
   3580    case MIRType::Int32:
   3581    case MIRType::Boolean:
   3582      redefine(truncate, opd);
   3583      break;
   3584 
   3585    case MIRType::Double:
   3586      // May call into JS::ToInt32() on the slow OOL path.
   3587      gen->setNeedsStaticStackAlignment();
   3588      lowerTruncateDToInt32(truncate);
   3589      break;
   3590 
   3591    case MIRType::Float32:
   3592      // May call into JS::ToInt32() on the slow OOL path.
   3593      gen->setNeedsStaticStackAlignment();
   3594      lowerTruncateFToInt32(truncate);
   3595      break;
   3596 
   3597    default:
   3598      // Objects might be effectful. Symbols throw.
   3599      // Strings are complicated - we don't handle them yet.
   3600      MOZ_CRASH("unexpected type");
   3601  }
   3602 }
   3603 
   3604 void LIRGenerator::visitInt32ToIntPtr(MInt32ToIntPtr* ins) {
   3605  MDefinition* input = ins->input();
   3606  MOZ_ASSERT(input->type() == MIRType::Int32);
   3607  MOZ_ASSERT(ins->type() == MIRType::IntPtr);
   3608 
   3609 #ifdef JS_64BIT
   3610  // If the result is only used by instructions that expect a bounds-checked
   3611  // index, we must have eliminated or hoisted a bounds check and we can assume
   3612  // the index is non-negative. This lets us generate more efficient code.
   3613  if (ins->canBeNegative()) {
   3614    bool canBeNegative = false;
   3615    for (MUseDefIterator iter(ins); iter; iter++) {
   3616      if (iter.def()->isSpectreMaskIndex()) {
   3617        continue;
   3618      }
   3619      if (iter.def()->isLoadUnboxedScalar() ||
   3620          iter.def()->isStoreUnboxedScalar() ||
   3621          iter.def()->isLoadDataViewElement() ||
   3622          iter.def()->isStoreDataViewElement()) {
   3623        MOZ_ASSERT(iter.def()->indexOf(iter.use()) == 1,
   3624                   "unexpected non-index operand use");
   3625        continue;
   3626      }
   3627 
   3628      canBeNegative = true;
   3629      break;
   3630    }
   3631    if (!canBeNegative) {
   3632      ins->setCanNotBeNegative();
   3633    }
   3634  }
   3635 
   3636  if (ins->canBeNegative()) {
   3637    auto* lir = new (alloc()) LInt32ToIntPtr(useAnyAtStart(input));
   3638    define(lir, ins);
   3639  } else {
   3640    redefine(ins, input);
   3641  }
   3642 #else
   3643  // On 32-bit platforms this is a no-op.
   3644  redefine(ins, input);
   3645 #endif
   3646 }
   3647 
   3648 void LIRGenerator::visitNonNegativeIntPtrToInt32(
   3649    MNonNegativeIntPtrToInt32* ins) {
   3650  MDefinition* input = ins->input();
   3651  MOZ_ASSERT(input->type() == MIRType::IntPtr);
   3652  MOZ_ASSERT(ins->type() == MIRType::Int32);
   3653 
   3654 #ifdef JS_64BIT
   3655  auto* lir =
   3656      new (alloc()) LNonNegativeIntPtrToInt32(useRegisterAtStart(input));
   3657  assignSnapshot(lir, ins->bailoutKind());
   3658  defineReuseInput(lir, ins, 0);
   3659 #else
   3660  // On 32-bit platforms this is a no-op.
   3661  redefine(ins, input);
   3662 #endif
   3663 }
   3664 
   3665 void LIRGenerator::visitWasmExtendU32Index(MWasmExtendU32Index* ins) {
   3666 #ifdef JS_64BIT
   3667  // Technically this produces an Int64 register and I guess we could clean that
   3668  // up, but it's a 64-bit only operation, so it doesn't actually matter.
   3669 
   3670  MDefinition* input = ins->input();
   3671  MOZ_ASSERT(input->type() == MIRType::Int32);
   3672  MOZ_ASSERT(ins->type() == MIRType::Int64);
   3673 
   3674  // Input reuse is OK even on ARM64 because this node *must* reuse its input in
   3675  // order not to generate any code at all, as is the intent.
   3676  auto* lir = new (alloc()) LWasmExtendU32Index(useRegisterAtStart(input));
   3677  defineReuseInput(lir, ins, 0);
   3678 #else
   3679  MOZ_CRASH("64-bit only");
   3680 #endif
   3681 }
   3682 
   3683 void LIRGenerator::visitWasmWrapU32Index(MWasmWrapU32Index* ins) {
   3684  MDefinition* input = ins->input();
   3685  MOZ_ASSERT(input->type() == MIRType::Int64);
   3686  MOZ_ASSERT(ins->type() == MIRType::Int32);
   3687 
   3688  // Tricky: On 64-bit, this just returns its input (except on MIPS64 there may
   3689  // be a sign/zero extension).  On 32-bit, it returns the low register of the
   3690  // input, and should generate no code.
   3691 
   3692 #ifdef JS_64BIT
   3693  LAllocation index = useRegisterAtStart(input);
   3694 #else
   3695  LAllocation index = useLowWordRegisterAtStart(input);
   3696 #endif
   3697 
   3698  auto* lir = new (alloc()) LWasmWrapU32Index(index);
   3699  defineReuseInput(lir, ins, 0);
   3700 }
   3701 
   3702 void LIRGenerator::visitWasmClampTable64Address(MWasmClampTable64Address* ins) {
   3703  MDefinition* input = ins->address();
   3704  MOZ_ASSERT(input->type() == MIRType::Int64);
   3705  MOZ_ASSERT(ins->type() == MIRType::Int32);
   3706 
   3707  auto* lir =
   3708      new (alloc()) LWasmClampTable64Address(useInt64RegisterAtStart(input));
   3709  define(lir, ins);
   3710 }
   3711 
   3712 void LIRGenerator::visitIntPtrToDouble(MIntPtrToDouble* ins) {
   3713  MDefinition* input = ins->input();
   3714  MOZ_ASSERT(input->type() == MIRType::IntPtr);
   3715  MOZ_ASSERT(ins->type() == MIRType::Double);
   3716 
   3717  auto* lir = new (alloc()) LIntPtrToDouble(useRegister(input));
   3718  define(lir, ins);
   3719 }
   3720 
   3721 void LIRGenerator::visitAdjustDataViewLength(MAdjustDataViewLength* ins) {
   3722  MDefinition* input = ins->input();
   3723  MOZ_ASSERT(input->type() == MIRType::IntPtr);
   3724 
   3725  auto* lir = new (alloc()) LAdjustDataViewLength(useRegisterAtStart(input));
   3726  assignSnapshot(lir, ins->bailoutKind());
   3727  defineReuseInput(lir, ins, 0);
   3728 }
   3729 
   3730 void LIRGenerator::visitToBigInt(MToBigInt* ins) {
   3731  MDefinition* opd = ins->input();
   3732 
   3733  switch (opd->type()) {
   3734    case MIRType::Value: {
   3735      auto* lir = new (alloc()) LValueToBigInt(useBox(opd));
   3736      assignSnapshot(lir, ins->bailoutKind());
   3737      define(lir, ins);
   3738      assignSafepoint(lir, ins);
   3739      break;
   3740    }
   3741 
   3742    case MIRType::BigInt:
   3743      redefine(ins, opd);
   3744      break;
   3745 
   3746    default:
   3747      MOZ_CRASH("unexpected type");
   3748  }
   3749 }
   3750 
   3751 void LIRGenerator::visitToInt64(MToInt64* ins) {
   3752  MDefinition* opd = ins->input();
   3753 
   3754  switch (opd->type()) {
   3755    case MIRType::Value: {
   3756      auto* lir = new (alloc()) LValueToInt64(useBox(opd), temp());
   3757      assignSnapshot(lir, ins->bailoutKind());
   3758      defineInt64(lir, ins);
   3759      assignSafepoint(lir, ins);
   3760      break;
   3761    }
   3762 
   3763    case MIRType::Boolean: {
   3764      auto* lir = new (alloc()) LBooleanToInt64(useRegisterAtStart(opd));
   3765      defineInt64(lir, ins);
   3766      break;
   3767    }
   3768 
   3769    case MIRType::String: {
   3770      auto* lir = new (alloc()) LStringToInt64(useRegister(opd));
   3771      defineInt64(lir, ins);
   3772      assignSafepoint(lir, ins);
   3773      break;
   3774    }
   3775 
   3776    // An Int64 may be passed here from a BigInt to Int64 conversion.
   3777    case MIRType::Int64: {
   3778      redefine(ins, opd);
   3779      break;
   3780    }
   3781 
   3782    default:
   3783      // Undefined, Null, Number, and Symbol throw.
   3784      // Objects may be effectful.
   3785      // BigInt operands are eliminated by the type policy.
   3786      MOZ_CRASH("unexpected type");
   3787  }
   3788 }
   3789 
   3790 void LIRGenerator::visitTruncateBigIntToInt64(MTruncateBigIntToInt64* ins) {
   3791  MOZ_ASSERT(ins->input()->type() == MIRType::BigInt);
   3792  auto* lir = new (alloc()) LTruncateBigIntToInt64(useRegister(ins->input()));
   3793  defineInt64(lir, ins);
   3794 }
   3795 
   3796 void LIRGenerator::visitInt64ToBigInt(MInt64ToBigInt* ins) {
   3797  MOZ_ASSERT(ins->input()->type() == MIRType::Int64);
   3798 
   3799  if (ins->isSigned()) {
   3800    auto* lir = new (alloc())
   3801        LInt64ToBigInt(useInt64Register(ins->input()), tempInt64());
   3802    define(lir, ins);
   3803    assignSafepoint(lir, ins);
   3804  } else {
   3805    auto* lir =
   3806        new (alloc()) LUint64ToBigInt(useInt64Register(ins->input()), temp());
   3807    define(lir, ins);
   3808    assignSafepoint(lir, ins);
   3809  }
   3810 }
   3811 
   3812 void LIRGenerator::visitInt64ToIntPtr(MInt64ToIntPtr* ins) {
   3813  MOZ_ASSERT(ins->input()->type() == MIRType::Int64);
   3814 
   3815 #ifdef JS_64BIT
   3816  if (ins->isSigned()) {
   3817    redefine(ins, ins->input());
   3818    return;
   3819  }
   3820 #endif
   3821 
   3822  auto* lir =
   3823      new (alloc()) LInt64ToIntPtr(useInt64RegisterAtStart(ins->input()));
   3824  assignSnapshot(lir, ins->bailoutKind());
   3825 #ifdef JS_64BIT
   3826  defineReuseInput(lir, ins, 0);
   3827 #else
   3828  define(lir, ins);
   3829 #endif
   3830 }
   3831 
   3832 void LIRGenerator::visitIntPtrToInt64(MIntPtrToInt64* ins) {
   3833  MOZ_ASSERT(ins->input()->type() == MIRType::IntPtr);
   3834 
   3835 #ifdef JS_64BIT
   3836  redefine(ins, ins->input());
   3837 #else
   3838  auto* lir = new (alloc()) LIntPtrToInt64(useRegister(ins->input()));
   3839  defineInt64(lir, ins);
   3840 #endif
   3841 }
   3842 
   3843 void LIRGenerator::visitWasmTruncateToInt32(MWasmTruncateToInt32* ins) {
   3844  MDefinition* input = ins->input();
   3845  switch (input->type()) {
   3846    case MIRType::Double:
   3847    case MIRType::Float32: {
   3848      auto* lir = new (alloc()) LWasmTruncateToInt32(useRegisterAtStart(input));
   3849      define(lir, ins);
   3850      break;
   3851    }
   3852    default:
   3853      MOZ_CRASH("unexpected type in WasmTruncateToInt32");
   3854  }
   3855 }
   3856 
   3857 void LIRGenerator::visitWasmBuiltinTruncateToInt32(
   3858    MWasmBuiltinTruncateToInt32* truncate) {
   3859  mozilla::DebugOnly<MDefinition*> opd = truncate->input();
   3860  MOZ_ASSERT(opd->type() == MIRType::Double || opd->type() == MIRType::Float32);
   3861 
   3862  // May call into JS::ToInt32() on the slow OOL path.
   3863  gen->setNeedsStaticStackAlignment();
   3864  lowerWasmBuiltinTruncateToInt32(truncate);
   3865 }
   3866 
   3867 void LIRGenerator::visitWasmAnyRefFromJSValue(MWasmAnyRefFromJSValue* ins) {
   3868  LWasmAnyRefFromJSValue* lir =
   3869      new (alloc()) LWasmAnyRefFromJSValue(useBox(ins->input()), tempDouble());
   3870  define(lir, ins);
   3871  assignSafepoint(lir, ins);
   3872 }
   3873 
   3874 void LIRGenerator::visitWasmAnyRefFromJSObject(MWasmAnyRefFromJSObject* ins) {
   3875  LWasmAnyRefFromJSObject* lir =
   3876      new (alloc()) LWasmAnyRefFromJSObject(useRegisterAtStart(ins->input()));
   3877  define(lir, ins);
   3878 }
   3879 
   3880 void LIRGenerator::visitWasmAnyRefFromJSString(MWasmAnyRefFromJSString* ins) {
   3881  LWasmAnyRefFromJSString* lir =
   3882      new (alloc()) LWasmAnyRefFromJSString(useRegisterAtStart(ins->input()));
   3883  define(lir, ins);
   3884 }
   3885 
   3886 void LIRGenerator::visitWasmAnyRefIsJSString(MWasmAnyRefIsJSString* ins) {
   3887  LWasmAnyRefIsJSString* lir = new (alloc())
   3888      LWasmAnyRefIsJSString(useRegisterAtStart(ins->input()), temp());
   3889  define(lir, ins);
   3890 }
   3891 
   3892 void LIRGenerator::visitWasmTrapIfAnyRefIsNotJSString(
   3893    MWasmTrapIfAnyRefIsNotJSString* ins) {
   3894  LWasmTrapIfAnyRefIsNotJSString* lir = new (alloc())
   3895      LWasmTrapIfAnyRefIsNotJSString(useRegisterAtStart(ins->input()), temp());
   3896  add(lir, ins);
   3897 }
   3898 
   3899 void LIRGenerator::visitWasmAnyRefJSStringLength(
   3900    MWasmAnyRefJSStringLength* ins) {
   3901  LWasmAnyRefJSStringLength* lir = new (alloc())
   3902      LWasmAnyRefJSStringLength(useRegisterAtStart(ins->input()), temp());
   3903  define(lir, ins);
   3904 }
   3905 
   3906 void LIRGenerator::visitWasmNewI31Ref(MWasmNewI31Ref* ins) {
   3907  // If it's a constant, it will be put directly into the register.
   3908  LWasmNewI31Ref* lir =
   3909      new (alloc()) LWasmNewI31Ref(useRegisterOrConstant(ins->input()));
   3910  define(lir, ins);
   3911 }
   3912 
   3913 void LIRGenerator::visitWasmI31RefGet(MWasmI31RefGet* ins) {
   3914  LWasmI31RefGet* lir = new (alloc()) LWasmI31RefGet(useRegister(ins->input()));
   3915  define(lir, ins);
   3916 }
   3917 
   3918 void LIRGenerator::visitWrapInt64ToInt32(MWrapInt64ToInt32* ins) {
   3919  define(new (alloc()) LWrapInt64ToInt32(useInt64AtStart(ins->input())), ins);
   3920 }
   3921 
   3922 void LIRGenerator::visitToString(MToString* ins) {
   3923  MDefinition* opd = ins->input();
   3924 
   3925  switch (opd->type()) {
   3926    case MIRType::Null: {
   3927      const JSAtomState& names = gen->runtime->names();
   3928      LPointer* lir = new (alloc()) LPointer(names.null);
   3929      define(lir, ins);
   3930      break;
   3931    }
   3932 
   3933    case MIRType::Undefined: {
   3934      const JSAtomState& names = gen->runtime->names();
   3935      LPointer* lir = new (alloc()) LPointer(names.undefined);
   3936      define(lir, ins);
   3937      break;
   3938    }
   3939 
   3940    case MIRType::Boolean: {
   3941      LBooleanToString* lir = new (alloc()) LBooleanToString(useRegister(opd));
   3942      define(lir, ins);
   3943      break;
   3944    }
   3945 
   3946    case MIRType::Double: {
   3947      LDoubleToString* lir =
   3948          new (alloc()) LDoubleToString(useRegister(opd), temp());
   3949 
   3950      define(lir, ins);
   3951      assignSafepoint(lir, ins);
   3952      break;
   3953    }
   3954 
   3955    case MIRType::Int32: {
   3956      LIntToString* lir = new (alloc()) LIntToString(useRegister(opd));
   3957 
   3958      define(lir, ins);
   3959      assignSafepoint(lir, ins);
   3960      break;
   3961    }
   3962 
   3963    case MIRType::String:
   3964      redefine(ins, ins->input());
   3965      break;
   3966 
   3967    case MIRType::Value: {
   3968      LValueToString* lir =
   3969          new (alloc()) LValueToString(useBox(opd), tempToUnbox());
   3970      if (ins->needsSnapshot()) {
   3971        assignSnapshot(lir, ins->bailoutKind());
   3972      }
   3973      define(lir, ins);
   3974      assignSafepoint(lir, ins);
   3975      break;
   3976    }
   3977 
   3978    default:
   3979      // Float32, symbols, bigint, and objects are not supported.
   3980      MOZ_CRASH("unexpected type");
   3981  }
   3982 }
   3983 
   3984 void LIRGenerator::visitRegExp(MRegExp* ins) {
   3985  LRegExp* lir = new (alloc()) LRegExp(temp());
   3986  define(lir, ins);
   3987  assignSafepoint(lir, ins);
   3988 }
   3989 
   3990 void LIRGenerator::visitRegExpMatcher(MRegExpMatcher* ins) {
   3991  MOZ_ASSERT(ins->regexp()->type() == MIRType::Object);
   3992  MOZ_ASSERT(ins->string()->type() == MIRType::String);
   3993  MOZ_ASSERT(ins->lastIndex()->type() == MIRType::Int32);
   3994 
   3995  LRegExpMatcher* lir = new (alloc()) LRegExpMatcher(
   3996      useFixedAtStart(ins->regexp(), RegExpMatcherRegExpReg),
   3997      useFixedAtStart(ins->string(), RegExpMatcherStringReg),
   3998      useFixedAtStart(ins->lastIndex(), RegExpMatcherLastIndexReg));
   3999  defineReturn(lir, ins);
   4000  assignSafepoint(lir, ins);
   4001 }
   4002 
   4003 void LIRGenerator::visitRegExpSearcher(MRegExpSearcher* ins) {
   4004  MOZ_ASSERT(ins->regexp()->type() == MIRType::Object);
   4005  MOZ_ASSERT(ins->string()->type() == MIRType::String);
   4006  MOZ_ASSERT(ins->lastIndex()->type() == MIRType::Int32);
   4007 
   4008  LRegExpSearcher* lir = new (alloc()) LRegExpSearcher(
   4009      useFixedAtStart(ins->regexp(), RegExpSearcherRegExpReg),
   4010      useFixedAtStart(ins->string(), RegExpSearcherStringReg),
   4011      useFixedAtStart(ins->lastIndex(), RegExpSearcherLastIndexReg));
   4012  defineReturn(lir, ins);
   4013  assignSafepoint(lir, ins);
   4014 }
   4015 
   4016 void LIRGenerator::visitRegExpSearcherLastLimit(MRegExpSearcherLastLimit* ins) {
   4017  auto* lir = new (alloc()) LRegExpSearcherLastLimit(temp());
   4018  define(lir, ins);
   4019 }
   4020 
   4021 void LIRGenerator::visitRegExpExecMatch(MRegExpExecMatch* ins) {
   4022  MOZ_ASSERT(ins->regexp()->type() == MIRType::Object);
   4023  MOZ_ASSERT(ins->string()->type() == MIRType::String);
   4024 
   4025  auto* lir = new (alloc())
   4026      LRegExpExecMatch(useFixedAtStart(ins->regexp(), RegExpMatcherRegExpReg),
   4027                       useFixedAtStart(ins->string(), RegExpMatcherStringReg));
   4028  defineReturn(lir, ins);
   4029  assignSafepoint(lir, ins);
   4030 }
   4031 
   4032 void LIRGenerator::visitRegExpExecTest(MRegExpExecTest* ins) {
   4033  MOZ_ASSERT(ins->regexp()->type() == MIRType::Object);
   4034  MOZ_ASSERT(ins->string()->type() == MIRType::String);
   4035 
   4036  auto* lir = new (alloc())
   4037      LRegExpExecTest(useFixedAtStart(ins->regexp(), RegExpExecTestRegExpReg),
   4038                      useFixedAtStart(ins->string(), RegExpExecTestStringReg));
   4039  defineReturn(lir, ins);
   4040  assignSafepoint(lir, ins);
   4041 }
   4042 
   4043 void LIRGenerator::visitRegExpHasCaptureGroups(MRegExpHasCaptureGroups* ins) {
   4044  MOZ_ASSERT(ins->regexp()->type() == MIRType::Object);
   4045  MOZ_ASSERT(ins->input()->type() == MIRType::String);
   4046  MOZ_ASSERT(ins->type() == MIRType::Boolean);
   4047 
   4048  auto* lir = new (alloc()) LRegExpHasCaptureGroups(useRegister(ins->regexp()),
   4049                                                    useRegister(ins->input()));
   4050  define(lir, ins);
   4051  assignSafepoint(lir, ins);
   4052 }
   4053 
   4054 void LIRGenerator::visitGetFirstDollarIndex(MGetFirstDollarIndex* ins) {
   4055  MOZ_ASSERT(ins->str()->type() == MIRType::String);
   4056  MOZ_ASSERT(ins->type() == MIRType::Int32);
   4057  LGetFirstDollarIndex* lir = new (alloc())
   4058      LGetFirstDollarIndex(useRegister(ins->str()), temp(), temp(), temp());
   4059  define(lir, ins);
   4060  assignSafepoint(lir, ins);
   4061 }
   4062 
   4063 void LIRGenerator::visitStringReplace(MStringReplace* ins) {
   4064  MOZ_ASSERT(ins->pattern()->type() == MIRType::String);
   4065  MOZ_ASSERT(ins->string()->type() == MIRType::String);
   4066  MOZ_ASSERT(ins->replacement()->type() == MIRType::String);
   4067 
   4068  LStringReplace* lir = new (alloc())
   4069      LStringReplace(useRegisterOrConstantAtStart(ins->string()),
   4070                     useRegisterAtStart(ins->pattern()),
   4071                     useRegisterOrConstantAtStart(ins->replacement()));
   4072  defineReturn(lir, ins);
   4073  assignSafepoint(lir, ins);
   4074 }
   4075 
   4076 void LIRGenerator::visitBinaryCache(MBinaryCache* ins) {
   4077  MDefinition* lhs = ins->getOperand(0);
   4078  MDefinition* rhs = ins->getOperand(1);
   4079 
   4080  MOZ_ASSERT(ins->type() == MIRType::Value || ins->type() == MIRType::Boolean);
   4081  LInstruction* lir;
   4082  if (ins->type() == MIRType::Value) {
   4083    LBinaryValueCache* valueLir = new (alloc()) LBinaryValueCache(
   4084        useBox(lhs), useBox(rhs), tempFixed(FloatReg0), tempFixed(FloatReg1));
   4085    defineBox(valueLir, ins);
   4086    lir = valueLir;
   4087  } else {
   4088    MOZ_ASSERT(ins->type() == MIRType::Boolean);
   4089    LBinaryBoolCache* boolLir = new (alloc()) LBinaryBoolCache(
   4090        useBox(lhs), useBox(rhs), tempFixed(FloatReg0), tempFixed(FloatReg1));
   4091    define(boolLir, ins);
   4092    lir = boolLir;
   4093  }
   4094  assignSafepoint(lir, ins);
   4095 }
   4096 
   4097 void LIRGenerator::visitUnaryCache(MUnaryCache* ins) {
   4098  MDefinition* input = ins->getOperand(0);
   4099  MOZ_ASSERT(ins->type() == MIRType::Value);
   4100 
   4101  LUnaryCache* lir = new (alloc()) LUnaryCache(useBox(input));
   4102  defineBox(lir, ins);
   4103  assignSafepoint(lir, ins);
   4104 }
   4105 
   4106 void LIRGenerator::visitModuleMetadata(MModuleMetadata* ins) {
   4107  LModuleMetadata* lir = new (alloc()) LModuleMetadata();
   4108  defineReturn(lir, ins);
   4109  assignSafepoint(lir, ins);
   4110 }
   4111 
   4112 void LIRGenerator::visitDynamicImport(MDynamicImport* ins) {
   4113  LDynamicImport* lir = new (alloc()) LDynamicImport(
   4114      useBoxAtStart(ins->specifier()), useBoxAtStart(ins->options()));
   4115  defineReturn(lir, ins);
   4116  assignSafepoint(lir, ins);
   4117 }
   4118 
   4119 void LIRGenerator::visitLambda(MLambda* ins) {
   4120  MOZ_ASSERT(ins->environmentChain()->type() == MIRType::Object);
   4121 
   4122  auto* lir =
   4123      new (alloc()) LLambda(useRegister(ins->environmentChain()), temp());
   4124  define(lir, ins);
   4125  assignSafepoint(lir, ins);
   4126 }
   4127 
   4128 void LIRGenerator::visitFunctionWithProto(MFunctionWithProto* ins) {
   4129  MOZ_ASSERT(ins->environmentChain()->type() == MIRType::Object);
   4130  MOZ_ASSERT(ins->prototype()->type() == MIRType::Object);
   4131 
   4132  auto* lir = new (alloc())
   4133      LFunctionWithProto(useRegisterAtStart(ins->environmentChain()),
   4134                         useRegisterAtStart(ins->prototype()));
   4135  defineReturn(lir, ins);
   4136  assignSafepoint(lir, ins);
   4137 }
   4138 
   4139 void LIRGenerator::visitSetFunName(MSetFunName* ins) {
   4140  MOZ_ASSERT(ins->fun()->type() == MIRType::Object);
   4141  MOZ_ASSERT(ins->name()->type() == MIRType::Value);
   4142 
   4143  LSetFunName* lir = new (alloc())
   4144      LSetFunName(useRegisterAtStart(ins->fun()), useBoxAtStart(ins->name()));
   4145  add(lir, ins);
   4146  assignSafepoint(lir, ins);
   4147 }
   4148 
   4149 void LIRGenerator::visitNewLexicalEnvironmentObject(
   4150    MNewLexicalEnvironmentObject* ins) {
   4151  auto* lir = new (alloc()) LNewLexicalEnvironmentObject(temp());
   4152 
   4153  define(lir, ins);
   4154  assignSafepoint(lir, ins);
   4155 }
   4156 
   4157 void LIRGenerator::visitNewClassBodyEnvironmentObject(
   4158    MNewClassBodyEnvironmentObject* ins) {
   4159  auto* lir = new (alloc()) LNewClassBodyEnvironmentObject(temp());
   4160 
   4161  define(lir, ins);
   4162  assignSafepoint(lir, ins);
   4163 }
   4164 
   4165 void LIRGenerator::visitNewVarEnvironmentObject(MNewVarEnvironmentObject* ins) {
   4166  auto* lir = new (alloc()) LNewVarEnvironmentObject(temp());
   4167 
   4168  define(lir, ins);
   4169  assignSafepoint(lir, ins);
   4170 }
   4171 
   4172 void LIRGenerator::visitKeepAliveObject(MKeepAliveObject* ins) {
   4173  MDefinition* obj = ins->object();
   4174  MOZ_ASSERT(obj->type() == MIRType::Object);
   4175 
   4176  add(new (alloc()) LKeepAliveObject(useKeepalive(obj)), ins);
   4177 }
   4178 
   4179 void LIRGenerator::visitDebugEnterGCUnsafeRegion(
   4180    MDebugEnterGCUnsafeRegion* ins) {
   4181  add(new (alloc()) LDebugEnterGCUnsafeRegion(temp()), ins);
   4182 }
   4183 
   4184 void LIRGenerator::visitDebugLeaveGCUnsafeRegion(
   4185    MDebugLeaveGCUnsafeRegion* ins) {
   4186  add(new (alloc()) LDebugLeaveGCUnsafeRegion(temp()), ins);
   4187 }
   4188 
   4189 void LIRGenerator::visitSlots(MSlots* ins) {
   4190  define(new (alloc()) LSlots(useRegisterAtStart(ins->object())), ins);
   4191 }
   4192 
   4193 void LIRGenerator::visitElements(MElements* ins) {
   4194  define(new (alloc()) LElements(useRegisterAtStart(ins->object())), ins);
   4195 }
   4196 
   4197 void LIRGenerator::visitLoadDynamicSlot(MLoadDynamicSlot* ins) {
   4198  MOZ_ASSERT(ins->type() == MIRType::Value);
   4199  if (ins->usedAsPropertyKey()) {
   4200    auto* lir = new (alloc())
   4201        LLoadDynamicSlotAndAtomize(useRegister(ins->slots()), temp());
   4202    defineBox(lir, ins);
   4203    assignSafepoint(lir, ins);
   4204  } else {
   4205    defineBox(new (alloc()) LLoadDynamicSlotV(useRegisterAtStart(ins->slots())),
   4206              ins);
   4207  }
   4208 }
   4209 
   4210 void LIRGenerator::visitLoadDynamicSlotFromOffset(
   4211    MLoadDynamicSlotFromOffset* ins) {
   4212  MOZ_ASSERT(ins->slots()->type() == MIRType::Slots);
   4213 
   4214  auto* lir = new (alloc()) LLoadDynamicSlotFromOffset(
   4215      useRegisterAtStart(ins->slots()), useRegisterAtStart(ins->offset()));
   4216  defineBox(lir, ins);
   4217 }
   4218 
   4219 void LIRGenerator::visitFunctionEnvironment(MFunctionEnvironment* ins) {
   4220  define(new (alloc())
   4221             LFunctionEnvironment(useRegisterAtStart(ins->function())),
   4222         ins);
   4223 }
   4224 
   4225 void LIRGenerator::visitHomeObject(MHomeObject* ins) {
   4226  define(new (alloc()) LHomeObject(useRegisterAtStart(ins->function())), ins);
   4227 }
   4228 
   4229 void LIRGenerator::visitHomeObjectSuperBase(MHomeObjectSuperBase* ins) {
   4230  MOZ_ASSERT(ins->homeObject()->type() == MIRType::Object);
   4231  MOZ_ASSERT(ins->type() == MIRType::Value);
   4232 
   4233  auto lir =
   4234      new (alloc()) LHomeObjectSuperBase(useRegisterAtStart(ins->homeObject()));
   4235  defineBox(lir, ins);
   4236 }
   4237 
   4238 void LIRGenerator::visitInterruptCheck(MInterruptCheck* ins) {
   4239  auto* lir = new (alloc()) LInterruptCheck();
   4240  add(lir, ins);
   4241  assignSafepoint(lir, ins);
   4242 }
   4243 
   4244 void LIRGenerator::visitWasmInterruptCheck(MWasmInterruptCheck* ins) {
   4245  auto* lir =
   4246      new (alloc()) LWasmInterruptCheck(useRegisterAtStart(ins->instance()));
   4247  add(lir, ins);
   4248  assignWasmSafepoint(lir);
   4249 }
   4250 
   4251 void LIRGenerator::visitWasmTrap(MWasmTrap* ins) {
   4252  add(new (alloc()) LWasmTrap, ins);
   4253 }
   4254 
   4255 void LIRGenerator::visitWasmRefAsNonNull(MWasmRefAsNonNull* ins) {
   4256  defineReuseInput(
   4257      new (alloc()) LWasmRefAsNonNull(useRegisterAtStart(ins->ref())), ins, 0);
   4258 }
   4259 
   4260 void LIRGenerator::visitReinterpretCast(MReinterpretCast* ins) {
   4261  if (ins->type() == MIRType::Int64) {
   4262    defineInt64(new (alloc())
   4263                    LReinterpretCastToI64(useRegisterAtStart(ins->input())),
   4264                ins);
   4265  } else if (ins->input()->type() == MIRType::Int64) {
   4266    define(new (alloc())
   4267               LReinterpretCastFromI64(useInt64RegisterAtStart(ins->input())),
   4268           ins);
   4269  } else {
   4270    define(new (alloc()) LReinterpretCast(useRegisterAtStart(ins->input())),
   4271           ins);
   4272  }
   4273 }
   4274 
   4275 void LIRGenerator::visitStoreDynamicSlot(MStoreDynamicSlot* ins) {
   4276  switch (ins->value()->type()) {
   4277    case MIRType::Value:
   4278      add(new (alloc()) LStoreDynamicSlotV(useRegister(ins->slots()),
   4279                                           useBox(ins->value())),
   4280          ins);
   4281      break;
   4282 
   4283    case MIRType::Double:
   4284      add(new (alloc()) LStoreDynamicSlotT(useRegister(ins->slots()),
   4285                                           useRegister(ins->value())),
   4286          ins);
   4287      break;
   4288 
   4289    case MIRType::Float32:
   4290      MOZ_CRASH("Float32 shouldn't be stored in a slot.");
   4291 
   4292    default:
   4293      add(new (alloc()) LStoreDynamicSlotT(useRegister(ins->slots()),
   4294                                           useRegisterOrConstant(ins->value())),
   4295          ins);
   4296      break;
   4297  }
   4298 }
   4299 
   4300 void LIRGenerator::visitPostWriteBarrier(MPostWriteBarrier* ins) {
   4301  MOZ_ASSERT(ins->object()->type() == MIRType::Object);
   4302 
   4303  // We need a barrier if the value might be allocated in the nursery. If the
   4304  // value is a constant, it must be tenured because MIR can't contain nursery
   4305  // pointers.
   4306  MConstant* constValue = ins->value()->maybeConstantValue();
   4307  if (constValue) {
   4308    MOZ_ASSERT(JS::GCPolicy<Value>::isTenured(constValue->toJSValue()));
   4309    return;
   4310  }
   4311 
   4312  switch (ins->value()->type()) {
   4313    case MIRType::Object: {
   4314      LDefinition tmp =
   4315          needTempForPostBarrier() ? temp() : LDefinition::BogusTemp();
   4316      LPostWriteBarrierO* lir = new (alloc()) LPostWriteBarrierO(
   4317          useRegisterOrConstant(ins->object()), useRegister(ins->value()), tmp);
   4318      add(lir, ins);
   4319      assignSafepoint(lir, ins);
   4320      break;
   4321    }
   4322    case MIRType::String: {
   4323      LDefinition tmp =
   4324          needTempForPostBarrier() ? temp() : LDefinition::BogusTemp();
   4325      LPostWriteBarrierS* lir = new (alloc()) LPostWriteBarrierS(
   4326          useRegisterOrConstant(ins->object()), useRegister(ins->value()), tmp);
   4327      add(lir, ins);
   4328      assignSafepoint(lir, ins);
   4329      break;
   4330    }
   4331    case MIRType::BigInt: {
   4332      LDefinition tmp =
   4333          needTempForPostBarrier() ? temp() : LDefinition::BogusTemp();
   4334      auto* lir = new (alloc()) LPostWriteBarrierBI(
   4335          useRegisterOrConstant(ins->object()), useRegister(ins->value()), tmp);
   4336      add(lir, ins);
   4337      assignSafepoint(lir, ins);
   4338      break;
   4339    }
   4340    case MIRType::Value: {
   4341      LDefinition tmp =
   4342          needTempForPostBarrier() ? temp() : LDefinition::BogusTemp();
   4343      LPostWriteBarrierV* lir = new (alloc()) LPostWriteBarrierV(
   4344          useRegisterOrConstant(ins->object()), useBox(ins->value()), tmp);
   4345      add(lir, ins);
   4346      assignSafepoint(lir, ins);
   4347      break;
   4348    }
   4349    default:
   4350      // Currently, only objects, strings, and bigints can be in the nursery.
   4351      // Other instruction types cannot hold nursery pointers.
   4352      MOZ_ASSERT(!NeedsPostBarrier(ins->value()->type()));
   4353      break;
   4354  }
   4355 }
   4356 
   4357 void LIRGenerator::visitPostWriteElementBarrier(MPostWriteElementBarrier* ins) {
   4358  MOZ_ASSERT(ins->object()->type() == MIRType::Object);
   4359  MOZ_ASSERT(ins->index()->type() == MIRType::Int32);
   4360 
   4361  // We need a barrier if the value might be allocated in the nursery. If the
   4362  // value is a constant, it must be tenured because MIR can't contain nursery
   4363  // pointers.
   4364  MConstant* constValue = ins->value()->maybeConstantValue();
   4365  if (constValue) {
   4366    MOZ_ASSERT(JS::GCPolicy<Value>::isTenured(constValue->toJSValue()));
   4367    return;
   4368  }
   4369 
   4370  switch (ins->value()->type()) {
   4371    case MIRType::Object: {
   4372      LDefinition tmp =
   4373          needTempForPostBarrier() ? temp() : LDefinition::BogusTemp();
   4374      LPostWriteElementBarrierO* lir = new (alloc()) LPostWriteElementBarrierO(
   4375          useRegisterOrConstant(ins->object()), useRegister(ins->value()),
   4376          useRegister(ins->index()), tmp);
   4377      add(lir, ins);
   4378      assignSafepoint(lir, ins);
   4379      break;
   4380    }
   4381    case MIRType::String: {
   4382      LDefinition tmp =
   4383          needTempForPostBarrier() ? temp() : LDefinition::BogusTemp();
   4384      LPostWriteElementBarrierS* lir = new (alloc()) LPostWriteElementBarrierS(
   4385          useRegisterOrConstant(ins->object()), useRegister(ins->value()),
   4386          useRegister(ins->index()), tmp);
   4387      add(lir, ins);
   4388      assignSafepoint(lir, ins);
   4389      break;
   4390    }
   4391    case MIRType::BigInt: {
   4392      LDefinition tmp =
   4393          needTempForPostBarrier() ? temp() : LDefinition::BogusTemp();
   4394      auto* lir = new (alloc()) LPostWriteElementBarrierBI(
   4395          useRegisterOrConstant(ins->object()), useRegister(ins->value()),
   4396          useRegister(ins->index()), tmp);
   4397      add(lir, ins);
   4398      assignSafepoint(lir, ins);
   4399      break;
   4400    }
   4401    case MIRType::Value: {
   4402      LDefinition tmp =
   4403          needTempForPostBarrier() ? temp() : LDefinition::BogusTemp();
   4404      LPostWriteElementBarrierV* lir = new (alloc()) LPostWriteElementBarrierV(
   4405          useRegisterOrConstant(ins->object()), useRegister(ins->index()),
   4406          useBox(ins->value()), tmp);
   4407      add(lir, ins);
   4408      assignSafepoint(lir, ins);
   4409      break;
   4410    }
   4411    default:
   4412      // Currently, only objects, strings, and bigints can be in the nursery.
   4413      // Other instruction types cannot hold nursery pointers.
   4414      MOZ_ASSERT(!NeedsPostBarrier(ins->value()->type()));
   4415      break;
   4416  }
   4417 }
   4418 
   4419 void LIRGenerator::visitAssertCanElidePostWriteBarrier(
   4420    MAssertCanElidePostWriteBarrier* ins) {
   4421  auto* lir = new (alloc()) LAssertCanElidePostWriteBarrier(
   4422      useRegister(ins->object()), useBox(ins->value()), temp());
   4423  add(lir, ins);
   4424 }
   4425 
   4426 void LIRGenerator::visitArrayLength(MArrayLength* ins) {
   4427  MOZ_ASSERT(ins->elements()->type() == MIRType::Elements);
   4428  auto* lir = new (alloc()) LArrayLength(useRegisterAtStart(ins->elements()));
   4429  assignSnapshot(lir, ins->bailoutKind());
   4430  define(lir, ins);
   4431 }
   4432 
   4433 void LIRGenerator::visitSetArrayLength(MSetArrayLength* ins) {
   4434  MOZ_ASSERT(ins->elements()->type() == MIRType::Elements);
   4435  MOZ_ASSERT(ins->index()->type() == MIRType::Int32);
   4436 
   4437  MOZ_ASSERT(ins->index()->isConstant());
   4438  add(new (alloc()) LSetArrayLength(useRegister(ins->elements()),
   4439                                    useRegisterOrConstant(ins->index())),
   4440      ins);
   4441 }
   4442 
   4443 void LIRGenerator::visitFunctionLength(MFunctionLength* ins) {
   4444  MOZ_ASSERT(ins->function()->type() == MIRType::Object);
   4445 
   4446  auto* lir = new (alloc()) LFunctionLength(useRegister(ins->function()));
   4447  assignSnapshot(lir, ins->bailoutKind());
   4448  define(lir, ins);
   4449 }
   4450 
   4451 void LIRGenerator::visitFunctionName(MFunctionName* ins) {
   4452  MOZ_ASSERT(ins->function()->type() == MIRType::Object);
   4453 
   4454  auto* lir = new (alloc()) LFunctionName(useRegister(ins->function()));
   4455  assignSnapshot(lir, ins->bailoutKind());
   4456  define(lir, ins);
   4457 }
   4458 
   4459 void LIRGenerator::visitGetNextEntryForIterator(MGetNextEntryForIterator* ins) {
   4460  MOZ_ASSERT(ins->iter()->type() == MIRType::Object);
   4461  MOZ_ASSERT(ins->result()->type() == MIRType::Object);
   4462  auto lir = new (alloc()) LGetNextEntryForIterator(useRegister(ins->iter()),
   4463                                                    useRegister(ins->result()),
   4464                                                    temp(), temp(), temp());
   4465  define(lir, ins);
   4466 }
   4467 
   4468 void LIRGenerator::visitArrayBufferByteLength(MArrayBufferByteLength* ins) {
   4469  MOZ_ASSERT(ins->object()->type() == MIRType::Object);
   4470  MOZ_ASSERT(ins->type() == MIRType::IntPtr);
   4471 
   4472  auto* lir =
   4473      new (alloc()) LArrayBufferByteLength(useRegisterAtStart(ins->object()));
   4474  define(lir, ins);
   4475 }
   4476 
   4477 void LIRGenerator::visitArrayBufferViewLength(MArrayBufferViewLength* ins) {
   4478  MOZ_ASSERT(ins->object()->type() == MIRType::Object);
   4479  MOZ_ASSERT(ins->type() == MIRType::IntPtr);
   4480 
   4481  auto* lir =
   4482      new (alloc()) LArrayBufferViewLength(useRegisterAtStart(ins->object()));
   4483  define(lir, ins);
   4484 }
   4485 
   4486 void LIRGenerator::visitArrayBufferViewByteOffset(
   4487    MArrayBufferViewByteOffset* ins) {
   4488  MOZ_ASSERT(ins->object()->type() == MIRType::Object);
   4489  MOZ_ASSERT(ins->type() == MIRType::IntPtr);
   4490 
   4491  auto* lir = new (alloc())
   4492      LArrayBufferViewByteOffset(useRegisterAtStart(ins->object()));
   4493  define(lir, ins);
   4494 }
   4495 
   4496 void LIRGenerator::visitArrayBufferViewElements(MArrayBufferViewElements* ins) {
   4497  MOZ_ASSERT(ins->type() == MIRType::Elements);
   4498  define(new (alloc())
   4499             LArrayBufferViewElements(useRegisterAtStart(ins->object())),
   4500         ins);
   4501 }
   4502 
   4503 void LIRGenerator::visitArrayBufferViewElementsWithOffset(
   4504    MArrayBufferViewElementsWithOffset* ins) {
   4505  MOZ_ASSERT(ins->offset()->type() == MIRType::IntPtr);
   4506  MOZ_ASSERT(ins->type() == MIRType::Elements);
   4507 
   4508  define(new (alloc()) LArrayBufferViewElementsWithOffset(
   4509             useRegister(ins->object()),
   4510             useRegisterOrIndexConstant(ins->offset(), ins->elementType())),
   4511         ins);
   4512 }
   4513 
   4514 void LIRGenerator::visitTypedArrayElementSize(MTypedArrayElementSize* ins) {
   4515  MOZ_ASSERT(ins->object()->type() == MIRType::Object);
   4516  define(new (alloc())
   4517             LTypedArrayElementSize(useRegisterAtStart(ins->object())),
   4518         ins);
   4519 }
   4520 
   4521 void LIRGenerator::visitResizableTypedArrayLength(
   4522    MResizableTypedArrayLength* ins) {
   4523  MOZ_ASSERT(ins->object()->type() == MIRType::Object);
   4524  MOZ_ASSERT(ins->type() == MIRType::IntPtr);
   4525 
   4526  auto* lir = new (alloc())
   4527      LResizableTypedArrayLength(useRegister(ins->object()), temp());
   4528  define(lir, ins);
   4529 }
   4530 
   4531 void LIRGenerator::visitResizableDataViewByteLength(
   4532    MResizableDataViewByteLength* ins) {
   4533  MOZ_ASSERT(ins->object()->type() == MIRType::Object);
   4534  MOZ_ASSERT(ins->type() == MIRType::IntPtr);
   4535 
   4536  auto* lir = new (alloc())
   4537      LResizableDataViewByteLength(useRegister(ins->object()), temp());
   4538  define(lir, ins);
   4539 }
   4540 
   4541 void LIRGenerator::visitGrowableSharedArrayBufferByteLength(
   4542    MGrowableSharedArrayBufferByteLength* ins) {
   4543  MOZ_ASSERT(ins->object()->type() == MIRType::Object);
   4544  MOZ_ASSERT(ins->type() == MIRType::IntPtr);
   4545 
   4546  auto* lir = new (alloc())
   4547      LGrowableSharedArrayBufferByteLength(useRegisterAtStart(ins->object()));
   4548  define(lir, ins);
   4549 }
   4550 
   4551 void LIRGenerator::visitGuardResizableArrayBufferViewInBounds(
   4552    MGuardResizableArrayBufferViewInBounds* ins) {
   4553  MOZ_ASSERT(ins->object()->type() == MIRType::Object);
   4554 
   4555  auto* lir = new (alloc()) LGuardResizableArrayBufferViewInBounds(
   4556      useRegister(ins->object()), temp());
   4557  assignSnapshot(lir, ins->bailoutKind());
   4558  add(lir, ins);
   4559  redefine(ins, ins->object());
   4560 }
   4561 
   4562 void LIRGenerator::visitGuardResizableArrayBufferViewInBoundsOrDetached(
   4563    MGuardResizableArrayBufferViewInBoundsOrDetached* ins) {
   4564  MOZ_ASSERT(ins->object()->type() == MIRType::Object);
   4565 
   4566  auto* lir = new (alloc()) LGuardResizableArrayBufferViewInBoundsOrDetached(
   4567      useRegister(ins->object()), temp());
   4568  assignSnapshot(lir, ins->bailoutKind());
   4569  add(lir, ins);
   4570  redefine(ins, ins->object());
   4571 }
   4572 
   4573 void LIRGenerator::visitGuardHasAttachedArrayBuffer(
   4574    MGuardHasAttachedArrayBuffer* ins) {
   4575  MOZ_ASSERT(ins->object()->type() == MIRType::Object);
   4576 
   4577  auto* lir = new (alloc())
   4578      LGuardHasAttachedArrayBuffer(useRegister(ins->object()), temp());
   4579  assignSnapshot(lir, ins->bailoutKind());
   4580  add(lir, ins);
   4581  redefine(ins, ins->object());
   4582 }
   4583 
   4584 void LIRGenerator::visitGuardTypedArraySetOffset(
   4585    MGuardTypedArraySetOffset* ins) {
   4586  auto* lir = new (alloc()) LGuardTypedArraySetOffset(
   4587      useRegister(ins->offset()), useRegister(ins->targetLength()),
   4588      useRegister(ins->sourceLength()), temp());
   4589  assignSnapshot(lir, ins->bailoutKind());
   4590  add(lir, ins);
   4591  redefine(ins, ins->offset());
   4592 }
   4593 
   4594 void LIRGenerator::visitTypedArrayFill(MTypedArrayFill* ins) {
   4595  if (ins->isBigIntWrite()) {
   4596    auto* lir = new (alloc()) LTypedArrayFill64(
   4597        useRegisterAtStart(ins->object()),
   4598        useInt64RegisterAtStart(ins->value()), useRegisterAtStart(ins->start()),
   4599        useRegisterAtStart(ins->end()));
   4600    add(lir, ins);
   4601  } else {
   4602    auto* lir = new (alloc()) LTypedArrayFill(
   4603        useRegisterAtStart(ins->object()), useRegisterAtStart(ins->value()),
   4604        useRegisterAtStart(ins->start()), useRegisterAtStart(ins->end()));
   4605    add(lir, ins);
   4606  }
   4607 }
   4608 
   4609 void LIRGenerator::visitTypedArraySet(MTypedArraySet* ins) {
   4610  auto* lir = new (alloc()) LTypedArraySet(useRegisterAtStart(ins->target()),
   4611                                           useRegisterAtStart(ins->source()),
   4612                                           useRegisterAtStart(ins->offset()));
   4613  add(lir, ins);
   4614  if (!ins->canUseBitwiseCopy()) {
   4615    assignSafepoint(lir, ins);
   4616  }
   4617 }
   4618 
   4619 void LIRGenerator::visitTypedArraySetFromSubarray(
   4620    MTypedArraySetFromSubarray* ins) {
   4621  auto* lir = new (alloc()) LTypedArraySetFromSubarray(
   4622      useRegisterAtStart(ins->target()), useRegisterAtStart(ins->source()),
   4623      useRegisterAtStart(ins->offset()),
   4624      useRegisterAtStart(ins->sourceOffset()),
   4625      useRegisterAtStart(ins->sourceLength()));
   4626  add(lir, ins);
   4627  if (!ins->canUseBitwiseCopy()) {
   4628    assignSafepoint(lir, ins);
   4629  }
   4630 }
   4631 
   4632 void LIRGenerator::visitTypedArraySubarray(MTypedArraySubarray* ins) {
   4633  auto* lir = new (alloc()) LTypedArraySubarray(
   4634      useRegisterAtStart(ins->object()), useRegisterAtStart(ins->start()),
   4635      useRegisterAtStart(ins->length()));
   4636  defineReturn(lir, ins);
   4637  assignSafepoint(lir, ins);
   4638 }
   4639 
   4640 void LIRGenerator::visitToIntegerIndex(MToIntegerIndex* ins) {
   4641  MOZ_ASSERT(ins->index()->type() == MIRType::IntPtr);
   4642  MOZ_ASSERT(ins->length()->type() == MIRType::IntPtr);
   4643 
   4644  auto* lir = new (alloc())
   4645      LToIntegerIndex(useRegister(ins->index()), useRegister(ins->length()));
   4646  define(lir, ins);
   4647 }
   4648 
   4649 void LIRGenerator::visitGuardNumberToIntPtrIndex(
   4650    MGuardNumberToIntPtrIndex* ins) {
   4651  MDefinition* input = ins->input();
   4652  MOZ_ASSERT(input->type() == MIRType::Double);
   4653 
   4654  auto* lir = new (alloc()) LGuardNumberToIntPtrIndex(useRegister(input));
   4655  if (!ins->supportOOB()) {
   4656    assignSnapshot(lir, ins->bailoutKind());
   4657  }
   4658  define(lir, ins);
   4659 }
   4660 
   4661 void LIRGenerator::visitInitializedLength(MInitializedLength* ins) {
   4662  MOZ_ASSERT(ins->elements()->type() == MIRType::Elements);
   4663  define(new (alloc()) LInitializedLength(useRegisterAtStart(ins->elements())),
   4664         ins);
   4665 }
   4666 
   4667 void LIRGenerator::visitSetInitializedLength(MSetInitializedLength* ins) {
   4668  MOZ_ASSERT(ins->elements()->type() == MIRType::Elements);
   4669  MOZ_ASSERT(ins->index()->type() == MIRType::Int32);
   4670 
   4671  MOZ_ASSERT(ins->index()->isConstant());
   4672  add(new (alloc()) LSetInitializedLength(useRegister(ins->elements()),
   4673                                          useRegisterOrConstant(ins->index())),
   4674      ins);
   4675 }
   4676 
   4677 void LIRGenerator::visitNot(MNot* ins) {
   4678  MDefinition* op = ins->input();
   4679 
   4680  // String is converted to length of string in the type analysis phase (see
   4681  // TestPolicy).
   4682  MOZ_ASSERT(op->type() != MIRType::String);
   4683 
   4684  // - boolean: x xor 1
   4685  // - int32: LCompare(x, 0)
   4686  // - double: LCompare(x, 0)
   4687  // - null or undefined: true
   4688  // - symbol: false
   4689  // - bigint: LNotBI(x)
   4690  // - object: false if it never emulates undefined, else LNotO(x)
   4691  switch (op->type()) {
   4692    case MIRType::Boolean: {
   4693      MConstant* cons = MConstant::NewInt32(alloc(), 1);
   4694      ins->block()->insertBefore(ins, cons);
   4695      lowerForALU(new (alloc()) LBitOpI(JSOp::BitXor), ins, op, cons);
   4696      break;
   4697    }
   4698    case MIRType::Int32:
   4699      define(new (alloc()) LNotI(useRegisterAtStart(op)), ins);
   4700      break;
   4701    case MIRType::IntPtr:
   4702      define(new (alloc()) LNotIPtr(useRegisterAtStart(op)), ins);
   4703      break;
   4704    case MIRType::Int64:
   4705      define(new (alloc()) LNotI64(useInt64RegisterAtStart(op)), ins);
   4706      break;
   4707    case MIRType::Double:
   4708      define(new (alloc()) LNotD(useRegister(op)), ins);
   4709      break;
   4710    case MIRType::Float32:
   4711      define(new (alloc()) LNotF(useRegister(op)), ins);
   4712      break;
   4713    case MIRType::Undefined:
   4714    case MIRType::Null:
   4715      define(new (alloc()) LInteger(1), ins);
   4716      break;
   4717    case MIRType::Symbol:
   4718      define(new (alloc()) LInteger(0), ins);
   4719      break;
   4720    case MIRType::BigInt:
   4721      define(new (alloc()) LNotBI(useRegisterAtStart(op)), ins);
   4722      break;
   4723    case MIRType::Object:
   4724      define(new (alloc()) LNotO(useRegister(op)), ins);
   4725      break;
   4726    case MIRType::Value: {
   4727      auto* lir = new (alloc()) LNotV(useBox(op), tempDouble(), tempToUnbox());
   4728      define(lir, ins);
   4729      break;
   4730    }
   4731 
   4732    default:
   4733      MOZ_CRASH("Unexpected MIRType.");
   4734  }
   4735 }
   4736 
   4737 void LIRGenerator::visitBoundsCheck(MBoundsCheck* ins) {
   4738  MOZ_ASSERT(ins->type() == MIRType::Int32 || ins->type() == MIRType::IntPtr);
   4739  MOZ_ASSERT(ins->index()->type() == ins->type());
   4740  MOZ_ASSERT(ins->length()->type() == ins->type());
   4741 
   4742  if (!ins->fallible()) {
   4743    return;
   4744  }
   4745 
   4746  if (ins->minimum() || ins->maximum()) {
   4747    auto* check = new (alloc())
   4748        LBoundsCheckRange(useRegisterOrInt32Constant(ins->index()),
   4749                          useAny(ins->length()), temp());
   4750    assignSnapshot(check, ins->bailoutKind());
   4751    add(check, ins);
   4752  } else {
   4753    auto* check =
   4754        new (alloc()) LBoundsCheck(useRegisterOrInt32Constant(ins->index()),
   4755                                   useAnyOrInt32Constant(ins->length()));
   4756    assignSnapshot(check, ins->bailoutKind());
   4757    add(check, ins);
   4758  }
   4759 }
   4760 
   4761 void LIRGenerator::visitSpectreMaskIndex(MSpectreMaskIndex* ins) {
   4762  MOZ_ASSERT(ins->type() == MIRType::Int32 || ins->type() == MIRType::IntPtr);
   4763  MOZ_ASSERT(ins->index()->type() == ins->type());
   4764  MOZ_ASSERT(ins->length()->type() == ins->type());
   4765 
   4766  auto* lir = new (alloc())
   4767      LSpectreMaskIndex(useRegister(ins->index()), useAny(ins->length()));
   4768  define(lir, ins);
   4769 }
   4770 
   4771 void LIRGenerator::visitBoundsCheckLower(MBoundsCheckLower* ins) {
   4772  MOZ_ASSERT(ins->index()->type() == MIRType::Int32);
   4773 
   4774  if (!ins->fallible()) {
   4775    return;
   4776  }
   4777 
   4778  auto* check = new (alloc()) LBoundsCheckLower(useRegister(ins->index()));
   4779  assignSnapshot(check, ins->bailoutKind());
   4780  add(check, ins);
   4781 }
   4782 
   4783 void LIRGenerator::visitInArray(MInArray* ins) {
   4784  MOZ_ASSERT(ins->elements()->type() == MIRType::Elements);
   4785  MOZ_ASSERT(ins->index()->type() == MIRType::Int32);
   4786  MOZ_ASSERT(ins->initLength()->type() == MIRType::Int32);
   4787  MOZ_ASSERT(ins->type() == MIRType::Boolean);
   4788 
   4789  auto* lir = new (alloc()) LInArray(useRegister(ins->elements()),
   4790                                     useRegisterOrConstant(ins->index()),
   4791                                     useRegister(ins->initLength()));
   4792  if (ins->needsNegativeIntCheck()) {
   4793    assignSnapshot(lir, ins->bailoutKind());
   4794  }
   4795  define(lir, ins);
   4796 }
   4797 
   4798 void LIRGenerator::visitGuardElementNotHole(MGuardElementNotHole* ins) {
   4799  MOZ_ASSERT(ins->elements()->type() == MIRType::Elements);
   4800  MOZ_ASSERT(ins->index()->type() == MIRType::Int32);
   4801 
   4802  auto* guard = new (alloc())
   4803      LGuardElementNotHole(useRegisterAtStart(ins->elements()),
   4804                           useRegisterOrConstantAtStart(ins->index()));
   4805  assignSnapshot(guard, ins->bailoutKind());
   4806  add(guard, ins);
   4807 }
   4808 
   4809 void LIRGenerator::visitLoadElement(MLoadElement* ins) {
   4810  MOZ_ASSERT(ins->elements()->type() == MIRType::Elements);
   4811  MOZ_ASSERT(ins->index()->type() == MIRType::Int32);
   4812  MOZ_ASSERT(ins->type() == MIRType::Value);
   4813 
   4814  auto* lir = new (alloc()) LLoadElementV(useRegister(ins->elements()),
   4815                                          useRegisterOrConstant(ins->index()));
   4816  if (ins->needsHoleCheck()) {
   4817    assignSnapshot(lir, ins->bailoutKind());
   4818  }
   4819  defineBox(lir, ins);
   4820 }
   4821 
   4822 void LIRGenerator::visitLoadElementHole(MLoadElementHole* ins) {
   4823  MOZ_ASSERT(ins->elements()->type() == MIRType::Elements);
   4824  MOZ_ASSERT(ins->index()->type() == MIRType::Int32);
   4825  MOZ_ASSERT(ins->initLength()->type() == MIRType::Int32);
   4826  MOZ_ASSERT(ins->type() == MIRType::Value);
   4827 
   4828  LLoadElementHole* lir = new (alloc())
   4829      LLoadElementHole(useRegister(ins->elements()), useRegister(ins->index()),
   4830                       useRegister(ins->initLength()));
   4831  if (ins->needsNegativeIntCheck()) {
   4832    assignSnapshot(lir, ins->bailoutKind());
   4833  }
   4834  defineBox(lir, ins);
   4835 }
   4836 
   4837 void LIRGenerator::visitStoreElement(MStoreElement* ins) {
   4838  MOZ_ASSERT(ins->elements()->type() == MIRType::Elements);
   4839  MOZ_ASSERT(ins->index()->type() == MIRType::Int32);
   4840 
   4841  const LUse elements = useRegister(ins->elements());
   4842  const LAllocation index = useRegisterOrConstant(ins->index());
   4843 
   4844  switch (ins->value()->type()) {
   4845    case MIRType::Value: {
   4846      auto* lir =
   4847          new (alloc()) LStoreElementV(elements, index, useBox(ins->value()));
   4848      if (ins->fallible()) {
   4849        assignSnapshot(lir, ins->bailoutKind());
   4850      }
   4851      add(lir, ins);
   4852      break;
   4853    }
   4854 
   4855    default: {
   4856      const LAllocation value = useRegisterOrNonDoubleConstant(ins->value());
   4857      auto* lir = new (alloc()) LStoreElementT(elements, index, value);
   4858      if (ins->fallible()) {
   4859        assignSnapshot(lir, ins->bailoutKind());
   4860      }
   4861      add(lir, ins);
   4862      break;
   4863    }
   4864  }
   4865 }
   4866 
   4867 void LIRGenerator::visitStoreHoleValueElement(MStoreHoleValueElement* ins) {
   4868  MOZ_ASSERT(ins->elements()->type() == MIRType::Elements);
   4869  MOZ_ASSERT(ins->index()->type() == MIRType::Int32);
   4870 
   4871  auto* lir = new (alloc()) LStoreHoleValueElement(useRegister(ins->elements()),
   4872                                                   useRegister(ins->index()));
   4873  add(lir, ins);
   4874 }
   4875 
   4876 static bool BoundsCheckNeedsSpectreTemp() {
   4877  // On x86, spectreBoundsCheck32 can emit better code if it has a scratch
   4878  // register and index masking is enabled.
   4879 #ifdef JS_CODEGEN_X86
   4880  return JitOptions.spectreIndexMasking;
   4881 #else
   4882  return false;
   4883 #endif
   4884 }
   4885 
   4886 void LIRGenerator::visitStoreElementHole(MStoreElementHole* ins) {
   4887  MOZ_ASSERT(ins->elements()->type() == MIRType::Elements);
   4888  MOZ_ASSERT(ins->index()->type() == MIRType::Int32);
   4889 
   4890  const LUse object = useRegister(ins->object());
   4891  const LUse elements = useRegister(ins->elements());
   4892  const LAllocation index = useRegister(ins->index());
   4893 
   4894  switch (ins->value()->type()) {
   4895    case MIRType::Value: {
   4896      auto* lir = new (alloc()) LStoreElementHoleV(
   4897          object, elements, index, useBox(ins->value()), temp());
   4898      assignSnapshot(lir, ins->bailoutKind());
   4899      add(lir, ins);
   4900      assignSafepoint(lir, ins);
   4901      break;
   4902    }
   4903    default: {
   4904      const LAllocation value = useRegisterOrNonDoubleConstant(ins->value());
   4905      auto* lir = new (alloc())
   4906          LStoreElementHoleT(object, elements, index, value, temp());
   4907      assignSnapshot(lir, ins->bailoutKind());
   4908      add(lir, ins);
   4909      assignSafepoint(lir, ins);
   4910      break;
   4911    }
   4912  }
   4913 }
   4914 
   4915 void LIRGenerator::visitEffectiveAddress3(MEffectiveAddress3* ins) {
   4916  define(new (alloc()) LEffectiveAddress3(useRegister(ins->base()),
   4917                                          useRegister(ins->index())),
   4918         ins);
   4919 }
   4920 
   4921 void LIRGenerator::visitEffectiveAddress2(MEffectiveAddress2* ins) {
   4922  define(new (alloc()) LEffectiveAddress2(useRegister(ins->index())), ins);
   4923 }
   4924 
   4925 void LIRGenerator::visitArrayPopShift(MArrayPopShift* ins) {
   4926  MOZ_ASSERT(ins->type() == MIRType::Value);
   4927 
   4928  auto* lir =
   4929      new (alloc()) LArrayPopShift(useRegister(ins->object()), temp(), temp());
   4930  assignSnapshot(lir, ins->bailoutKind());
   4931  defineBox(lir, ins);
   4932 
   4933  if (ins->mode() == MArrayPopShift::Shift) {
   4934    assignSafepoint(lir, ins);
   4935  }
   4936 }
   4937 
   4938 void LIRGenerator::visitArrayPush(MArrayPush* ins) {
   4939  MOZ_ASSERT(ins->type() == MIRType::Int32);
   4940  MOZ_ASSERT(ins->value()->type() == MIRType::Value);
   4941 
   4942  LUse object = useRegister(ins->object());
   4943 
   4944  LDefinition spectreTemp =
   4945      BoundsCheckNeedsSpectreTemp() ? temp() : LDefinition::BogusTemp();
   4946 
   4947  auto* lir = new (alloc())
   4948      LArrayPush(object, useBox(ins->value()), temp(), spectreTemp);
   4949  // We will bailout before pushing if the length would overflow INT32_MAX.
   4950  assignSnapshot(lir, ins->bailoutKind());
   4951  define(lir, ins);
   4952  assignSafepoint(lir, ins);
   4953 }
   4954 
   4955 void LIRGenerator::visitArraySlice(MArraySlice* ins) {
   4956  MOZ_ASSERT(ins->type() == MIRType::Object);
   4957  MOZ_ASSERT(ins->object()->type() == MIRType::Object);
   4958  MOZ_ASSERT(ins->begin()->type() == MIRType::Int32);
   4959  MOZ_ASSERT(ins->end()->type() == MIRType::Int32);
   4960 
   4961  LArraySlice* lir = new (alloc()) LArraySlice(
   4962      useRegisterAtStart(ins->object()), useRegisterAtStart(ins->begin()),
   4963      useRegisterAtStart(ins->end()), tempFixed(CallTempReg0),
   4964      tempFixed(CallTempReg1));
   4965  assignSnapshot(lir, ins->bailoutKind());
   4966  defineReturn(lir, ins);
   4967  assignSafepoint(lir, ins);
   4968 }
   4969 
   4970 void LIRGenerator::visitArgumentsSlice(MArgumentsSlice* ins) {
   4971  MOZ_ASSERT(ins->type() == MIRType::Object);
   4972  MOZ_ASSERT(ins->object()->type() == MIRType::Object);
   4973  MOZ_ASSERT(ins->begin()->type() == MIRType::Int32);
   4974  MOZ_ASSERT(ins->end()->type() == MIRType::Int32);
   4975 
   4976  auto* lir = new (alloc()) LArgumentsSlice(
   4977      useRegisterAtStart(ins->object()), useRegisterAtStart(ins->begin()),
   4978      useRegisterAtStart(ins->end()), tempFixed(CallTempReg0),
   4979      tempFixed(CallTempReg1));
   4980  defineReturn(lir, ins);
   4981  assignSafepoint(lir, ins);
   4982 }
   4983 
   4984 void LIRGenerator::visitFrameArgumentsSlice(MFrameArgumentsSlice* ins) {
   4985  MOZ_ASSERT(ins->type() == MIRType::Object);
   4986  MOZ_ASSERT(ins->begin()->type() == MIRType::Int32);
   4987  MOZ_ASSERT(ins->count()->type() == MIRType::Int32);
   4988 
   4989  auto* lir = new (alloc()) LFrameArgumentsSlice(
   4990      useRegister(ins->begin()), useRegister(ins->count()), temp());
   4991  define(lir, ins);
   4992  assignSafepoint(lir, ins);
   4993 }
   4994 
   4995 void LIRGenerator::visitInlineArgumentsSlice(MInlineArgumentsSlice* ins) {
   4996  LAllocation begin = useRegisterOrConstant(ins->begin());
   4997  LAllocation count = useRegisterOrConstant(ins->count());
   4998  uint32_t numActuals = ins->numActuals();
   4999  uint32_t numOperands =
   5000      numActuals * BOX_PIECES + LInlineArgumentsSlice::NumNonArgumentOperands;
   5001 
   5002  auto* lir = allocateVariadic<LInlineArgumentsSlice>(numOperands, temp());
   5003  if (!lir) {
   5004    abort(AbortReason::Alloc, "OOM: LIRGenerator::visitInlineArgumentsSlice");
   5005    return;
   5006  }
   5007 
   5008  lir->setOperand(LInlineArgumentsSlice::Begin, begin);
   5009  lir->setOperand(LInlineArgumentsSlice::Count, count);
   5010  for (uint32_t i = 0; i < numActuals; i++) {
   5011    MDefinition* arg = ins->getArg(i);
   5012    uint32_t index = LInlineArgumentsSlice::ArgIndex(i);
   5013    lir->setBoxOperand(index,
   5014                       useBoxOrTypedOrConstant(arg, /*useConstant = */ true));
   5015  }
   5016  define(lir, ins);
   5017  assignSafepoint(lir, ins);
   5018 }
   5019 
   5020 void LIRGenerator::visitNormalizeSliceTerm(MNormalizeSliceTerm* ins) {
   5021  MOZ_ASSERT(ins->type() == MIRType::Int32);
   5022  MOZ_ASSERT(ins->value()->type() == MIRType::Int32);
   5023  MOZ_ASSERT(ins->length()->type() == MIRType::Int32);
   5024 
   5025  auto* lir = new (alloc()) LNormalizeSliceTerm(useRegister(ins->value()),
   5026                                                useRegister(ins->length()));
   5027  define(lir, ins);
   5028 }
   5029 
   5030 void LIRGenerator::visitArrayJoin(MArrayJoin* ins) {
   5031  MOZ_ASSERT(ins->type() == MIRType::String);
   5032  MOZ_ASSERT(ins->array()->type() == MIRType::Object);
   5033  MOZ_ASSERT(ins->separator()->type() == MIRType::String);
   5034 
   5035  auto* lir = new (alloc())
   5036      LArrayJoin(useRegisterAtStart(ins->array()),
   5037                 useRegisterAtStart(ins->separator()), tempFixed(CallTempReg0));
   5038  defineReturn(lir, ins);
   5039  assignSafepoint(lir, ins);
   5040 }
   5041 
   5042 void LIRGenerator::visitObjectKeys(MObjectKeys* ins) {
   5043  MOZ_ASSERT(ins->object()->type() == MIRType::Object);
   5044  MOZ_ASSERT(ins->type() == MIRType::Object);
   5045 
   5046  auto* lir = new (alloc()) LObjectKeys(useRegisterAtStart(ins->object()));
   5047  defineReturn(lir, ins);
   5048  assignSafepoint(lir, ins);
   5049 }
   5050 
   5051 void LIRGenerator::visitObjectKeysFromIterator(MObjectKeysFromIterator* ins) {
   5052  MOZ_CRASH("ObjectKeysFromIterator is purely for recovery purposes.");
   5053 }
   5054 
   5055 void LIRGenerator::visitObjectKeysLength(MObjectKeysLength* ins) {
   5056  MOZ_ASSERT(ins->object()->type() == MIRType::Object);
   5057  MOZ_ASSERT(ins->type() == MIRType::Int32);
   5058 
   5059  auto* lir =
   5060      new (alloc()) LObjectKeysLength(useRegisterAtStart(ins->object()));
   5061  defineReturn(lir, ins);
   5062  assignSafepoint(lir, ins);
   5063 }
   5064 
   5065 void LIRGenerator::visitStringSplit(MStringSplit* ins) {
   5066  MOZ_ASSERT(ins->type() == MIRType::Object);
   5067  MOZ_ASSERT(ins->string()->type() == MIRType::String);
   5068  MOZ_ASSERT(ins->separator()->type() == MIRType::String);
   5069 
   5070  LStringSplit* lir = new (alloc()) LStringSplit(
   5071      useRegisterAtStart(ins->string()), useRegisterAtStart(ins->separator()));
   5072  defineReturn(lir, ins);
   5073  assignSafepoint(lir, ins);
   5074 }
   5075 
   5076 void LIRGenerator::visitLoadUnboxedScalar(MLoadUnboxedScalar* ins) {
   5077  MOZ_ASSERT(ins->elements()->type() == MIRType::Elements);
   5078  MOZ_ASSERT(ins->index()->type() == MIRType::IntPtr);
   5079  MOZ_ASSERT(IsNumberType(ins->type()));
   5080 
   5081  auto sync = SynchronizeLoad(ins->requiresMemoryBarrier());
   5082 
   5083  if (Scalar::isBigIntType(ins->storageType()) && !sync.isNone()) {
   5084    lowerAtomicLoad64(ins);
   5085    return;
   5086  }
   5087 
   5088  const LUse elements = useRegister(ins->elements());
   5089  const LAllocation index =
   5090      useRegisterOrIndexConstant(ins->index(), ins->storageType());
   5091 
   5092  if (Scalar::isBigIntType(ins->storageType())) {
   5093    MOZ_ASSERT(ins->type() == MIRType::Int64);
   5094 
   5095    auto* lir = new (alloc()) LLoadUnboxedInt64(elements, index);
   5096    defineInt64(lir, ins);
   5097    return;
   5098  }
   5099 
   5100  // NOTE: the generated code must match the assembly code in gen_load in
   5101  // GenerateAtomicOperations.py
   5102  if (!sync.isNone()) {
   5103    LMemoryBarrier* fence = new (alloc()) LMemoryBarrier(sync.barrierBefore);
   5104    add(fence, ins);
   5105  }
   5106 
   5107  // We need a temp register for Uint32Array with known double result and for
   5108  // Float16Array.
   5109  LDefinition temp1 = LDefinition::BogusTemp();
   5110  if ((ins->storageType() == Scalar::Uint32 &&
   5111       IsFloatingPointType(ins->type())) ||
   5112      ins->storageType() == Scalar::Float16) {
   5113    temp1 = temp();
   5114  }
   5115 
   5116  // Additional temp when Float16 to Float32 conversion requires a call.
   5117  LDefinition temp2 = LDefinition::BogusTemp();
   5118  if (MacroAssembler::LoadRequiresCall(ins->storageType())) {
   5119    temp2 = temp();
   5120  }
   5121 
   5122  auto* lir = new (alloc()) LLoadUnboxedScalar(elements, index, temp1, temp2);
   5123  if (ins->fallible()) {
   5124    assignSnapshot(lir, ins->bailoutKind());
   5125  }
   5126  define(lir, ins);
   5127 
   5128  if (MacroAssembler::LoadRequiresCall(ins->storageType())) {
   5129    assignSafepoint(lir, ins);
   5130  }
   5131 
   5132  if (!sync.isNone()) {
   5133    LMemoryBarrier* fence = new (alloc()) LMemoryBarrier(sync.barrierAfter);
   5134    add(fence, ins);
   5135  }
   5136 }
   5137 
   5138 void LIRGenerator::visitLoadDataViewElement(MLoadDataViewElement* ins) {
   5139  MOZ_ASSERT(ins->elements()->type() == MIRType::Elements);
   5140  MOZ_ASSERT(ins->index()->type() == MIRType::IntPtr);
   5141 
   5142  MOZ_ASSERT(IsNumberType(ins->type()));
   5143 
   5144  LUse elements = useRegister(ins->elements());
   5145  LAllocation index = useRegisterOrIndexConstant(ins->index(), Scalar::Uint8);
   5146  LAllocation littleEndian = useRegisterOrConstant(ins->littleEndian());
   5147 
   5148  if (Scalar::isBigIntType(ins->storageType())) {
   5149    auto* lir =
   5150        new (alloc()) LLoadDataViewElement64(elements, index, littleEndian);
   5151    defineInt64(lir, ins);
   5152    return;
   5153  }
   5154 
   5155  // We need a temp register for:
   5156  // - Uint32Array with known double result,
   5157  // - Float16Array,
   5158  // - Float32Array.
   5159  LDefinition temp1 = LDefinition::BogusTemp();
   5160  if ((ins->storageType() == Scalar::Uint32 &&
   5161       IsFloatingPointType(ins->type())) ||
   5162      ins->storageType() == Scalar::Float16 ||
   5163      ins->storageType() == Scalar::Float32) {
   5164    temp1 = temp();
   5165  }
   5166 
   5167  // Additional temp when Float16 to Float64 conversion requires a call.
   5168  LDefinition temp2 = LDefinition::BogusTemp();
   5169  if (MacroAssembler::LoadRequiresCall(ins->storageType())) {
   5170    temp2 = temp();
   5171  }
   5172 
   5173  // We also need a separate 64-bit temp register for Float64Array.
   5174  LInt64Definition temp64 = LInt64Definition::BogusTemp();
   5175  if (ins->storageType() == Scalar::Float64) {
   5176    temp64 = tempInt64();
   5177  }
   5178 
   5179  auto* lir = new (alloc())
   5180      LLoadDataViewElement(elements, index, littleEndian, temp1, temp2, temp64);
   5181  if (ins->fallible()) {
   5182    assignSnapshot(lir, ins->bailoutKind());
   5183  }
   5184  define(lir, ins);
   5185  if (MacroAssembler::LoadRequiresCall(ins->storageType())) {
   5186    assignSafepoint(lir, ins);
   5187  }
   5188 }
   5189 
   5190 void LIRGenerator::visitClampToUint8(MClampToUint8* ins) {
   5191  MDefinition* in = ins->input();
   5192 
   5193  switch (in->type()) {
   5194    case MIRType::Int32:
   5195      defineReuseInput(new (alloc()) LClampIToUint8(useRegisterAtStart(in)),
   5196                       ins, 0);
   5197      break;
   5198 
   5199    case MIRType::Double:
   5200      // LClampDToUint8 clobbers its input register. Making it available as
   5201      // a temp copy describes this behavior to the register allocator.
   5202      define(new (alloc())
   5203                 LClampDToUint8(useRegisterAtStart(in), tempCopy(in, 0)),
   5204             ins);
   5205      break;
   5206 
   5207    case MIRType::Value: {
   5208      LClampVToUint8* lir =
   5209          new (alloc()) LClampVToUint8(useBox(in), tempDouble());
   5210      assignSnapshot(lir, ins->bailoutKind());
   5211      define(lir, ins);
   5212      assignSafepoint(lir, ins);
   5213      break;
   5214    }
   5215 
   5216    default:
   5217      MOZ_CRASH("unexpected type");
   5218  }
   5219 }
   5220 
   5221 void LIRGenerator::visitLoadTypedArrayElementHole(
   5222    MLoadTypedArrayElementHole* ins) {
   5223  MOZ_ASSERT(ins->elements()->type() == MIRType::Elements);
   5224  MOZ_ASSERT(ins->index()->type() == MIRType::IntPtr);
   5225  MOZ_ASSERT(ins->length()->type() == MIRType::IntPtr);
   5226 
   5227  MOZ_ASSERT(ins->type() == MIRType::Value);
   5228 
   5229  const LUse elements = useRegister(ins->elements());
   5230  const LAllocation index = useRegister(ins->index());
   5231  const LAllocation length = useRegister(ins->length());
   5232 
   5233  if (!Scalar::isBigIntType(ins->arrayType())) {
   5234    LDefinition tempDef = LDefinition::BogusTemp();
   5235    if (MacroAssembler::LoadRequiresCall(ins->arrayType())) {
   5236      tempDef = temp();
   5237    }
   5238 
   5239    auto* lir = new (alloc())
   5240        LLoadTypedArrayElementHole(elements, index, length, tempDef);
   5241    if (ins->fallible()) {
   5242      assignSnapshot(lir, ins->bailoutKind());
   5243    }
   5244    defineBox(lir, ins);
   5245 
   5246    if (MacroAssembler::LoadRequiresCall(ins->arrayType())) {
   5247      assignSafepoint(lir, ins);
   5248    }
   5249  } else {
   5250 #ifdef JS_CODEGEN_X86
   5251    LInt64Definition temp64 = LInt64Definition::BogusTemp();
   5252 #else
   5253    LInt64Definition temp64 = tempInt64();
   5254 #endif
   5255 
   5256    auto* lir = new (alloc()) LLoadTypedArrayElementHoleBigInt(
   5257        elements, index, length, temp(), temp64);
   5258    defineBox(lir, ins);
   5259    assignSafepoint(lir, ins);
   5260  }
   5261 }
   5262 
   5263 void LIRGenerator::visitStoreUnboxedScalar(MStoreUnboxedScalar* ins) {
   5264  MOZ_ASSERT(ins->elements()->type() == MIRType::Elements);
   5265  MOZ_ASSERT(ins->index()->type() == MIRType::IntPtr);
   5266 
   5267  if (ins->isFloatWrite()) {
   5268    MOZ_ASSERT_IF(ins->writeType() == Scalar::Float16,
   5269                  ins->value()->type() == MIRType::Float32);
   5270    MOZ_ASSERT_IF(ins->writeType() == Scalar::Float32,
   5271                  ins->value()->type() == MIRType::Float32);
   5272    MOZ_ASSERT_IF(ins->writeType() == Scalar::Float64,
   5273                  ins->value()->type() == MIRType::Double);
   5274  } else if (ins->isBigIntWrite()) {
   5275    MOZ_ASSERT(ins->value()->type() == MIRType::Int64);
   5276  } else {
   5277    MOZ_ASSERT(ins->value()->type() == MIRType::Int32);
   5278  }
   5279 
   5280  auto sync = SynchronizeStore(ins->requiresMemoryBarrier());
   5281 
   5282  if (ins->isBigIntWrite() && !sync.isNone()) {
   5283    lowerAtomicStore64(ins);
   5284    return;
   5285  }
   5286 
   5287  LUse elements = useRegister(ins->elements());
   5288  LAllocation index =
   5289      useRegisterOrIndexConstant(ins->index(), ins->writeType());
   5290 
   5291  if (ins->isBigIntWrite()) {
   5292    LInt64Allocation value = useInt64RegisterOrConstant(ins->value());
   5293    add(new (alloc()) LStoreUnboxedInt64(elements, index, value), ins);
   5294    return;
   5295  }
   5296 
   5297  // For byte arrays, the value has to be in a byte register on x86.
   5298  LAllocation value;
   5299  if (ins->isByteWrite()) {
   5300    value = useByteOpRegisterOrNonDoubleConstant(ins->value());
   5301  } else {
   5302    value = useRegisterOrNonDoubleConstant(ins->value());
   5303  }
   5304 
   5305  // Optimization opportunity for atomics: on some platforms there
   5306  // is a store instruction that incorporates the necessary
   5307  // barriers, and we could use that instead of separate barrier and
   5308  // store instructions.  See bug #1077027.
   5309  //
   5310  // NOTE: the generated code must match the assembly code in gen_store in
   5311  // GenerateAtomicOperations.py
   5312  if (!sync.isNone()) {
   5313    LMemoryBarrier* fence = new (alloc()) LMemoryBarrier(sync.barrierBefore);
   5314    add(fence, ins);
   5315  }
   5316 
   5317  // We need a temp register for Float16Array.
   5318  LDefinition tempDef = LDefinition::BogusTemp();
   5319  if (ins->writeType() == Scalar::Float16) {
   5320    tempDef = temp();
   5321  }
   5322 
   5323  auto* lir =
   5324      new (alloc()) LStoreUnboxedScalar(elements, index, value, tempDef);
   5325  add(lir, ins);
   5326 
   5327  if (MacroAssembler::StoreRequiresCall(ins->writeType())) {
   5328    assignSafepoint(lir, ins);
   5329  }
   5330 
   5331  if (!sync.isNone()) {
   5332    LMemoryBarrier* fence = new (alloc()) LMemoryBarrier(sync.barrierAfter);
   5333    add(fence, ins);
   5334  }
   5335 }
   5336 
   5337 void LIRGenerator::visitStoreDataViewElement(MStoreDataViewElement* ins) {
   5338  MOZ_ASSERT(ins->elements()->type() == MIRType::Elements);
   5339  MOZ_ASSERT(ins->index()->type() == MIRType::IntPtr);
   5340  MOZ_ASSERT(ins->littleEndian()->type() == MIRType::Boolean);
   5341 
   5342  if (ins->isFloatWrite()) {
   5343    MOZ_ASSERT_IF(ins->writeType() == Scalar::Float16,
   5344                  ins->value()->type() == MIRType::Float32);
   5345    MOZ_ASSERT_IF(ins->writeType() == Scalar::Float32,
   5346                  ins->value()->type() == MIRType::Float32);
   5347    MOZ_ASSERT_IF(ins->writeType() == Scalar::Float64,
   5348                  ins->value()->type() == MIRType::Double);
   5349  } else if (ins->isBigIntWrite()) {
   5350    MOZ_ASSERT(ins->value()->type() == MIRType::Int64);
   5351  } else {
   5352    MOZ_ASSERT(ins->value()->type() == MIRType::Int32);
   5353  }
   5354 
   5355  LUse elements = useRegister(ins->elements());
   5356  LAllocation index = useRegisterOrIndexConstant(ins->index(), Scalar::Uint8);
   5357  LAllocation littleEndian = useRegisterOrConstant(ins->littleEndian());
   5358 
   5359  if (ins->isBigIntWrite()) {
   5360 #ifdef JS_CODEGEN_X86
   5361    LInt64Allocation value = useInt64Register(ins->value());
   5362    LInt64Definition temp = LInt64Definition::BogusTemp();
   5363    if (littleEndian.isConstant()) {
   5364      temp = tempInt64();
   5365    }
   5366 #else
   5367    LInt64Allocation value = useInt64RegisterOrConstant(ins->value());
   5368    LInt64Definition temp = tempInt64();
   5369 #endif
   5370 
   5371    auto* lir = new (alloc())
   5372        LStoreDataViewElement64(elements, index, value, littleEndian, temp);
   5373    add(lir, ins);
   5374    return;
   5375  }
   5376 
   5377  LAllocation value = useRegisterOrNonDoubleConstant(ins->value());
   5378 
   5379  LDefinition tempDef = LDefinition::BogusTemp();
   5380  LInt64Definition temp64Def = LInt64Definition::BogusTemp();
   5381  if (ins->writeType() != Scalar::Float64) {
   5382    tempDef = temp();
   5383  } else {
   5384    temp64Def = tempInt64();
   5385  }
   5386 
   5387  auto* lir = new (alloc()) LStoreDataViewElement(
   5388      elements, index, value, littleEndian, tempDef, temp64Def);
   5389  add(lir, ins);
   5390 
   5391  if (MacroAssembler::StoreRequiresCall(ins->writeType())) {
   5392    assignSafepoint(lir, ins);
   5393  }
   5394 }
   5395 
   5396 void LIRGenerator::visitStoreTypedArrayElementHole(
   5397    MStoreTypedArrayElementHole* ins) {
   5398  MOZ_ASSERT(ins->elements()->type() == MIRType::Elements);
   5399  MOZ_ASSERT(ins->index()->type() == MIRType::IntPtr);
   5400  MOZ_ASSERT(ins->length()->type() == MIRType::IntPtr);
   5401 
   5402  if (ins->isFloatWrite()) {
   5403    MOZ_ASSERT_IF(ins->arrayType() == Scalar::Float16,
   5404                  ins->value()->type() == MIRType::Float32);
   5405    MOZ_ASSERT_IF(ins->arrayType() == Scalar::Float32,
   5406                  ins->value()->type() == MIRType::Float32);
   5407    MOZ_ASSERT_IF(ins->arrayType() == Scalar::Float64,
   5408                  ins->value()->type() == MIRType::Double);
   5409  } else if (ins->isBigIntWrite()) {
   5410    MOZ_ASSERT(ins->value()->type() == MIRType::Int64);
   5411  } else {
   5412    MOZ_ASSERT(ins->value()->type() == MIRType::Int32);
   5413  }
   5414 
   5415  LUse elements = useRegister(ins->elements());
   5416  LAllocation length = useAny(ins->length());
   5417  LAllocation index = useRegister(ins->index());
   5418 
   5419  if (ins->isBigIntWrite()) {
   5420    LInt64Allocation value = useInt64RegisterOrConstant(ins->value());
   5421    LDefinition spectreTemp =
   5422        BoundsCheckNeedsSpectreTemp() ? temp() : LDefinition::BogusTemp();
   5423 
   5424    auto* lir = new (alloc()) LStoreTypedArrayElementHoleInt64(
   5425        elements, length, index, value, spectreTemp);
   5426    add(lir, ins);
   5427    return;
   5428  }
   5429 
   5430  // For byte arrays, the value has to be in a byte register on x86.
   5431  LAllocation value;
   5432  if (ins->isByteWrite()) {
   5433    value = useByteOpRegisterOrNonDoubleConstant(ins->value());
   5434  } else {
   5435    value = useRegisterOrNonDoubleConstant(ins->value());
   5436  }
   5437 
   5438  LDefinition tempDef = LDefinition::BogusTemp();
   5439  if (BoundsCheckNeedsSpectreTemp() || ins->arrayType() == Scalar::Float16) {
   5440    tempDef = temp();
   5441  }
   5442 
   5443  auto* lir = new (alloc())
   5444      LStoreTypedArrayElementHole(elements, length, index, value, tempDef);
   5445  add(lir, ins);
   5446 
   5447  if (MacroAssembler::StoreRequiresCall(ins->arrayType())) {
   5448    assignSafepoint(lir, ins);
   5449  }
   5450 }
   5451 
   5452 void LIRGenerator::visitLoadScriptedProxyHandler(
   5453    MLoadScriptedProxyHandler* ins) {
   5454  LLoadScriptedProxyHandler* lir = new (alloc())
   5455      LLoadScriptedProxyHandler(useRegisterAtStart(ins->object()));
   5456  assignSnapshot(lir, ins->bailoutKind());
   5457  define(lir, ins);
   5458 }
   5459 
   5460 void LIRGenerator::visitIdToStringOrSymbol(MIdToStringOrSymbol* ins) {
   5461  LIdToStringOrSymbol* lir =
   5462      new (alloc()) LIdToStringOrSymbol(useBoxAtStart(ins->idVal()), temp());
   5463  assignSnapshot(lir, ins->bailoutKind());
   5464  defineBox(lir, ins);
   5465  assignSafepoint(lir, ins);
   5466 }
   5467 
   5468 void LIRGenerator::visitLoadFixedSlot(MLoadFixedSlot* ins) {
   5469  MDefinition* obj = ins->object();
   5470  MOZ_ASSERT(obj->type() == MIRType::Object);
   5471 
   5472  MIRType type = ins->type();
   5473 
   5474  if (type == MIRType::Value) {
   5475    if (ins->usedAsPropertyKey()) {
   5476      LLoadFixedSlotAndAtomize* lir =
   5477          new (alloc()) LLoadFixedSlotAndAtomize(useRegister(obj), temp());
   5478      defineBox(lir, ins);
   5479      assignSafepoint(lir, ins);
   5480    } else {
   5481      LLoadFixedSlotV* lir =
   5482          new (alloc()) LLoadFixedSlotV(useRegisterAtStart(obj));
   5483      defineBox(lir, ins);
   5484    }
   5485  } else {
   5486    LLoadFixedSlotT* lir =
   5487        new (alloc()) LLoadFixedSlotT(useRegisterForTypedLoad(obj, type));
   5488    define(lir, ins);
   5489  }
   5490 }
   5491 
   5492 void LIRGenerator::visitLoadFixedSlotFromOffset(MLoadFixedSlotFromOffset* ins) {
   5493  MDefinition* obj = ins->object();
   5494  MOZ_ASSERT(obj->type() == MIRType::Object);
   5495  MOZ_ASSERT(ins->type() == MIRType::Value);
   5496 
   5497  auto* lir = new (alloc()) LLoadFixedSlotFromOffset(
   5498      useRegisterAtStart(obj), useRegisterAtStart(ins->offset()));
   5499  defineBox(lir, ins);
   5500 }
   5501 
   5502 void LIRGenerator::visitLoadFixedSlotAndUnbox(MLoadFixedSlotAndUnbox* ins) {
   5503  MDefinition* obj = ins->object();
   5504  MOZ_ASSERT(obj->type() == MIRType::Object);
   5505 
   5506  if (ins->usedAsPropertyKey() && ins->type() == MIRType::String) {
   5507    LLoadFixedSlotUnboxAndAtomize* lir =
   5508        new (alloc()) LLoadFixedSlotUnboxAndAtomize(useRegister(obj));
   5509    if (ins->fallible()) {
   5510      assignSnapshot(lir, ins->bailoutKind());
   5511    }
   5512    define(lir, ins);
   5513    assignSafepoint(lir, ins);
   5514  } else {
   5515    LInt64Definition temp0 = ins->type() == MIRType::Double
   5516                                 ? tempInt64()
   5517                                 : LInt64Definition::BogusTemp();
   5518 
   5519    LLoadFixedSlotAndUnbox* lir =
   5520        new (alloc()) LLoadFixedSlotAndUnbox(useRegisterAtStart(obj), temp0);
   5521    if (ins->fallible()) {
   5522      assignSnapshot(lir, ins->bailoutKind());
   5523    }
   5524    define(lir, ins);
   5525  }
   5526 }
   5527 
   5528 void LIRGenerator::visitLoadDynamicSlotAndUnbox(MLoadDynamicSlotAndUnbox* ins) {
   5529  MDefinition* slots = ins->slots();
   5530  MOZ_ASSERT(slots->type() == MIRType::Slots);
   5531 
   5532  if (ins->usedAsPropertyKey() && ins->type() == MIRType::String) {
   5533    auto* lir =
   5534        new (alloc()) LLoadDynamicSlotUnboxAndAtomize(useRegister(slots));
   5535    if (ins->fallible()) {
   5536      assignSnapshot(lir, ins->bailoutKind());
   5537    }
   5538    define(lir, ins);
   5539    assignSafepoint(lir, ins);
   5540  } else {
   5541    LInt64Definition temp0 = ins->type() == MIRType::Double
   5542                                 ? tempInt64()
   5543                                 : LInt64Definition::BogusTemp();
   5544    auto* lir = new (alloc())
   5545        LLoadDynamicSlotAndUnbox(useRegisterAtStart(slots), temp0);
   5546    if (ins->fallible()) {
   5547      assignSnapshot(lir, ins->bailoutKind());
   5548    }
   5549    define(lir, ins);
   5550  }
   5551 }
   5552 
   5553 void LIRGenerator::visitLoadElementAndUnbox(MLoadElementAndUnbox* ins) {
   5554  MDefinition* elements = ins->elements();
   5555  MDefinition* index = ins->index();
   5556  MOZ_ASSERT(elements->type() == MIRType::Elements);
   5557  MOZ_ASSERT(index->type() == MIRType::Int32);
   5558 
   5559  LInt64Definition temp0 = ins->type() == MIRType::Double
   5560                               ? tempInt64()
   5561                               : LInt64Definition::BogusTemp();
   5562 
   5563  auto* lir = new (alloc()) LLoadElementAndUnbox(
   5564      useRegister(elements), useRegisterOrConstant(index), temp0);
   5565  if (ins->fallible()) {
   5566    assignSnapshot(lir, ins->bailoutKind());
   5567  }
   5568  define(lir, ins);
   5569 }
   5570 
   5571 void LIRGenerator::visitAddAndStoreSlot(MAddAndStoreSlot* ins) {
   5572  MOZ_ASSERT(ins->object()->type() == MIRType::Object);
   5573 
   5574  if (ins->preserveWrapper()) {
   5575    auto* lir = new (alloc()) LAddAndStoreSlotPreserveWrapper(
   5576        useRegister(ins->object()), useBox(ins->value()), temp(), temp());
   5577    assignSnapshot(lir, ins->bailoutKind());
   5578    add(lir, ins);
   5579    assignSafepoint(lir, ins);
   5580  } else {
   5581    LDefinition maybeTemp = LDefinition::BogusTemp();
   5582    if (ins->kind() != MAddAndStoreSlot::Kind::FixedSlot) {
   5583      maybeTemp = temp();
   5584    }
   5585    auto* lir = new (alloc()) LAddAndStoreSlot(useRegister(ins->object()),
   5586                                               useBox(ins->value()), maybeTemp);
   5587    add(lir, ins);
   5588  }
   5589 }
   5590 
   5591 void LIRGenerator::visitAllocateAndStoreSlot(MAllocateAndStoreSlot* ins) {
   5592  MOZ_ASSERT(ins->object()->type() == MIRType::Object);
   5593 
   5594  auto* lir = new (alloc()) LAllocateAndStoreSlot(
   5595      useRegisterAtStart(ins->object()), useBoxAtStart(ins->value()),
   5596      tempFixed(CallTempReg0), tempFixed(CallTempReg1));
   5597  assignSnapshot(lir, ins->bailoutKind());
   5598  add(lir, ins);
   5599 }
   5600 
   5601 void LIRGenerator::visitAddSlotAndCallAddPropHook(
   5602    MAddSlotAndCallAddPropHook* ins) {
   5603  MOZ_ASSERT(ins->object()->type() == MIRType::Object);
   5604  MOZ_ASSERT(ins->value()->type() == MIRType::Value);
   5605 
   5606  auto* lir = new (alloc()) LAddSlotAndCallAddPropHook(
   5607      useRegisterAtStart(ins->object()), useBoxAtStart(ins->value()));
   5608  add(lir, ins);
   5609  assignSafepoint(lir, ins);
   5610 }
   5611 
   5612 void LIRGenerator::visitStoreFixedSlot(MStoreFixedSlot* ins) {
   5613  MOZ_ASSERT(ins->object()->type() == MIRType::Object);
   5614 
   5615  if (ins->value()->type() == MIRType::Value) {
   5616    LStoreFixedSlotV* lir = new (alloc())
   5617        LStoreFixedSlotV(useRegister(ins->object()), useBox(ins->value()));
   5618    add(lir, ins);
   5619  } else {
   5620    LStoreFixedSlotT* lir = new (alloc()) LStoreFixedSlotT(
   5621        useRegister(ins->object()), useRegisterOrConstant(ins->value()));
   5622    add(lir, ins);
   5623  }
   5624 }
   5625 
   5626 void LIRGenerator::visitStoreFixedSlotFromOffset(
   5627    MStoreFixedSlotFromOffset* ins) {
   5628  MOZ_ASSERT(ins->object()->type() == MIRType::Object);
   5629 
   5630  if (ins->value()->type() == MIRType::Value) {
   5631    LStoreFixedSlotFromOffsetV* lir = new (alloc()) LStoreFixedSlotFromOffsetV(
   5632        useRegister(ins->object()), useRegister(ins->offset()),
   5633        useBox(ins->value()), temp());
   5634    add(lir, ins);
   5635  } else {
   5636    LStoreFixedSlotFromOffsetT* lir = new (alloc()) LStoreFixedSlotFromOffsetT(
   5637        useRegister(ins->object()), useRegister(ins->offset()),
   5638        useRegisterOrConstant(ins->value()), temp());
   5639    add(lir, ins);
   5640  }
   5641 }
   5642 
   5643 void LIRGenerator::visitStoreDynamicSlotFromOffset(
   5644    MStoreDynamicSlotFromOffset* ins) {
   5645  MOZ_ASSERT(ins->slots()->type() == MIRType::Slots);
   5646 
   5647  if (ins->value()->type() == MIRType::Value) {
   5648    auto* lir = new (alloc()) LStoreDynamicSlotFromOffsetV(
   5649        useRegister(ins->slots()), useRegister(ins->offset()),
   5650        useBox(ins->value()), temp());
   5651    add(lir, ins);
   5652  } else {
   5653    auto* lir = new (alloc()) LStoreDynamicSlotFromOffsetT(
   5654        useRegister(ins->slots()), useRegister(ins->offset()),
   5655        useRegisterOrConstant(ins->value()), temp());
   5656    add(lir, ins);
   5657  }
   5658 }
   5659 
   5660 void LIRGenerator::visitGetNameCache(MGetNameCache* ins) {
   5661  MOZ_ASSERT(ins->envObj()->type() == MIRType::Object);
   5662 
   5663  // Emit an overrecursed check: this is necessary because the cache can
   5664  // attach a scripted getter stub that calls this script recursively.
   5665  gen->setNeedsOverrecursedCheck();
   5666 
   5667  LGetNameCache* lir =
   5668      new (alloc()) LGetNameCache(useRegister(ins->envObj()), temp());
   5669  defineBox(lir, ins);
   5670  assignSafepoint(lir, ins);
   5671 }
   5672 
   5673 void LIRGenerator::visitCallGetIntrinsicValue(MCallGetIntrinsicValue* ins) {
   5674  LCallGetIntrinsicValue* lir = new (alloc()) LCallGetIntrinsicValue();
   5675  defineReturn(lir, ins);
   5676  assignSafepoint(lir, ins);
   5677 }
   5678 
   5679 void LIRGenerator::visitGetPropSuperCache(MGetPropSuperCache* ins) {
   5680  MDefinition* obj = ins->object();
   5681  MDefinition* receiver = ins->receiver();
   5682  MDefinition* id = ins->idval();
   5683 
   5684  gen->setNeedsOverrecursedCheck();
   5685 
   5686  bool useConstId =
   5687      id->type() == MIRType::String || id->type() == MIRType::Symbol;
   5688 
   5689  auto* lir = new (alloc())
   5690      LGetPropSuperCache(useRegister(obj), useBoxOrTyped(receiver),
   5691                         useBoxOrTypedOrConstant(id, useConstId));
   5692  defineBox(lir, ins);
   5693  assignSafepoint(lir, ins);
   5694 }
   5695 
   5696 void LIRGenerator::visitGetPropertyCache(MGetPropertyCache* ins) {
   5697  MDefinition* value = ins->value();
   5698  MOZ_ASSERT(value->type() == MIRType::Object ||
   5699             value->type() == MIRType::Value);
   5700 
   5701  MDefinition* id = ins->idval();
   5702  MOZ_ASSERT(id->type() == MIRType::String || id->type() == MIRType::Symbol ||
   5703             id->type() == MIRType::Int32 || id->type() == MIRType::Value);
   5704 
   5705  // Emit an overrecursed check: this is necessary because the cache can
   5706  // attach a scripted getter stub that calls this script recursively.
   5707  gen->setNeedsOverrecursedCheck();
   5708 
   5709  // If this is a GetProp, the id is a constant string. Allow passing it as a
   5710  // constant to reduce register allocation pressure.
   5711  bool useConstId =
   5712      id->type() == MIRType::String || id->type() == MIRType::Symbol;
   5713 
   5714  auto* lir = new (alloc()) LGetPropertyCache(
   5715      useBoxOrTyped(value), useBoxOrTypedOrConstant(id, useConstId));
   5716  defineBox(lir, ins);
   5717  assignSafepoint(lir, ins);
   5718 }
   5719 
   5720 void LIRGenerator::visitBindNameCache(MBindNameCache* ins) {
   5721  MOZ_ASSERT(ins->environmentChain()->type() == MIRType::Object);
   5722  MOZ_ASSERT(ins->type() == MIRType::Object);
   5723 
   5724  LBindNameCache* lir = new (alloc())
   5725      LBindNameCache(useRegister(ins->environmentChain()), temp());
   5726  define(lir, ins);
   5727  assignSafepoint(lir, ins);
   5728 }
   5729 
   5730 void LIRGenerator::visitCallBindVar(MCallBindVar* ins) {
   5731  MOZ_ASSERT(ins->environmentChain()->type() == MIRType::Object);
   5732  MOZ_ASSERT(ins->type() == MIRType::Object);
   5733 
   5734  LCallBindVar* lir =
   5735      new (alloc()) LCallBindVar(useRegister(ins->environmentChain()));
   5736  define(lir, ins);
   5737 }
   5738 
   5739 void LIRGenerator::visitGuardObjectIdentity(MGuardObjectIdentity* ins) {
   5740  LGuardObjectIdentity* guard = new (alloc()) LGuardObjectIdentity(
   5741      useRegister(ins->object()), useRegister(ins->expected()));
   5742  assignSnapshot(guard, ins->bailoutKind());
   5743  add(guard, ins);
   5744  redefine(ins, ins->object());
   5745 }
   5746 
   5747 void LIRGenerator::visitGuardSpecificFunction(MGuardSpecificFunction* ins) {
   5748  auto* guard = new (alloc()) LGuardSpecificFunction(
   5749      useRegister(ins->function()), useRegister(ins->expected()));
   5750  assignSnapshot(guard, ins->bailoutKind());
   5751  add(guard, ins);
   5752  redefine(ins, ins->function());
   5753 }
   5754 
   5755 void LIRGenerator::visitGuardSpecificAtom(MGuardSpecificAtom* ins) {
   5756  auto* guard =
   5757      new (alloc()) LGuardSpecificAtom(useRegister(ins->str()), temp());
   5758  assignSnapshot(guard, ins->bailoutKind());
   5759  add(guard, ins);
   5760  redefine(ins, ins->str());
   5761  assignSafepoint(guard, ins);
   5762 }
   5763 
   5764 void LIRGenerator::visitGuardSpecificSymbol(MGuardSpecificSymbol* ins) {
   5765  auto* guard = new (alloc()) LGuardSpecificSymbol(useRegister(ins->symbol()));
   5766  assignSnapshot(guard, ins->bailoutKind());
   5767  add(guard, ins);
   5768  redefine(ins, ins->symbol());
   5769 }
   5770 
   5771 void LIRGenerator::visitGuardSpecificInt32(MGuardSpecificInt32* ins) {
   5772  auto* guard = new (alloc()) LGuardSpecificInt32(useRegister(ins->num()));
   5773  assignSnapshot(guard, ins->bailoutKind());
   5774  add(guard, ins);
   5775  redefine(ins, ins->num());
   5776 }
   5777 
   5778 void LIRGenerator::visitGuardStringToIndex(MGuardStringToIndex* ins) {
   5779  MOZ_ASSERT(ins->string()->type() == MIRType::String);
   5780  auto* guard = new (alloc()) LGuardStringToIndex(useRegister(ins->string()));
   5781  assignSnapshot(guard, ins->bailoutKind());
   5782  define(guard, ins);
   5783  assignSafepoint(guard, ins);
   5784 }
   5785 
   5786 void LIRGenerator::visitGuardStringToInt32(MGuardStringToInt32* ins) {
   5787  MOZ_ASSERT(ins->string()->type() == MIRType::String);
   5788  auto* guard =
   5789      new (alloc()) LGuardStringToInt32(useRegister(ins->string()), temp());
   5790  assignSnapshot(guard, ins->bailoutKind());
   5791  define(guard, ins);
   5792  assignSafepoint(guard, ins);
   5793 }
   5794 
   5795 void LIRGenerator::visitGuardStringToDouble(MGuardStringToDouble* ins) {
   5796  MOZ_ASSERT(ins->string()->type() == MIRType::String);
   5797  auto* guard = new (alloc())
   5798      LGuardStringToDouble(useRegister(ins->string()), temp(), temp());
   5799  assignSnapshot(guard, ins->bailoutKind());
   5800  define(guard, ins);
   5801  assignSafepoint(guard, ins);
   5802 }
   5803 
   5804 void LIRGenerator::visitGuardNoDenseElements(MGuardNoDenseElements* ins) {
   5805  auto* guard =
   5806      new (alloc()) LGuardNoDenseElements(useRegister(ins->object()), temp());
   5807  assignSnapshot(guard, ins->bailoutKind());
   5808  add(guard, ins);
   5809  redefine(ins, ins->object());
   5810 }
   5811 
   5812 void LIRGenerator::visitGuardShape(MGuardShape* ins) {
   5813  MOZ_ASSERT(ins->object()->type() == MIRType::Object);
   5814 
   5815  if (JitOptions.spectreObjectMitigations) {
   5816    auto* lir =
   5817        new (alloc()) LGuardShape(useRegisterAtStart(ins->object()), temp());
   5818    assignSnapshot(lir, ins->bailoutKind());
   5819    defineReuseInput(lir, ins, 0);
   5820  } else {
   5821    auto* lir = new (alloc())
   5822        LGuardShape(useRegister(ins->object()), LDefinition::BogusTemp());
   5823    assignSnapshot(lir, ins->bailoutKind());
   5824    addUnchecked(lir, ins);
   5825    redefine(ins, ins->object());
   5826  }
   5827 }
   5828 
   5829 void LIRGenerator::visitGuardMultipleShapes(MGuardMultipleShapes* ins) {
   5830  MOZ_ASSERT(ins->object()->type() == MIRType::Object);
   5831 
   5832  if (JitOptions.spectreObjectMitigations) {
   5833    auto* lir = new (alloc()) LGuardMultipleShapes(
   5834        useRegisterAtStart(ins->object()), useRegister(ins->shapeList()),
   5835        temp(), temp(), temp(), temp());
   5836    assignSnapshot(lir, ins->bailoutKind());
   5837    defineReuseInput(lir, ins, 0);
   5838  } else {
   5839    auto* lir = new (alloc()) LGuardMultipleShapes(
   5840        useRegister(ins->object()), useRegister(ins->shapeList()), temp(),
   5841        temp(), temp(), LDefinition::BogusTemp());
   5842    assignSnapshot(lir, ins->bailoutKind());
   5843    addUnchecked(lir, ins);
   5844    redefine(ins, ins->object());
   5845  }
   5846 }
   5847 
   5848 void LIRGenerator::visitGuardShapeList(MGuardShapeList* ins) {
   5849  MOZ_ASSERT(ins->object()->type() == MIRType::Object);
   5850 
   5851  if (JitOptions.spectreObjectMitigations) {
   5852    auto* lir = new (alloc())
   5853        LGuardShapeList(useRegisterAtStart(ins->object()), temp(), temp());
   5854    assignSnapshot(lir, ins->bailoutKind());
   5855    defineReuseInput(lir, ins, 0);
   5856  } else {
   5857    auto* lir = new (alloc()) LGuardShapeList(useRegister(ins->object()),
   5858                                              temp(), LDefinition::BogusTemp());
   5859    assignSnapshot(lir, ins->bailoutKind());
   5860    addUnchecked(lir, ins);
   5861    redefine(ins, ins->object());
   5862  }
   5863 }
   5864 
   5865 void LIRGenerator::visitGuardShapeListToOffset(MGuardShapeListToOffset* ins) {
   5866  MOZ_ASSERT(ins->object()->type() == MIRType::Object);
   5867 
   5868  if (JitOptions.spectreObjectMitigations) {
   5869    auto* lir = new (alloc())
   5870        LGuardShapeListToOffset(useRegister(ins->object()), temp(), temp());
   5871    assignSnapshot(lir, ins->bailoutKind());
   5872    define(lir, ins);
   5873  } else {
   5874    auto* lir = new (alloc()) LGuardShapeListToOffset(
   5875        useRegister(ins->object()), temp(), LDefinition::BogusTemp());
   5876    assignSnapshot(lir, ins->bailoutKind());
   5877    define(lir, ins);
   5878  }
   5879 }
   5880 
   5881 void LIRGenerator::visitGuardMultipleShapesToOffset(
   5882    MGuardMultipleShapesToOffset* ins) {
   5883  MOZ_ASSERT(ins->object()->type() == MIRType::Object);
   5884 
   5885  auto* lir = new (alloc()) LGuardMultipleShapesToOffset(
   5886      useRegister(ins->object()), useRegister(ins->shapeList()), temp(), temp(),
   5887      temp());
   5888  assignSnapshot(lir, ins->bailoutKind());
   5889  define(lir, ins);
   5890 }
   5891 
   5892 void LIRGenerator::visitGuardProto(MGuardProto* ins) {
   5893  MOZ_ASSERT(ins->object()->type() == MIRType::Object);
   5894  MOZ_ASSERT(ins->expected()->type() == MIRType::Object);
   5895 
   5896  auto* lir = new (alloc()) LGuardProto(useRegister(ins->object()),
   5897                                        useRegister(ins->expected()), temp());
   5898  assignSnapshot(lir, ins->bailoutKind());
   5899  add(lir, ins);
   5900  redefine(ins, ins->object());
   5901 }
   5902 
   5903 void LIRGenerator::visitGuardNullProto(MGuardNullProto* ins) {
   5904  MOZ_ASSERT(ins->object()->type() == MIRType::Object);
   5905 
   5906  auto* lir = new (alloc()) LGuardNullProto(useRegister(ins->object()), temp());
   5907  assignSnapshot(lir, ins->bailoutKind());
   5908  add(lir, ins);
   5909  redefine(ins, ins->object());
   5910 }
   5911 
   5912 void LIRGenerator::visitGuardIsNativeObject(MGuardIsNativeObject* ins) {
   5913  MOZ_ASSERT(ins->object()->type() == MIRType::Object);
   5914 
   5915  auto* lir =
   5916      new (alloc()) LGuardIsNativeObject(useRegister(ins->object()), temp());
   5917  assignSnapshot(lir, ins->bailoutKind());
   5918  add(lir, ins);
   5919  redefine(ins, ins->object());
   5920 }
   5921 
   5922 void LIRGenerator::visitGuardGlobalGeneration(MGuardGlobalGeneration* ins) {
   5923  auto* lir = new (alloc()) LGuardGlobalGeneration(temp());
   5924  assignSnapshot(lir, ins->bailoutKind());
   5925  add(lir, ins);
   5926 }
   5927 
   5928 void LIRGenerator::visitGuardFuse(MGuardFuse* ins) {
   5929  auto* lir = new (alloc()) LGuardFuse();
   5930  assignSnapshot(lir, ins->bailoutKind());
   5931  add(lir, ins);
   5932 }
   5933 
   5934 void LIRGenerator::visitGuardIsProxy(MGuardIsProxy* ins) {
   5935  MOZ_ASSERT(ins->object()->type() == MIRType::Object);
   5936 
   5937  auto* lir = new (alloc()) LGuardIsProxy(useRegister(ins->object()), temp());
   5938  assignSnapshot(lir, ins->bailoutKind());
   5939  add(lir, ins);
   5940  redefine(ins, ins->object());
   5941 }
   5942 
   5943 void LIRGenerator::visitGuardIsNotProxy(MGuardIsNotProxy* ins) {
   5944  MOZ_ASSERT(ins->object()->type() == MIRType::Object);
   5945 
   5946  auto* lir =
   5947      new (alloc()) LGuardIsNotProxy(useRegister(ins->object()), temp());
   5948  assignSnapshot(lir, ins->bailoutKind());
   5949  add(lir, ins);
   5950  redefine(ins, ins->object());
   5951 }
   5952 
   5953 void LIRGenerator::visitGuardIsNotDOMProxy(MGuardIsNotDOMProxy* ins) {
   5954  MOZ_ASSERT(ins->proxy()->type() == MIRType::Object);
   5955 
   5956  auto* lir =
   5957      new (alloc()) LGuardIsNotDOMProxy(useRegister(ins->proxy()), temp());
   5958  assignSnapshot(lir, ins->bailoutKind());
   5959  add(lir, ins);
   5960  redefine(ins, ins->proxy());
   5961 }
   5962 
   5963 void LIRGenerator::visitProxyGet(MProxyGet* ins) {
   5964  MOZ_ASSERT(ins->proxy()->type() == MIRType::Object);
   5965  auto* lir = new (alloc())
   5966      LProxyGet(useRegisterAtStart(ins->proxy()), tempFixed(CallTempReg0));
   5967  defineReturn(lir, ins);
   5968  assignSafepoint(lir, ins);
   5969 }
   5970 
   5971 void LIRGenerator::visitProxyGetByValue(MProxyGetByValue* ins) {
   5972  MOZ_ASSERT(ins->proxy()->type() == MIRType::Object);
   5973  MOZ_ASSERT(ins->idVal()->type() == MIRType::Value);
   5974  auto* lir = new (alloc()) LProxyGetByValue(useRegisterAtStart(ins->proxy()),
   5975                                             useBoxAtStart(ins->idVal()));
   5976  defineReturn(lir, ins);
   5977  assignSafepoint(lir, ins);
   5978 }
   5979 
   5980 void LIRGenerator::visitProxyHasProp(MProxyHasProp* ins) {
   5981  MOZ_ASSERT(ins->proxy()->type() == MIRType::Object);
   5982  MOZ_ASSERT(ins->idVal()->type() == MIRType::Value);
   5983  auto* lir = new (alloc()) LProxyHasProp(useRegisterAtStart(ins->proxy()),
   5984                                          useBoxAtStart(ins->idVal()));
   5985  defineReturn(lir, ins);
   5986  assignSafepoint(lir, ins);
   5987 }
   5988 
   5989 void LIRGenerator::visitProxySet(MProxySet* ins) {
   5990  MOZ_ASSERT(ins->proxy()->type() == MIRType::Object);
   5991  MOZ_ASSERT(ins->rhs()->type() == MIRType::Value);
   5992  auto* lir = new (alloc())
   5993      LProxySet(useRegisterAtStart(ins->proxy()), useBoxAtStart(ins->rhs()),
   5994                tempFixed(CallTempReg0));
   5995  add(lir, ins);
   5996  assignSafepoint(lir, ins);
   5997 }
   5998 
   5999 void LIRGenerator::visitProxySetByValue(MProxySetByValue* ins) {
   6000  MOZ_ASSERT(ins->proxy()->type() == MIRType::Object);
   6001  MOZ_ASSERT(ins->idVal()->type() == MIRType::Value);
   6002  MOZ_ASSERT(ins->rhs()->type() == MIRType::Value);
   6003  auto* lir = new (alloc())
   6004      LProxySetByValue(useRegisterAtStart(ins->proxy()),
   6005                       useBoxAtStart(ins->idVal()), useBoxAtStart(ins->rhs()));
   6006  add(lir, ins);
   6007  assignSafepoint(lir, ins);
   6008 }
   6009 
   6010 void LIRGenerator::visitCallSetArrayLength(MCallSetArrayLength* ins) {
   6011  MOZ_ASSERT(ins->obj()->type() == MIRType::Object);
   6012  MOZ_ASSERT(ins->rhs()->type() == MIRType::Value);
   6013  auto* lir = new (alloc()) LCallSetArrayLength(useRegisterAtStart(ins->obj()),
   6014                                                useBoxAtStart(ins->rhs()));
   6015  add(lir, ins);
   6016  assignSafepoint(lir, ins);
   6017 }
   6018 
   6019 void LIRGenerator::visitMegamorphicLoadSlot(MMegamorphicLoadSlot* ins) {
   6020  MOZ_ASSERT(ins->object()->type() == MIRType::Object);
   6021  auto* lir = new (alloc())
   6022      LMegamorphicLoadSlot(useRegisterAtStart(ins->object()),
   6023                           tempFixed(CallTempReg0), tempFixed(CallTempReg1),
   6024                           tempFixed(CallTempReg2), tempFixed(CallTempReg3));
   6025  assignSnapshot(lir, ins->bailoutKind());
   6026  defineReturn(lir, ins);
   6027 }
   6028 
   6029 void LIRGenerator::visitMegamorphicLoadSlotPermissive(
   6030    MMegamorphicLoadSlotPermissive* ins) {
   6031  MOZ_ASSERT(ins->object()->type() == MIRType::Object);
   6032  static_assert(IonGenericCallCalleeReg == CallTempReg1);
   6033  static_assert(IonGenericCallArgcReg == CallTempReg2);
   6034 
   6035  auto* lir = new (alloc()) LMegamorphicLoadSlotPermissive(
   6036      useRegisterAtStart(ins->object()), tempFixed(CallTempReg0),
   6037      tempFixed(IonGenericCallCalleeReg), tempFixed(IonGenericCallArgcReg),
   6038      tempFixed(CallTempReg4));
   6039  defineReturn(lir, ins);
   6040  assignSafepoint(lir, ins);
   6041  lirGraph_.addExtraSafepointUses(1);
   6042 }
   6043 
   6044 void LIRGenerator::visitMegamorphicLoadSlotByValue(
   6045    MMegamorphicLoadSlotByValue* ins) {
   6046  MOZ_ASSERT(ins->object()->type() == MIRType::Object);
   6047  MOZ_ASSERT(ins->idVal()->type() == MIRType::Value);
   6048  auto* lir = new (alloc()) LMegamorphicLoadSlotByValue(
   6049      useRegisterAtStart(ins->object()), useBoxAtStart(ins->idVal()),
   6050      tempFixed(CallTempReg0), tempFixed(CallTempReg1),
   6051      tempFixed(CallTempReg2));
   6052  assignSnapshot(lir, ins->bailoutKind());
   6053  defineReturn(lir, ins);
   6054 }
   6055 
   6056 void LIRGenerator::visitMegamorphicLoadSlotByValuePermissive(
   6057    MMegamorphicLoadSlotByValuePermissive* ins) {
   6058  MOZ_ASSERT(ins->object()->type() == MIRType::Object);
   6059  MOZ_ASSERT(ins->idVal()->type() == MIRType::Value);
   6060 #ifdef JS_CODEGEN_X86
   6061  auto* lir = new (alloc()) LMegamorphicLoadSlotByValuePermissive(
   6062      useRegisterAtStart(ins->object()), useBoxAtStart(ins->idVal()),
   6063      tempFixed(CallTempReg0), tempFixed(IonGenericCallCalleeReg),
   6064      tempFixed(IonGenericCallArgcReg));
   6065  defineReturn(lir, ins);
   6066  assignSafepoint(lir, ins);
   6067 #else
   6068  static_assert(IonGenericCallCalleeReg == CallTempReg1);
   6069  static_assert(IonGenericCallArgcReg == CallTempReg2);
   6070 
   6071  auto* lir = new (alloc()) LMegamorphicLoadSlotByValuePermissive(
   6072      useRegisterAtStart(ins->object()), useBoxAtStart(ins->idVal()),
   6073      tempFixed(CallTempReg0), tempFixed(IonGenericCallCalleeReg),
   6074      tempFixed(IonGenericCallArgcReg), tempFixed(CallTempReg4));
   6075  defineReturn(lir, ins);
   6076  assignSafepoint(lir, ins);
   6077  lirGraph_.addExtraSafepointUses(1);
   6078 #endif
   6079 }
   6080 
   6081 void LIRGenerator::visitMegamorphicStoreSlot(MMegamorphicStoreSlot* ins) {
   6082  MOZ_ASSERT(ins->object()->type() == MIRType::Object);
   6083  MOZ_ASSERT(ins->rhs()->type() == MIRType::Value);
   6084 
   6085 #ifdef JS_CODEGEN_X86
   6086  auto* lir = new (alloc()) LMegamorphicStoreSlot(
   6087      useFixedAtStart(ins->object(), CallTempReg0),
   6088      useBoxFixedAtStart(ins->rhs(), CallTempReg1, CallTempReg2),
   6089      tempFixed(CallTempReg5));
   6090 #else
   6091  auto* lir = new (alloc())
   6092      LMegamorphicStoreSlot(useRegisterAtStart(ins->object()),
   6093                            useBoxAtStart(ins->rhs()), tempFixed(CallTempReg0),
   6094                            tempFixed(CallTempReg1), tempFixed(CallTempReg2));
   6095 #endif
   6096 
   6097  add(lir, ins);
   6098  assignSafepoint(lir, ins);
   6099 }
   6100 
   6101 void LIRGenerator::visitMegamorphicHasProp(MMegamorphicHasProp* ins) {
   6102  MOZ_ASSERT(ins->object()->type() == MIRType::Object);
   6103  MOZ_ASSERT(ins->idVal()->type() == MIRType::Value);
   6104  auto* lir = new (alloc())
   6105      LMegamorphicHasProp(useRegisterAtStart(ins->object()),
   6106                          useBoxAtStart(ins->idVal()), tempFixed(CallTempReg0),
   6107                          tempFixed(CallTempReg1), tempFixed(CallTempReg2));
   6108  assignSnapshot(lir, ins->bailoutKind());
   6109  defineReturn(lir, ins);
   6110 }
   6111 
   6112 void LIRGenerator::visitSmallObjectVariableKeyHasProp(
   6113    MSmallObjectVariableKeyHasProp* ins) {
   6114  MOZ_ASSERT(ins->idStr()->type() == MIRType::String);
   6115  auto* lir = new (alloc())
   6116      LSmallObjectVariableKeyHasProp(useRegisterAtStart(ins->idStr()));
   6117  define(lir, ins);
   6118  assignSafepoint(lir, ins);
   6119 }
   6120 
   6121 void LIRGenerator::visitGuardToArrayBuffer(MGuardToArrayBuffer* ins) {
   6122  MOZ_ASSERT(ins->object()->type() == MIRType::Object);
   6123 
   6124  auto* lir = new (alloc())
   6125      LGuardToArrayBuffer(useRegisterAtStart(ins->object()), temp());
   6126  assignSnapshot(lir, ins->bailoutKind());
   6127  defineReuseInput(lir, ins, 0);
   6128 }
   6129 
   6130 void LIRGenerator::visitGuardToSharedArrayBuffer(
   6131    MGuardToSharedArrayBuffer* ins) {
   6132  MOZ_ASSERT(ins->object()->type() == MIRType::Object);
   6133 
   6134  auto* lir = new (alloc())
   6135      LGuardToSharedArrayBuffer(useRegisterAtStart(ins->object()), temp());
   6136  assignSnapshot(lir, ins->bailoutKind());
   6137  defineReuseInput(lir, ins, 0);
   6138 }
   6139 
   6140 void LIRGenerator::visitGuardIsNotArrayBufferMaybeShared(
   6141    MGuardIsNotArrayBufferMaybeShared* ins) {
   6142  MOZ_ASSERT(ins->object()->type() == MIRType::Object);
   6143 
   6144  auto* lir = new (alloc())
   6145      LGuardIsNotArrayBufferMaybeShared(useRegister(ins->object()), temp());
   6146  assignSnapshot(lir, ins->bailoutKind());
   6147  add(lir, ins);
   6148  redefine(ins, ins->object());
   6149 }
   6150 
   6151 void LIRGenerator::visitGuardIsTypedArray(MGuardIsTypedArray* ins) {
   6152  MOZ_ASSERT(ins->object()->type() == MIRType::Object);
   6153 
   6154  auto* lir =
   6155      new (alloc()) LGuardIsTypedArray(useRegister(ins->object()), temp());
   6156  assignSnapshot(lir, ins->bailoutKind());
   6157  add(lir, ins);
   6158  redefine(ins, ins->object());
   6159 }
   6160 
   6161 void LIRGenerator::visitGuardIsNonResizableTypedArray(
   6162    MGuardIsNonResizableTypedArray* ins) {
   6163  MOZ_ASSERT(ins->object()->type() == MIRType::Object);
   6164 
   6165  auto* lir = new (alloc())
   6166      LGuardIsNonResizableTypedArray(useRegister(ins->object()), temp());
   6167  assignSnapshot(lir, ins->bailoutKind());
   6168  add(lir, ins);
   6169  redefine(ins, ins->object());
   6170 }
   6171 
   6172 void LIRGenerator::visitGuardIsResizableTypedArray(
   6173    MGuardIsResizableTypedArray* ins) {
   6174  MOZ_ASSERT(ins->object()->type() == MIRType::Object);
   6175 
   6176  auto* lir = new (alloc())
   6177      LGuardIsResizableTypedArray(useRegister(ins->object()), temp());
   6178  assignSnapshot(lir, ins->bailoutKind());
   6179  add(lir, ins);
   6180  redefine(ins, ins->object());
   6181 }
   6182 
   6183 void LIRGenerator::visitGuardHasProxyHandler(MGuardHasProxyHandler* ins) {
   6184  MOZ_ASSERT(ins->object()->type() == MIRType::Object);
   6185 
   6186  auto* lir = new (alloc()) LGuardHasProxyHandler(useRegister(ins->object()));
   6187  assignSnapshot(lir, ins->bailoutKind());
   6188  add(lir, ins);
   6189  redefine(ins, ins->object());
   6190 }
   6191 
   6192 void LIRGenerator::visitNurseryObject(MNurseryObject* ins) {
   6193  MOZ_ASSERT(ins->type() == MIRType::Object);
   6194 
   6195  auto* lir = new (alloc()) LNurseryObject();
   6196  define(lir, ins);
   6197 }
   6198 
   6199 void LIRGenerator::visitGuardValue(MGuardValue* ins) {
   6200  MOZ_ASSERT(ins->value()->type() == MIRType::Value);
   6201  LDefinition tempDef = LDefinition::BogusTemp();
   6202  if (!ins->expected().isValue() || ins->expected().toValue().isNaN()) {
   6203    tempDef = temp();
   6204  }
   6205  auto* lir = new (alloc()) LGuardValue(useBox(ins->value()), tempDef);
   6206  assignSnapshot(lir, ins->bailoutKind());
   6207  add(lir, ins);
   6208  redefine(ins, ins->value());
   6209 }
   6210 
   6211 void LIRGenerator::visitGuardNullOrUndefined(MGuardNullOrUndefined* ins) {
   6212  MOZ_ASSERT(ins->value()->type() == MIRType::Value);
   6213  auto* lir = new (alloc()) LGuardNullOrUndefined(useBox(ins->value()));
   6214  assignSnapshot(lir, ins->bailoutKind());
   6215  add(lir, ins);
   6216  redefine(ins, ins->value());
   6217 }
   6218 
   6219 void LIRGenerator::visitGuardIsNotObject(MGuardIsNotObject* ins) {
   6220  MOZ_ASSERT(ins->value()->type() == MIRType::Value);
   6221  auto* lir = new (alloc()) LGuardIsNotObject(useBox(ins->value()));
   6222  assignSnapshot(lir, ins->bailoutKind());
   6223  add(lir, ins);
   6224  redefine(ins, ins->value());
   6225 }
   6226 
   6227 void LIRGenerator::visitGuardFunctionFlags(MGuardFunctionFlags* ins) {
   6228  MOZ_ASSERT(ins->function()->type() == MIRType::Object);
   6229 
   6230  auto* lir = new (alloc()) LGuardFunctionFlags(useRegister(ins->function()));
   6231  assignSnapshot(lir, ins->bailoutKind());
   6232  add(lir, ins);
   6233  redefine(ins, ins->function());
   6234 }
   6235 
   6236 void LIRGenerator::visitGuardFunctionIsNonBuiltinCtor(
   6237    MGuardFunctionIsNonBuiltinCtor* ins) {
   6238  MOZ_ASSERT(ins->function()->type() == MIRType::Object);
   6239 
   6240  auto* lir = new (alloc())
   6241      LGuardFunctionIsNonBuiltinCtor(useRegister(ins->function()), temp());
   6242  assignSnapshot(lir, ins->bailoutKind());
   6243  add(lir, ins);
   6244  redefine(ins, ins->function());
   6245 }
   6246 
   6247 void LIRGenerator::visitGuardFunctionKind(MGuardFunctionKind* ins) {
   6248  MOZ_ASSERT(ins->function()->type() == MIRType::Object);
   6249 
   6250  auto* lir =
   6251      new (alloc()) LGuardFunctionKind(useRegister(ins->function()), temp());
   6252  assignSnapshot(lir, ins->bailoutKind());
   6253  add(lir, ins);
   6254  redefine(ins, ins->function());
   6255 }
   6256 
   6257 void LIRGenerator::visitGuardFunctionScript(MGuardFunctionScript* ins) {
   6258  MOZ_ASSERT(ins->function()->type() == MIRType::Object);
   6259 
   6260  auto* lir = new (alloc()) LGuardFunctionScript(useRegister(ins->function()));
   6261  assignSnapshot(lir, ins->bailoutKind());
   6262  add(lir, ins);
   6263  redefine(ins, ins->function());
   6264 }
   6265 
   6266 void LIRGenerator::visitAssertRange(MAssertRange* ins) {
   6267  MDefinition* input = ins->input();
   6268  switch (input->type()) {
   6269    case MIRType::Boolean:
   6270    case MIRType::Int32:
   6271    case MIRType::IntPtr:
   6272      add(new (alloc()) LAssertRangeI(useRegisterAtStart(input)), ins);
   6273      break;
   6274 
   6275    case MIRType::Double:
   6276      add(new (alloc()) LAssertRangeD(useRegister(input), tempDouble()), ins);
   6277      break;
   6278 
   6279    case MIRType::Float32:
   6280      add(new (alloc())
   6281              LAssertRangeF(useRegister(input), tempDouble(), tempDouble()),
   6282          ins);
   6283      break;
   6284 
   6285    case MIRType::Value:
   6286      add(new (alloc()) LAssertRangeV(useBox(input), tempToUnbox(),
   6287                                      tempDouble(), tempDouble()),
   6288          ins);
   6289      break;
   6290 
   6291    default:
   6292      MOZ_CRASH("Unexpected Range for MIRType");
   6293      break;
   6294  }
   6295 }
   6296 
   6297 void LIRGenerator::visitAssertClass(MAssertClass* ins) {
   6298  auto* lir =
   6299      new (alloc()) LAssertClass(useRegisterAtStart(ins->input()), temp());
   6300  add(lir, ins);
   6301 }
   6302 
   6303 void LIRGenerator::visitAssertShape(MAssertShape* ins) {
   6304  auto* lir = new (alloc()) LAssertShape(useRegisterAtStart(ins->input()));
   6305  add(lir, ins);
   6306 }
   6307 
   6308 void LIRGenerator::visitDeleteProperty(MDeleteProperty* ins) {
   6309  LDeleteProperty* lir =
   6310      new (alloc()) LDeleteProperty(useBoxAtStart(ins->value()));
   6311  defineReturn(lir, ins);
   6312  assignSafepoint(lir, ins);
   6313 }
   6314 
   6315 void LIRGenerator::visitDeleteElement(MDeleteElement* ins) {
   6316  LDeleteElement* lir = new (alloc())
   6317      LDeleteElement(useBoxAtStart(ins->value()), useBoxAtStart(ins->index()));
   6318  defineReturn(lir, ins);
   6319  assignSafepoint(lir, ins);
   6320 }
   6321 
   6322 void LIRGenerator::visitObjectToIterator(MObjectToIterator* ins) {
   6323  auto* lir = new (alloc())
   6324      LObjectToIterator(useRegister(ins->object()), temp(), temp(), temp());
   6325  define(lir, ins);
   6326  assignSafepoint(lir, ins);
   6327 }
   6328 
   6329 void LIRGenerator::visitValueToIterator(MValueToIterator* ins) {
   6330  auto* lir = new (alloc()) LValueToIterator(useBoxAtStart(ins->value()));
   6331  defineReturn(lir, ins);
   6332  assignSafepoint(lir, ins);
   6333 }
   6334 
   6335 void LIRGenerator::visitLoadSlotByIteratorIndex(MLoadSlotByIteratorIndex* ins) {
   6336  auto* lir = new (alloc()) LLoadSlotByIteratorIndex(
   6337      useRegisterAtStart(ins->object()), useRegisterAtStart(ins->iterator()),
   6338      temp(), temp());
   6339  defineBox(lir, ins);
   6340 }
   6341 
   6342 void LIRGenerator::visitStoreSlotByIteratorIndex(
   6343    MStoreSlotByIteratorIndex* ins) {
   6344  auto* lir = new (alloc()) LStoreSlotByIteratorIndex(
   6345      useRegister(ins->object()), useRegister(ins->iterator()),
   6346      useBox(ins->value()), temp(), temp());
   6347  add(lir, ins);
   6348 }
   6349 
   6350 void LIRGenerator::visitLoadSlotByIteratorIndexIndexed(
   6351    MLoadSlotByIteratorIndexIndexed* ins) {
   6352  auto* lir = new (alloc()) LLoadSlotByIteratorIndexIndexed(
   6353      useRegister(ins->object()), useRegister(ins->iterator()),
   6354      useRegister(ins->index()), temp(), temp());
   6355  defineBox(lir, ins);
   6356 }
   6357 
   6358 void LIRGenerator::visitStoreSlotByIteratorIndexIndexed(
   6359    MStoreSlotByIteratorIndexIndexed* ins) {
   6360  auto* lir = new (alloc()) LStoreSlotByIteratorIndexIndexed(
   6361      useRegister(ins->object()), useRegister(ins->iterator()),
   6362      useRegister(ins->index()), useBox(ins->value()), temp(), temp());
   6363  add(lir, ins);
   6364 }
   6365 
   6366 void LIRGenerator::visitIteratorHasIndices(MIteratorHasIndices* ins) {
   6367  MOZ_ASSERT(ins->hasOneUse());
   6368  emitAtUses(ins);
   6369 }
   6370 
   6371 void LIRGenerator::visitIteratorsMatchAndHaveIndices(
   6372    MIteratorsMatchAndHaveIndices* ins) {
   6373  MOZ_ASSERT(ins->hasOneUse());
   6374  emitAtUses(ins);
   6375 }
   6376 
   6377 void LIRGenerator::visitSetPropertyCache(MSetPropertyCache* ins) {
   6378  MOZ_ASSERT(ins->object()->type() == MIRType::Object);
   6379 
   6380  MDefinition* id = ins->idval();
   6381  MOZ_ASSERT(id->type() == MIRType::String || id->type() == MIRType::Symbol ||
   6382             id->type() == MIRType::Int32 || id->type() == MIRType::Value);
   6383 
   6384  // If this is a SetProp, the id is a constant string. Allow passing it as a
   6385  // constant to reduce register allocation pressure.
   6386  bool useConstId =
   6387      id->type() == MIRType::String || id->type() == MIRType::Symbol;
   6388  bool useConstValue = ins->value()->isConstant();
   6389 
   6390  // Emit an overrecursed check: this is necessary because the cache can
   6391  // attach a scripted setter stub that calls this script recursively.
   6392  gen->setNeedsOverrecursedCheck();
   6393 
   6394  // We need a double temp register for TypedArray stubs.
   6395  LDefinition tempD = tempFixed(FloatReg0);
   6396 
   6397  auto* lir = new (alloc()) LSetPropertyCache(
   6398      useRegister(ins->object()), useBoxOrTypedOrConstant(id, useConstId),
   6399      useBoxOrTypedOrConstant(ins->value(), useConstValue), temp(), tempD);
   6400  add(lir, ins);
   6401  assignSafepoint(lir, ins);
   6402 }
   6403 
   6404 void LIRGenerator::visitMegamorphicSetElement(MMegamorphicSetElement* ins) {
   6405  MOZ_ASSERT(ins->object()->type() == MIRType::Object);
   6406  MOZ_ASSERT(ins->index()->type() == MIRType::Value);
   6407  MOZ_ASSERT(ins->value()->type() == MIRType::Value);
   6408 
   6409  // See comment in LIROps.yaml (x86 is short on registers)
   6410 #ifdef JS_CODEGEN_X86
   6411  auto* lir = new (alloc()) LMegamorphicSetElement(
   6412      useFixedAtStart(ins->object(), CallTempReg0),
   6413      useBoxFixedAtStart(ins->index(), CallTempReg1, CallTempReg2),
   6414      useBoxFixedAtStart(ins->value(), CallTempReg3, CallTempReg4),
   6415      tempFixed(CallTempReg5));
   6416 #else
   6417  auto* lir = new (alloc()) LMegamorphicSetElement(
   6418      useRegisterAtStart(ins->object()), useBoxAtStart(ins->index()),
   6419      useBoxAtStart(ins->value()), tempFixed(CallTempReg0),
   6420      tempFixed(CallTempReg1), tempFixed(CallTempReg2));
   6421 #endif
   6422  add(lir, ins);
   6423  assignSafepoint(lir, ins);
   6424 }
   6425 
   6426 void LIRGenerator::visitGetIteratorCache(MGetIteratorCache* ins) {
   6427  MDefinition* value = ins->value();
   6428  MOZ_ASSERT(value->type() == MIRType::Object ||
   6429             value->type() == MIRType::Value);
   6430 
   6431  LGetIteratorCache* lir =
   6432      new (alloc()) LGetIteratorCache(useBoxOrTyped(value), temp(), temp());
   6433  define(lir, ins);
   6434  assignSafepoint(lir, ins);
   6435 }
   6436 
   6437 void LIRGenerator::visitOptimizeSpreadCallCache(MOptimizeSpreadCallCache* ins) {
   6438  MDefinition* value = ins->value();
   6439  MOZ_ASSERT(value->type() == MIRType::Value);
   6440 
   6441  auto* lir = new (alloc()) LOptimizeSpreadCallCache(useBox(value), temp());
   6442  defineBox(lir, ins);
   6443  assignSafepoint(lir, ins);
   6444 }
   6445 
   6446 void LIRGenerator::visitIteratorMore(MIteratorMore* ins) {
   6447  LIteratorMore* lir =
   6448      new (alloc()) LIteratorMore(useRegister(ins->iterator()), temp());
   6449  defineBox(lir, ins);
   6450 }
   6451 
   6452 void LIRGenerator::visitIsNoIter(MIsNoIter* ins) {
   6453  MOZ_ASSERT(ins->hasOneUse());
   6454  emitAtUses(ins);
   6455 }
   6456 
   6457 void LIRGenerator::visitIteratorEnd(MIteratorEnd* ins) {
   6458  LIteratorEnd* lir = new (alloc())
   6459      LIteratorEnd(useRegister(ins->iterator()), temp(), temp(), temp());
   6460  add(lir, ins);
   6461 }
   6462 
   6463 void LIRGenerator::visitCloseIterCache(MCloseIterCache* ins) {
   6464  LCloseIterCache* lir =
   6465      new (alloc()) LCloseIterCache(useRegister(ins->iter()), temp());
   6466  add(lir, ins);
   6467  assignSafepoint(lir, ins);
   6468 }
   6469 
   6470 void LIRGenerator::visitLoadIteratorElement(MLoadIteratorElement* ins) {
   6471  MOZ_ASSERT(ins->iter()->type() == MIRType::Object);
   6472  MOZ_ASSERT(ins->index()->type() == MIRType::Int32);
   6473  MOZ_ASSERT(ins->type() == MIRType::String);
   6474 
   6475  auto* lir = new (alloc()) LLoadIteratorElement(
   6476      useRegister(ins->iter()), useRegisterOrConstant(ins->index()));
   6477  define(lir, ins);
   6478 }
   6479 
   6480 void LIRGenerator::visitIteratorLength(MIteratorLength* ins) {
   6481  MOZ_ASSERT(ins->iter()->type() == MIRType::Object);
   6482  MOZ_ASSERT(ins->type() == MIRType::Int32);
   6483 
   6484  auto* lir = new (alloc()) LIteratorLength(useRegister(ins->iter()));
   6485  define(lir, ins);
   6486 }
   6487 
   6488 void LIRGenerator::visitOptimizeGetIteratorCache(
   6489    MOptimizeGetIteratorCache* ins) {
   6490  MDefinition* value = ins->value();
   6491  MOZ_ASSERT(value->type() == MIRType::Value);
   6492 
   6493  auto* lir = new (alloc()) LOptimizeGetIteratorCache(useBox(value), temp());
   6494  define(lir, ins);
   6495  assignSafepoint(lir, ins);
   6496 }
   6497 
   6498 void LIRGenerator::visitStringLength(MStringLength* ins) {
   6499  MOZ_ASSERT(ins->string()->type() == MIRType::String);
   6500  define(new (alloc()) LStringLength(useRegisterAtStart(ins->string())), ins);
   6501 }
   6502 
   6503 void LIRGenerator::visitArgumentsLength(MArgumentsLength* ins) {
   6504  define(new (alloc()) LArgumentsLength(), ins);
   6505 }
   6506 
   6507 void LIRGenerator::visitGetFrameArgument(MGetFrameArgument* ins) {
   6508  LGetFrameArgument* lir =
   6509      new (alloc()) LGetFrameArgument(useRegisterOrConstant(ins->index()));
   6510  defineBox(lir, ins);
   6511 }
   6512 
   6513 void LIRGenerator::visitGetFrameArgumentHole(MGetFrameArgumentHole* ins) {
   6514  LDefinition spectreTemp =
   6515      BoundsCheckNeedsSpectreTemp() ? temp() : LDefinition::BogusTemp();
   6516 
   6517  auto* lir = new (alloc()) LGetFrameArgumentHole(
   6518      useRegister(ins->index()), useRegister(ins->length()), spectreTemp);
   6519  assignSnapshot(lir, ins->bailoutKind());
   6520  defineBox(lir, ins);
   6521 }
   6522 
   6523 void LIRGenerator::visitNewTarget(MNewTarget* ins) {
   6524  LNewTarget* lir = new (alloc()) LNewTarget();
   6525  defineBox(lir, ins);
   6526 }
   6527 
   6528 void LIRGenerator::visitRest(MRest* ins) {
   6529  MOZ_ASSERT(ins->numActuals()->type() == MIRType::Int32);
   6530 
   6531  LRest* lir =
   6532      new (alloc()) LRest(useRegisterAtStart(ins->numActuals()),
   6533                          tempFixed(CallTempReg0), tempFixed(CallTempReg1),
   6534                          tempFixed(CallTempReg2), tempFixed(CallTempReg3));
   6535  defineReturn(lir, ins);
   6536  assignSafepoint(lir, ins);
   6537 }
   6538 
   6539 void LIRGenerator::visitThrow(MThrow* ins) {
   6540  MDefinition* value = ins->value();
   6541  MOZ_ASSERT(value->type() == MIRType::Value);
   6542 
   6543  LThrow* lir = new (alloc()) LThrow(useBoxAtStart(value));
   6544  add(lir, ins);
   6545  assignSafepoint(lir, ins);
   6546 }
   6547 
   6548 void LIRGenerator::visitThrowWithStack(MThrowWithStack* ins) {
   6549  MDefinition* value = ins->value();
   6550  MOZ_ASSERT(value->type() == MIRType::Value);
   6551 
   6552  MDefinition* stack = ins->stack();
   6553  MOZ_ASSERT(stack->type() == MIRType::Value);
   6554 
   6555  auto* lir =
   6556      new (alloc()) LThrowWithStack(useBoxAtStart(value), useBoxAtStart(stack));
   6557  add(lir, ins);
   6558  assignSafepoint(lir, ins);
   6559 }
   6560 
   6561 void LIRGenerator::visitInCache(MInCache* ins) {
   6562  MDefinition* lhs = ins->lhs();
   6563  MDefinition* rhs = ins->rhs();
   6564 
   6565  MOZ_ASSERT(lhs->type() == MIRType::String || lhs->type() == MIRType::Symbol ||
   6566             lhs->type() == MIRType::Int32 || lhs->type() == MIRType::Value);
   6567  MOZ_ASSERT(rhs->type() == MIRType::Object);
   6568 
   6569  LInCache* lir =
   6570      new (alloc()) LInCache(useBoxOrTyped(lhs), useRegister(rhs), temp());
   6571  define(lir, ins);
   6572  assignSafepoint(lir, ins);
   6573 }
   6574 
   6575 void LIRGenerator::visitHasOwnCache(MHasOwnCache* ins) {
   6576  MDefinition* value = ins->value();
   6577  MOZ_ASSERT(value->type() == MIRType::Object ||
   6578             value->type() == MIRType::Value);
   6579 
   6580  MDefinition* id = ins->idval();
   6581  MOZ_ASSERT(id->type() == MIRType::String || id->type() == MIRType::Symbol ||
   6582             id->type() == MIRType::Int32 || id->type() == MIRType::Value);
   6583 
   6584  // Emit an overrecursed check: this is necessary because the cache can
   6585  // attach a scripted getter stub that calls this script recursively.
   6586  gen->setNeedsOverrecursedCheck();
   6587 
   6588  LHasOwnCache* lir =
   6589      new (alloc()) LHasOwnCache(useBoxOrTyped(value), useBoxOrTyped(id));
   6590  define(lir, ins);
   6591  assignSafepoint(lir, ins);
   6592 }
   6593 
   6594 void LIRGenerator::visitCheckPrivateFieldCache(MCheckPrivateFieldCache* ins) {
   6595  MDefinition* value = ins->value();
   6596  MOZ_ASSERT(value->type() == MIRType::Object ||
   6597             value->type() == MIRType::Value);
   6598 
   6599  MDefinition* id = ins->idval();
   6600  MOZ_ASSERT(id->type() == MIRType::String || id->type() == MIRType::Symbol ||
   6601             id->type() == MIRType::Int32 || id->type() == MIRType::Value);
   6602 
   6603  LCheckPrivateFieldCache* lir = new (alloc())
   6604      LCheckPrivateFieldCache(useBoxOrTyped(value), useBoxOrTyped(id));
   6605  define(lir, ins);
   6606  assignSafepoint(lir, ins);
   6607 }
   6608 
   6609 void LIRGenerator::visitNewPrivateName(MNewPrivateName* ins) {
   6610  auto* lir = new (alloc()) LNewPrivateName();
   6611  defineReturn(lir, ins);
   6612  assignSafepoint(lir, ins);
   6613 }
   6614 
   6615 void LIRGenerator::visitInstanceOf(MInstanceOf* ins) {
   6616  MDefinition* lhs = ins->lhs();
   6617  MDefinition* rhs = ins->rhs();
   6618 
   6619  MOZ_ASSERT(lhs->type() == MIRType::Value || lhs->type() == MIRType::Object);
   6620  MOZ_ASSERT(rhs->type() == MIRType::Object);
   6621 
   6622  if (lhs->type() == MIRType::Object) {
   6623    auto* lir = new (alloc()) LInstanceOfO(useRegister(lhs), useRegister(rhs));
   6624    define(lir, ins);
   6625    assignSafepoint(lir, ins);
   6626  } else {
   6627    auto* lir = new (alloc()) LInstanceOfV(useBox(lhs), useRegister(rhs));
   6628    define(lir, ins);
   6629    assignSafepoint(lir, ins);
   6630  }
   6631 }
   6632 
   6633 void LIRGenerator::visitInstanceOfCache(MInstanceOfCache* ins) {
   6634  MDefinition* lhs = ins->lhs();
   6635  MDefinition* rhs = ins->rhs();
   6636 
   6637  MOZ_ASSERT(lhs->type() == MIRType::Value);
   6638  MOZ_ASSERT(rhs->type() == MIRType::Object);
   6639 
   6640  LInstanceOfCache* lir =
   6641      new (alloc()) LInstanceOfCache(useBox(lhs), useRegister(rhs));
   6642  define(lir, ins);
   6643  assignSafepoint(lir, ins);
   6644 }
   6645 
   6646 void LIRGenerator::visitIsArray(MIsArray* ins) {
   6647  MOZ_ASSERT(ins->type() == MIRType::Boolean);
   6648 
   6649  if (ins->value()->type() == MIRType::Object) {
   6650    LIsArrayO* lir = new (alloc()) LIsArrayO(useRegister(ins->value()));
   6651    define(lir, ins);
   6652    assignSafepoint(lir, ins);
   6653  } else {
   6654    MOZ_ASSERT(ins->value()->type() == MIRType::Value);
   6655    LIsArrayV* lir = new (alloc()) LIsArrayV(useBox(ins->value()), temp());
   6656    define(lir, ins);
   6657    assignSafepoint(lir, ins);
   6658  }
   6659 }
   6660 
   6661 void LIRGenerator::visitIsTypedArray(MIsTypedArray* ins) {
   6662  MOZ_ASSERT(ins->value()->type() == MIRType::Object);
   6663  MOZ_ASSERT(ins->type() == MIRType::Boolean);
   6664 
   6665  auto* lir = new (alloc()) LIsTypedArray(useRegister(ins->value()));
   6666  define(lir, ins);
   6667 
   6668  if (ins->isPossiblyWrapped()) {
   6669    assignSafepoint(lir, ins);
   6670  }
   6671 }
   6672 
   6673 void LIRGenerator::visitIsCallable(MIsCallable* ins) {
   6674  MOZ_ASSERT(ins->type() == MIRType::Boolean);
   6675 
   6676  if (ins->object()->type() == MIRType::Object) {
   6677    define(new (alloc()) LIsCallableO(useRegister(ins->object())), ins);
   6678  } else {
   6679    MOZ_ASSERT(ins->object()->type() == MIRType::Value);
   6680    define(new (alloc()) LIsCallableV(useBox(ins->object()), temp()), ins);
   6681  }
   6682 }
   6683 
   6684 void LIRGenerator::visitIsConstructor(MIsConstructor* ins) {
   6685  MOZ_ASSERT(ins->object()->type() == MIRType::Object);
   6686  MOZ_ASSERT(ins->type() == MIRType::Boolean);
   6687  define(new (alloc()) LIsConstructor(useRegister(ins->object())), ins);
   6688 }
   6689 
   6690 void LIRGenerator::visitIsCrossRealmArrayConstructor(
   6691    MIsCrossRealmArrayConstructor* ins) {
   6692  MOZ_ASSERT(ins->object()->type() == MIRType::Object);
   6693  MOZ_ASSERT(ins->type() == MIRType::Boolean);
   6694  define(new (alloc())
   6695             LIsCrossRealmArrayConstructor(useRegister(ins->object())),
   6696         ins);
   6697 }
   6698 
   6699 static bool CanEmitAtUseForSingleTest(MInstruction* ins) {
   6700  if (!ins->canEmitAtUses()) {
   6701    return false;
   6702  }
   6703 
   6704  MUseIterator iter(ins->usesBegin());
   6705  if (iter == ins->usesEnd()) {
   6706    return false;
   6707  }
   6708 
   6709  MNode* node = iter->consumer();
   6710  if (!node->isDefinition()) {
   6711    return false;
   6712  }
   6713 
   6714  if (!node->toDefinition()->isTest()) {
   6715    return false;
   6716  }
   6717 
   6718  iter++;
   6719  return iter == ins->usesEnd();
   6720 }
   6721 
   6722 void LIRGenerator::visitIsObject(MIsObject* ins) {
   6723  if (CanEmitAtUseForSingleTest(ins)) {
   6724    emitAtUses(ins);
   6725    return;
   6726  }
   6727 
   6728  MDefinition* opd = ins->input();
   6729  MOZ_ASSERT(opd->type() == MIRType::Value);
   6730  LIsObject* lir = new (alloc()) LIsObject(useBoxAtStart(opd));
   6731  define(lir, ins);
   6732 }
   6733 
   6734 void LIRGenerator::visitIsNullOrUndefined(MIsNullOrUndefined* ins) {
   6735  if (CanEmitAtUseForSingleTest(ins)) {
   6736    emitAtUses(ins);
   6737    return;
   6738  }
   6739 
   6740  MDefinition* opd = ins->input();
   6741  if (opd->type() == MIRType::Value) {
   6742    auto* lir = new (alloc()) LIsNullOrUndefined(useBoxAtStart(opd));
   6743    define(lir, ins);
   6744  } else {
   6745    define(new (alloc()) LInteger(IsNullOrUndefined(opd->type())), ins);
   6746  }
   6747 }
   6748 
   6749 void LIRGenerator::visitHasClass(MHasClass* ins) {
   6750  MOZ_ASSERT(ins->object()->type() == MIRType::Object);
   6751  MOZ_ASSERT(ins->type() == MIRType::Boolean);
   6752  define(new (alloc()) LHasClass(useRegister(ins->object())), ins);
   6753 }
   6754 
   6755 void LIRGenerator::visitHasShape(MHasShape* ins) {
   6756  MOZ_ASSERT(ins->object()->type() == MIRType::Object);
   6757  MOZ_ASSERT(ins->type() == MIRType::Boolean);
   6758  define(new (alloc()) LHasShape(useRegister(ins->object())), ins);
   6759 }
   6760 
   6761 void LIRGenerator::visitGuardToClass(MGuardToClass* ins) {
   6762  MOZ_ASSERT(ins->object()->type() == MIRType::Object);
   6763  MOZ_ASSERT(ins->type() == MIRType::Object);
   6764  LGuardToClass* lir =
   6765      new (alloc()) LGuardToClass(useRegisterAtStart(ins->object()), temp());
   6766  assignSnapshot(lir, ins->bailoutKind());
   6767  defineReuseInput(lir, ins, 0);
   6768 }
   6769 
   6770 void LIRGenerator::visitGuardToFunction(MGuardToFunction* ins) {
   6771  MOZ_ASSERT(ins->object()->type() == MIRType::Object);
   6772  MOZ_ASSERT(ins->type() == MIRType::Object);
   6773  LGuardToFunction* lir =
   6774      new (alloc()) LGuardToFunction(useRegisterAtStart(ins->object()), temp());
   6775  assignSnapshot(lir, ins->bailoutKind());
   6776  defineReuseInput(lir, ins, 0);
   6777 }
   6778 
   6779 void LIRGenerator::visitObjectClassToString(MObjectClassToString* ins) {
   6780  MOZ_ASSERT(ins->object()->type() == MIRType::Object);
   6781  MOZ_ASSERT(ins->type() == MIRType::String);
   6782  auto* lir = new (alloc()) LObjectClassToString(
   6783      useRegisterAtStart(ins->object()), tempFixed(CallTempReg0));
   6784  assignSnapshot(lir, ins->bailoutKind());
   6785  defineReturn(lir, ins);
   6786 }
   6787 
   6788 void LIRGenerator::visitWasmAddOffset(MWasmAddOffset* ins) {
   6789  MOZ_ASSERT(ins->offset());
   6790  if (ins->base()->type() == MIRType::Int32) {
   6791    MOZ_ASSERT(ins->type() == MIRType::Int32);
   6792    MOZ_ASSERT(ins->offset() <= UINT32_MAX);  // Because memory32
   6793    define(new (alloc()) LWasmAddOffset(useRegisterAtStart(ins->base())), ins);
   6794  } else {
   6795    MOZ_ASSERT(ins->type() == MIRType::Int64);
   6796 #ifdef JS_64BIT
   6797    defineInt64(new (alloc())
   6798                    LWasmAddOffset64(useInt64RegisterAtStart(ins->base())),
   6799                ins);
   6800 #else
   6801    // Avoid situation where the input is (a,b) and the output is (b,a).
   6802    defineInt64ReuseInput(
   6803        new (alloc()) LWasmAddOffset64(useInt64RegisterAtStart(ins->base())),
   6804        ins, 0);
   6805 #endif
   6806  }
   6807 }
   6808 
   6809 // When MWasmLoadInstance is used with MWasmBoundsCheck, it can be used as a
   6810 // memory operand instead of being allocated to a register.
   6811 static bool CanEmitWasmLoadInstanceAtUses(MWasmLoadInstance* ins) {
   6812  if (!ins->canEmitAtUses()) {
   6813    return false;
   6814  }
   6815 
   6816  if (!ins->hasOneUse()) {
   6817    return false;
   6818  }
   6819 
   6820  MUseIterator iter(ins->usesBegin());
   6821  MNode* node = iter->consumer();
   6822  if (!node->isDefinition() || !node->toDefinition()->isInstruction()) {
   6823    return false;
   6824  }
   6825 
   6826  MInstruction* use = node->toDefinition()->toInstruction();
   6827  return use->isWasmBoundsCheck();
   6828 }
   6829 
   6830 void LIRGenerator::visitWasmLoadInstance(MWasmLoadInstance* ins) {
   6831  if (CanEmitWasmLoadInstanceAtUses(ins)) {
   6832    emitAtUses(ins);
   6833    return;
   6834  }
   6835 
   6836  if (ins->type() == MIRType::Int64) {
   6837 #ifdef JS_PUNBOX64
   6838    LAllocation instance = useRegisterAtStart(ins->instance());
   6839 #else
   6840    // Avoid reusing instance for a 64-bit output pair as the load clobbers the
   6841    // first half of that pair before loading the second half.
   6842    LAllocation instance = useRegister(ins->instance());
   6843 #endif
   6844    auto* lir = new (alloc()) LWasmLoadInstance64(instance);
   6845    defineInt64(lir, ins);
   6846  } else {
   6847    auto* lir =
   6848        new (alloc()) LWasmLoadInstance(useRegisterAtStart(ins->instance()));
   6849    define(lir, ins);
   6850  }
   6851 }
   6852 
   6853 void LIRGenerator::visitWasmStoreInstance(MWasmStoreInstance* ins) {
   6854  MDefinition* value = ins->value();
   6855  if (value->type() == MIRType::Int64) {
   6856 #ifdef JS_PUNBOX64
   6857    LAllocation instance = useRegisterAtStart(ins->instance());
   6858    LInt64Allocation valueAlloc = useInt64RegisterAtStart(value);
   6859 #else
   6860    LAllocation instance = useRegister(ins->instance());
   6861    LInt64Allocation valueAlloc = useInt64Register(value);
   6862 #endif
   6863    add(new (alloc()) LWasmStoreSlotI64(valueAlloc, instance, ins->offset(),
   6864                                        mozilla::Nothing()),
   6865        ins);
   6866  } else {
   6867    MOZ_ASSERT(value->type() != MIRType::WasmAnyRef);
   6868    LAllocation instance = useRegisterAtStart(ins->instance());
   6869    LAllocation valueAlloc = useRegisterAtStart(value);
   6870    add(new (alloc())
   6871            LWasmStoreSlot(valueAlloc, instance, ins->offset(), value->type(),
   6872                           MNarrowingOp::None, mozilla::Nothing()),
   6873        ins);
   6874  }
   6875 }
   6876 
   6877 void LIRGenerator::visitWasmHeapReg(MWasmHeapReg* ins) {
   6878 #ifdef WASM_HAS_HEAPREG
   6879  auto* lir = new (alloc()) LWasmHeapReg();
   6880  define(lir, ins);
   6881 #else
   6882  MOZ_CRASH();
   6883 #endif
   6884 }
   6885 
   6886 void LIRGenerator::visitWasmBoundsCheck(MWasmBoundsCheck* ins) {
   6887  MOZ_ASSERT(!ins->isRedundant());
   6888 
   6889  MDefinition* index = ins->index();
   6890  MDefinition* boundsCheckLimit = ins->boundsCheckLimit();
   6891 
   6892  MOZ_ASSERT(boundsCheckLimit->type() == index->type());
   6893 
   6894  // Fold the instance load into the bounds check as a memory operand,
   6895  // if possible
   6896  if (boundsCheckLimit->isWasmLoadInstance() &&
   6897      boundsCheckLimit->isEmittedAtUses()) {
   6898    MWasmLoadInstance* lengthFromInstance =
   6899        boundsCheckLimit->toWasmLoadInstance();
   6900    if (index->type() == MIRType::Int64) {
   6901      if (JitOptions.spectreIndexMasking) {
   6902        auto* lir = new (alloc()) LWasmBoundsCheckInstanceField64(
   6903            useRegister(lengthFromInstance->instance()),
   6904            useInt64RegisterAtStart(index), lengthFromInstance->offset());
   6905        defineInt64ReuseInput(lir, ins, 1);
   6906      } else {
   6907        auto* lir = new (alloc()) LWasmBoundsCheckInstanceField64(
   6908            useRegisterAtStart(lengthFromInstance->instance()),
   6909            useInt64RegisterAtStart(index), lengthFromInstance->offset());
   6910        addUnchecked(lir, ins);
   6911      }
   6912    } else {
   6913      MOZ_ASSERT(index->type() == MIRType::Int32);
   6914 
   6915      if (JitOptions.spectreIndexMasking) {
   6916        auto* lir = new (alloc()) LWasmBoundsCheckInstanceField(
   6917            useRegister(lengthFromInstance->instance()),
   6918            useRegisterAtStart(index), lengthFromInstance->offset());
   6919        defineReuseInput(lir, ins, 1);
   6920      } else {
   6921        auto* lir = new (alloc()) LWasmBoundsCheckInstanceField(
   6922            useRegisterAtStart(lengthFromInstance->instance()),
   6923            useRegisterAtStart(index), lengthFromInstance->offset());
   6924        addUnchecked(lir, ins);
   6925      }
   6926    }
   6927 
   6928    return;
   6929  }
   6930 
   6931  if (index->type() == MIRType::Int64) {
   6932    if (JitOptions.spectreIndexMasking) {
   6933      auto* lir = new (alloc())
   6934          LWasmBoundsCheck64(useInt64RegisterAtStart(index),
   6935                             useInt64RegisterOrConstant(boundsCheckLimit));
   6936      defineInt64ReuseInput(lir, ins, 0);
   6937    } else {
   6938      auto* lir = new (alloc()) LWasmBoundsCheck64(
   6939          useInt64RegisterAtStart(index),
   6940          useInt64RegisterOrConstantAtStart(boundsCheckLimit));
   6941      addUnchecked(lir, ins);
   6942    }
   6943  } else {
   6944    MOZ_ASSERT(index->type() == MIRType::Int32);
   6945 
   6946    if (JitOptions.spectreIndexMasking) {
   6947      auto* lir = new (alloc()) LWasmBoundsCheck(
   6948          useRegisterAtStart(index), useRegisterOrConstant(boundsCheckLimit));
   6949      defineReuseInput(lir, ins, 0);
   6950    } else {
   6951      auto* lir = new (alloc())
   6952          LWasmBoundsCheck(useRegisterAtStart(index),
   6953                           useRegisterOrConstantAtStart(boundsCheckLimit));
   6954      addUnchecked(lir, ins);
   6955    }
   6956  }
   6957 }
   6958 
   6959 void LIRGenerator::visitWasmBoundsCheckRange32(MWasmBoundsCheckRange32* ins) {
   6960  MDefinition* index = ins->index();
   6961  MDefinition* length = ins->length();
   6962  MDefinition* limit = ins->limit();
   6963 
   6964  MOZ_ASSERT(index->type() == MIRType::Int32);
   6965  MOZ_ASSERT(length->type() == MIRType::Int32);
   6966  MOZ_ASSERT(limit->type() == MIRType::Int32);
   6967 
   6968  add(new (alloc()) LWasmBoundsCheckRange32(
   6969          useRegister(index), useRegister(length), useRegister(limit), temp()),
   6970      ins);
   6971 }
   6972 
   6973 void LIRGenerator::visitWasmAlignmentCheck(MWasmAlignmentCheck* ins) {
   6974  MDefinition* index = ins->index();
   6975  if (index->type() == MIRType::Int64) {
   6976    auto* lir =
   6977        new (alloc()) LWasmAlignmentCheck64(useInt64RegisterAtStart(index));
   6978    add(lir, ins);
   6979  } else {
   6980    auto* lir = new (alloc()) LWasmAlignmentCheck(useRegisterAtStart(index));
   6981    add(lir, ins);
   6982  }
   6983 }
   6984 
   6985 void LIRGenerator::visitWasmLoadInstanceDataField(
   6986    MWasmLoadInstanceDataField* ins) {
   6987  size_t offs = wasm::Instance::offsetInData(ins->instanceDataOffset());
   6988  if (ins->type() == MIRType::Int64) {
   6989 #ifdef JS_PUNBOX64
   6990    LAllocation instance = useRegisterAtStart(ins->instance());
   6991 #else
   6992    // Avoid reusing instance for the output pair as the load clobbers the first
   6993    // half of that pair before loading the second half.
   6994    LAllocation instance = useRegister(ins->instance());
   6995 #endif
   6996    defineInt64(new (alloc())
   6997                    LWasmLoadSlotI64(instance, offs, mozilla::Nothing()),
   6998                ins);
   6999  } else {
   7000    LAllocation instance = useRegisterAtStart(ins->instance());
   7001    define(new (alloc()) LWasmLoadSlot(instance, offs, ins->type(),
   7002                                       MWideningOp::None, mozilla::Nothing()),
   7003           ins);
   7004  }
   7005 }
   7006 
   7007 void LIRGenerator::visitWasmLoadGlobalCell(MWasmLoadGlobalCell* ins) {
   7008  if (ins->type() == MIRType::Int64) {
   7009 #ifdef JS_PUNBOX64
   7010    LAllocation cellPtr = useRegisterAtStart(ins->cellPtr());
   7011 #else
   7012    // Avoid reusing cellPtr for the output pair as the load clobbers the first
   7013    // half of that pair before loading the second half.
   7014    LAllocation cellPtr = useRegister(ins->cellPtr());
   7015 #endif
   7016    defineInt64(new (alloc())
   7017                    LWasmLoadSlotI64(cellPtr, /*offset=*/0, mozilla::Nothing()),
   7018                ins);
   7019  } else {
   7020    LAllocation cellPtr = useRegisterAtStart(ins->cellPtr());
   7021    define(new (alloc()) LWasmLoadSlot(cellPtr, /*offset=*/0, ins->type(),
   7022                                       MWideningOp::None, mozilla::Nothing()),
   7023           ins);
   7024  }
   7025 }
   7026 
   7027 void LIRGenerator::visitWasmLoadTableElement(MWasmLoadTableElement* ins) {
   7028  LAllocation elements = useRegisterAtStart(ins->elements());
   7029  LAllocation index = useRegisterAtStart(ins->index());
   7030  define(new (alloc()) LWasmLoadTableElement(elements, index), ins);
   7031 }
   7032 
   7033 void LIRGenerator::visitWasmStoreInstanceDataField(
   7034    MWasmStoreInstanceDataField* ins) {
   7035  MDefinition* value = ins->value();
   7036  size_t offs = wasm::Instance::offsetInData(ins->instanceDataOffset());
   7037  if (value->type() == MIRType::Int64) {
   7038 #ifdef JS_PUNBOX64
   7039    LAllocation instance = useRegisterAtStart(ins->instance());
   7040    LInt64Allocation valueAlloc = useInt64RegisterAtStart(value);
   7041 #else
   7042    LAllocation instance = useRegister(ins->instance());
   7043    LInt64Allocation valueAlloc = useInt64Register(value);
   7044 #endif
   7045    add(new (alloc())
   7046            LWasmStoreSlotI64(valueAlloc, instance, offs, mozilla::Nothing()),
   7047        ins);
   7048  } else {
   7049    MOZ_ASSERT(value->type() != MIRType::WasmAnyRef);
   7050    LAllocation instance = useRegisterAtStart(ins->instance());
   7051    LAllocation valueAlloc = useRegisterAtStart(value);
   7052    add(new (alloc()) LWasmStoreSlot(valueAlloc, instance, offs, value->type(),
   7053                                     MNarrowingOp::None, mozilla::Nothing()),
   7054        ins);
   7055  }
   7056 }
   7057 
   7058 void LIRGenerator::visitWasmStoreGlobalCell(MWasmStoreGlobalCell* ins) {
   7059  MDefinition* value = ins->value();
   7060  size_t offs = 0;
   7061  if (value->type() == MIRType::Int64) {
   7062 #ifdef JS_PUNBOX64
   7063    LAllocation cellPtr = useRegisterAtStart(ins->cellPtr());
   7064    LInt64Allocation valueAlloc = useInt64RegisterAtStart(value);
   7065 #else
   7066    LAllocation cellPtr = useRegister(ins->cellPtr());
   7067    LInt64Allocation valueAlloc = useInt64Register(value);
   7068 #endif
   7069    add(new (alloc())
   7070            LWasmStoreSlotI64(valueAlloc, cellPtr, offs, mozilla::Nothing()));
   7071  } else {
   7072    MOZ_ASSERT(value->type() != MIRType::WasmAnyRef);
   7073    LAllocation cellPtr = useRegisterAtStart(ins->cellPtr());
   7074    LAllocation valueAlloc = useRegisterAtStart(value);
   7075    add(new (alloc()) LWasmStoreSlot(valueAlloc, cellPtr, offs, value->type(),
   7076                                     MNarrowingOp::None, mozilla::Nothing()));
   7077  }
   7078 }
   7079 
   7080 void LIRGenerator::visitWasmStoreStackResult(MWasmStoreStackResult* ins) {
   7081  MDefinition* stackResultArea = ins->stackResultArea();
   7082  MDefinition* value = ins->value();
   7083  size_t offs = ins->offset();
   7084  if (value->type() == MIRType::Int64) {
   7085    add(new (alloc()) LWasmStoreStackResultI64(
   7086            useInt64Register(value), useRegister(stackResultArea), offs),
   7087        ins);
   7088  } else {
   7089    add(new (alloc()) LWasmStoreStackResult(useRegister(value),
   7090                                            useRegister(stackResultArea), offs,
   7091                                            value->type()),
   7092        ins);
   7093  }
   7094 }
   7095 
   7096 void LIRGenerator::visitWasmDerivedPointer(MWasmDerivedPointer* ins) {
   7097  LAllocation base = useRegisterAtStart(ins->base());
   7098  define(new (alloc()) LWasmDerivedPointer(base), ins);
   7099 }
   7100 
   7101 void LIRGenerator::visitWasmDerivedIndexPointer(MWasmDerivedIndexPointer* ins) {
   7102  LAllocation base = useRegisterAtStart(ins->base());
   7103  LAllocation index = useRegisterAtStart(ins->index());
   7104  define(new (alloc()) LWasmDerivedIndexPointer(base, index), ins);
   7105 }
   7106 
   7107 void LIRGenerator::visitWasmStoreRef(MWasmStoreRef* ins) {
   7108  LAllocation instance = useRegister(ins->instance());
   7109  LAllocation valueBase = useFixed(ins->valueBase(), PreBarrierReg);
   7110  LAllocation value = useRegister(ins->value());
   7111  uint32_t valueOffset = ins->offset();
   7112  add(new (alloc())
   7113          LWasmStoreRef(instance, valueBase, value, temp(), valueOffset,
   7114                        mozilla::Nothing(), ins->preBarrierKind()),
   7115      ins);
   7116 }
   7117 
   7118 void LIRGenerator::visitWasmPostWriteBarrierWholeCell(
   7119    MWasmPostWriteBarrierWholeCell* ins) {
   7120  LWasmPostWriteBarrierWholeCell* lir = new (alloc())
   7121      LWasmPostWriteBarrierWholeCell(useFixed(ins->instance(), InstanceReg),
   7122                                     useRegister(ins->object()),
   7123                                     useRegister(ins->value()), temp());
   7124  add(lir, ins);
   7125  assignWasmSafepoint(lir);
   7126 }
   7127 
   7128 void LIRGenerator::visitWasmPostWriteBarrierEdgeAtIndex(
   7129    MWasmPostWriteBarrierEdgeAtIndex* ins) {
   7130  LWasmPostWriteBarrierEdgeAtIndex* lir =
   7131      new (alloc()) LWasmPostWriteBarrierEdgeAtIndex(
   7132          useFixed(ins->instance(), InstanceReg), useRegister(ins->object()),
   7133          useRegister(ins->valueBase()), useRegister(ins->index()),
   7134          useRegister(ins->value()), temp(), ins->elemSize());
   7135  add(lir, ins);
   7136  assignWasmSafepoint(lir);
   7137 }
   7138 
   7139 void LIRGenerator::visitWasmParameter(MWasmParameter* ins) {
   7140  ABIArg abi = ins->abi();
   7141  if (ins->type() == MIRType::StackResults) {
   7142    // Functions that return stack results receive an extra incoming parameter
   7143    // with type MIRType::StackResults.  This value is a pointer to fresh
   7144    // memory.  Here we treat it as if it were in fact MIRType::Pointer.
   7145    auto* lir = new (alloc()) LWasmParameter;
   7146    LDefinition def(LDefinition::TypeFrom(MIRType::Pointer),
   7147                    LDefinition::FIXED);
   7148    def.setOutput(abi.argInRegister() ? LAllocation(abi.reg())
   7149                                      : LArgument(abi.offsetFromArgBase()));
   7150    define(lir, ins, def);
   7151    return;
   7152  }
   7153  if (abi.argInRegister()) {
   7154 #if defined(JS_NUNBOX32)
   7155    if (abi.isGeneralRegPair()) {
   7156      defineInt64Fixed(
   7157          new (alloc()) LWasmParameterI64, ins,
   7158          LInt64Allocation(LAllocation(AnyRegister(abi.gpr64().high)),
   7159                           LAllocation(AnyRegister(abi.gpr64().low))));
   7160      return;
   7161    }
   7162 #endif
   7163    defineFixed(new (alloc()) LWasmParameter, ins, LAllocation(abi.reg()));
   7164    return;
   7165  }
   7166  if (ins->type() == MIRType::Int64) {
   7167    MOZ_ASSERT(!abi.argInRegister());
   7168    defineInt64Fixed(
   7169        new (alloc()) LWasmParameterI64, ins,
   7170 #if defined(JS_NUNBOX32)
   7171        LInt64Allocation(LArgument(abi.offsetFromArgBase() + INT64HIGH_OFFSET),
   7172                         LArgument(abi.offsetFromArgBase() + INT64LOW_OFFSET))
   7173 #else
   7174        LInt64Allocation(LArgument(abi.offsetFromArgBase()))
   7175 #endif
   7176    );
   7177  } else {
   7178    MOZ_ASSERT(IsNumberType(ins->type()) || ins->type() == MIRType::WasmAnyRef
   7179 #ifdef ENABLE_WASM_SIMD
   7180               || ins->type() == MIRType::Simd128
   7181 #endif
   7182    );
   7183    defineFixed(new (alloc()) LWasmParameter, ins,
   7184                LArgument(abi.offsetFromArgBase()));
   7185  }
   7186 }
   7187 
   7188 void LIRGenerator::visitWasmReturn(MWasmReturn* ins) {
   7189  MDefinition* rval = ins->getOperand(0);
   7190  MDefinition* instance = ins->getOperand(1);
   7191 
   7192  if (rval->type() == MIRType::Int64) {
   7193    add(new (alloc()) LWasmReturnI64(useInt64Fixed(rval, ReturnReg64),
   7194                                     useFixed(instance, InstanceReg)));
   7195    return;
   7196  }
   7197 
   7198  LAllocation returnReg;
   7199  if (rval->type() == MIRType::Float32) {
   7200    returnReg = useFixed(rval, ReturnFloat32Reg);
   7201  } else if (rval->type() == MIRType::Double) {
   7202    returnReg = useFixed(rval, ReturnDoubleReg);
   7203 #ifdef ENABLE_WASM_SIMD
   7204  } else if (rval->type() == MIRType::Simd128) {
   7205    returnReg = useFixed(rval, ReturnSimd128Reg);
   7206 #endif
   7207  } else if (rval->type() == MIRType::Int32 ||
   7208             rval->type() == MIRType::WasmAnyRef) {
   7209    returnReg = useFixed(rval, ReturnReg);
   7210  } else {
   7211    MOZ_CRASH("Unexpected wasm return type");
   7212  }
   7213 
   7214  LWasmReturn* lir =
   7215      new (alloc()) LWasmReturn(useFixed(instance, InstanceReg), returnReg);
   7216  add(lir);
   7217 }
   7218 
   7219 void LIRGenerator::visitWasmReturnVoid(MWasmReturnVoid* ins) {
   7220  MDefinition* instance = ins->getOperand(0);
   7221  LWasmReturnVoid* lir =
   7222      new (alloc()) LWasmReturnVoid(useFixed(instance, InstanceReg));
   7223  add(lir);
   7224 }
   7225 
   7226 void LIRGenerator::visitWasmStackArg(MWasmStackArg* ins) {
   7227  if (ins->arg()->type() == MIRType::Int64) {
   7228    add(new (alloc())
   7229            LWasmStackArgI64(useInt64RegisterOrConstantAtStart(ins->arg())),
   7230        ins);
   7231  } else if (IsFloatingPointType(ins->arg()->type())) {
   7232    MOZ_ASSERT(!ins->arg()->isEmittedAtUses());
   7233    add(new (alloc()) LWasmStackArg(useRegisterAtStart(ins->arg())), ins);
   7234  } else {
   7235    add(new (alloc()) LWasmStackArg(useRegisterOrConstantAtStart(ins->arg())),
   7236        ins);
   7237  }
   7238 }
   7239 
   7240 void LIRGenerator::visitWasmRegisterResult(MWasmRegisterResult* ins) {
   7241  auto* lir = new (alloc()) LWasmRegisterResult();
   7242  uint32_t vreg = getVirtualRegister();
   7243  MOZ_ASSERT(ins->type() != MIRType::Int64);
   7244  auto type = LDefinition::TypeFrom(ins->type());
   7245  lir->setDef(0, LDefinition(vreg, type, LGeneralReg(ins->loc())));
   7246  ins->setVirtualRegister(vreg);
   7247  addUnchecked(lir, ins);
   7248 }
   7249 
   7250 void LIRGenerator::visitWasmFloatRegisterResult(MWasmFloatRegisterResult* ins) {
   7251  auto* lir = new (alloc()) LWasmRegisterResult();
   7252  uint32_t vreg = getVirtualRegister();
   7253  auto type = LDefinition::TypeFrom(ins->type());
   7254  lir->setDef(0, LDefinition(vreg, type, LFloatReg(ins->loc())));
   7255  ins->setVirtualRegister(vreg);
   7256  addUnchecked(lir, ins);
   7257 }
   7258 
   7259 void LIRGenerator::visitWasmSystemFloatRegisterResult(
   7260    MWasmSystemFloatRegisterResult* ins) {
   7261  auto* lir = new (alloc()) LWasmSystemFloatRegisterResult();
   7262  uint32_t vreg = getVirtualRegister();
   7263  auto type = LDefinition::TypeFrom(ins->type());
   7264  lir->setDef(0, LDefinition(vreg, type, LFloatReg(ins->loc())));
   7265  ins->setVirtualRegister(vreg);
   7266  addUnchecked(lir, ins);
   7267 }
   7268 
   7269 void LIRGenerator::visitWasmRegister64Result(MWasmRegister64Result* ins) {
   7270  MOZ_ASSERT(ins->type() == MIRType::Int64);
   7271  uint32_t vreg = getVirtualRegister();
   7272 
   7273 #if defined(JS_NUNBOX32)
   7274  auto* lir = new (alloc()) LWasmRegisterPairResult();
   7275  lir->setDef(INT64LOW_INDEX,
   7276              LDefinition(vreg + INT64LOW_INDEX, LDefinition::GENERAL,
   7277                          LGeneralReg(ins->loc().low)));
   7278  lir->setDef(INT64HIGH_INDEX,
   7279              LDefinition(vreg + INT64HIGH_INDEX, LDefinition::GENERAL,
   7280                          LGeneralReg(ins->loc().high)));
   7281  getVirtualRegister();
   7282 #elif defined(JS_PUNBOX64)
   7283  auto* lir = new (alloc()) LWasmRegisterResult();
   7284  lir->setDef(
   7285      0, LDefinition(vreg, LDefinition::GENERAL, LGeneralReg(ins->loc().reg)));
   7286 #else
   7287 #  error expected either JS_NUNBOX32 or JS_PUNBOX64
   7288 #endif
   7289 
   7290  ins->setVirtualRegister(vreg);
   7291  addUnchecked(lir, ins);
   7292 }
   7293 
   7294 void LIRGenerator::visitWasmStackResultArea(MWasmStackResultArea* ins) {
   7295  MOZ_ASSERT(ins->type() == MIRType::StackResults);
   7296  auto* lir = new (alloc()) LWasmStackResultArea(temp());
   7297  uint32_t vreg = getVirtualRegister();
   7298  lir->setDef(0,
   7299              LDefinition(vreg, LDefinition::STACKRESULTS, LDefinition::STACK));
   7300  ins->setVirtualRegister(vreg);
   7301  addUnchecked(lir, ins);
   7302 }
   7303 
   7304 void LIRGenerator::visitWasmStackResult(MWasmStackResult* ins) {
   7305  MWasmStackResultArea* area = ins->resultArea()->toWasmStackResultArea();
   7306  LDefinition::Policy pol = LDefinition::STACK;
   7307 
   7308  if (ins->type() == MIRType::Int64) {
   7309    auto* lir = new (alloc()) LWasmStackResult64;
   7310    lir->setOperand(0, use(area, LUse(LUse::STACK, /* usedAtStart = */ true)));
   7311    uint32_t vreg = getVirtualRegister();
   7312    LDefinition::Type typ = LDefinition::GENERAL;
   7313 #if defined(JS_NUNBOX32)
   7314    getVirtualRegister();
   7315    lir->setDef(INT64LOW_INDEX, LDefinition(vreg + INT64LOW_INDEX, typ, pol));
   7316    lir->setDef(INT64HIGH_INDEX, LDefinition(vreg + INT64HIGH_INDEX, typ, pol));
   7317 #else
   7318    lir->setDef(0, LDefinition(vreg, typ, pol));
   7319 #endif
   7320    ins->setVirtualRegister(vreg);
   7321    addUnchecked(lir, ins);
   7322    return;
   7323  }
   7324 
   7325  auto* lir = new (alloc()) LWasmStackResult;
   7326  lir->setOperand(0, use(area, LUse(LUse::STACK, /* usedAtStart = */ true)));
   7327  uint32_t vreg = getVirtualRegister();
   7328  LDefinition::Type typ = LDefinition::TypeFrom(ins->type());
   7329  lir->setDef(0, LDefinition(vreg, typ, pol));
   7330  ins->setVirtualRegister(vreg);
   7331  addUnchecked(lir, ins);
   7332 }
   7333 
   7334 void LIRGenerator::visitWasmStackSwitchToSuspendable(
   7335    MWasmStackSwitchToSuspendable* ins) {
   7336 #ifdef ENABLE_WASM_JSPI
   7337  auto* lir = new (alloc()) LWasmStackSwitchToSuspendable(
   7338      useFixedAtStart(ins->instance(), InstanceReg),
   7339      useFixedAtStart(ins->suspender(), ABINonArgReg0),
   7340      useFixedAtStart(ins->fn(), ABINonArgReg1),
   7341      useFixedAtStart(ins->data(), ABINonArgReg2));
   7342 
   7343  add(lir, ins);
   7344  assignWasmSafepoint(lir);
   7345 #else
   7346  MOZ_CRASH("NYI");
   7347 #endif
   7348 }
   7349 
   7350 void LIRGenerator::visitWasmStackSwitchToMain(MWasmStackSwitchToMain* ins) {
   7351 #ifdef ENABLE_WASM_JSPI
   7352  auto* lir = new (alloc())
   7353      LWasmStackSwitchToMain(useFixedAtStart(ins->instance(), InstanceReg),
   7354                             useFixedAtStart(ins->suspender(), ABINonArgReg0),
   7355                             useFixedAtStart(ins->fn(), ABINonArgReg1),
   7356                             useFixedAtStart(ins->data(), ABINonArgReg2));
   7357 
   7358  defineReturn(lir, ins);
   7359  assignWasmSafepoint(lir);
   7360 #else
   7361  MOZ_CRASH("NYI");
   7362 #endif
   7363 }
   7364 
   7365 void LIRGenerator::visitWasmStackContinueOnSuspendable(
   7366    MWasmStackContinueOnSuspendable* ins) {
   7367 #ifdef ENABLE_WASM_JSPI
   7368  auto* lir = new (alloc()) LWasmStackContinueOnSuspendable(
   7369      useFixedAtStart(ins->instance(), InstanceReg),
   7370      useRegisterAtStart(ins->suspender()), useRegisterAtStart(ins->result()),
   7371      tempFixed(ABINonArgReturnReg0), tempFixed(ReturnReg));
   7372 
   7373  add(lir, ins);
   7374  assignWasmSafepoint(lir);
   7375 #else
   7376  MOZ_CRASH("NYI");
   7377 #endif
   7378 }
   7379 
   7380 template <class MWasmCallT>
   7381 void LIRGenerator::visitWasmCall(MWasmCallT ins) {
   7382  auto* lir = allocateVariadic<LWasmCall>(ins->numOperands());
   7383  if (!lir) {
   7384    abort(AbortReason::Alloc, "OOM: LIRGenerator::lowerWasmCall");
   7385    return;
   7386  }
   7387 
   7388  for (unsigned i = 0; i < ins->numArgs(); i++) {
   7389    lir->setOperand(
   7390        i, useFixedAtStart(ins->getOperand(i), ins->registerForArg(i)));
   7391  }
   7392 
   7393  if (ins->callee().isTable()) {
   7394    MDefinition* index = ins->getOperand(ins->numArgs());
   7395    lir->setOperand(ins->numArgs(),
   7396                    useFixedAtStart(index, WasmTableCallIndexReg));
   7397  }
   7398  if (ins->callee().isFuncRef()) {
   7399    MDefinition* ref = ins->getOperand(ins->numArgs());
   7400    lir->setOperand(ins->numArgs(), useFixedAtStart(ref, WasmCallRefReg));
   7401  }
   7402 
   7403  add(lir, ins);
   7404  assignWasmSafepoint(lir);
   7405 
   7406  // WasmCall with WasmTable has two call instructions, and they both need a
   7407  // safepoint associated with them.  Create a second safepoint here; the node
   7408  // otherwise does nothing, and codegen for it only marks the safepoint at the
   7409  // node.
   7410  if ((ins->callee().which() == wasm::CalleeDesc::WasmTable ||
   7411       ins->callee().which() == wasm::CalleeDesc::FuncRef) &&
   7412      !ins->isWasmReturnCall()) {
   7413    auto* adjunctSafepoint = new (alloc()) LWasmCallIndirectAdjunctSafepoint();
   7414    add(adjunctSafepoint);
   7415    assignWasmSafepoint(adjunctSafepoint);
   7416    lir->setAdjunctSafepoint(adjunctSafepoint);
   7417  }
   7418 }
   7419 
   7420 void LIRGenerator::visitWasmCallCatchable(MWasmCallCatchable* ins) {
   7421  visitWasmCall(ins);
   7422 }
   7423 
   7424 void LIRGenerator::visitWasmCallUncatchable(MWasmCallUncatchable* ins) {
   7425  visitWasmCall(ins);
   7426 }
   7427 
   7428 void LIRGenerator::visitWasmReturnCall(MWasmReturnCall* ins) {
   7429  visitWasmCall(ins);
   7430 }
   7431 
   7432 void LIRGenerator::visitWasmCallLandingPrePad(MWasmCallLandingPrePad* ins) {
   7433  add(new (alloc()) LWasmCallLandingPrePad, ins);
   7434 }
   7435 
   7436 void LIRGenerator::visitSetDOMProperty(MSetDOMProperty* ins) {
   7437  MDefinition* val = ins->value();
   7438 
   7439  Register cxReg, objReg, privReg, valueReg;
   7440  GetTempRegForIntArg(0, 0, &cxReg);
   7441  GetTempRegForIntArg(1, 0, &objReg);
   7442  GetTempRegForIntArg(2, 0, &privReg);
   7443  GetTempRegForIntArg(3, 0, &valueReg);
   7444 
   7445  // Keep using GetTempRegForIntArg, since we want to make sure we
   7446  // don't clobber registers we're already using.
   7447  Register tempReg1, tempReg2;
   7448  GetTempRegForIntArg(4, 0, &tempReg1);
   7449  mozilla::DebugOnly<bool> ok = GetTempRegForIntArg(5, 0, &tempReg2);
   7450  MOZ_ASSERT(ok, "How can we not have six temp registers?");
   7451 
   7452  auto* lir = new (alloc()) LSetDOMProperty(
   7453      useFixedAtStart(ins->object(), objReg),
   7454      useBoxFixedAtStart(val, tempReg1, tempReg2), tempFixed(cxReg),
   7455      tempFixed(privReg), tempFixed(valueReg));
   7456  add(lir, ins);
   7457  assignSafepoint(lir, ins);
   7458 }
   7459 
   7460 void LIRGenerator::visitGetDOMProperty(MGetDOMProperty* ins) {
   7461  Register cxReg, objReg, privReg, valueReg;
   7462  GetTempRegForIntArg(0, 0, &cxReg);
   7463  GetTempRegForIntArg(1, 0, &objReg);
   7464  GetTempRegForIntArg(2, 0, &privReg);
   7465  mozilla::DebugOnly<bool> ok = GetTempRegForIntArg(3, 0, &valueReg);
   7466  MOZ_ASSERT(ok, "How can we not have four temp registers?");
   7467  auto* lir = new (alloc())
   7468      LGetDOMProperty(useFixedAtStart(ins->object(), objReg), tempFixed(cxReg),
   7469                      tempFixed(privReg), tempFixed(valueReg));
   7470 
   7471  defineReturn(lir, ins);
   7472  assignSafepoint(lir, ins);
   7473 }
   7474 
   7475 void LIRGenerator::visitGetDOMMember(MGetDOMMember* ins) {
   7476  MOZ_ASSERT(ins->isDomMovable(), "Members had better be movable");
   7477  // We wish we could assert that ins->domAliasSet() == JSJitInfo::AliasNone,
   7478  // but some MGetDOMMembers are for [Pure], not [Constant] properties, whose
   7479  // value can in fact change as a result of DOM setters and method calls.
   7480  MOZ_ASSERT(ins->domAliasSet() != JSJitInfo::AliasEverything,
   7481             "Member gets had better not alias the world");
   7482 
   7483  MDefinition* obj = ins->object();
   7484  MOZ_ASSERT(obj->type() == MIRType::Object);
   7485 
   7486  MIRType type = ins->type();
   7487 
   7488  if (type == MIRType::Value) {
   7489    LGetDOMMemberV* lir = new (alloc()) LGetDOMMemberV(useRegisterAtStart(obj));
   7490    defineBox(lir, ins);
   7491  } else {
   7492    LGetDOMMemberT* lir =
   7493        new (alloc()) LGetDOMMemberT(useRegisterForTypedLoad(obj, type));
   7494    define(lir, ins);
   7495  }
   7496 }
   7497 
   7498 void LIRGenerator::visitLoadDOMExpandoValue(MLoadDOMExpandoValue* ins) {
   7499  MOZ_ASSERT(ins->proxy()->type() == MIRType::Object);
   7500  auto* lir =
   7501      new (alloc()) LLoadDOMExpandoValue(useRegisterAtStart(ins->proxy()));
   7502  defineBox(lir, ins);
   7503 }
   7504 
   7505 void LIRGenerator::visitLoadDOMExpandoValueGuardGeneration(
   7506    MLoadDOMExpandoValueGuardGeneration* ins) {
   7507  MOZ_ASSERT(ins->proxy()->type() == MIRType::Object);
   7508  auto* lir = new (alloc())
   7509      LLoadDOMExpandoValueGuardGeneration(useRegisterAtStart(ins->proxy()));
   7510  assignSnapshot(lir, ins->bailoutKind());
   7511  defineBox(lir, ins);
   7512 }
   7513 
   7514 void LIRGenerator::visitLoadDOMExpandoValueIgnoreGeneration(
   7515    MLoadDOMExpandoValueIgnoreGeneration* ins) {
   7516  MOZ_ASSERT(ins->proxy()->type() == MIRType::Object);
   7517  auto* lir = new (alloc())
   7518      LLoadDOMExpandoValueIgnoreGeneration(useRegisterAtStart(ins->proxy()));
   7519  defineBox(lir, ins);
   7520 }
   7521 
   7522 void LIRGenerator::visitGuardDOMExpandoMissingOrGuardShape(
   7523    MGuardDOMExpandoMissingOrGuardShape* ins) {
   7524  MOZ_ASSERT(ins->expando()->type() == MIRType::Value);
   7525  auto* lir = new (alloc())
   7526      LGuardDOMExpandoMissingOrGuardShape(useBox(ins->expando()), temp());
   7527  assignSnapshot(lir, ins->bailoutKind());
   7528  add(lir, ins);
   7529  redefine(ins, ins->expando());
   7530 }
   7531 
   7532 void LIRGenerator::visitIncrementWarmUpCounter(MIncrementWarmUpCounter* ins) {
   7533  LIncrementWarmUpCounter* lir = new (alloc()) LIncrementWarmUpCounter(temp());
   7534  add(lir, ins);
   7535 }
   7536 
   7537 void LIRGenerator::visitLexicalCheck(MLexicalCheck* ins) {
   7538  MDefinition* input = ins->input();
   7539  MOZ_ASSERT(input->type() == MIRType::Value);
   7540  LLexicalCheck* lir = new (alloc()) LLexicalCheck(useBox(input));
   7541  assignSnapshot(lir, ins->bailoutKind());
   7542  add(lir, ins);
   7543  redefine(ins, input);
   7544 }
   7545 
   7546 void LIRGenerator::visitThrowRuntimeLexicalError(
   7547    MThrowRuntimeLexicalError* ins) {
   7548  LThrowRuntimeLexicalError* lir = new (alloc()) LThrowRuntimeLexicalError();
   7549  add(lir, ins);
   7550  assignSafepoint(lir, ins);
   7551 }
   7552 
   7553 void LIRGenerator::visitThrowMsg(MThrowMsg* ins) {
   7554  LThrowMsg* lir = new (alloc()) LThrowMsg();
   7555  add(lir, ins);
   7556  assignSafepoint(lir, ins);
   7557 }
   7558 
   7559 void LIRGenerator::visitGlobalDeclInstantiation(MGlobalDeclInstantiation* ins) {
   7560  LGlobalDeclInstantiation* lir = new (alloc()) LGlobalDeclInstantiation();
   7561  add(lir, ins);
   7562  assignSafepoint(lir, ins);
   7563 }
   7564 
   7565 void LIRGenerator::visitDebugger(MDebugger* ins) {
   7566  auto* lir = new (alloc()) LDebugger(tempFixed(CallTempReg0));
   7567  assignSnapshot(lir, ins->bailoutKind());
   7568  add(lir, ins);
   7569 }
   7570 
   7571 void LIRGenerator::visitAtomicIsLockFree(MAtomicIsLockFree* ins) {
   7572  define(new (alloc()) LAtomicIsLockFree(useRegister(ins->input())), ins);
   7573 }
   7574 
   7575 void LIRGenerator::visitAtomicPause(MAtomicPause* ins) {
   7576  add(new (alloc()) LAtomicPause());
   7577 }
   7578 
   7579 void LIRGenerator::visitCheckReturn(MCheckReturn* ins) {
   7580  MDefinition* retVal = ins->returnValue();
   7581  MDefinition* thisVal = ins->thisValue();
   7582  MOZ_ASSERT(retVal->type() == MIRType::Value);
   7583  MOZ_ASSERT(thisVal->type() == MIRType::Value);
   7584 
   7585  auto* lir =
   7586      new (alloc()) LCheckReturn(useBoxAtStart(retVal), useBoxAtStart(thisVal));
   7587  defineBox(lir, ins);
   7588  assignSafepoint(lir, ins);
   7589 }
   7590 
   7591 void LIRGenerator::visitCheckIsObj(MCheckIsObj* ins) {
   7592  MDefinition* input = ins->input();
   7593  MOZ_ASSERT(input->type() == MIRType::Value);
   7594 
   7595  LCheckIsObj* lir = new (alloc()) LCheckIsObj(useBox(input));
   7596  define(lir, ins);
   7597  assignSafepoint(lir, ins);
   7598 }
   7599 
   7600 #ifdef JS_PUNBOX64
   7601 void LIRGenerator::visitCheckScriptedProxyGetResult(
   7602    MCheckScriptedProxyGetResult* ins) {
   7603  MDefinition* target = ins->target();
   7604  MDefinition* id = ins->id();
   7605  MDefinition* value = ins->value();
   7606 
   7607  LCheckScriptedProxyGetResult* lir =
   7608      new (alloc()) LCheckScriptedProxyGetResult(useBox(target), useBox(id),
   7609                                                 useBox(value), temp(), temp());
   7610  add(lir, ins);
   7611  assignSafepoint(lir, ins);
   7612 }
   7613 #endif
   7614 
   7615 void LIRGenerator::visitCheckObjCoercible(MCheckObjCoercible* ins) {
   7616  MDefinition* checkVal = ins->checkValue();
   7617  MOZ_ASSERT(checkVal->type() == MIRType::Value);
   7618 
   7619  auto* lir = new (alloc()) LCheckObjCoercible(useBoxAtStart(checkVal));
   7620  redefine(ins, checkVal);
   7621  add(lir, ins);
   7622  assignSafepoint(lir, ins);
   7623 }
   7624 
   7625 void LIRGenerator::visitCheckClassHeritage(MCheckClassHeritage* ins) {
   7626  MDefinition* heritage = ins->heritage();
   7627  MOZ_ASSERT(heritage->type() == MIRType::Value);
   7628 
   7629  auto* lir =
   7630      new (alloc()) LCheckClassHeritage(useBox(heritage), temp(), temp());
   7631  redefine(ins, heritage);
   7632  add(lir, ins);
   7633  assignSafepoint(lir, ins);
   7634 }
   7635 
   7636 void LIRGenerator::visitCheckThis(MCheckThis* ins) {
   7637  MDefinition* thisValue = ins->thisValue();
   7638  MOZ_ASSERT(thisValue->type() == MIRType::Value);
   7639 
   7640  auto* lir = new (alloc()) LCheckThis(useBoxAtStart(thisValue));
   7641  redefine(ins, thisValue);
   7642  add(lir, ins);
   7643  assignSafepoint(lir, ins);
   7644 }
   7645 
   7646 void LIRGenerator::visitCheckThisReinit(MCheckThisReinit* ins) {
   7647  MDefinition* thisValue = ins->thisValue();
   7648  MOZ_ASSERT(thisValue->type() == MIRType::Value);
   7649 
   7650  auto* lir = new (alloc()) LCheckThisReinit(useBoxAtStart(thisValue));
   7651  redefine(ins, thisValue);
   7652  add(lir, ins);
   7653  assignSafepoint(lir, ins);
   7654 }
   7655 
   7656 void LIRGenerator::visitGenerator(MGenerator* ins) {
   7657  auto* lir =
   7658      new (alloc()) LGenerator(useRegisterAtStart(ins->callee()),
   7659                               useRegisterAtStart(ins->environmentChain()),
   7660                               useRegisterAtStart(ins->argsObject()));
   7661  defineReturn(lir, ins);
   7662  assignSafepoint(lir, ins);
   7663 }
   7664 
   7665 void LIRGenerator::visitAsyncResolve(MAsyncResolve* ins) {
   7666  auto* lir = new (alloc()) LAsyncResolve(useRegisterAtStart(ins->generator()),
   7667                                          useBoxAtStart(ins->value()));
   7668  defineReturn(lir, ins);
   7669  assignSafepoint(lir, ins);
   7670 }
   7671 
   7672 void LIRGenerator::visitAsyncReject(MAsyncReject* ins) {
   7673  auto* lir = new (alloc())
   7674      LAsyncReject(useRegisterAtStart(ins->generator()),
   7675                   useBoxAtStart(ins->reason()), useBoxAtStart(ins->stack()));
   7676  defineReturn(lir, ins);
   7677  assignSafepoint(lir, ins);
   7678 }
   7679 
   7680 void LIRGenerator::visitAsyncAwait(MAsyncAwait* ins) {
   7681  MOZ_ASSERT(ins->generator()->type() == MIRType::Object);
   7682  auto* lir = new (alloc()) LAsyncAwait(useBoxAtStart(ins->value()),
   7683                                        useRegisterAtStart(ins->generator()));
   7684  defineReturn(lir, ins);
   7685  assignSafepoint(lir, ins);
   7686 }
   7687 
   7688 void LIRGenerator::visitCanSkipAwait(MCanSkipAwait* ins) {
   7689  auto* lir = new (alloc()) LCanSkipAwait(useBoxAtStart(ins->value()));
   7690  defineReturn(lir, ins);
   7691  assignSafepoint(lir, ins);
   7692 }
   7693 
   7694 void LIRGenerator::visitMaybeExtractAwaitValue(MMaybeExtractAwaitValue* ins) {
   7695  auto* lir = new (alloc()) LMaybeExtractAwaitValue(
   7696      useBoxAtStart(ins->value()), useRegisterAtStart(ins->canSkip()));
   7697  defineReturn(lir, ins);
   7698  assignSafepoint(lir, ins);
   7699 }
   7700 
   7701 void LIRGenerator::visitDebugCheckSelfHosted(MDebugCheckSelfHosted* ins) {
   7702  MDefinition* checkVal = ins->checkValue();
   7703  MOZ_ASSERT(checkVal->type() == MIRType::Value);
   7704 
   7705  LDebugCheckSelfHosted* lir =
   7706      new (alloc()) LDebugCheckSelfHosted(useBoxAtStart(checkVal));
   7707  redefine(ins, checkVal);
   7708  add(lir, ins);
   7709  assignSafepoint(lir, ins);
   7710 }
   7711 
   7712 void LIRGenerator::visitIsPackedArray(MIsPackedArray* ins) {
   7713  MOZ_ASSERT(ins->object()->type() == MIRType::Object);
   7714  MOZ_ASSERT(ins->type() == MIRType::Boolean);
   7715 
   7716  auto lir = new (alloc()) LIsPackedArray(useRegister(ins->object()), temp());
   7717  define(lir, ins);
   7718 }
   7719 
   7720 void LIRGenerator::visitGuardArrayIsPacked(MGuardArrayIsPacked* ins) {
   7721  MOZ_ASSERT(ins->array()->type() == MIRType::Object);
   7722 
   7723  auto* lir = new (alloc())
   7724      LGuardArrayIsPacked(useRegister(ins->array()), temp(), temp());
   7725  assignSnapshot(lir, ins->bailoutKind());
   7726  add(lir, ins);
   7727  redefine(ins, ins->array());
   7728 }
   7729 
   7730 void LIRGenerator::visitGuardElementsArePacked(MGuardElementsArePacked* ins) {
   7731  MOZ_ASSERT(ins->elements()->type() == MIRType::Elements);
   7732 
   7733  auto* lir =
   7734      new (alloc()) LGuardElementsArePacked(useRegister(ins->elements()));
   7735  assignSnapshot(lir, ins->bailoutKind());
   7736  add(lir, ins);
   7737 }
   7738 
   7739 void LIRGenerator::visitGetPrototypeOf(MGetPrototypeOf* ins) {
   7740  MOZ_ASSERT(ins->target()->type() == MIRType::Object);
   7741  MOZ_ASSERT(ins->type() == MIRType::Value);
   7742 
   7743  auto lir = new (alloc()) LGetPrototypeOf(useRegister(ins->target()));
   7744  defineBox(lir, ins);
   7745  assignSafepoint(lir, ins);
   7746 }
   7747 
   7748 void LIRGenerator::visitObjectWithProto(MObjectWithProto* ins) {
   7749  MOZ_ASSERT(ins->prototype()->type() == MIRType::Value);
   7750  MOZ_ASSERT(ins->type() == MIRType::Object);
   7751 
   7752  auto* lir = new (alloc()) LObjectWithProto(useBoxAtStart(ins->prototype()));
   7753  defineReturn(lir, ins);
   7754  assignSafepoint(lir, ins);
   7755 }
   7756 
   7757 void LIRGenerator::visitObjectStaticProto(MObjectStaticProto* ins) {
   7758  MOZ_ASSERT(ins->object()->type() == MIRType::Object);
   7759  MOZ_ASSERT(ins->type() == MIRType::Object);
   7760 
   7761  auto* lir =
   7762      new (alloc()) LObjectStaticProto(useRegisterAtStart(ins->object()));
   7763  define(lir, ins);
   7764 };
   7765 
   7766 void LIRGenerator::visitBuiltinObject(MBuiltinObject* ins) {
   7767  MOZ_ASSERT(ins->type() == MIRType::Object);
   7768 
   7769  auto* lir = new (alloc()) LBuiltinObject();
   7770  defineReturn(lir, ins);
   7771  assignSafepoint(lir, ins);
   7772 }
   7773 
   7774 void LIRGenerator::visitReturn(MReturn* ret) {
   7775  return visitReturnImpl(ret->getOperand(0));
   7776 }
   7777 
   7778 void LIRGenerator::visitGeneratorReturn(MGeneratorReturn* ret) {
   7779  return visitReturnImpl(ret->getOperand(0), true);
   7780 }
   7781 
   7782 void LIRGenerator::visitSuperFunction(MSuperFunction* ins) {
   7783  MOZ_ASSERT(ins->callee()->type() == MIRType::Object);
   7784  MOZ_ASSERT(ins->type() == MIRType::Value);
   7785 
   7786  auto* lir = new (alloc()) LSuperFunction(useRegister(ins->callee()));
   7787  defineBox(lir, ins);
   7788 }
   7789 
   7790 void LIRGenerator::visitSuperFunctionAndUnbox(MSuperFunctionAndUnbox* ins) {
   7791  MOZ_ASSERT(ins->callee()->type() == MIRType::Object);
   7792  MOZ_ASSERT(ins->type() == MIRType::Object);
   7793 
   7794  auto* lir = new (alloc()) LSuperFunctionAndUnbox(useRegister(ins->callee()));
   7795  assignSnapshot(lir, ins->bailoutKind());
   7796  define(lir, ins);
   7797 }
   7798 
   7799 void LIRGenerator::visitInitHomeObject(MInitHomeObject* ins) {
   7800  MDefinition* function = ins->function();
   7801  MOZ_ASSERT(function->type() == MIRType::Object);
   7802 
   7803  MDefinition* homeObject = ins->homeObject();
   7804  MOZ_ASSERT(homeObject->type() == MIRType::Value);
   7805 
   7806  MOZ_ASSERT(ins->type() == MIRType::Object);
   7807 
   7808  auto* lir = new (alloc())
   7809      LInitHomeObject(useRegisterAtStart(function), useBoxAtStart(homeObject));
   7810  redefine(ins, function);
   7811  add(lir, ins);
   7812 }
   7813 
   7814 void LIRGenerator::visitIsTypedArrayConstructor(MIsTypedArrayConstructor* ins) {
   7815  MDefinition* object = ins->object();
   7816  MOZ_ASSERT(object->type() == MIRType::Object);
   7817 
   7818  auto* lir = new (alloc()) LIsTypedArrayConstructor(useRegister(object));
   7819  define(lir, ins);
   7820 }
   7821 
   7822 void LIRGenerator::visitLoadValueTag(MLoadValueTag* ins) {
   7823  MDefinition* value = ins->value();
   7824  MOZ_ASSERT(value->type() == MIRType::Value);
   7825 
   7826  define(new (alloc()) LLoadValueTag(useBoxAtStart(value)), ins);
   7827 }
   7828 
   7829 void LIRGenerator::visitGuardTagNotEqual(MGuardTagNotEqual* ins) {
   7830  MDefinition* lhs = ins->lhs();
   7831  MOZ_ASSERT(lhs->type() == MIRType::Int32);
   7832 
   7833  MDefinition* rhs = ins->rhs();
   7834  MOZ_ASSERT(rhs->type() == MIRType::Int32);
   7835 
   7836  auto* guard =
   7837      new (alloc()) LGuardTagNotEqual(useRegister(lhs), useRegister(rhs));
   7838  assignSnapshot(guard, ins->bailoutKind());
   7839  add(guard, ins);
   7840 }
   7841 
   7842 void LIRGenerator::visitLoadWrapperTarget(MLoadWrapperTarget* ins) {
   7843  MDefinition* object = ins->object();
   7844  MOZ_ASSERT(object->type() == MIRType::Object);
   7845 
   7846  auto* lir = new (alloc()) LLoadWrapperTarget(useRegisterAtStart(object));
   7847  if (ins->fallible()) {
   7848    assignSnapshot(lir, ins->bailoutKind());
   7849  }
   7850  define(lir, ins);
   7851 }
   7852 
   7853 void LIRGenerator::visitLoadGetterSetterFunction(
   7854    MLoadGetterSetterFunction* ins) {
   7855  MDefinition* getterSetter = ins->getterSetter();
   7856 
   7857  LDefinition classGuardTemp =
   7858      ins->needsClassGuard() ? temp() : LDefinition::BogusTemp();
   7859  auto* lir = new (alloc())
   7860      LLoadGetterSetterFunction(useBoxAtStart(getterSetter), classGuardTemp);
   7861  assignSnapshot(lir, ins->bailoutKind());
   7862  define(lir, ins);
   7863 }
   7864 
   7865 void LIRGenerator::visitGuardHasGetterSetter(MGuardHasGetterSetter* ins) {
   7866  MDefinition* object = ins->object();
   7867  MOZ_ASSERT(object->type() == MIRType::Object);
   7868 
   7869  auto* guard = new (alloc())
   7870      LGuardHasGetterSetter(useRegisterAtStart(object), tempFixed(CallTempReg0),
   7871                            tempFixed(CallTempReg1), tempFixed(CallTempReg2));
   7872  assignSnapshot(guard, ins->bailoutKind());
   7873  add(guard, ins);
   7874  redefine(ins, object);
   7875 }
   7876 
   7877 void LIRGenerator::visitGuardIsExtensible(MGuardIsExtensible* ins) {
   7878  MDefinition* object = ins->object();
   7879  MOZ_ASSERT(object->type() == MIRType::Object);
   7880 
   7881  auto* guard = new (alloc()) LGuardIsExtensible(useRegister(object), temp());
   7882  assignSnapshot(guard, ins->bailoutKind());
   7883  add(guard, ins);
   7884  redefine(ins, object);
   7885 }
   7886 
   7887 void LIRGenerator::visitGuardInt32IsNonNegative(MGuardInt32IsNonNegative* ins) {
   7888  MDefinition* index = ins->index();
   7889  MOZ_ASSERT(index->type() == MIRType::Int32);
   7890 
   7891  auto* guard = new (alloc()) LGuardInt32IsNonNegative(useRegister(index));
   7892  assignSnapshot(guard, ins->bailoutKind());
   7893  add(guard, ins);
   7894  redefine(ins, index);
   7895 }
   7896 
   7897 void LIRGenerator::visitGuardIntPtrIsNonNegative(
   7898    MGuardIntPtrIsNonNegative* ins) {
   7899  MDefinition* index = ins->index();
   7900  MOZ_ASSERT(index->type() == MIRType::IntPtr);
   7901 
   7902  auto* guard = new (alloc()) LGuardIntPtrIsNonNegative(useRegister(index));
   7903  assignSnapshot(guard, ins->bailoutKind());
   7904  add(guard, ins);
   7905  redefine(ins, index);
   7906 }
   7907 
   7908 void LIRGenerator::visitGuardInt32Range(MGuardInt32Range* ins) {
   7909  MDefinition* input = ins->input();
   7910  MOZ_ASSERT(input->type() == MIRType::Int32);
   7911 
   7912  auto* guard = new (alloc()) LGuardInt32Range(useRegister(input));
   7913  assignSnapshot(guard, ins->bailoutKind());
   7914  add(guard, ins);
   7915  redefine(ins, input);
   7916 }
   7917 
   7918 void LIRGenerator::visitGuardIndexIsNotDenseElement(
   7919    MGuardIndexIsNotDenseElement* ins) {
   7920  MDefinition* object = ins->object();
   7921  MOZ_ASSERT(object->type() == MIRType::Object);
   7922 
   7923  MDefinition* index = ins->index();
   7924  MOZ_ASSERT(index->type() == MIRType::Int32);
   7925 
   7926  LDefinition spectreTemp =
   7927      BoundsCheckNeedsSpectreTemp() ? temp() : LDefinition::BogusTemp();
   7928 
   7929  auto* guard = new (alloc()) LGuardIndexIsNotDenseElement(
   7930      useRegister(object), useRegister(index), temp(), spectreTemp);
   7931  assignSnapshot(guard, ins->bailoutKind());
   7932  add(guard, ins);
   7933  redefine(ins, index);
   7934 }
   7935 
   7936 void LIRGenerator::visitGuardIndexIsValidUpdateOrAdd(
   7937    MGuardIndexIsValidUpdateOrAdd* ins) {
   7938  MDefinition* object = ins->object();
   7939  MOZ_ASSERT(object->type() == MIRType::Object);
   7940 
   7941  MDefinition* index = ins->index();
   7942  MOZ_ASSERT(index->type() == MIRType::Int32);
   7943 
   7944  LDefinition spectreTemp =
   7945      BoundsCheckNeedsSpectreTemp() ? temp() : LDefinition::BogusTemp();
   7946 
   7947  auto* guard = new (alloc()) LGuardIndexIsValidUpdateOrAdd(
   7948      useRegister(object), useRegister(index), temp(), spectreTemp);
   7949  assignSnapshot(guard, ins->bailoutKind());
   7950  add(guard, ins);
   7951  redefine(ins, index);
   7952 }
   7953 
   7954 void LIRGenerator::visitCallAddOrUpdateSparseElement(
   7955    MCallAddOrUpdateSparseElement* ins) {
   7956  MDefinition* object = ins->object();
   7957  MOZ_ASSERT(object->type() == MIRType::Object);
   7958 
   7959  MDefinition* index = ins->index();
   7960  MOZ_ASSERT(index->type() == MIRType::Int32);
   7961 
   7962  MDefinition* value = ins->value();
   7963  MOZ_ASSERT(value->type() == MIRType::Value);
   7964 
   7965  auto* lir = new (alloc()) LCallAddOrUpdateSparseElement(
   7966      useRegisterAtStart(object), useRegisterAtStart(index),
   7967      useBoxAtStart(value));
   7968  add(lir, ins);
   7969  assignSafepoint(lir, ins);
   7970 }
   7971 
   7972 void LIRGenerator::visitCallGetSparseElement(MCallGetSparseElement* ins) {
   7973  MDefinition* object = ins->object();
   7974  MOZ_ASSERT(object->type() == MIRType::Object);
   7975 
   7976  MDefinition* index = ins->index();
   7977  MOZ_ASSERT(index->type() == MIRType::Int32);
   7978 
   7979  auto* lir = new (alloc()) LCallGetSparseElement(useRegisterAtStart(object),
   7980                                                  useRegisterAtStart(index));
   7981  defineReturn(lir, ins);
   7982  assignSafepoint(lir, ins);
   7983 }
   7984 
   7985 void LIRGenerator::visitCallNativeGetElement(MCallNativeGetElement* ins) {
   7986  MDefinition* object = ins->object();
   7987  MOZ_ASSERT(object->type() == MIRType::Object);
   7988 
   7989  MDefinition* index = ins->index();
   7990  MOZ_ASSERT(index->type() == MIRType::Int32);
   7991 
   7992  auto* lir = new (alloc()) LCallNativeGetElement(useRegisterAtStart(object),
   7993                                                  useRegisterAtStart(index));
   7994  defineReturn(lir, ins);
   7995  assignSafepoint(lir, ins);
   7996 }
   7997 
   7998 void LIRGenerator::visitCallNativeGetElementSuper(
   7999    MCallNativeGetElementSuper* ins) {
   8000  MDefinition* object = ins->object();
   8001  MOZ_ASSERT(object->type() == MIRType::Object);
   8002 
   8003  MDefinition* index = ins->index();
   8004  MOZ_ASSERT(index->type() == MIRType::Int32);
   8005 
   8006  MDefinition* receiver = ins->receiver();
   8007 
   8008  auto* lir = new (alloc()) LCallNativeGetElementSuper(
   8009      useRegisterAtStart(object), useRegisterAtStart(index),
   8010      useBoxAtStart(receiver));
   8011  defineReturn(lir, ins);
   8012  assignSafepoint(lir, ins);
   8013 }
   8014 
   8015 void LIRGenerator::visitCallObjectHasSparseElement(
   8016    MCallObjectHasSparseElement* ins) {
   8017  MDefinition* object = ins->object();
   8018  MOZ_ASSERT(object->type() == MIRType::Object);
   8019 
   8020  MDefinition* index = ins->index();
   8021  MOZ_ASSERT(index->type() == MIRType::Int32);
   8022 
   8023  auto* lir = new (alloc()) LCallObjectHasSparseElement(
   8024      useRegisterAtStart(object), useRegisterAtStart(index),
   8025      tempFixed(CallTempReg0), tempFixed(CallTempReg1));
   8026  assignSnapshot(lir, ins->bailoutKind());
   8027  defineReturn(lir, ins);
   8028 }
   8029 
   8030 void LIRGenerator::visitBigIntAsIntN(MBigIntAsIntN* ins) {
   8031  MOZ_ASSERT(ins->bits()->type() == MIRType::Int32);
   8032  MOZ_ASSERT(ins->input()->type() == MIRType::BigInt);
   8033 
   8034  auto* lir = new (alloc()) LBigIntAsIntN(useRegisterAtStart(ins->bits()),
   8035                                          useRegisterAtStart(ins->input()));
   8036  defineReturn(lir, ins);
   8037  assignSafepoint(lir, ins);
   8038 }
   8039 
   8040 void LIRGenerator::visitBigIntAsUintN(MBigIntAsUintN* ins) {
   8041  MOZ_ASSERT(ins->bits()->type() == MIRType::Int32);
   8042  MOZ_ASSERT(ins->input()->type() == MIRType::BigInt);
   8043 
   8044  auto* lir = new (alloc()) LBigIntAsUintN(useRegisterAtStart(ins->bits()),
   8045                                           useRegisterAtStart(ins->input()));
   8046  defineReturn(lir, ins);
   8047  assignSafepoint(lir, ins);
   8048 }
   8049 
   8050 void LIRGenerator::visitGuardNonGCThing(MGuardNonGCThing* ins) {
   8051  MDefinition* input = ins->input();
   8052 
   8053  auto* guard = new (alloc()) LGuardNonGCThing(useBox(input));
   8054  assignSnapshot(guard, ins->bailoutKind());
   8055  add(guard, ins);
   8056  redefine(ins, input);
   8057 }
   8058 
   8059 void LIRGenerator::visitToHashableNonGCThing(MToHashableNonGCThing* ins) {
   8060  auto* lir =
   8061      new (alloc()) LToHashableNonGCThing(useBox(ins->input()), tempDouble());
   8062  defineBox(lir, ins);
   8063 }
   8064 
   8065 void LIRGenerator::visitToHashableString(MToHashableString* ins) {
   8066  auto* lir = new (alloc()) LToHashableString(useRegister(ins->input()));
   8067  define(lir, ins);
   8068  assignSafepoint(lir, ins);
   8069 }
   8070 
   8071 void LIRGenerator::visitToHashableValue(MToHashableValue* ins) {
   8072  auto* lir =
   8073      new (alloc()) LToHashableValue(useBox(ins->input()), tempDouble());
   8074  defineBox(lir, ins);
   8075  assignSafepoint(lir, ins);
   8076 }
   8077 
   8078 void LIRGenerator::visitHashNonGCThing(MHashNonGCThing* ins) {
   8079  auto* lir = new (alloc()) LHashNonGCThing(useBox(ins->input()), temp());
   8080  define(lir, ins);
   8081 }
   8082 
   8083 void LIRGenerator::visitHashString(MHashString* ins) {
   8084  auto* lir = new (alloc()) LHashString(useRegister(ins->input()), temp());
   8085  define(lir, ins);
   8086 }
   8087 
   8088 void LIRGenerator::visitHashSymbol(MHashSymbol* ins) {
   8089  auto* lir = new (alloc()) LHashSymbol(useRegister(ins->input()));
   8090  define(lir, ins);
   8091 }
   8092 
   8093 void LIRGenerator::visitHashBigInt(MHashBigInt* ins) {
   8094  auto* lir = new (alloc())
   8095      LHashBigInt(useRegister(ins->input()), temp(), temp(), temp());
   8096  define(lir, ins);
   8097 }
   8098 
   8099 void LIRGenerator::visitHashObject(MHashObject* ins) {
   8100  auto* lir = new (alloc())
   8101      LHashObject(useRegister(ins->setObject()), useBox(ins->input()), temp(),
   8102                  temp(), temp(), temp());
   8103  define(lir, ins);
   8104 }
   8105 
   8106 void LIRGenerator::visitHashValue(MHashValue* ins) {
   8107  auto* lir = new (alloc())
   8108      LHashValue(useRegister(ins->setObject()), useBox(ins->input()), temp(),
   8109                 temp(), temp(), temp());
   8110  define(lir, ins);
   8111 }
   8112 
   8113 void LIRGenerator::visitSetObjectHasNonBigInt(MSetObjectHasNonBigInt* ins) {
   8114  auto* lir = new (alloc()) LSetObjectHasNonBigInt(
   8115      useRegister(ins->setObject()), useBox(ins->value()),
   8116      useRegister(ins->hash()), temp(), temp());
   8117  define(lir, ins);
   8118 }
   8119 
   8120 void LIRGenerator::visitSetObjectHasBigInt(MSetObjectHasBigInt* ins) {
   8121  auto* lir = new (alloc()) LSetObjectHasBigInt(
   8122      useRegister(ins->setObject()), useBox(ins->value()),
   8123      useRegister(ins->hash()), temp(), temp(), temp(), temp());
   8124  define(lir, ins);
   8125 }
   8126 
   8127 void LIRGenerator::visitSetObjectHasValue(MSetObjectHasValue* ins) {
   8128  auto* lir = new (alloc()) LSetObjectHasValue(
   8129      useRegister(ins->setObject()), useBox(ins->value()),
   8130      useRegister(ins->hash()), temp(), temp(), temp(), temp());
   8131  define(lir, ins);
   8132 }
   8133 
   8134 void LIRGenerator::visitSetObjectHasValueVMCall(MSetObjectHasValueVMCall* ins) {
   8135  auto* lir = new (alloc()) LSetObjectHasValueVMCall(
   8136      useRegisterAtStart(ins->setObject()), useBoxAtStart(ins->value()));
   8137  defineReturn(lir, ins);
   8138  assignSafepoint(lir, ins);
   8139 }
   8140 
   8141 void LIRGenerator::visitSetObjectDelete(MSetObjectDelete* ins) {
   8142  auto* lir = new (alloc()) LSetObjectDelete(
   8143      useRegisterAtStart(ins->setObject()), useBoxAtStart(ins->key()));
   8144  defineReturn(lir, ins);
   8145  assignSafepoint(lir, ins);
   8146 }
   8147 
   8148 void LIRGenerator::visitSetObjectAdd(MSetObjectAdd* ins) {
   8149  auto* lir = new (alloc()) LSetObjectAdd(useRegisterAtStart(ins->setObject()),
   8150                                          useBoxAtStart(ins->key()));
   8151  add(lir, ins);
   8152  assignSafepoint(lir, ins);
   8153 }
   8154 
   8155 void LIRGenerator::visitSetObjectSize(MSetObjectSize* ins) {
   8156  auto* lir =
   8157      new (alloc()) LSetObjectSize(useRegisterAtStart(ins->setObject()));
   8158  define(lir, ins);
   8159 }
   8160 
   8161 void LIRGenerator::visitMapObjectHasNonBigInt(MMapObjectHasNonBigInt* ins) {
   8162  auto* lir = new (alloc()) LMapObjectHasNonBigInt(
   8163      useRegister(ins->mapObject()), useBox(ins->value()),
   8164      useRegister(ins->hash()), temp(), temp());
   8165  define(lir, ins);
   8166 }
   8167 
   8168 void LIRGenerator::visitMapObjectHasBigInt(MMapObjectHasBigInt* ins) {
   8169  auto* lir = new (alloc()) LMapObjectHasBigInt(
   8170      useRegister(ins->mapObject()), useBox(ins->value()),
   8171      useRegister(ins->hash()), temp(), temp(), temp(), temp());
   8172  define(lir, ins);
   8173 }
   8174 
   8175 void LIRGenerator::visitMapObjectHasValue(MMapObjectHasValue* ins) {
   8176  auto* lir = new (alloc()) LMapObjectHasValue(
   8177      useRegister(ins->mapObject()), useBox(ins->value()),
   8178      useRegister(ins->hash()), temp(), temp(), temp(), temp());
   8179  define(lir, ins);
   8180 }
   8181 
   8182 void LIRGenerator::visitMapObjectHasValueVMCall(MMapObjectHasValueVMCall* ins) {
   8183  auto* lir = new (alloc()) LMapObjectHasValueVMCall(
   8184      useRegisterAtStart(ins->mapObject()), useBoxAtStart(ins->value()));
   8185  defineReturn(lir, ins);
   8186  assignSafepoint(lir, ins);
   8187 }
   8188 
   8189 void LIRGenerator::visitMapObjectGetNonBigInt(MMapObjectGetNonBigInt* ins) {
   8190  auto* lir = new (alloc()) LMapObjectGetNonBigInt(
   8191      useRegister(ins->mapObject()), useBox(ins->value()),
   8192      useRegister(ins->hash()), temp(), temp());
   8193  defineBox(lir, ins);
   8194 }
   8195 
   8196 void LIRGenerator::visitMapObjectGetBigInt(MMapObjectGetBigInt* ins) {
   8197  auto* lir = new (alloc()) LMapObjectGetBigInt(
   8198      useRegister(ins->mapObject()), useBox(ins->value()),
   8199      useRegister(ins->hash()), temp(), temp(), temp(), temp());
   8200  defineBox(lir, ins);
   8201 }
   8202 
   8203 void LIRGenerator::visitMapObjectGetValue(MMapObjectGetValue* ins) {
   8204  auto* lir = new (alloc()) LMapObjectGetValue(
   8205      useRegister(ins->mapObject()), useBox(ins->value()),
   8206      useRegister(ins->hash()), temp(), temp(), temp(), temp());
   8207  defineBox(lir, ins);
   8208 }
   8209 
   8210 void LIRGenerator::visitMapObjectGetValueVMCall(MMapObjectGetValueVMCall* ins) {
   8211  auto* lir = new (alloc()) LMapObjectGetValueVMCall(
   8212      useRegisterAtStart(ins->mapObject()), useBoxAtStart(ins->value()));
   8213  defineReturn(lir, ins);
   8214  assignSafepoint(lir, ins);
   8215 }
   8216 
   8217 void LIRGenerator::visitMapObjectDelete(MMapObjectDelete* ins) {
   8218  auto* lir = new (alloc()) LMapObjectDelete(
   8219      useRegisterAtStart(ins->mapObject()), useBoxAtStart(ins->key()));
   8220  defineReturn(lir, ins);
   8221  assignSafepoint(lir, ins);
   8222 }
   8223 
   8224 void LIRGenerator::visitMapObjectSet(MMapObjectSet* ins) {
   8225  auto* lir = new (alloc())
   8226      LMapObjectSet(useRegisterAtStart(ins->mapObject()),
   8227                    useBoxAtStart(ins->key()), useBoxAtStart(ins->value()));
   8228  add(lir, ins);
   8229  assignSafepoint(lir, ins);
   8230 }
   8231 
   8232 void LIRGenerator::visitMapObjectSize(MMapObjectSize* ins) {
   8233  auto* lir =
   8234      new (alloc()) LMapObjectSize(useRegisterAtStart(ins->mapObject()));
   8235  define(lir, ins);
   8236 }
   8237 
   8238 void LIRGenerator::visitWeakMapGetObject(MWeakMapGetObject* ins) {
   8239 #ifdef JS_CODEGEN_X86
   8240  auto* lir = new (alloc()) LWeakMapGetObject(
   8241      useFixedAtStart(ins->weakMap(), CallTempReg0),
   8242      useFixedAtStart(ins->object(), CallTempReg1), tempFixed(CallTempReg2));
   8243  defineReturn(lir, ins);
   8244 #else
   8245  auto* lir = new (alloc()) LWeakMapGetObject(
   8246      useRegisterAtStart(ins->weakMap()), useRegisterAtStart(ins->object()),
   8247      temp(), temp(), temp(), temp(), temp(), temp(), temp());
   8248  defineBox(lir, ins);
   8249 #endif
   8250 }
   8251 
   8252 void LIRGenerator::visitWeakMapHasObject(MWeakMapHasObject* ins) {
   8253 #ifdef JS_CODEGEN_X86
   8254  auto* lir = new (alloc()) LWeakMapHasObject(
   8255      useRegisterAtStart(ins->weakMap()), useRegisterAtStart(ins->object()));
   8256  defineReturn(lir, ins);
   8257 #else
   8258  auto* lir = new (alloc()) LWeakMapHasObject(
   8259      useRegisterAtStart(ins->weakMap()), useRegisterAtStart(ins->object()),
   8260      temp(), temp(), temp(), temp(), temp(), temp(), temp());
   8261  define(lir, ins);
   8262 #endif
   8263 }
   8264 
   8265 void LIRGenerator::visitWeakSetHasObject(MWeakSetHasObject* ins) {
   8266  auto* lir = new (alloc()) LWeakSetHasObject(
   8267      useRegisterAtStart(ins->weakSet()), useRegisterAtStart(ins->object()));
   8268  defineReturn(lir, ins);
   8269 }
   8270 
   8271 void LIRGenerator::visitDateFillLocalTimeSlots(MDateFillLocalTimeSlots* ins) {
   8272  auto* lir =
   8273      new (alloc()) LDateFillLocalTimeSlots(useRegister(ins->date()), temp());
   8274  add(lir, ins);
   8275  assignSafepoint(lir, ins);
   8276 }
   8277 
   8278 void LIRGenerator::visitDateHoursFromSecondsIntoYear(
   8279    MDateHoursFromSecondsIntoYear* ins) {
   8280  auto* lir = new (alloc()) LDateHoursFromSecondsIntoYear(
   8281      useBox(ins->secondsIntoYear()), temp(), temp());
   8282  defineBox(lir, ins);
   8283 }
   8284 
   8285 void LIRGenerator::visitDateMinutesFromSecondsIntoYear(
   8286    MDateMinutesFromSecondsIntoYear* ins) {
   8287  auto* lir = new (alloc()) LDateMinutesFromSecondsIntoYear(
   8288      useBox(ins->secondsIntoYear()), temp(), temp());
   8289  defineBox(lir, ins);
   8290 }
   8291 
   8292 void LIRGenerator::visitDateSecondsFromSecondsIntoYear(
   8293    MDateSecondsFromSecondsIntoYear* ins) {
   8294  auto* lir = new (alloc()) LDateSecondsFromSecondsIntoYear(
   8295      useBox(ins->secondsIntoYear()), temp(), temp());
   8296  defineBox(lir, ins);
   8297 }
   8298 
   8299 void LIRGenerator::visitPostIntPtrConversion(MPostIntPtrConversion* ins) {
   8300  // This operation is a no-op.
   8301  redefine(ins, ins->input());
   8302 }
   8303 
   8304 void LIRGenerator::visitCanonicalizeNaN(MCanonicalizeNaN* ins) {
   8305  MOZ_ASSERT(ins->type() == ins->input()->type());
   8306 
   8307  auto input = useRegisterAtStart(ins->input());
   8308  switch (ins->type()) {
   8309    case MIRType::Double:
   8310      defineReuseInput(new (alloc()) LCanonicalizeNaND(input), ins, 0);
   8311      return;
   8312    case MIRType::Float32:
   8313      defineReuseInput(new (alloc()) LCanonicalizeNaNF(input), ins, 0);
   8314      return;
   8315    default:
   8316      MOZ_CRASH("unexpected floating point type");
   8317  }
   8318 }
   8319 
   8320 void LIRGenerator::visitConstant(MConstant* ins) {
   8321  if (!IsFloatingPointType(ins->type()) && ins->canEmitAtUses()) {
   8322    emitAtUses(ins);
   8323    return;
   8324  }
   8325 
   8326  switch (ins->type()) {
   8327    case MIRType::Double:
   8328      define(new (alloc()) LDouble(ins->toDouble()), ins);
   8329      break;
   8330    case MIRType::Float32:
   8331      define(new (alloc()) LFloat32(ins->toFloat32()), ins);
   8332      break;
   8333    case MIRType::Boolean:
   8334      define(new (alloc()) LInteger(ins->toBoolean()), ins);
   8335      break;
   8336    case MIRType::Int32:
   8337      define(new (alloc()) LInteger(ins->toInt32()), ins);
   8338      break;
   8339    case MIRType::Int64:
   8340      defineInt64(new (alloc()) LInteger64(ins->toInt64()), ins);
   8341      break;
   8342    case MIRType::IntPtr:
   8343 #ifdef JS_64BIT
   8344      defineInt64(new (alloc()) LInteger64(ins->toIntPtr()), ins);
   8345 #else
   8346      define(new (alloc()) LInteger(ins->toIntPtr()), ins);
   8347 #endif
   8348      break;
   8349    case MIRType::String:
   8350      define(new (alloc()) LPointer(ins->toString()->raw()), ins);
   8351      break;
   8352    case MIRType::Symbol:
   8353      define(new (alloc()) LPointer(ins->toSymbol()), ins);
   8354      break;
   8355    case MIRType::BigInt:
   8356      define(new (alloc()) LPointer(ins->toBigInt()), ins);
   8357      break;
   8358    case MIRType::Object:
   8359      define(new (alloc()) LPointer(&ins->toObject()), ins);
   8360      break;
   8361    case MIRType::Shape:
   8362      MOZ_ASSERT(ins->isEmittedAtUses());
   8363      break;
   8364    default:
   8365      // Constants of special types (undefined, null) should never flow into
   8366      // here directly. Operations blindly consuming them require a Box.
   8367      MOZ_CRASH("unexpected constant type");
   8368  }
   8369 }
   8370 
   8371 void LIRGenerator::visitConstantProto(MConstantProto* ins) {
   8372  JSObject* obj = &ins->protoObject()->toConstant()->toObject();
   8373  define(new (alloc()) LPointer(obj), ins);
   8374 }
   8375 
   8376 void LIRGenerator::visitWasmNullConstant(MWasmNullConstant* ins) {
   8377  define(new (alloc()) LWasmNullConstant(), ins);
   8378 }
   8379 
   8380 void LIRGenerator::visitWasmFloatConstant(MWasmFloatConstant* ins) {
   8381  switch (ins->type()) {
   8382    case MIRType::Double:
   8383      define(new (alloc()) LDouble(ins->toDouble()), ins);
   8384      break;
   8385    case MIRType::Float32:
   8386      define(new (alloc()) LFloat32(ins->toFloat32()), ins);
   8387      break;
   8388 #ifdef ENABLE_WASM_SIMD
   8389    case MIRType::Simd128:
   8390      define(new (alloc()) LSimd128(ins->toSimd128()), ins);
   8391      break;
   8392 #endif
   8393    default:
   8394      MOZ_CRASH("unexpected constant type");
   8395  }
   8396 }
   8397 
   8398 #ifdef JS_JITSPEW
   8399 static void SpewResumePoint(MBasicBlock* block, MInstruction* ins,
   8400                            MResumePoint* resumePoint) {
   8401  Fprinter& out = JitSpewPrinter();
   8402  out.printf("Current resume point %p details:\n", (void*)resumePoint);
   8403  out.printf("    frame count: %u\n", resumePoint->frameCount());
   8404 
   8405  if (ins) {
   8406    out.printf("    taken after: ");
   8407    ins->printName(out);
   8408  } else {
   8409    out.printf("    taken at block %u entry", block->id());
   8410  }
   8411  out.printf("\n");
   8412 
   8413  out.printf("    pc: %p (script: %p, offset: %d)\n", (void*)resumePoint->pc(),
   8414             (void*)resumePoint->block()->info().script(),
   8415             int(resumePoint->block()->info().script()->pcToOffset(
   8416                 resumePoint->pc())));
   8417 
   8418  for (size_t i = 0, e = resumePoint->numOperands(); i < e; i++) {
   8419    MDefinition* in = resumePoint->getOperand(i);
   8420    out.printf("    slot%u: ", (unsigned)i);
   8421    in->printName(out);
   8422    out.printf("\n");
   8423  }
   8424 }
   8425 #endif
   8426 
   8427 void LIRGenerator::visitInstructionDispatch(MInstruction* ins) {
   8428 #ifdef JS_CODEGEN_NONE
   8429  // Don't compile the switch-statement below so that we don't have to define
   8430  // the platform-specific visit* methods for the none-backend.
   8431  MOZ_CRASH();
   8432 #else
   8433  switch (ins->op()) {
   8434 #  define MIR_OP(op)              \
   8435    case MDefinition::Opcode::op: \
   8436      visit##op(ins->to##op());   \
   8437      break;
   8438    MIR_OPCODE_LIST(MIR_OP)
   8439 #  undef MIR_OP
   8440    default:
   8441      MOZ_CRASH("Invalid instruction");
   8442  }
   8443 #endif
   8444 }
   8445 
   8446 void LIRGeneratorShared::visitEmittedAtUses(MInstruction* ins) {
   8447  static_cast<LIRGenerator*>(this)->visitInstructionDispatch(ins);
   8448 }
   8449 
   8450 bool LIRGenerator::visitInstruction(MInstruction* ins) {
   8451  MOZ_ASSERT(!errored());
   8452 
   8453  if (ins->isRecoveredOnBailout()) {
   8454    MOZ_ASSERT(!JitOptions.disableRecoverIns);
   8455    return true;
   8456  }
   8457 
   8458  if (!gen->ensureBallast()) {
   8459    return false;
   8460  }
   8461  visitInstructionDispatch(ins);
   8462 
   8463  if (ins->resumePoint()) {
   8464    updateResumeState(ins);
   8465  }
   8466 
   8467 #ifdef DEBUG
   8468  ins->setInWorklistUnchecked();
   8469 #endif
   8470 
   8471  // If no safepoint was created, there's no need for an OSI point.
   8472  if (LOsiPoint* osiPoint = popOsiPoint()) {
   8473    add(osiPoint);
   8474  }
   8475 
   8476  return !errored();
   8477 }
   8478 
   8479 bool LIRGenerator::definePhis() {
   8480  size_t lirIndex = 0;
   8481  MBasicBlock* block = current->mir();
   8482  for (MPhiIterator phi(block->phisBegin()); phi != block->phisEnd(); phi++) {
   8483    if (phi->type() == MIRType::Value) {
   8484      defineUntypedPhi(*phi, lirIndex);
   8485      lirIndex += BOX_PIECES;
   8486    } else if (phi->type() == MIRType::Int64) {
   8487      defineInt64Phi(*phi, lirIndex);
   8488      lirIndex += INT64_PIECES;
   8489    } else {
   8490      defineTypedPhi(*phi, lirIndex);
   8491      lirIndex += 1;
   8492    }
   8493  }
   8494  return !errored();
   8495 }
   8496 
   8497 void LIRGenerator::updateResumeState(MInstruction* ins) {
   8498  lastResumePoint_ = ins->resumePoint();
   8499 #ifdef JS_JITSPEW
   8500  if (JitSpewEnabled(JitSpew_IonSnapshots) && lastResumePoint_) {
   8501    SpewResumePoint(nullptr, ins, lastResumePoint_);
   8502  }
   8503 #endif
   8504 }
   8505 
   8506 void LIRGenerator::updateResumeState(MBasicBlock* block) {
   8507  // Note: RangeAnalysis can flag blocks as unreachable, but they are only
   8508  // removed iff GVN (including UCE) is enabled.
   8509  MOZ_ASSERT_IF(!mir()->compilingWasm() && !block->unreachable(),
   8510                block->entryResumePoint());
   8511  MOZ_ASSERT_IF(block->unreachable(), !mir()->optimizationInfo().gvnEnabled());
   8512  lastResumePoint_ = block->entryResumePoint();
   8513 #ifdef JS_JITSPEW
   8514  if (JitSpewEnabled(JitSpew_IonSnapshots) && lastResumePoint_) {
   8515    SpewResumePoint(block, nullptr, lastResumePoint_);
   8516  }
   8517 #endif
   8518 }
   8519 
   8520 bool LIRGenerator::visitBlock(MBasicBlock* block) {
   8521  current = block->lir();
   8522  updateResumeState(block);
   8523 
   8524  if (!definePhis()) {
   8525    return false;
   8526  }
   8527 
   8528  MOZ_ASSERT_IF(block->unreachable(), !mir()->optimizationInfo().gvnEnabled());
   8529  for (MInstructionIterator iter = block->begin(); *iter != block->lastIns();
   8530       iter++) {
   8531    if (gen->shouldCancel("Lowering (instruction loop)")) {
   8532      return false;
   8533    }
   8534    if (!visitInstruction(*iter)) {
   8535      return false;
   8536    }
   8537  }
   8538 
   8539  if (block->successorWithPhis()) {
   8540    // If we have a successor with phis, lower the phi input now that we
   8541    // are approaching the join point.
   8542    MBasicBlock* successor = block->successorWithPhis();
   8543    uint32_t position = block->positionInPhiSuccessor();
   8544    size_t lirIndex = 0;
   8545    for (MPhiIterator phi(successor->phisBegin()); phi != successor->phisEnd();
   8546         phi++) {
   8547      if (!gen->ensureBallast()) {
   8548        return false;
   8549      }
   8550 
   8551      MDefinition* opd = phi->getOperand(position);
   8552      ensureDefined(opd);
   8553 
   8554      MOZ_ASSERT(opd->type() == phi->type());
   8555 
   8556      if (phi->type() == MIRType::Value) {
   8557        lowerUntypedPhiInput(*phi, position, successor->lir(), lirIndex);
   8558        lirIndex += BOX_PIECES;
   8559      } else if (phi->type() == MIRType::Int64) {
   8560        lowerInt64PhiInput(*phi, position, successor->lir(), lirIndex);
   8561        lirIndex += INT64_PIECES;
   8562      } else {
   8563        lowerTypedPhiInput(*phi, position, successor->lir(), lirIndex);
   8564        lirIndex += 1;
   8565      }
   8566    }
   8567  }
   8568 
   8569  // Now emit the last instruction, which is some form of branch.
   8570  if (!visitInstruction(block->lastIns())) {
   8571    return false;
   8572  }
   8573 
   8574  return true;
   8575 }
   8576 
   8577 void LIRGenerator::visitNaNToZero(MNaNToZero* ins) {
   8578  MDefinition* input = ins->input();
   8579 
   8580  if (ins->operandIsNeverNaN() && ins->operandIsNeverNegativeZero()) {
   8581    redefine(ins, input);
   8582    return;
   8583  }
   8584  LNaNToZero* lir =
   8585      new (alloc()) LNaNToZero(useRegisterAtStart(input), tempDouble());
   8586  defineReuseInput(lir, ins, 0);
   8587 }
   8588 
   8589 bool LIRGenerator::generate() {
   8590  // Create all blocks and prep all phis beforehand.
   8591  for (ReversePostorderIterator block(graph.rpoBegin());
   8592       block != graph.rpoEnd(); block++) {
   8593    if (gen->shouldCancel("Lowering (preparation loop)")) {
   8594      return false;
   8595    }
   8596 
   8597    if (!lirGraph_.initBlock(*block)) {
   8598      return false;
   8599    }
   8600  }
   8601 
   8602  for (ReversePostorderIterator block(graph.rpoBegin());
   8603       block != graph.rpoEnd(); block++) {
   8604    if (gen->shouldCancel("Lowering (main loop)")) {
   8605      return false;
   8606    }
   8607 
   8608    if (!visitBlock(*block)) {
   8609      return false;
   8610    }
   8611  }
   8612 
   8613  lirGraph_.setArgumentSlotCount(maxargslots_);
   8614  return true;
   8615 }
   8616 
   8617 void LIRGenerator::visitPhi(MPhi* phi) {
   8618  // Phi nodes are not lowered because they are only meaningful for the register
   8619  // allocator.
   8620  MOZ_CRASH("Unexpected Phi node during Lowering.");
   8621 }
   8622 
   8623 void LIRGenerator::visitBeta(MBeta* beta) {
   8624  // Beta nodes are supposed to be removed before because they are
   8625  // only used to carry the range information for Range analysis
   8626  MOZ_CRASH("Unexpected Beta node during Lowering.");
   8627 }
   8628 
   8629 void LIRGenerator::visitObjectState(MObjectState* objState) {
   8630  // ObjectState nodes are always recovered on bailouts
   8631  MOZ_CRASH("Unexpected ObjectState node during Lowering.");
   8632 }
   8633 
   8634 void LIRGenerator::visitArrayState(MArrayState* objState) {
   8635  // ArrayState nodes are always recovered on bailouts
   8636  MOZ_CRASH("Unexpected ArrayState node during Lowering.");
   8637 }
   8638 
   8639 void LIRGenerator::visitIonToWasmCall(MIonToWasmCall* ins) {
   8640  // The instruction needs a temp register:
   8641  // - that's not the FramePointer, since wasm is going to use it in the
   8642  // function.
   8643  // - that's not aliasing an input register.
   8644  LDefinition scratch = tempFixed(ABINonArgReg0);
   8645 
   8646  // Note that since this is a LIR call instruction, regalloc will prevent
   8647  // the use*AtStart below from reusing any of the temporaries.
   8648 
   8649  LInstruction* lir;
   8650  if (ins->type() == MIRType::Value) {
   8651    lir = allocateVariadic<LIonToWasmCallV>(ins->numOperands(), scratch);
   8652  } else if (ins->type() == MIRType::Int64) {
   8653    lir = allocateVariadic<LIonToWasmCallI64>(ins->numOperands(), scratch);
   8654  } else {
   8655    lir = allocateVariadic<LIonToWasmCall>(ins->numOperands(), scratch);
   8656  }
   8657  if (!lir) {
   8658    abort(AbortReason::Alloc, "OOM: LIRGenerator::visitIonToWasmCall");
   8659    return;
   8660  }
   8661 
   8662  ABIArgGenerator abi(ABIKind::Wasm);
   8663  for (unsigned i = 0; i < ins->numOperands(); i++) {
   8664    MDefinition* argDef = ins->getOperand(i);
   8665    ABIArg arg = abi.next(ToMIRType(argDef->type()));
   8666    switch (arg.kind()) {
   8667      case ABIArg::GPR:
   8668      case ABIArg::FPU:
   8669        lir->setOperand(i, useFixedAtStart(argDef, arg.reg()));
   8670        break;
   8671      case ABIArg::Stack:
   8672        lir->setOperand(i, useAtStart(argDef));
   8673        break;
   8674 #ifdef JS_CODEGEN_REGISTER_PAIR
   8675      case ABIArg::GPR_PAIR:
   8676        MOZ_CRASH(
   8677            "no way to pass i64, and wasm uses hardfp for function calls");
   8678 #endif
   8679      case ABIArg::Uninitialized:
   8680        MOZ_CRASH("Uninitialized ABIArg kind");
   8681    }
   8682  }
   8683 
   8684  defineReturn(lir, ins);
   8685  assignSafepoint(lir, ins);
   8686 }
   8687 
   8688 void LIRGenerator::visitWasmSelect(MWasmSelect* ins) {
   8689  MDefinition* condExpr = ins->condExpr();
   8690 
   8691  // Pick off specific cases that we can do with LWasmCompareAndSelect to avoid
   8692  // generating a boolean that we then have to test again.
   8693  if (condExpr->isCompare() && condExpr->isEmittedAtUses()) {
   8694    MCompare* comp = condExpr->toCompare();
   8695    MCompare::CompareType compTy = comp->compareType();
   8696    if (canSpecializeWasmCompareAndSelect(compTy, ins->type())) {
   8697      JSOp jsop = comp->jsop();
   8698      // We don't currently generate any other JSOPs for the comparison, and if
   8699      // that changes, we want to know about it.  Hence this assertion.
   8700      MOZ_ASSERT(jsop == JSOp::Eq || jsop == JSOp::Ne || jsop == JSOp::Lt ||
   8701                 jsop == JSOp::Gt || jsop == JSOp::Le || jsop == JSOp::Ge);
   8702      MDefinition* lhs = comp->lhs();
   8703      MDefinition* rhs = comp->rhs();
   8704      jsop = ReorderComparison(jsop, &lhs, &rhs);
   8705      lowerWasmCompareAndSelect(ins, lhs, rhs, compTy, jsop);
   8706      return;
   8707    }
   8708  }
   8709  // Fall through to code that generates a boolean and selects on that.
   8710 
   8711  if (ins->type() == MIRType::Int64) {
   8712    lowerWasmSelectI64(ins);
   8713    return;
   8714  }
   8715 
   8716  lowerWasmSelectI(ins);
   8717 }
   8718 
   8719 void LIRGenerator::visitWasmFence(MWasmFence* ins) {
   8720  add(new (alloc()) LWasmFence, ins);
   8721 }
   8722 
   8723 void LIRGenerator::visitWasmLoadField(MWasmLoadField* ins) {
   8724  uint32_t offset = ins->offset();
   8725  LAllocation data = useRegisterAtStart(ins->base());
   8726  MWideningOp wideningOp = ins->wideningOp();
   8727  if (ins->type() == MIRType::Int64) {
   8728    MOZ_RELEASE_ASSERT(wideningOp == MWideningOp::None);
   8729    defineInt64(new (alloc()) LWasmLoadSlotI64(data, offset, ins->maybeTrap()),
   8730                ins);
   8731  } else {
   8732    define(new (alloc()) LWasmLoadSlot(data, offset, ins->type(), wideningOp,
   8733                                       ins->maybeTrap()),
   8734           ins);
   8735  }
   8736  if (ins->keepAlive() != ins->base()) {
   8737    add(new (alloc()) LKeepAliveObject(useKeepalive(ins->keepAlive())), ins);
   8738  }
   8739 }
   8740 
   8741 void LIRGenerator::visitWasmLoadElement(MWasmLoadElement* ins) {
   8742  LAllocation base = useRegister(ins->base());
   8743  LAllocation index = useRegister(ins->index());
   8744  MWideningOp wideningOp = ins->wideningOp();
   8745  Scale scale = ins->scale();
   8746  if (ins->type() == MIRType::Int64) {
   8747    MOZ_RELEASE_ASSERT(wideningOp == MWideningOp::None);
   8748    defineInt64(
   8749        new (alloc()) LWasmLoadElementI64(base, index, ins->maybeTrap()), ins);
   8750  } else {
   8751    LDefinition tmp =
   8752        ins->type() == MIRType::Simd128 ? temp() : LDefinition::BogusTemp();
   8753    define(new (alloc()) LWasmLoadElement(base, index, tmp, ins->type(),
   8754                                          wideningOp, scale, ins->maybeTrap()),
   8755           ins);
   8756  }
   8757  if (ins->keepAlive() != ins->base()) {
   8758    add(new (alloc()) LKeepAliveObject(useKeepalive(ins->keepAlive())), ins);
   8759  }
   8760 }
   8761 
   8762 void LIRGenerator::visitWasmStoreField(MWasmStoreField* ins) {
   8763  MDefinition* value = ins->value();
   8764  uint32_t offs = ins->offset();
   8765  MNarrowingOp narrowingOp = ins->narrowingOp();
   8766  LAllocation base = useRegister(ins->base());
   8767  if (value->type() == MIRType::Int64) {
   8768    MOZ_RELEASE_ASSERT(narrowingOp == MNarrowingOp::None);
   8769    add(new (alloc()) LWasmStoreSlotI64(useInt64Register(value), base, offs,
   8770                                        ins->maybeTrap()),
   8771        ins);
   8772  } else {
   8773    add(new (alloc())
   8774            LWasmStoreSlot(useRegister(value), base, offs, value->type(),
   8775                           narrowingOp, ins->maybeTrap()),
   8776        ins);
   8777  }
   8778  if (ins->keepAlive() != ins->base()) {
   8779    add(new (alloc()) LKeepAliveObject(useKeepalive(ins->keepAlive())), ins);
   8780  }
   8781 }
   8782 
   8783 void LIRGenerator::visitWasmStoreFieldRef(MWasmStoreFieldRef* ins) {
   8784  LAllocation instance = useRegister(ins->instance());
   8785  LAllocation base = useFixed(ins->base(), PreBarrierReg);
   8786  LAllocation value = useRegister(ins->value());
   8787  uint32_t offset = ins->offset();
   8788  add(new (alloc()) LWasmStoreRef(instance, base, value, temp(), offset,
   8789                                  ins->maybeTrap(), ins->preBarrierKind()),
   8790      ins);
   8791  if (ins->keepAlive() != ins->base()) {
   8792    add(new (alloc()) LKeepAliveObject(useKeepalive(ins->keepAlive())), ins);
   8793  }
   8794 }
   8795 
   8796 void LIRGenerator::visitWasmStoreElement(MWasmStoreElement* ins) {
   8797  LAllocation base = useRegister(ins->base());
   8798  LAllocation index = useRegister(ins->index());
   8799  MDefinition* value = ins->value();
   8800  MNarrowingOp narrowingOp = ins->narrowingOp();
   8801  Scale scale = ins->scale();
   8802  if (value->type() == MIRType::Int64) {
   8803    MOZ_RELEASE_ASSERT(narrowingOp == MNarrowingOp::None);
   8804    add(new (alloc()) LWasmStoreElementI64(base, index, useInt64Register(value),
   8805                                           ins->maybeTrap()),
   8806        ins);
   8807  } else {
   8808    LDefinition tmp =
   8809        value->type() == MIRType::Simd128 ? temp() : LDefinition::BogusTemp();
   8810    add(new (alloc()) LWasmStoreElement(base, index, useRegister(value), tmp,
   8811                                        value->type(), narrowingOp, scale,
   8812                                        ins->maybeTrap()),
   8813        ins);
   8814  }
   8815  if (ins->keepAlive() != ins->base()) {
   8816    add(new (alloc()) LKeepAliveObject(useKeepalive(ins->keepAlive())), ins);
   8817  }
   8818 }
   8819 
   8820 void LIRGenerator::visitWasmStoreElementRef(MWasmStoreElementRef* ins) {
   8821  LAllocation instance = useRegister(ins->instance());
   8822  LAllocation base = useFixed(ins->base(), PreBarrierReg);
   8823  LAllocation index = useRegister(ins->index());
   8824  LAllocation value = useRegister(ins->value());
   8825  bool needTemps = ins->preBarrierKind() == WasmPreBarrierKind::Normal;
   8826  LDefinition temp0 = needTemps ? temp() : LDefinition::BogusTemp();
   8827  LDefinition temp1 = needTemps ? temp() : LDefinition::BogusTemp();
   8828  add(new (alloc())
   8829          LWasmStoreElementRef(instance, base, index, value, temp0, temp1,
   8830                               ins->maybeTrap(), ins->preBarrierKind()),
   8831      ins);
   8832  if (ins->keepAlive() != ins->base()) {
   8833    add(new (alloc()) LKeepAliveObject(useKeepalive(ins->keepAlive())), ins);
   8834  }
   8835 }
   8836 
   8837 WasmRefIsSubtypeDefs LIRGenerator::useWasmRefIsSubtype(wasm::RefType destType,
   8838                                                       MDefinition* superSTV) {
   8839  BranchWasmRefIsSubtypeRegisters needs =
   8840      MacroAssembler::regsForBranchWasmRefIsSubtype(destType);
   8841  return WasmRefIsSubtypeDefs{
   8842      .superSTV = needs.needSuperSTV ? useRegister(superSTV) : LAllocation(),
   8843      .scratch1 = needs.needScratch1 ? temp() : LDefinition(),
   8844      .scratch2 = needs.needScratch2 ? temp() : LDefinition(),
   8845  };
   8846 }
   8847 
   8848 void LIRGenerator::visitWasmRefTestAbstract(MWasmRefTestAbstract* ins) {
   8849  if (CanEmitAtUseForSingleTest(ins)) {
   8850    emitAtUses(ins);
   8851    return;
   8852  }
   8853 
   8854  LAllocation ref = useRegister(ins->ref());
   8855  WasmRefIsSubtypeDefs regs =
   8856      useWasmRefIsSubtype(ins->destType(), /*superSTV=*/nullptr);
   8857  define(new (alloc()) LWasmRefTestAbstract(ref, regs.scratch1), ins);
   8858 }
   8859 
   8860 void LIRGenerator::visitWasmRefTestConcrete(MWasmRefTestConcrete* ins) {
   8861  if (CanEmitAtUseForSingleTest(ins)) {
   8862    emitAtUses(ins);
   8863    return;
   8864  }
   8865 
   8866  LAllocation ref = useRegister(ins->ref());
   8867  WasmRefIsSubtypeDefs regs =
   8868      useWasmRefIsSubtype(ins->destType(), ins->superSTV());
   8869  define(new (alloc()) LWasmRefTestConcrete(ref, regs.superSTV, regs.scratch1,
   8870                                            regs.scratch2),
   8871         ins);
   8872 }
   8873 
   8874 void LIRGenerator::visitWasmRefCastAbstract(MWasmRefCastAbstract* ins) {
   8875  LAllocation ref = useRegisterAtStart(ins->ref());
   8876  WasmRefIsSubtypeDefs regs =
   8877      useWasmRefIsSubtype(ins->destType(), /*superSTV=*/nullptr);
   8878  defineReuseInput(new (alloc()) LWasmRefCastAbstract(ref, regs.scratch1), ins,
   8879                   0);
   8880 }
   8881 
   8882 void LIRGenerator::visitWasmRefCastConcrete(MWasmRefCastConcrete* ins) {
   8883  LAllocation ref = useRegisterAtStart(ins->ref());
   8884  WasmRefIsSubtypeDefs regs =
   8885      useWasmRefIsSubtype(ins->destType(), ins->superSTV());
   8886  defineReuseInput(new (alloc()) LWasmRefCastConcrete(
   8887                       ref, regs.superSTV, regs.scratch1, regs.scratch2),
   8888                   ins, 0);
   8889 }
   8890 
   8891 void LIRGenerator::visitWasmRefConvertAnyExtern(MWasmRefConvertAnyExtern* ins) {
   8892  // Because any and extern have the same representation, this is a no-op.
   8893  return redefine(ins, ins->ref());
   8894 }
   8895 
   8896 void LIRGenerator::visitWasmNewStructObject(MWasmNewStructObject* ins) {
   8897  LWasmNewStructObject* lir =
   8898      new (alloc()) LWasmNewStructObject(useFixed(ins->instance(), InstanceReg),
   8899                                         useRegister(ins->allocSite()), temp());
   8900  define(lir, ins);
   8901  assignWasmSafepoint(lir);
   8902 }
   8903 
   8904 void LIRGenerator::visitWasmNewArrayObject(MWasmNewArrayObject* ins) {
   8905  LWasmNewArrayObject* lir = new (alloc())
   8906      LWasmNewArrayObject(useFixed(ins->instance(), InstanceReg),
   8907                          useRegisterOrConstant(ins->numElements()),
   8908                          useRegister(ins->allocSite()), temp(), temp());
   8909  define(lir, ins);
   8910  assignWasmSafepoint(lir);
   8911 }
   8912 
   8913 #ifdef ENABLE_EXPLICIT_RESOURCE_MANAGEMENT
   8914 void LIRGenerator::visitAddDisposableResource(MAddDisposableResource* ins) {
   8915  MDefinition* env = ins->environment();
   8916 
   8917  MOZ_ASSERT(env->type() == MIRType::Object);
   8918 
   8919  MDefinition* resource = ins->resource();
   8920  MDefinition* method = ins->method();
   8921  MDefinition* needsClosure = ins->needsClosure();
   8922 
   8923  auto* lir = new (alloc()) LAddDisposableResource(
   8924      useRegisterAtStart(env), useBoxAtStart(resource), useBoxAtStart(method),
   8925      useRegisterAtStart(needsClosure));
   8926  add(lir, ins);
   8927  assignSafepoint(lir, ins);
   8928 }
   8929 
   8930 void LIRGenerator::visitTakeDisposeCapability(MTakeDisposeCapability* ins) {
   8931  MDefinition* env = ins->environment();
   8932 
   8933  LTakeDisposeCapability* lir =
   8934      new (alloc()) LTakeDisposeCapability(useRegister(env));
   8935  defineBox(lir, ins);
   8936  assignSafepoint(lir, ins);
   8937 }
   8938 
   8939 void LIRGenerator::visitCreateSuppressedError(MCreateSuppressedError* ins) {
   8940  MDefinition* error = ins->error();
   8941  MDefinition* suppressed = ins->suppressed();
   8942 
   8943  LCreateSuppressedError* lir = new (alloc())
   8944      LCreateSuppressedError(useBoxAtStart(error), useBoxAtStart(suppressed));
   8945  define(lir, ins);
   8946  assignSafepoint(lir, ins);
   8947 }
   8948 #endif
   8949 
   8950 #ifdef FUZZING_JS_FUZZILLI
   8951 void LIRGenerator::visitFuzzilliHash(MFuzzilliHash* ins) {
   8952  MDefinition* value = ins->input();
   8953 
   8954  switch (value->type()) {
   8955    case MIRType::Undefined:
   8956    case MIRType::Null: {
   8957      auto* lir =
   8958          new (alloc()) LFuzzilliHashT(LAllocation(), temp(), tempDouble());
   8959      define(lir, ins);
   8960      break;
   8961    }
   8962 
   8963    case MIRType::Int32:
   8964    case MIRType::Double:
   8965    case MIRType::Float32:
   8966    case MIRType::Boolean: {
   8967      auto* lir = new (alloc())
   8968          LFuzzilliHashT(useRegister(value), temp(), tempDouble());
   8969      define(lir, ins);
   8970      break;
   8971    }
   8972 
   8973    case MIRType::BigInt:
   8974    case MIRType::Object: {
   8975      auto* lir = new (alloc())
   8976          LFuzzilliHashT(useRegister(value), LDefinition::BogusTemp(),
   8977                         LDefinition::BogusTemp());
   8978      define(lir, ins);
   8979      assignSafepoint(lir, ins);
   8980      break;
   8981    }
   8982 
   8983    case MIRType::Value: {
   8984      auto* lir =
   8985          new (alloc()) LFuzzilliHashV(useBox(value), temp(), tempDouble());
   8986      define(lir, ins);
   8987      assignSafepoint(lir, ins);
   8988      break;
   8989    }
   8990 
   8991    case MIRType::String:
   8992    case MIRType::Symbol: {
   8993      define(new (alloc()) LInteger(0), ins);
   8994      break;
   8995    }
   8996 
   8997    default:
   8998      MOZ_CRASH("Bad type");
   8999  }
   9000 }
   9001 
   9002 void LIRGenerator::visitFuzzilliHashStore(MFuzzilliHashStore* ins) {
   9003  MDefinition* value = ins->input();
   9004  MOZ_ASSERT(value->type() == MIRType::Int32);
   9005  add(new (alloc()) LFuzzilliHashStore(useRegister(value), temp(), temp()),
   9006      ins);
   9007 }
   9008 #endif
   9009 
   9010 static_assert(!std::is_polymorphic_v<LIRGenerator>,
   9011              "LIRGenerator should not have any virtual methods");
   9012 
   9013 #ifdef JS_CODEGEN_NONE
   9014 void LIRGenerator::visitReturnImpl(MDefinition*, bool) { MOZ_CRASH(); }
   9015 #endif