LCOV - code coverage report
Current view: top level - js/src/jit - Lowering.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 723 2943 24.6 %
Date: 2017-07-14 16:53:18 Functions: 80 293 27.3 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
       2             :  * vim: set ts=8 sts=4 et sw=4 tw=99:
       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             : 
      11             : #include "jit/JitSpewer.h"
      12             : #include "jit/LIR.h"
      13             : #include "jit/MIR.h"
      14             : #include "jit/MIRGraph.h"
      15             : #include "wasm/WasmSignalHandlers.h"
      16             : 
      17             : #include "jsobjinlines.h"
      18             : #include "jsopcodeinlines.h"
      19             : 
      20             : #include "jit/shared/Lowering-shared-inl.h"
      21             : 
      22             : using namespace js;
      23             : using namespace jit;
      24             : 
      25             : using mozilla::DebugOnly;
      26             : using JS::GenericNaN;
      27             : 
      28             : LBoxAllocation
      29           0 : LIRGenerator::useBoxFixedAtStart(MDefinition* mir, ValueOperand op)
      30             : {
      31             : #if defined(JS_NUNBOX32)
      32             :     return useBoxFixed(mir, op.typeReg(), op.payloadReg(), true);
      33             : #elif defined(JS_PUNBOX64)
      34           0 :     return useBoxFixed(mir, op.valueReg(), op.scratchReg(), true);
      35             : #endif
      36             : }
      37             : 
      38             : LBoxAllocation
      39           4 : LIRGenerator::useBoxAtStart(MDefinition* mir, LUse::Policy policy)
      40             : {
      41           4 :     return useBox(mir, policy, /* useAtStart = */ true);
      42             : }
      43             : 
      44             : void
      45           0 : LIRGenerator::visitCloneLiteral(MCloneLiteral* ins)
      46             : {
      47           0 :     MOZ_ASSERT(ins->type() == MIRType::Object);
      48           0 :     MOZ_ASSERT(ins->input()->type() == MIRType::Object);
      49             : 
      50           0 :     LCloneLiteral* lir = new(alloc()) LCloneLiteral(useRegisterAtStart(ins->input()));
      51           0 :     defineReturn(lir, ins);
      52           0 :     assignSafepoint(lir, ins);
      53           0 : }
      54             : 
      55             : void
      56          36 : LIRGenerator::visitParameter(MParameter* param)
      57             : {
      58             :     ptrdiff_t offset;
      59          36 :     if (param->index() == MParameter::THIS_SLOT)
      60          11 :         offset = THIS_FRAME_ARGSLOT;
      61             :     else
      62          25 :         offset = 1 + param->index();
      63             : 
      64          36 :     LParameter* ins = new(alloc()) LParameter;
      65          36 :     defineBox(ins, param, LDefinition::FIXED);
      66             : 
      67          36 :     offset *= sizeof(Value);
      68             : #if defined(JS_NUNBOX32)
      69             : # if MOZ_BIG_ENDIAN
      70             :     ins->getDef(0)->setOutput(LArgument(offset));
      71             :     ins->getDef(1)->setOutput(LArgument(offset + 4));
      72             : # else
      73             :     ins->getDef(0)->setOutput(LArgument(offset + 4));
      74             :     ins->getDef(1)->setOutput(LArgument(offset));
      75             : # endif
      76             : #elif defined(JS_PUNBOX64)
      77          36 :     ins->getDef(0)->setOutput(LArgument(offset));
      78             : #endif
      79          36 : }
      80             : 
      81             : void
      82           3 : LIRGenerator::visitCallee(MCallee* ins)
      83             : {
      84           3 :     define(new(alloc()) LCallee(), ins);
      85           3 : }
      86             : 
      87             : void
      88           0 : LIRGenerator::visitIsConstructing(MIsConstructing* ins)
      89             : {
      90           0 :     define(new(alloc()) LIsConstructing(), ins);
      91           0 : }
      92             : 
      93             : static void
      94           5 : TryToUseImplicitInterruptCheck(MIRGraph& graph, MBasicBlock* backedge)
      95             : {
      96             :     // Implicit interrupt checks require wasm signal handlers to be installed.
      97           5 :     if (!wasm::HaveSignalHandlers() || JitOptions.ionInterruptWithoutSignals)
      98           5 :         return;
      99             : 
     100             :     // To avoid triggering expensive interrupts (backedge patching) in
     101             :     // requestMajorGC and requestMinorGC, use an implicit interrupt check only
     102             :     // if the loop body can not trigger GC or affect GC state like the store
     103             :     // buffer. We do this by checking there are no safepoints attached to LIR
     104             :     // instructions inside the loop.
     105             : 
     106           5 :     MBasicBlockIterator block = graph.begin(backedge->loopHeaderOfBackedge());
     107           5 :     LInterruptCheck* check = nullptr;
     108             :     while (true) {
     109          18 :         LBlock* lir = block->lir();
     110          58 :         for (LInstructionIterator iter = lir->begin(); iter != lir->end(); iter++) {
     111          45 :             if (iter->isInterruptCheck()) {
     112           5 :                 if (!check) {
     113           5 :                     MOZ_ASSERT(*block == backedge->loopHeaderOfBackedge());
     114           5 :                     check = iter->toInterruptCheck();
     115             :                 }
     116           5 :                 continue;
     117             :             }
     118             : 
     119          40 :             MOZ_ASSERT_IF(iter->isPostWriteBarrierO() || iter->isPostWriteBarrierV(),
     120             :                           iter->safepoint());
     121             : 
     122          40 :             if (iter->safepoint())
     123           5 :                 return;
     124             :         }
     125          13 :         if (*block == backedge)
     126           0 :             break;
     127          13 :         block++;
     128          13 :     }
     129             : 
     130           0 :     check->setImplicit();
     131             : }
     132             : 
     133             : void
     134         255 : LIRGenerator::visitGoto(MGoto* ins)
     135             : {
     136         255 :     if (!gen->compilingWasm() && ins->block()->isLoopBackedge())
     137           5 :         TryToUseImplicitInterruptCheck(graph, ins->block());
     138             : 
     139         255 :     add(new(alloc()) LGoto(ins->target()));
     140         255 : }
     141             : 
     142             : void
     143           0 : LIRGenerator::visitTableSwitch(MTableSwitch* tableswitch)
     144             : {
     145           0 :     MDefinition* opd = tableswitch->getOperand(0);
     146             : 
     147             :     // There should be at least 1 successor. The default case!
     148           0 :     MOZ_ASSERT(tableswitch->numSuccessors() > 0);
     149             : 
     150             :     // If there are no cases, the default case is always taken.
     151           0 :     if (tableswitch->numSuccessors() == 1) {
     152           0 :         add(new(alloc()) LGoto(tableswitch->getDefault()));
     153           0 :         return;
     154             :     }
     155             : 
     156             :     // If we don't know the type.
     157           0 :     if (opd->type() == MIRType::Value) {
     158           0 :         LTableSwitchV* lir = newLTableSwitchV(tableswitch);
     159           0 :         add(lir);
     160           0 :         return;
     161             :     }
     162             : 
     163             :     // Case indices are numeric, so other types will always go to the default case.
     164           0 :     if (opd->type() != MIRType::Int32 && opd->type() != MIRType::Double) {
     165           0 :         add(new(alloc()) LGoto(tableswitch->getDefault()));
     166           0 :         return;
     167             :     }
     168             : 
     169             :     // Return an LTableSwitch, capable of handling either an integer or
     170             :     // floating-point index.
     171           0 :     LAllocation index;
     172           0 :     LDefinition tempInt;
     173           0 :     if (opd->type() == MIRType::Int32) {
     174           0 :         index = useRegisterAtStart(opd);
     175           0 :         tempInt = tempCopy(opd, 0);
     176             :     } else {
     177           0 :         index = useRegister(opd);
     178           0 :         tempInt = temp(LDefinition::GENERAL);
     179             :     }
     180           0 :     add(newLTableSwitch(index, tempInt, tableswitch));
     181             : }
     182             : 
     183             : void
     184           8 : LIRGenerator::visitCheckOverRecursed(MCheckOverRecursed* ins)
     185             : {
     186           8 :     LCheckOverRecursed* lir = new(alloc()) LCheckOverRecursed(temp());
     187           8 :     add(lir, ins);
     188           8 :     assignSafepoint(lir, ins);
     189           8 : }
     190             : 
     191             : void
     192           0 : LIRGenerator::visitDefVar(MDefVar* ins)
     193             : {
     194           0 :     LDefVar* lir = new(alloc()) LDefVar(useRegisterAtStart(ins->environmentChain()));
     195           0 :     add(lir, ins);
     196           0 :     assignSafepoint(lir, ins);
     197           0 : }
     198             : 
     199             : void
     200           0 : LIRGenerator::visitDefLexical(MDefLexical* ins)
     201             : {
     202           0 :     LDefLexical* lir = new(alloc()) LDefLexical();
     203           0 :     add(lir, ins);
     204           0 :     assignSafepoint(lir, ins);
     205           0 : }
     206             : 
     207             : void
     208           0 : LIRGenerator::visitDefFun(MDefFun* ins)
     209             : {
     210           0 :     MDefinition* fun = ins->fun();
     211           0 :     MOZ_ASSERT(fun->type() == MIRType::Object);
     212             : 
     213           0 :     LDefFun* lir = new(alloc()) LDefFun(useRegisterAtStart(fun),
     214           0 :                                         useRegisterAtStart(ins->environmentChain()));
     215           0 :     add(lir, ins);
     216           0 :     assignSafepoint(lir, ins);
     217           0 : }
     218             : 
     219             : void
     220           3 : LIRGenerator::visitNewArray(MNewArray* ins)
     221             : {
     222           3 :     LNewArray* lir = new(alloc()) LNewArray(temp());
     223           3 :     define(lir, ins);
     224           3 :     assignSafepoint(lir, ins);
     225           3 : }
     226             : 
     227             : void
     228           0 : LIRGenerator::visitNewArrayCopyOnWrite(MNewArrayCopyOnWrite* ins)
     229             : {
     230           0 :     LNewArrayCopyOnWrite* lir = new(alloc()) LNewArrayCopyOnWrite(temp());
     231           0 :     define(lir, ins);
     232           0 :     assignSafepoint(lir, ins);
     233           0 : }
     234             : 
     235             : void
     236           0 : LIRGenerator::visitNewArrayDynamicLength(MNewArrayDynamicLength* ins)
     237             : {
     238           0 :     MDefinition* length = ins->length();
     239           0 :     MOZ_ASSERT(length->type() == MIRType::Int32);
     240             : 
     241           0 :     LNewArrayDynamicLength* lir = new(alloc()) LNewArrayDynamicLength(useRegister(length), temp());
     242           0 :     define(lir, ins);
     243           0 :     assignSafepoint(lir, ins);
     244           0 : }
     245             : 
     246             : void
     247           0 : LIRGenerator::visitNewIterator(MNewIterator* ins)
     248             : {
     249           0 :     LNewIterator* lir = new(alloc()) LNewIterator(temp());
     250           0 :     define(lir, ins);
     251           0 :     assignSafepoint(lir, ins);
     252           0 : }
     253             : 
     254             : void
     255           0 : LIRGenerator::visitNewTypedArray(MNewTypedArray* ins)
     256             : {
     257           0 :     LNewTypedArray* lir = new(alloc()) LNewTypedArray(temp(), temp());
     258           0 :     define(lir, ins);
     259           0 :     assignSafepoint(lir, ins);
     260           0 : }
     261             : 
     262             : void
     263           0 : LIRGenerator::visitNewTypedArrayDynamicLength(MNewTypedArrayDynamicLength* ins)
     264             : {
     265           0 :     MDefinition* length = ins->length();
     266           0 :     MOZ_ASSERT(length->type() == MIRType::Int32);
     267             : 
     268           0 :     LNewTypedArrayDynamicLength* lir = new(alloc()) LNewTypedArrayDynamicLength(useRegister(length), temp());
     269           0 :     define(lir, ins);
     270           0 :     assignSafepoint(lir, ins);
     271           0 : }
     272             : 
     273             : void
     274           1 : LIRGenerator::visitNewObject(MNewObject* ins)
     275             : {
     276           1 :     LNewObject* lir = new(alloc()) LNewObject(temp());
     277           1 :     define(lir, ins);
     278           1 :     assignSafepoint(lir, ins);
     279           1 : }
     280             : 
     281             : void
     282           0 : LIRGenerator::visitNewTypedObject(MNewTypedObject* ins)
     283             : {
     284           0 :     LNewTypedObject* lir = new(alloc()) LNewTypedObject(temp());
     285           0 :     define(lir, ins);
     286           0 :     assignSafepoint(lir, ins);
     287           0 : }
     288             : 
     289             : void
     290           0 : LIRGenerator::visitNewNamedLambdaObject(MNewNamedLambdaObject* ins)
     291             : {
     292           0 :     LNewNamedLambdaObject* lir = new(alloc()) LNewNamedLambdaObject(temp());
     293           0 :     define(lir, ins);
     294           0 :     assignSafepoint(lir, ins);
     295           0 : }
     296             : 
     297             : void
     298           2 : LIRGenerator::visitNewCallObject(MNewCallObject* ins)
     299             : {
     300           2 :     LNewCallObject* lir = new(alloc()) LNewCallObject(temp());
     301           2 :     define(lir, ins);
     302           2 :     assignSafepoint(lir, ins);
     303           2 : }
     304             : 
     305             : void
     306           0 : LIRGenerator::visitNewSingletonCallObject(MNewSingletonCallObject* ins)
     307             : {
     308           0 :     LNewSingletonCallObject* lir = new(alloc()) LNewSingletonCallObject(temp());
     309           0 :     define(lir, ins);
     310           0 :     assignSafepoint(lir, ins);
     311           0 : }
     312             : 
     313             : void
     314           0 : LIRGenerator::visitNewDerivedTypedObject(MNewDerivedTypedObject* ins)
     315             : {
     316             :     LNewDerivedTypedObject* lir =
     317           0 :         new(alloc()) LNewDerivedTypedObject(useRegisterAtStart(ins->type()),
     318           0 :                                             useRegisterAtStart(ins->owner()),
     319           0 :                                             useRegisterAtStart(ins->offset()));
     320           0 :     defineReturn(lir, ins);
     321           0 :     assignSafepoint(lir, ins);
     322           0 : }
     323             : 
     324             : void
     325           0 : LIRGenerator::visitNewStringObject(MNewStringObject* ins)
     326             : {
     327           0 :     MOZ_ASSERT(ins->input()->type() == MIRType::String);
     328             : 
     329           0 :     LNewStringObject* lir = new(alloc()) LNewStringObject(useRegister(ins->input()), temp());
     330           0 :     define(lir, ins);
     331           0 :     assignSafepoint(lir, ins);
     332           0 : }
     333             : 
     334             : void
     335           0 : LIRGenerator::visitInitElem(MInitElem* ins)
     336             : {
     337           0 :     LInitElem* lir = new(alloc()) LInitElem(useRegisterAtStart(ins->getObject()),
     338           0 :                                             useBoxAtStart(ins->getId()),
     339           0 :                                             useBoxAtStart(ins->getValue()));
     340           0 :     add(lir, ins);
     341           0 :     assignSafepoint(lir, ins);
     342           0 : }
     343             : 
     344             : void
     345           0 : LIRGenerator::visitInitElemGetterSetter(MInitElemGetterSetter* ins)
     346             : {
     347             :     LInitElemGetterSetter* lir =
     348           0 :         new(alloc()) LInitElemGetterSetter(useRegisterAtStart(ins->object()),
     349           0 :                                            useBoxAtStart(ins->idValue()),
     350           0 :                                            useRegisterAtStart(ins->value()));
     351           0 :     add(lir, ins);
     352           0 :     assignSafepoint(lir, ins);
     353           0 : }
     354             : 
     355             : void
     356           0 : LIRGenerator::visitMutateProto(MMutateProto* ins)
     357             : {
     358           0 :     LMutateProto* lir = new(alloc()) LMutateProto(useRegisterAtStart(ins->getObject()),
     359           0 :                                                   useBoxAtStart(ins->getValue()));
     360           0 :     add(lir, ins);
     361           0 :     assignSafepoint(lir, ins);
     362           0 : }
     363             : 
     364             : void
     365           0 : LIRGenerator::visitInitProp(MInitProp* ins)
     366             : {
     367           0 :     LInitProp* lir = new(alloc()) LInitProp(useRegisterAtStart(ins->getObject()),
     368           0 :                                             useBoxAtStart(ins->getValue()));
     369           0 :     add(lir, ins);
     370           0 :     assignSafepoint(lir, ins);
     371           0 : }
     372             : 
     373             : void
     374           0 : LIRGenerator::visitInitPropGetterSetter(MInitPropGetterSetter* ins)
     375             : {
     376             :     LInitPropGetterSetter* lir =
     377           0 :         new(alloc()) LInitPropGetterSetter(useRegisterAtStart(ins->object()),
     378           0 :                                            useRegisterAtStart(ins->value()));
     379           0 :     add(lir, ins);
     380           0 :     assignSafepoint(lir, ins);
     381           0 : }
     382             : 
     383             : void
     384           0 : LIRGenerator::visitCreateThisWithTemplate(MCreateThisWithTemplate* ins)
     385             : {
     386           0 :     LCreateThisWithTemplate* lir = new(alloc()) LCreateThisWithTemplate(temp());
     387           0 :     define(lir, ins);
     388           0 :     assignSafepoint(lir, ins);
     389           0 : }
     390             : 
     391             : void
     392           0 : LIRGenerator::visitCreateThisWithProto(MCreateThisWithProto* ins)
     393             : {
     394             :     LCreateThisWithProto* lir =
     395           0 :         new(alloc()) LCreateThisWithProto(useRegisterOrConstantAtStart(ins->getCallee()),
     396           0 :                                           useRegisterOrConstantAtStart(ins->getNewTarget()),
     397           0 :                                           useRegisterOrConstantAtStart(ins->getPrototype()));
     398           0 :     defineReturn(lir, ins);
     399           0 :     assignSafepoint(lir, ins);
     400           0 : }
     401             : 
     402             : void
     403           4 : LIRGenerator::visitCreateThis(MCreateThis* ins)
     404             : {
     405          12 :     LCreateThis* lir = new(alloc()) LCreateThis(useRegisterOrConstantAtStart(ins->getCallee()),
     406           8 :                                                 useRegisterOrConstantAtStart(ins->getNewTarget()));
     407           4 :     defineReturn(lir, ins);
     408           4 :     assignSafepoint(lir, ins);
     409           4 : }
     410             : 
     411             : void
     412           0 : LIRGenerator::visitCreateArgumentsObject(MCreateArgumentsObject* ins)
     413             : {
     414           0 :     LAllocation callObj = useFixedAtStart(ins->getCallObject(), CallTempReg0);
     415           0 :     LCreateArgumentsObject* lir = new(alloc()) LCreateArgumentsObject(callObj, tempFixed(CallTempReg1),
     416           0 :                                                                       tempFixed(CallTempReg2),
     417           0 :                                                                       tempFixed(CallTempReg3));
     418           0 :     defineReturn(lir, ins);
     419           0 :     assignSafepoint(lir, ins);
     420           0 : }
     421             : 
     422             : void
     423           0 : LIRGenerator::visitGetArgumentsObjectArg(MGetArgumentsObjectArg* ins)
     424             : {
     425           0 :     LAllocation argsObj = useRegister(ins->getArgsObject());
     426           0 :     LGetArgumentsObjectArg* lir = new(alloc()) LGetArgumentsObjectArg(argsObj, temp());
     427           0 :     defineBox(lir, ins);
     428           0 : }
     429             : 
     430             : void
     431           0 : LIRGenerator::visitSetArgumentsObjectArg(MSetArgumentsObjectArg* ins)
     432             : {
     433           0 :     LAllocation argsObj = useRegister(ins->getArgsObject());
     434             :     LSetArgumentsObjectArg* lir =
     435           0 :         new(alloc()) LSetArgumentsObjectArg(argsObj, useBox(ins->getValue()), temp());
     436           0 :     add(lir, ins);
     437           0 : }
     438             : 
     439             : void
     440           0 : LIRGenerator::visitReturnFromCtor(MReturnFromCtor* ins)
     441             : {
     442           0 :     LReturnFromCtor* lir = new(alloc()) LReturnFromCtor(useBox(ins->getValue()),
     443           0 :                                                         useRegister(ins->getObject()));
     444           0 :     define(lir, ins);
     445           0 : }
     446             : 
     447             : void
     448           0 : LIRGenerator::visitComputeThis(MComputeThis* ins)
     449             : {
     450           0 :     MOZ_ASSERT(ins->type() == MIRType::Value);
     451           0 :     MOZ_ASSERT(ins->input()->type() == MIRType::Value);
     452             : 
     453             :     // Don't use useBoxAtStart because ComputeThis has a safepoint and needs to
     454             :     // have its inputs in different registers than its return value so that
     455             :     // they aren't clobbered.
     456           0 :     LComputeThis* lir = new(alloc()) LComputeThis(useBox(ins->input()));
     457           0 :     defineBox(lir, ins);
     458           0 :     assignSafepoint(lir, ins);
     459           0 : }
     460             : 
     461             : void
     462           0 : LIRGenerator::visitArrowNewTarget(MArrowNewTarget* ins)
     463             : {
     464           0 :     MOZ_ASSERT(ins->type() == MIRType::Value);
     465           0 :     MOZ_ASSERT(ins->callee()->type() == MIRType::Object);
     466             : 
     467           0 :     LArrowNewTarget* lir = new(alloc()) LArrowNewTarget(useRegister(ins->callee()));
     468           0 :     defineBox(lir, ins);
     469           0 : }
     470             : 
     471             : bool
     472          27 : LIRGenerator::lowerCallArguments(MCall* call)
     473             : {
     474          27 :     uint32_t argc = call->numStackArgs();
     475             : 
     476             :     // Align the arguments of a call such that the callee would keep the same
     477             :     // alignment as the caller.
     478          27 :     uint32_t baseSlot = 0;
     479             :     if (JitStackValueAlignment > 1)
     480          27 :         baseSlot = AlignBytes(argc, JitStackValueAlignment);
     481             :     else
     482             :         baseSlot = argc;
     483             : 
     484             :     // Save the maximum number of argument, such that we can have one unique
     485             :     // frame size.
     486          27 :     if (baseSlot > maxargslots_)
     487           8 :         maxargslots_ = baseSlot;
     488             : 
     489          98 :     for (size_t i = 0; i < argc; i++) {
     490          71 :         MDefinition* arg = call->getArg(i);
     491          71 :         uint32_t argslot = baseSlot - i;
     492             : 
     493             :         // Values take a slow path.
     494          71 :         if (arg->type() == MIRType::Value) {
     495           9 :             LStackArgV* stack = new(alloc()) LStackArgV(argslot, useBox(arg));
     496           9 :             add(stack);
     497             :         } else {
     498             :             // Known types can move constant types and/or payloads.
     499          62 :             LStackArgT* stack = new(alloc()) LStackArgT(argslot, arg->type(), useRegisterOrConstant(arg));
     500          62 :             add(stack);
     501             :         }
     502             : 
     503          71 :         if (!alloc().ensureBallast())
     504           0 :             return false;
     505             :     }
     506          27 :     return true;
     507             : }
     508             : 
     509             : void
     510          27 : LIRGenerator::visitCall(MCall* call)
     511             : {
     512          27 :     MOZ_ASSERT(CallTempReg0 != CallTempReg1);
     513          27 :     MOZ_ASSERT(CallTempReg0 != ArgumentsRectifierReg);
     514          27 :     MOZ_ASSERT(CallTempReg1 != ArgumentsRectifierReg);
     515          27 :     MOZ_ASSERT(call->getFunction()->type() == MIRType::Object);
     516             : 
     517             :     // In case of oom, skip the rest of the allocations.
     518          27 :     if (!lowerCallArguments(call)) {
     519           0 :         abort(AbortReason::Alloc, "OOM: LIRGenerator::visitCall");
     520           0 :         return;
     521             :     }
     522             : 
     523          27 :     WrappedFunction* target = call->getSingleTarget();
     524             : 
     525             :     LInstruction* lir;
     526             : 
     527          27 :     if (call->isCallDOMNative()) {
     528             :         // Call DOM functions.
     529           0 :         MOZ_ASSERT(target && target->isNative());
     530           0 :         Register cxReg, objReg, privReg, argsReg;
     531           0 :         GetTempRegForIntArg(0, 0, &cxReg);
     532           0 :         GetTempRegForIntArg(1, 0, &objReg);
     533           0 :         GetTempRegForIntArg(2, 0, &privReg);
     534           0 :         mozilla::DebugOnly<bool> ok = GetTempRegForIntArg(3, 0, &argsReg);
     535           0 :         MOZ_ASSERT(ok, "How can we not have four temp registers?");
     536           0 :         lir = new(alloc()) LCallDOMNative(tempFixed(cxReg), tempFixed(objReg),
     537           0 :                                           tempFixed(privReg), tempFixed(argsReg));
     538          27 :     } else if (target) {
     539             :         // Call known functions.
     540          18 :         if (target->isNative()) {
     541           9 :             Register cxReg, numReg, vpReg, tmpReg;
     542           9 :             GetTempRegForIntArg(0, 0, &cxReg);
     543           9 :             GetTempRegForIntArg(1, 0, &numReg);
     544           9 :             GetTempRegForIntArg(2, 0, &vpReg);
     545             : 
     546             :             // Even though this is just a temp reg, use the same API to avoid
     547             :             // register collisions.
     548          18 :             mozilla::DebugOnly<bool> ok = GetTempRegForIntArg(3, 0, &tmpReg);
     549           9 :             MOZ_ASSERT(ok, "How can we not have four temp registers?");
     550             : 
     551          45 :             lir = new(alloc()) LCallNative(tempFixed(cxReg), tempFixed(numReg),
     552          36 :                                            tempFixed(vpReg), tempFixed(tmpReg));
     553             :         } else {
     554          36 :             lir = new(alloc()) LCallKnown(useFixedAtStart(call->getFunction(), CallTempReg0),
     555          27 :                                           tempFixed(CallTempReg2));
     556             :         }
     557             :     } else {
     558             :         // Call anything, using the most generic code.
     559          36 :         lir = new(alloc()) LCallGeneric(useFixedAtStart(call->getFunction(), CallTempReg0),
     560          18 :                                         tempFixed(ArgumentsRectifierReg),
     561          36 :                                         tempFixed(CallTempReg2));
     562             :     }
     563          27 :     defineReturn(lir, call);
     564          27 :     assignSafepoint(lir, call);
     565             : }
     566             : 
     567             : void
     568           0 : LIRGenerator::visitApplyArgs(MApplyArgs* apply)
     569             : {
     570           0 :     MOZ_ASSERT(apply->getFunction()->type() == MIRType::Object);
     571             : 
     572             :     // Assert if we cannot build a rectifier frame.
     573           0 :     MOZ_ASSERT(CallTempReg0 != ArgumentsRectifierReg);
     574           0 :     MOZ_ASSERT(CallTempReg1 != ArgumentsRectifierReg);
     575             : 
     576             :     // Assert if the return value is already erased.
     577           0 :     MOZ_ASSERT(CallTempReg2 != JSReturnReg_Type);
     578           0 :     MOZ_ASSERT(CallTempReg2 != JSReturnReg_Data);
     579             : 
     580           0 :     LApplyArgsGeneric* lir = new(alloc()) LApplyArgsGeneric(
     581           0 :         useFixedAtStart(apply->getFunction(), CallTempReg3),
     582           0 :         useFixedAtStart(apply->getArgc(), CallTempReg0),
     583           0 :         useBoxFixedAtStart(apply->getThis(), CallTempReg4, CallTempReg5),
     584           0 :         tempFixed(CallTempReg1),  // object register
     585           0 :         tempFixed(CallTempReg2)); // stack counter register
     586             : 
     587             :     // Bailout is needed in the case of possible non-JSFunction callee or too
     588             :     // many values in the arguments array.  I'm going to use NonJSFunctionCallee
     589             :     // for the code even if that is not an adequate description.
     590           0 :     assignSnapshot(lir, Bailout_NonJSFunctionCallee);
     591             : 
     592           0 :     defineReturn(lir, apply);
     593           0 :     assignSafepoint(lir, apply);
     594           0 : }
     595             : 
     596             : void
     597           0 : LIRGenerator::visitApplyArray(MApplyArray* apply)
     598             : {
     599           0 :     MOZ_ASSERT(apply->getFunction()->type() == MIRType::Object);
     600             : 
     601             :     // Assert if we cannot build a rectifier frame.
     602           0 :     MOZ_ASSERT(CallTempReg0 != ArgumentsRectifierReg);
     603           0 :     MOZ_ASSERT(CallTempReg1 != ArgumentsRectifierReg);
     604             : 
     605             :     // Assert if the return value is already erased.
     606           0 :     MOZ_ASSERT(CallTempReg2 != JSReturnReg_Type);
     607           0 :     MOZ_ASSERT(CallTempReg2 != JSReturnReg_Data);
     608             : 
     609           0 :     LApplyArrayGeneric* lir = new(alloc()) LApplyArrayGeneric(
     610           0 :         useFixedAtStart(apply->getFunction(), CallTempReg3),
     611           0 :         useFixedAtStart(apply->getElements(), CallTempReg0),
     612           0 :         useBoxFixedAtStart(apply->getThis(), CallTempReg4, CallTempReg5),
     613           0 :         tempFixed(CallTempReg1),  // object register
     614           0 :         tempFixed(CallTempReg2)); // stack counter register
     615             : 
     616             :     // Bailout is needed in the case of possible non-JSFunction callee,
     617             :     // too many values in the array, or empty space at the end of the
     618             :     // array.  I'm going to use NonJSFunctionCallee for the code even
     619             :     // if that is not an adequate description.
     620           0 :     assignSnapshot(lir, Bailout_NonJSFunctionCallee);
     621             : 
     622           0 :     defineReturn(lir, apply);
     623           0 :     assignSafepoint(lir, apply);
     624           0 : }
     625             : 
     626             : void
     627          18 : LIRGenerator::visitBail(MBail* bail)
     628             : {
     629          18 :     LBail* lir = new(alloc()) LBail();
     630          18 :     assignSnapshot(lir, bail->bailoutKind());
     631          18 :     add(lir, bail);
     632          18 : }
     633             : 
     634             : void
     635          18 : LIRGenerator::visitUnreachable(MUnreachable* unreachable)
     636             : {
     637          18 :     LUnreachable* lir = new(alloc()) LUnreachable();
     638          18 :     add(lir, unreachable);
     639          18 : }
     640             : 
     641             : void
     642           0 : LIRGenerator::visitEncodeSnapshot(MEncodeSnapshot* mir)
     643             : {
     644           0 :     LEncodeSnapshot* lir = new(alloc()) LEncodeSnapshot();
     645           0 :     assignSnapshot(lir, Bailout_Inevitable);
     646           0 :     add(lir, mir);
     647           0 : }
     648             : 
     649             : void
     650           0 : LIRGenerator::visitAssertFloat32(MAssertFloat32* assertion)
     651             : {
     652           0 :     MIRType type = assertion->input()->type();
     653           0 :     DebugOnly<bool> checkIsFloat32 = assertion->mustBeFloat32();
     654             : 
     655           0 :     if (type != MIRType::Value && !JitOptions.eagerCompilation) {
     656           0 :         MOZ_ASSERT_IF(checkIsFloat32, type == MIRType::Float32);
     657           0 :         MOZ_ASSERT_IF(!checkIsFloat32, type != MIRType::Float32);
     658             :     }
     659           0 : }
     660             : 
     661             : void
     662           0 : LIRGenerator::visitAssertRecoveredOnBailout(MAssertRecoveredOnBailout* assertion)
     663             : {
     664           0 :     MOZ_CRASH("AssertRecoveredOnBailout nodes are always recovered on bailouts.");
     665             : }
     666             : 
     667             : void
     668           0 : LIRGenerator::visitGetDynamicName(MGetDynamicName* ins)
     669             : {
     670           0 :     MDefinition* envChain = ins->getEnvironmentChain();
     671           0 :     MOZ_ASSERT(envChain->type() == MIRType::Object);
     672             : 
     673           0 :     MDefinition* name = ins->getName();
     674           0 :     MOZ_ASSERT(name->type() == MIRType::String);
     675             : 
     676           0 :     LGetDynamicName* lir = new(alloc()) LGetDynamicName(useFixedAtStart(envChain, CallTempReg0),
     677           0 :                                                         useFixedAtStart(name, CallTempReg1),
     678           0 :                                                         tempFixed(CallTempReg2),
     679           0 :                                                         tempFixed(CallTempReg3),
     680           0 :                                                         tempFixed(CallTempReg4));
     681             : 
     682           0 :     assignSnapshot(lir, Bailout_DynamicNameNotFound);
     683           0 :     defineReturn(lir, ins);
     684           0 : }
     685             : 
     686             : void
     687           0 : LIRGenerator::visitCallDirectEval(MCallDirectEval* ins)
     688             : {
     689           0 :     MDefinition* envChain = ins->getEnvironmentChain();
     690           0 :     MOZ_ASSERT(envChain->type() == MIRType::Object);
     691             : 
     692           0 :     MDefinition* string = ins->getString();
     693           0 :     MOZ_ASSERT(string->type() == MIRType::String);
     694             : 
     695           0 :     MDefinition* newTargetValue = ins->getNewTargetValue();
     696             : 
     697           0 :     LInstruction* lir = new(alloc()) LCallDirectEval(useRegisterAtStart(envChain),
     698           0 :                                                      useRegisterAtStart(string),
     699           0 :                                                      useBoxAtStart(newTargetValue));
     700           0 :     defineReturn(lir, ins);
     701           0 :     assignSafepoint(lir, ins);
     702           0 : }
     703             : 
     704             : static JSOp
     705          45 : ReorderComparison(JSOp op, MDefinition** lhsp, MDefinition** rhsp)
     706             : {
     707          45 :     MDefinition* lhs = *lhsp;
     708          45 :     MDefinition* rhs = *rhsp;
     709             : 
     710          45 :     if (lhs->maybeConstantValue()) {
     711           1 :         *rhsp = lhs;
     712           1 :         *lhsp = rhs;
     713           1 :         return ReverseCompareOp(op);
     714             :     }
     715          44 :     return op;
     716             : }
     717             : 
     718             : void
     719         108 : LIRGenerator::visitTest(MTest* test)
     720             : {
     721         108 :     MDefinition* opd = test->getOperand(0);
     722         108 :     MBasicBlock* ifTrue = test->ifTrue();
     723         108 :     MBasicBlock* ifFalse = test->ifFalse();
     724             : 
     725             :     // String is converted to length of string in the type analysis phase (see
     726             :     // TestPolicy).
     727         108 :     MOZ_ASSERT(opd->type() != MIRType::String);
     728             : 
     729             :     // Testing a constant.
     730         108 :     if (MConstant* constant = opd->maybeConstantValue()) {
     731             :         bool b;
     732           0 :         if (constant->valueToBoolean(&b)) {
     733           0 :             add(new(alloc()) LGoto(b ? ifTrue : ifFalse));
     734           0 :             return;
     735             :         }
     736             :     }
     737             : 
     738         108 :     if (opd->type() == MIRType::Value) {
     739          30 :         LDefinition temp0, temp1;
     740          30 :         if (test->operandMightEmulateUndefined()) {
     741          10 :             temp0 = temp();
     742          10 :             temp1 = temp();
     743             :         } else {
     744          20 :             temp0 = LDefinition::BogusTemp();
     745          20 :             temp1 = LDefinition::BogusTemp();
     746             :         }
     747             :         LTestVAndBranch* lir =
     748          30 :             new(alloc()) LTestVAndBranch(ifTrue, ifFalse, useBox(opd), tempDouble(), temp0, temp1);
     749          30 :         add(lir, test);
     750          30 :         return;
     751             :     }
     752             : 
     753          78 :     if (opd->type() == MIRType::ObjectOrNull) {
     754           0 :         LDefinition temp0 = test->operandMightEmulateUndefined() ? temp() : LDefinition::BogusTemp();
     755           0 :         add(new(alloc()) LTestOAndBranch(useRegister(opd), ifTrue, ifFalse, temp0), test);
     756           0 :         return;
     757             :     }
     758             : 
     759             :     // Objects are truthy, except if it might emulate undefined.
     760          78 :     if (opd->type() == MIRType::Object) {
     761           0 :         if (test->operandMightEmulateUndefined())
     762           0 :             add(new(alloc()) LTestOAndBranch(useRegister(opd), ifTrue, ifFalse, temp()), test);
     763             :         else
     764           0 :             add(new(alloc()) LGoto(ifTrue));
     765           0 :         return;
     766             :     }
     767             : 
     768             :     // These must be explicitly sniffed out since they are constants and have
     769             :     // no payload.
     770          78 :     if (opd->type() == MIRType::Undefined || opd->type() == MIRType::Null) {
     771           0 :         add(new(alloc()) LGoto(ifFalse));
     772           0 :         return;
     773             :     }
     774             : 
     775             :     // All symbols are truthy.
     776          78 :     if (opd->type() == MIRType::Symbol) {
     777           0 :         add(new(alloc()) LGoto(ifTrue));
     778           0 :         return;
     779             :     }
     780             : 
     781          78 :     if (opd->isCompare() && opd->isEmittedAtUses()) {
     782             :         // Emit LBitAndBranch for cases like |if ((x & y) === 0)|.
     783          23 :         MCompare* comp = opd->toCompare();
     784          46 :         if ((comp->isInt32Comparison() ||
     785          23 :              comp->compareType() == MCompare::Compare_UInt32) &&
     786          37 :             comp->getOperand(1)->isConstant() &&
     787          15 :             comp->getOperand(1)->toConstant()->isInt32(0) &&
     788          24 :             comp->getOperand(0)->isBitAnd() &&
     789           0 :             comp->getOperand(0)->isEmittedAtUses())
     790             :         {
     791           0 :             MDefinition* bitAnd = opd->getOperand(0);
     792           0 :             MDefinition* lhs = bitAnd->getOperand(0);
     793           0 :             MDefinition* rhs = bitAnd->getOperand(1);
     794             : 
     795           0 :             Assembler::Condition cond = JSOpToCondition(comp->compareType(),
     796           0 :                                                         comp->jsop());
     797             : 
     798           0 :             if (lhs->type() == MIRType::Int32 && rhs->type() == MIRType::Int32 &&
     799           0 :                 (cond == Assembler::Equal || cond == Assembler::NotEqual))
     800             :             {
     801           0 :                 ReorderCommutative(&lhs, &rhs, test);
     802           0 :                 if (cond == Assembler::Equal)
     803           0 :                     cond = Assembler::Zero;
     804           0 :                 else if(cond == Assembler::NotEqual)
     805           0 :                     cond = Assembler::NonZero;
     806             :                 else
     807           0 :                     MOZ_ASSERT_UNREACHABLE("inequality operators cannot be folded");
     808           0 :                 lowerForBitAndAndBranch(new(alloc()) LBitAndAndBranch(ifTrue, ifFalse, cond),
     809           0 :                                         test, lhs, rhs);
     810           0 :                 return;
     811             :             }
     812             :         }
     813             :     }
     814             : 
     815             :     // Check if the operand for this test is a compare operation. If it is, we want
     816             :     // to emit an LCompare*AndBranch rather than an LTest*AndBranch, to fuse the
     817             :     // compare and jump instructions.
     818          78 :     if (opd->isCompare() && opd->isEmittedAtUses()) {
     819          23 :         MCompare* comp = opd->toCompare();
     820          23 :         MDefinition* left = comp->lhs();
     821          23 :         MDefinition* right = comp->rhs();
     822             : 
     823             :         // Try to fold the comparison so that we don't have to handle all cases.
     824             :         bool result;
     825          23 :         if (comp->tryFold(&result)) {
     826           0 :             add(new(alloc()) LGoto(result ? ifTrue : ifFalse));
     827           0 :             return;
     828             :         }
     829             : 
     830             :         // Emit LCompare*AndBranch.
     831             : 
     832             :         // Compare and branch null/undefined.
     833             :         // The second operand has known null/undefined type,
     834             :         // so just test the first operand.
     835          46 :         if (comp->compareType() == MCompare::Compare_Null ||
     836          23 :             comp->compareType() == MCompare::Compare_Undefined)
     837             :         {
     838           0 :             if (left->type() == MIRType::Object || left->type() == MIRType::ObjectOrNull) {
     839           0 :                 MOZ_ASSERT(left->type() == MIRType::ObjectOrNull ||
     840             :                            comp->operandMightEmulateUndefined(),
     841             :                            "MCompare::tryFold should handle the never-emulates-undefined case");
     842             : 
     843             :                 LDefinition tmp =
     844           0 :                     comp->operandMightEmulateUndefined() ? temp() : LDefinition::BogusTemp();
     845             :                 LIsNullOrLikeUndefinedAndBranchT* lir =
     846           0 :                     new(alloc()) LIsNullOrLikeUndefinedAndBranchT(comp, useRegister(left),
     847           0 :                                                                   ifTrue, ifFalse, tmp);
     848           0 :                 add(lir, test);
     849           0 :                 return;
     850             :             }
     851             : 
     852           0 :             LDefinition tmp, tmpToUnbox;
     853           0 :             if (comp->operandMightEmulateUndefined()) {
     854           0 :                 tmp = temp();
     855           0 :                 tmpToUnbox = tempToUnbox();
     856             :             } else {
     857           0 :                 tmp = LDefinition::BogusTemp();
     858           0 :                 tmpToUnbox = LDefinition::BogusTemp();
     859             :             }
     860             : 
     861             :             LIsNullOrLikeUndefinedAndBranchV* lir =
     862           0 :                 new(alloc()) LIsNullOrLikeUndefinedAndBranchV(comp, ifTrue, ifFalse, useBox(left),
     863           0 :                                                               tmp, tmpToUnbox);
     864           0 :             add(lir, test);
     865           0 :             return;
     866             :         }
     867             : 
     868             :         // Compare and branch booleans.
     869          23 :         if (comp->compareType() == MCompare::Compare_Boolean) {
     870           0 :             MOZ_ASSERT(left->type() == MIRType::Value);
     871           0 :             MOZ_ASSERT(right->type() == MIRType::Boolean);
     872             : 
     873           0 :             LCompareBAndBranch* lir = new(alloc()) LCompareBAndBranch(comp, useBox(left),
     874           0 :                                                                       useRegisterOrConstant(right),
     875           0 :                                                                       ifTrue, ifFalse);
     876           0 :             add(lir, test);
     877           0 :             return;
     878             :         }
     879             : 
     880             :         // Compare and branch Int32, Symbol or Object pointers.
     881          46 :         if (comp->isInt32Comparison() ||
     882           0 :             comp->compareType() == MCompare::Compare_UInt32 ||
     883          23 :             comp->compareType() == MCompare::Compare_Object ||
     884           0 :             comp->compareType() == MCompare::Compare_Symbol)
     885             :         {
     886          23 :             JSOp op = ReorderComparison(comp->jsop(), &left, &right);
     887          23 :             LAllocation lhs = useRegister(left);
     888          23 :             LAllocation rhs;
     889          23 :             if (comp->isInt32Comparison() || comp->compareType() == MCompare::Compare_UInt32)
     890          23 :                 rhs = useAnyOrConstant(right);
     891             :             else
     892           0 :                 rhs = useRegister(right);
     893          23 :             LCompareAndBranch* lir = new(alloc()) LCompareAndBranch(comp, op, lhs, rhs,
     894          23 :                                                                     ifTrue, ifFalse);
     895          23 :             add(lir, test);
     896          23 :             return;
     897             :         }
     898             : 
     899             :         // Compare and branch Int64.
     900           0 :         if (comp->compareType() == MCompare::Compare_Int64 ||
     901           0 :             comp->compareType() == MCompare::Compare_UInt64)
     902             :         {
     903           0 :             JSOp op = ReorderComparison(comp->jsop(), &left, &right);
     904           0 :             LCompareI64AndBranch* lir = new(alloc()) LCompareI64AndBranch(comp, op,
     905           0 :                                                                           useInt64Register(left),
     906           0 :                                                                           useInt64OrConstant(right),
     907           0 :                                                                           ifTrue, ifFalse);
     908           0 :             add(lir, test);
     909           0 :             return;
     910             :         }
     911             : 
     912             :         // Compare and branch doubles.
     913           0 :         if (comp->isDoubleComparison()) {
     914           0 :             LAllocation lhs = useRegister(left);
     915           0 :             LAllocation rhs = useRegister(right);
     916           0 :             LCompareDAndBranch* lir = new(alloc()) LCompareDAndBranch(comp, lhs, rhs,
     917           0 :                                                                       ifTrue, ifFalse);
     918           0 :             add(lir, test);
     919           0 :             return;
     920             :         }
     921             : 
     922             :         // Compare and branch floats.
     923           0 :         if (comp->isFloat32Comparison()) {
     924           0 :             LAllocation lhs = useRegister(left);
     925           0 :             LAllocation rhs = useRegister(right);
     926           0 :             LCompareFAndBranch* lir = new(alloc()) LCompareFAndBranch(comp, lhs, rhs,
     927           0 :                                                                       ifTrue, ifFalse);
     928           0 :             add(lir, test);
     929           0 :             return;
     930             :         }
     931             : 
     932             :         // Compare values.
     933           0 :         if (comp->compareType() == MCompare::Compare_Bitwise) {
     934             :             LCompareBitwiseAndBranch* lir =
     935           0 :                 new(alloc()) LCompareBitwiseAndBranch(comp, ifTrue, ifFalse,
     936           0 :                                                       useBoxAtStart(left),
     937           0 :                                                       useBoxAtStart(right));
     938           0 :             add(lir, test);
     939           0 :             return;
     940             :         }
     941             :     }
     942             : 
     943             :     // Check if the operand for this test is a bitand operation. If it is, we want
     944             :     // to emit an LBitAndAndBranch rather than an LTest*AndBranch.
     945          55 :     if (opd->isBitAnd() && opd->isEmittedAtUses()) {
     946           0 :         MDefinition* lhs = opd->getOperand(0);
     947           0 :         MDefinition* rhs = opd->getOperand(1);
     948           0 :         if (lhs->type() == MIRType::Int32 && rhs->type() == MIRType::Int32) {
     949           0 :             ReorderCommutative(&lhs, &rhs, test);
     950           0 :             lowerForBitAndAndBranch(new(alloc()) LBitAndAndBranch(ifTrue, ifFalse), test, lhs, rhs);
     951           0 :             return;
     952             :         }
     953             :     }
     954             : 
     955          55 :     if (opd->isIsObject() && opd->isEmittedAtUses()) {
     956           0 :         MDefinition* input = opd->toIsObject()->input();
     957           0 :         MOZ_ASSERT(input->type() == MIRType::Value);
     958             : 
     959           0 :         LIsObjectAndBranch* lir = new(alloc()) LIsObjectAndBranch(ifTrue, ifFalse,
     960           0 :                                                                   useBoxAtStart(input));
     961           0 :         add(lir, test);
     962           0 :         return;
     963             :     }
     964             : 
     965          55 :     if (opd->isIsNoIter()) {
     966           0 :         MOZ_ASSERT(opd->isEmittedAtUses());
     967             : 
     968           0 :         MDefinition* input = opd->toIsNoIter()->input();
     969           0 :         MOZ_ASSERT(input->type() == MIRType::Value);
     970             : 
     971           0 :         LIsNoIterAndBranch* lir = new(alloc()) LIsNoIterAndBranch(ifTrue, ifFalse,
     972           0 :                                                                   useBox(input));
     973           0 :         add(lir, test);
     974           0 :         return;
     975             :     }
     976             : 
     977          55 :     switch (opd->type()) {
     978             :       case MIRType::Double:
     979           0 :         add(new(alloc()) LTestDAndBranch(useRegister(opd), ifTrue, ifFalse));
     980           0 :         break;
     981             :       case MIRType::Float32:
     982           0 :         add(new(alloc()) LTestFAndBranch(useRegister(opd), ifTrue, ifFalse));
     983           0 :         break;
     984             :       case MIRType::Int32:
     985             :       case MIRType::Boolean:
     986          55 :         add(new(alloc()) LTestIAndBranch(useRegister(opd), ifTrue, ifFalse));
     987          55 :         break;
     988             :       case MIRType::Int64:
     989           0 :         add(new(alloc()) LTestI64AndBranch(useInt64Register(opd), ifTrue, ifFalse));
     990           0 :         break;
     991             :       default:
     992           0 :         MOZ_CRASH("Bad type");
     993             :     }
     994             : }
     995             : 
     996             : void
     997           1 : LIRGenerator::visitGotoWithFake(MGotoWithFake* gotoWithFake)
     998             : {
     999           1 :     add(new(alloc()) LGoto(gotoWithFake->target()));
    1000           1 : }
    1001             : 
    1002             : void
    1003           3 : LIRGenerator::visitFunctionDispatch(MFunctionDispatch* ins)
    1004             : {
    1005           3 :     LFunctionDispatch* lir = new(alloc()) LFunctionDispatch(useRegister(ins->input()));
    1006           3 :     add(lir, ins);
    1007           3 : }
    1008             : 
    1009             : void
    1010           0 : LIRGenerator::visitObjectGroupDispatch(MObjectGroupDispatch* ins)
    1011             : {
    1012           0 :     LObjectGroupDispatch* lir = new(alloc()) LObjectGroupDispatch(useRegister(ins->input()), temp());
    1013           0 :     add(lir, ins);
    1014           0 : }
    1015             : 
    1016             : static inline bool
    1017          45 : CanEmitCompareAtUses(MInstruction* ins)
    1018             : {
    1019          45 :     if (!ins->canEmitAtUses())
    1020           0 :         return false;
    1021             : 
    1022          45 :     bool foundTest = false;
    1023          68 :     for (MUseIterator iter(ins->usesBegin()); iter != ins->usesEnd(); iter++) {
    1024          45 :         MNode* node = iter->consumer();
    1025          45 :         if (!node->isDefinition())
    1026          22 :             return false;
    1027          45 :         if (!node->toDefinition()->isTest())
    1028          22 :             return false;
    1029          23 :         if (foundTest)
    1030           0 :             return false;
    1031          23 :         foundTest = true;
    1032             :     }
    1033          23 :     return true;
    1034             : }
    1035             : 
    1036             : void
    1037          45 : LIRGenerator::visitCompare(MCompare* comp)
    1038             : {
    1039          45 :     MDefinition* left = comp->lhs();
    1040          45 :     MDefinition* right = comp->rhs();
    1041             : 
    1042             :     // Try to fold the comparison so that we don't have to handle all cases.
    1043             :     bool result;
    1044          45 :     if (comp->tryFold(&result)) {
    1045           0 :         define(new(alloc()) LInteger(result), comp);
    1046           0 :         return;
    1047             :     }
    1048             : 
    1049             :     // Move below the emitAtUses call if we ever implement
    1050             :     // LCompareSAndBranch. Doing this now wouldn't be wrong, but doesn't
    1051             :     // make sense and avoids confusion.
    1052          45 :     if (comp->compareType() == MCompare::Compare_String) {
    1053           0 :         LCompareS* lir = new(alloc()) LCompareS(useRegister(left), useRegister(right));
    1054           0 :         define(lir, comp);
    1055           0 :         assignSafepoint(lir, comp);
    1056           0 :         return;
    1057             :     }
    1058             : 
    1059             :     // Strict compare between value and string
    1060          45 :     if (comp->compareType() == MCompare::Compare_StrictString) {
    1061           0 :         MOZ_ASSERT(left->type() == MIRType::Value);
    1062           0 :         MOZ_ASSERT(right->type() == MIRType::String);
    1063             : 
    1064           0 :         LCompareStrictS* lir = new(alloc()) LCompareStrictS(useBox(left), useRegister(right),
    1065           0 :                                                             tempToUnbox());
    1066           0 :         define(lir, comp);
    1067           0 :         assignSafepoint(lir, comp);
    1068           0 :         return;
    1069             :     }
    1070             : 
    1071             :     // Unknown/unspecialized compare use a VM call.
    1072          45 :     if (comp->compareType() == MCompare::Compare_Unknown) {
    1073           0 :         LCompareVM* lir = new(alloc()) LCompareVM(useBoxAtStart(left), useBoxAtStart(right));
    1074           0 :         defineReturn(lir, comp);
    1075           0 :         assignSafepoint(lir, comp);
    1076           0 :         return;
    1077             :     }
    1078             : 
    1079             :     // Sniff out if the output of this compare is used only for a branching.
    1080             :     // If it is, then we will emit an LCompare*AndBranch instruction in place
    1081             :     // of this compare and any test that uses this compare. Thus, we can
    1082             :     // ignore this Compare.
    1083          45 :     if (CanEmitCompareAtUses(comp)) {
    1084          23 :         emitAtUses(comp);
    1085          23 :         return;
    1086             :     }
    1087             : 
    1088             :     // Compare Null and Undefined.
    1089          44 :     if (comp->compareType() == MCompare::Compare_Null ||
    1090          22 :         comp->compareType() == MCompare::Compare_Undefined)
    1091             :     {
    1092           0 :         if (left->type() == MIRType::Object || left->type() == MIRType::ObjectOrNull) {
    1093           0 :             MOZ_ASSERT(left->type() == MIRType::ObjectOrNull ||
    1094             :                        comp->operandMightEmulateUndefined(),
    1095             :                        "MCompare::tryFold should have folded this away");
    1096             : 
    1097           0 :             define(new(alloc()) LIsNullOrLikeUndefinedT(useRegister(left)), comp);
    1098           0 :             return;
    1099             :         }
    1100             : 
    1101           0 :         LDefinition tmp, tmpToUnbox;
    1102           0 :         if (comp->operandMightEmulateUndefined()) {
    1103           0 :             tmp = temp();
    1104           0 :             tmpToUnbox = tempToUnbox();
    1105             :         } else {
    1106           0 :             tmp = LDefinition::BogusTemp();
    1107           0 :             tmpToUnbox = LDefinition::BogusTemp();
    1108             :         }
    1109             : 
    1110           0 :         LIsNullOrLikeUndefinedV* lir = new(alloc()) LIsNullOrLikeUndefinedV(useBox(left),
    1111           0 :                                                                             tmp, tmpToUnbox);
    1112           0 :         define(lir, comp);
    1113           0 :         return;
    1114             :     }
    1115             : 
    1116             :     // Compare booleans.
    1117          22 :     if (comp->compareType() == MCompare::Compare_Boolean) {
    1118           0 :         MOZ_ASSERT(left->type() == MIRType::Value);
    1119           0 :         MOZ_ASSERT(right->type() == MIRType::Boolean);
    1120             : 
    1121           0 :         LCompareB* lir = new(alloc()) LCompareB(useBox(left), useRegisterOrConstant(right));
    1122           0 :         define(lir, comp);
    1123           0 :         return;
    1124             :     }
    1125             : 
    1126             :     // Compare Int32, Symbol or Object pointers.
    1127          44 :     if (comp->isInt32Comparison() ||
    1128           0 :         comp->compareType() == MCompare::Compare_UInt32 ||
    1129          22 :         comp->compareType() == MCompare::Compare_Object ||
    1130           0 :         comp->compareType() == MCompare::Compare_Symbol)
    1131             :     {
    1132          22 :         JSOp op = ReorderComparison(comp->jsop(), &left, &right);
    1133          22 :         LAllocation lhs = useRegister(left);
    1134          22 :         LAllocation rhs;
    1135          22 :         if (comp->isInt32Comparison() ||
    1136           0 :             comp->compareType() == MCompare::Compare_UInt32)
    1137             :         {
    1138          22 :             rhs = useAnyOrConstant(right);
    1139             :         } else {
    1140           0 :             rhs = useRegister(right);
    1141             :         }
    1142          22 :         define(new(alloc()) LCompare(op, lhs, rhs), comp);
    1143          22 :         return;
    1144             :     }
    1145             : 
    1146             :     // Compare Int64.
    1147           0 :     if (comp->compareType() == MCompare::Compare_Int64 ||
    1148           0 :         comp->compareType() == MCompare::Compare_UInt64)
    1149             :     {
    1150           0 :         JSOp op = ReorderComparison(comp->jsop(), &left, &right);
    1151           0 :         define(new(alloc()) LCompareI64(op, useInt64Register(left), useInt64OrConstant(right)),
    1152           0 :                comp);
    1153           0 :         return;
    1154             :     }
    1155             : 
    1156             :     // Compare doubles.
    1157           0 :     if (comp->isDoubleComparison()) {
    1158           0 :         define(new(alloc()) LCompareD(useRegister(left), useRegister(right)), comp);
    1159           0 :         return;
    1160             :     }
    1161             : 
    1162             :     // Compare float32.
    1163           0 :     if (comp->isFloat32Comparison()) {
    1164           0 :         define(new(alloc()) LCompareF(useRegister(left), useRegister(right)), comp);
    1165           0 :         return;
    1166             :     }
    1167             : 
    1168             :     // Compare values.
    1169           0 :     if (comp->compareType() == MCompare::Compare_Bitwise) {
    1170           0 :         LCompareBitwise* lir = new(alloc()) LCompareBitwise(useBoxAtStart(left),
    1171           0 :                                                             useBoxAtStart(right));
    1172           0 :         define(lir, comp);
    1173           0 :         return;
    1174             :     }
    1175             : 
    1176           0 :     MOZ_CRASH("Unrecognized compare type.");
    1177             : }
    1178             : 
    1179             : void
    1180           0 : LIRGenerator::lowerBitOp(JSOp op, MInstruction* ins)
    1181             : {
    1182           0 :     MDefinition* lhs = ins->getOperand(0);
    1183           0 :     MDefinition* rhs = ins->getOperand(1);
    1184             : 
    1185           0 :     if (lhs->type() == MIRType::Int32) {
    1186           0 :         MOZ_ASSERT(rhs->type() == MIRType::Int32);
    1187           0 :         ReorderCommutative(&lhs, &rhs, ins);
    1188           0 :         lowerForALU(new(alloc()) LBitOpI(op), ins, lhs, rhs);
    1189           0 :         return;
    1190             :     }
    1191             : 
    1192           0 :     if (lhs->type() == MIRType::Int64) {
    1193           0 :         MOZ_ASSERT(rhs->type() == MIRType::Int64);
    1194           0 :         ReorderCommutative(&lhs, &rhs, ins);
    1195           0 :         lowerForALUInt64(new(alloc()) LBitOpI64(op), ins, lhs, rhs);
    1196           0 :         return;
    1197             :     }
    1198             : 
    1199           0 :     LBitOpV* lir = new(alloc()) LBitOpV(op, useBoxAtStart(lhs), useBoxAtStart(rhs));
    1200           0 :     defineReturn(lir, ins);
    1201           0 :     assignSafepoint(lir, ins);
    1202             : }
    1203             : 
    1204             : void
    1205           0 : LIRGenerator::visitTypeOf(MTypeOf* ins)
    1206             : {
    1207           0 :     MDefinition* opd = ins->input();
    1208           0 :     MOZ_ASSERT(opd->type() == MIRType::Value);
    1209             : 
    1210           0 :     LTypeOfV* lir = new(alloc()) LTypeOfV(useBox(opd), tempToUnbox());
    1211           0 :     define(lir, ins);
    1212           0 : }
    1213             : 
    1214             : void
    1215           0 : LIRGenerator::visitToAsync(MToAsync* ins)
    1216             : {
    1217           0 :     LToAsync* lir = new(alloc()) LToAsync(useRegisterAtStart(ins->input()));
    1218           0 :     defineReturn(lir, ins);
    1219           0 :     assignSafepoint(lir, ins);
    1220           0 : }
    1221             : 
    1222             : void
    1223           0 : LIRGenerator::visitToAsyncGen(MToAsyncGen* ins)
    1224             : {
    1225           0 :     LToAsyncGen* lir = new(alloc()) LToAsyncGen(useRegisterAtStart(ins->input()));
    1226           0 :     defineReturn(lir, ins);
    1227           0 :     assignSafepoint(lir, ins);
    1228           0 : }
    1229             : 
    1230             : void
    1231           0 : LIRGenerator::visitToAsyncIter(MToAsyncIter* ins)
    1232             : {
    1233           0 :     LToAsyncIter* lir = new(alloc()) LToAsyncIter(useRegisterAtStart(ins->input()));
    1234           0 :     defineReturn(lir, ins);
    1235           0 :     assignSafepoint(lir, ins);
    1236           0 : }
    1237             : 
    1238             : void
    1239           0 : LIRGenerator::visitToId(MToId* ins)
    1240             : {
    1241           0 :     LToIdV* lir = new(alloc()) LToIdV(useBox(ins->input()), tempDouble());
    1242           0 :     defineBox(lir, ins);
    1243           0 :     assignSafepoint(lir, ins);
    1244           0 : }
    1245             : 
    1246             : void
    1247           0 : LIRGenerator::visitBitNot(MBitNot* ins)
    1248             : {
    1249           0 :     MDefinition* input = ins->getOperand(0);
    1250             : 
    1251           0 :     if (input->type() == MIRType::Int32) {
    1252           0 :         lowerForALU(new(alloc()) LBitNotI(), ins, input);
    1253           0 :         return;
    1254             :     }
    1255             : 
    1256           0 :     LBitNotV* lir = new(alloc()) LBitNotV(useBoxAtStart(input));
    1257           0 :     defineReturn(lir, ins);
    1258           0 :     assignSafepoint(lir, ins);
    1259             : }
    1260             : 
    1261             : static bool
    1262           0 : CanEmitBitAndAtUses(MInstruction* ins)
    1263             : {
    1264           0 :     if (!ins->canEmitAtUses())
    1265           0 :         return false;
    1266             : 
    1267           0 :     if (ins->getOperand(0)->type() != MIRType::Int32 || ins->getOperand(1)->type() != MIRType::Int32)
    1268           0 :         return false;
    1269             : 
    1270           0 :     MUseIterator iter(ins->usesBegin());
    1271           0 :     if (iter == ins->usesEnd())
    1272           0 :         return false;
    1273             : 
    1274           0 :     MNode* node = iter->consumer();
    1275           0 :     if (!node->isDefinition() || !node->toDefinition()->isInstruction())
    1276           0 :         return false;
    1277             : 
    1278           0 :     MInstruction* use = node->toDefinition()->toInstruction();
    1279           0 :     if (!use->isTest() && !(use->isCompare() && CanEmitCompareAtUses(use)))
    1280           0 :         return false;
    1281             : 
    1282           0 :     iter++;
    1283           0 :     return iter == ins->usesEnd();
    1284             : }
    1285             : 
    1286             : void
    1287           0 : LIRGenerator::visitBitAnd(MBitAnd* ins)
    1288             : {
    1289             :     // Sniff out if the output of this bitand is used only for a branching.
    1290             :     // If it is, then we will emit an LBitAndAndBranch instruction in place
    1291             :     // of this bitand and any test that uses this bitand. Thus, we can
    1292             :     // ignore this BitAnd.
    1293           0 :     if (CanEmitBitAndAtUses(ins))
    1294           0 :         emitAtUses(ins);
    1295             :     else
    1296           0 :         lowerBitOp(JSOP_BITAND, ins);
    1297           0 : }
    1298             : 
    1299             : void
    1300           0 : LIRGenerator::visitBitOr(MBitOr* ins)
    1301             : {
    1302           0 :     lowerBitOp(JSOP_BITOR, ins);
    1303           0 : }
    1304             : 
    1305             : void
    1306           0 : LIRGenerator::visitBitXor(MBitXor* ins)
    1307             : {
    1308           0 :     lowerBitOp(JSOP_BITXOR, ins);
    1309           0 : }
    1310             : 
    1311             : void
    1312           0 : LIRGenerator::lowerShiftOp(JSOp op, MShiftInstruction* ins)
    1313             : {
    1314           0 :     MDefinition* lhs = ins->getOperand(0);
    1315           0 :     MDefinition* rhs = ins->getOperand(1);
    1316             : 
    1317           0 :     if (lhs->type() == MIRType::Int32) {
    1318           0 :         MOZ_ASSERT(rhs->type() == MIRType::Int32);
    1319             : 
    1320           0 :         if (ins->type() == MIRType::Double) {
    1321           0 :             MOZ_ASSERT(op == JSOP_URSH);
    1322           0 :             lowerUrshD(ins->toUrsh());
    1323           0 :             return;
    1324             :         }
    1325             : 
    1326           0 :         LShiftI* lir = new(alloc()) LShiftI(op);
    1327           0 :         if (op == JSOP_URSH) {
    1328           0 :             if (ins->toUrsh()->fallible())
    1329           0 :                 assignSnapshot(lir, Bailout_OverflowInvalidate);
    1330             :         }
    1331           0 :         lowerForShift(lir, ins, lhs, rhs);
    1332           0 :         return;
    1333             :     }
    1334             : 
    1335           0 :     if (lhs->type() == MIRType::Int64) {
    1336           0 :         MOZ_ASSERT(rhs->type() == MIRType::Int64);
    1337           0 :         lowerForShiftInt64(new(alloc()) LShiftI64(op), ins, lhs, rhs);
    1338           0 :         return;
    1339             :     }
    1340             : 
    1341           0 :     MOZ_ASSERT(ins->specialization() == MIRType::None);
    1342             : 
    1343           0 :     if (op == JSOP_URSH) {
    1344             :         // Result is either int32 or double so we have to use BinaryV.
    1345           0 :         lowerBinaryV(JSOP_URSH, ins);
    1346           0 :         return;
    1347             :     }
    1348             : 
    1349           0 :     LBitOpV* lir = new(alloc()) LBitOpV(op, useBoxAtStart(lhs), useBoxAtStart(rhs));
    1350           0 :     defineReturn(lir, ins);
    1351           0 :     assignSafepoint(lir, ins);
    1352             : }
    1353             : 
    1354             : void
    1355           0 : LIRGenerator::visitLsh(MLsh* ins)
    1356             : {
    1357           0 :     lowerShiftOp(JSOP_LSH, ins);
    1358           0 : }
    1359             : 
    1360             : void
    1361           0 : LIRGenerator::visitRsh(MRsh* ins)
    1362             : {
    1363           0 :     lowerShiftOp(JSOP_RSH, ins);
    1364           0 : }
    1365             : 
    1366             : void
    1367           0 : LIRGenerator::visitUrsh(MUrsh* ins)
    1368             : {
    1369           0 :     lowerShiftOp(JSOP_URSH, ins);
    1370           0 : }
    1371             : 
    1372             : void
    1373           0 : LIRGenerator::visitSignExtend(MSignExtend* ins)
    1374             : {
    1375             :     LInstructionHelper<1, 1, 0>* lir;
    1376             : 
    1377           0 :     if (ins->mode() == MSignExtend::Byte)
    1378           0 :         lir = new(alloc()) LSignExtend(useByteOpRegisterAtStart(ins->input()), ins->mode());
    1379             :     else
    1380           0 :         lir = new(alloc()) LSignExtend(useRegisterAtStart(ins->input()), ins->mode());
    1381             : 
    1382           0 :     define(lir, ins);
    1383           0 : }
    1384             : 
    1385             : void
    1386           0 : LIRGenerator::visitRotate(MRotate* ins)
    1387             : {
    1388           0 :     MDefinition* input = ins->input();
    1389           0 :     MDefinition* count = ins->count();
    1390             : 
    1391           0 :     if (ins->type() == MIRType::Int32) {
    1392           0 :         auto* lir = new(alloc()) LRotate();
    1393           0 :         lowerForShift(lir, ins, input, count);
    1394           0 :     } else if (ins->type() == MIRType::Int64) {
    1395           0 :         auto* lir = new(alloc()) LRotateI64();
    1396           0 :         lowerForShiftInt64(lir, ins, input, count);
    1397             :     } else {
    1398           0 :         MOZ_CRASH("unexpected type in visitRotate");
    1399             :     }
    1400           0 : }
    1401             : 
    1402             : void
    1403           0 : LIRGenerator::visitFloor(MFloor* ins)
    1404             : {
    1405           0 :     MIRType type = ins->input()->type();
    1406           0 :     MOZ_ASSERT(IsFloatingPointType(type));
    1407             : 
    1408             :     LInstructionHelper<1, 1, 0>* lir;
    1409           0 :     if (type == MIRType::Double)
    1410           0 :         lir = new(alloc()) LFloor(useRegister(ins->input()));
    1411             :     else
    1412           0 :         lir = new(alloc()) LFloorF(useRegister(ins->input()));
    1413             : 
    1414           0 :     assignSnapshot(lir, Bailout_Round);
    1415           0 :     define(lir, ins);
    1416           0 : }
    1417             : 
    1418             : void
    1419           0 : LIRGenerator::visitCeil(MCeil* ins)
    1420             : {
    1421           0 :     MIRType type = ins->input()->type();
    1422           0 :     MOZ_ASSERT(IsFloatingPointType(type));
    1423             : 
    1424             :     LInstructionHelper<1, 1, 0>* lir;
    1425           0 :     if (type == MIRType::Double)
    1426           0 :         lir = new(alloc()) LCeil(useRegister(ins->input()));
    1427             :     else
    1428           0 :         lir = new(alloc()) LCeilF(useRegister(ins->input()));
    1429             : 
    1430           0 :     assignSnapshot(lir, Bailout_Round);
    1431           0 :     define(lir, ins);
    1432           0 : }
    1433             : 
    1434             : void
    1435           0 : LIRGenerator::visitRound(MRound* ins)
    1436             : {
    1437           0 :     MIRType type = ins->input()->type();
    1438           0 :     MOZ_ASSERT(IsFloatingPointType(type));
    1439             : 
    1440             :     LInstructionHelper<1, 1, 1>* lir;
    1441           0 :     if (type == MIRType::Double)
    1442           0 :         lir = new (alloc()) LRound(useRegister(ins->input()), tempDouble());
    1443             :     else
    1444           0 :         lir = new (alloc()) LRoundF(useRegister(ins->input()), tempFloat32());
    1445             : 
    1446           0 :     assignSnapshot(lir, Bailout_Round);
    1447           0 :     define(lir, ins);
    1448           0 : }
    1449             : 
    1450             : void
    1451           0 : LIRGenerator::visitNearbyInt(MNearbyInt* ins)
    1452             : {
    1453           0 :     MIRType inputType = ins->input()->type();
    1454           0 :     MOZ_ASSERT(IsFloatingPointType(inputType));
    1455           0 :     MOZ_ASSERT(ins->type() == inputType);
    1456             : 
    1457             :     LInstructionHelper<1, 1, 0>* lir;
    1458           0 :     if (inputType == MIRType::Double)
    1459           0 :         lir = new(alloc()) LNearbyInt(useRegisterAtStart(ins->input()));
    1460             :     else
    1461           0 :         lir = new(alloc()) LNearbyIntF(useRegisterAtStart(ins->input()));
    1462             : 
    1463           0 :     define(lir, ins);
    1464           0 : }
    1465             : 
    1466             : void
    1467           5 : LIRGenerator::visitMinMax(MMinMax* ins)
    1468             : {
    1469           5 :     MDefinition* first = ins->getOperand(0);
    1470           5 :     MDefinition* second = ins->getOperand(1);
    1471             : 
    1472           5 :     ReorderCommutative(&first, &second, ins);
    1473             : 
    1474             :     LMinMaxBase* lir;
    1475           5 :     switch (ins->specialization()) {
    1476             :       case MIRType::Int32:
    1477           5 :         lir = new(alloc()) LMinMaxI(useRegisterAtStart(first), useRegisterOrConstant(second));
    1478           5 :         break;
    1479             :       case MIRType::Float32:
    1480           0 :         lir = new(alloc()) LMinMaxF(useRegisterAtStart(first), useRegister(second));
    1481           0 :         break;
    1482             :       case MIRType::Double:
    1483           0 :         lir = new(alloc()) LMinMaxD(useRegisterAtStart(first), useRegister(second));
    1484           0 :         break;
    1485             :       default:
    1486           0 :         MOZ_CRASH();
    1487             :     }
    1488             : 
    1489           5 :     defineReuseInput(lir, ins, 0);
    1490           5 : }
    1491             : 
    1492             : void
    1493           0 : LIRGenerator::visitAbs(MAbs* ins)
    1494             : {
    1495           0 :     MDefinition* num = ins->input();
    1496           0 :     MOZ_ASSERT(IsNumberType(num->type()));
    1497             : 
    1498             :     LInstructionHelper<1, 1, 0>* lir;
    1499           0 :     switch (num->type()) {
    1500             :       case MIRType::Int32:
    1501           0 :         lir = new(alloc()) LAbsI(useRegisterAtStart(num));
    1502             :         // needed to handle abs(INT32_MIN)
    1503           0 :         if (ins->fallible())
    1504           0 :             assignSnapshot(lir, Bailout_Overflow);
    1505           0 :         break;
    1506             :       case MIRType::Float32:
    1507           0 :         lir = new(alloc()) LAbsF(useRegisterAtStart(num));
    1508           0 :         break;
    1509             :       case MIRType::Double:
    1510           0 :         lir = new(alloc()) LAbsD(useRegisterAtStart(num));
    1511           0 :         break;
    1512             :       default:
    1513           0 :         MOZ_CRASH();
    1514             :     }
    1515             : 
    1516           0 :     defineReuseInput(lir, ins, 0);
    1517           0 : }
    1518             : 
    1519             : void
    1520           0 : LIRGenerator::visitClz(MClz* ins)
    1521             : {
    1522           0 :     MDefinition* num = ins->num();
    1523             : 
    1524           0 :     MOZ_ASSERT(IsIntType(ins->type()));
    1525             : 
    1526           0 :     if (ins->type() == MIRType::Int32) {
    1527           0 :         LClzI* lir = new(alloc()) LClzI(useRegisterAtStart(num));
    1528           0 :         define(lir, ins);
    1529           0 :         return;
    1530             :     }
    1531             : 
    1532           0 :     auto* lir = new(alloc()) LClzI64(useInt64RegisterAtStart(num));
    1533           0 :     defineInt64(lir, ins);
    1534             : }
    1535             : 
    1536             : void
    1537           0 : LIRGenerator::visitCtz(MCtz* ins)
    1538             : {
    1539           0 :     MDefinition* num = ins->num();
    1540             : 
    1541           0 :     MOZ_ASSERT(IsIntType(ins->type()));
    1542             : 
    1543           0 :     if (ins->type() == MIRType::Int32) {
    1544           0 :         LCtzI* lir = new(alloc()) LCtzI(useRegisterAtStart(num));
    1545           0 :         define(lir, ins);
    1546           0 :         return;
    1547             :     }
    1548             : 
    1549           0 :     auto* lir = new(alloc()) LCtzI64(useInt64RegisterAtStart(num));
    1550           0 :     defineInt64(lir, ins);
    1551             : }
    1552             : 
    1553             : void
    1554           0 : LIRGenerator::visitPopcnt(MPopcnt* ins)
    1555             : {
    1556           0 :     MDefinition* num = ins->num();
    1557             : 
    1558           0 :     MOZ_ASSERT(IsIntType(ins->type()));
    1559             : 
    1560           0 :     if (ins->type() == MIRType::Int32) {
    1561           0 :         LPopcntI* lir = new(alloc()) LPopcntI(useRegisterAtStart(num), temp());
    1562           0 :         define(lir, ins);
    1563           0 :         return;
    1564             :     }
    1565             : 
    1566           0 :     auto* lir = new(alloc()) LPopcntI64(useInt64RegisterAtStart(num), temp());
    1567           0 :     defineInt64(lir, ins);
    1568             : }
    1569             : 
    1570             : void
    1571           0 : LIRGenerator::visitSqrt(MSqrt* ins)
    1572             : {
    1573           0 :     MDefinition* num = ins->input();
    1574           0 :     MOZ_ASSERT(IsFloatingPointType(num->type()));
    1575             : 
    1576             :     LInstructionHelper<1, 1, 0>* lir;
    1577           0 :     if (num->type() == MIRType::Double)
    1578           0 :         lir = new(alloc()) LSqrtD(useRegisterAtStart(num));
    1579             :     else
    1580           0 :         lir = new(alloc()) LSqrtF(useRegisterAtStart(num));
    1581           0 :     define(lir, ins);
    1582           0 : }
    1583             : 
    1584             : void
    1585           0 : LIRGenerator::visitAtan2(MAtan2* ins)
    1586             : {
    1587           0 :     MDefinition* y = ins->y();
    1588           0 :     MOZ_ASSERT(y->type() == MIRType::Double);
    1589             : 
    1590           0 :     MDefinition* x = ins->x();
    1591           0 :     MOZ_ASSERT(x->type() == MIRType::Double);
    1592             : 
    1593           0 :     LAtan2D* lir = new(alloc()) LAtan2D(useRegisterAtStart(y), useRegisterAtStart(x),
    1594           0 :                                         tempFixed(CallTempReg0));
    1595           0 :     defineReturn(lir, ins);
    1596           0 : }
    1597             : 
    1598             : void
    1599           0 : LIRGenerator::visitHypot(MHypot* ins)
    1600             : {
    1601           0 :     LHypot* lir = nullptr;
    1602           0 :     uint32_t length = ins->numOperands();
    1603           0 :     for (uint32_t i = 0; i < length; ++i)
    1604           0 :         MOZ_ASSERT(ins->getOperand(i)->type() == MIRType::Double);
    1605             : 
    1606           0 :     switch(length) {
    1607             :       case 2:
    1608           0 :         lir = new(alloc()) LHypot(useRegisterAtStart(ins->getOperand(0)),
    1609           0 :                                   useRegisterAtStart(ins->getOperand(1)),
    1610           0 :                                   tempFixed(CallTempReg0));
    1611           0 :         break;
    1612             :       case 3:
    1613           0 :         lir = new(alloc()) LHypot(useRegisterAtStart(ins->getOperand(0)),
    1614           0 :                                   useRegisterAtStart(ins->getOperand(1)),
    1615           0 :                                   useRegisterAtStart(ins->getOperand(2)),
    1616           0 :                                   tempFixed(CallTempReg0));
    1617           0 :         break;
    1618             :       case 4:
    1619           0 :         lir = new(alloc()) LHypot(useRegisterAtStart(ins->getOperand(0)),
    1620           0 :                                   useRegisterAtStart(ins->getOperand(1)),
    1621           0 :                                   useRegisterAtStart(ins->getOperand(2)),
    1622           0 :                                   useRegisterAtStart(ins->getOperand(3)),
    1623           0 :                                   tempFixed(CallTempReg0));
    1624           0 :         break;
    1625             :       default:
    1626           0 :         MOZ_CRASH("Unexpected number of arguments to LHypot.");
    1627             :     }
    1628             : 
    1629           0 :     defineReturn(lir, ins);
    1630           0 : }
    1631             : 
    1632             : void
    1633           0 : LIRGenerator::visitPow(MPow* ins)
    1634             : {
    1635           0 :     MDefinition* input = ins->input();
    1636           0 :     MDefinition* power = ins->power();
    1637             :     LInstruction* lir;
    1638             : 
    1639           0 :     if (ins->specialization() == MIRType::None) {
    1640           0 :         MOZ_ASSERT(input->type() == MIRType::Value);
    1641           0 :         MOZ_ASSERT(power->type() == MIRType::Value);
    1642             : 
    1643           0 :         lir = new(alloc()) LPowV(useBoxAtStart(input), useBoxAtStart(power));
    1644           0 :         defineReturn(lir, ins);
    1645           0 :         assignSafepoint(lir, ins);
    1646           0 :         return;
    1647             :     }
    1648             : 
    1649           0 :     MOZ_ASSERT(input->type() == MIRType::Double);
    1650           0 :     MOZ_ASSERT(power->type() == MIRType::Int32 || power->type() == MIRType::Double);
    1651             : 
    1652           0 :     if (power->type() == MIRType::Int32) {
    1653             :         // Note: useRegisterAtStart here is safe, the temp is a GP register so
    1654             :         // it will never get the same register.
    1655           0 :         lir = new(alloc()) LPowI(useRegisterAtStart(input), useFixedAtStart(power, CallTempReg1),
    1656           0 :                                  tempFixed(CallTempReg0));
    1657             :     } else {
    1658           0 :         lir = new(alloc()) LPowD(useRegisterAtStart(input), useRegisterAtStart(power),
    1659           0 :                                  tempFixed(CallTempReg0));
    1660             :     }
    1661           0 :     defineReturn(lir, ins);
    1662             : }
    1663             : 
    1664             : void
    1665           0 : LIRGenerator::visitMathFunction(MMathFunction* ins)
    1666             : {
    1667           0 :     MOZ_ASSERT(IsFloatingPointType(ins->type()));
    1668           0 :     MOZ_ASSERT_IF(ins->input()->type() != MIRType::SinCosDouble,
    1669             :                   ins->type() == ins->input()->type());
    1670             : 
    1671           0 :     if (ins->input()->type() == MIRType::SinCosDouble) {
    1672           0 :         MOZ_ASSERT(ins->type() == MIRType::Double);
    1673           0 :         redefine(ins, ins->input(), ins->function());
    1674           0 :         return;
    1675             :     }
    1676             : 
    1677             :     LInstruction* lir;
    1678           0 :     if (ins->type() == MIRType::Double) {
    1679             :         // Note: useRegisterAtStart is safe here, the temp is not a FP register.
    1680           0 :         lir = new(alloc()) LMathFunctionD(useRegisterAtStart(ins->input()),
    1681           0 :                                           tempFixed(CallTempReg0));
    1682             :     } else {
    1683           0 :         lir = new(alloc()) LMathFunctionF(useRegisterAtStart(ins->input()),
    1684           0 :                                           tempFixed(CallTempReg0));
    1685             :     }
    1686           0 :     defineReturn(lir, ins);
    1687             : }
    1688             : 
    1689             : // Try to mark an add or sub instruction as able to recover its input when
    1690             : // bailing out.
    1691             : template <typename S, typename T>
    1692             : static void
    1693           8 : MaybeSetRecoversInput(S* mir, T* lir)
    1694             : {
    1695           8 :     MOZ_ASSERT(lir->mirRaw() == mir);
    1696           8 :     if (!mir->fallible() || !lir->snapshot())
    1697           7 :         return;
    1698             : 
    1699           1 :     if (lir->output()->policy() != LDefinition::MUST_REUSE_INPUT)
    1700           0 :         return;
    1701             : 
    1702             :     // The original operands to an add or sub can't be recovered if they both
    1703             :     // use the same register.
    1704           1 :     if (lir->lhs()->isUse() && lir->rhs()->isUse() &&
    1705           0 :         lir->lhs()->toUse()->virtualRegister() == lir->rhs()->toUse()->virtualRegister())
    1706             :     {
    1707           0 :         return;
    1708             :     }
    1709             : 
    1710             :     // Add instructions that are on two different values can recover
    1711             :     // the input they clobbered via MUST_REUSE_INPUT. Thus, a copy
    1712             :     // of that input does not need to be kept alive in the snapshot
    1713             :     // for the instruction.
    1714             : 
    1715           1 :     lir->setRecoversInput();
    1716             : 
    1717           1 :     const LUse* input = lir->getOperand(lir->output()->getReusedInput())->toUse();
    1718           1 :     lir->snapshot()->rewriteRecoveredInput(*input);
    1719             : }
    1720             : 
    1721             : void
    1722           8 : LIRGenerator::visitAdd(MAdd* ins)
    1723             : {
    1724           8 :     MDefinition* lhs = ins->getOperand(0);
    1725           8 :     MDefinition* rhs = ins->getOperand(1);
    1726             : 
    1727           8 :     MOZ_ASSERT(lhs->type() == rhs->type());
    1728             : 
    1729           8 :     if (ins->specialization() == MIRType::Int32) {
    1730           8 :         MOZ_ASSERT(lhs->type() == MIRType::Int32);
    1731           8 :         ReorderCommutative(&lhs, &rhs, ins);
    1732           8 :         LAddI* lir = new(alloc()) LAddI;
    1733             : 
    1734           8 :         if (ins->fallible())
    1735           1 :             assignSnapshot(lir, Bailout_OverflowInvalidate);
    1736             : 
    1737           8 :         lowerForALU(lir, ins, lhs, rhs);
    1738           8 :         MaybeSetRecoversInput(ins, lir);
    1739           8 :         return;
    1740             :     }
    1741             : 
    1742           0 :     if (ins->specialization() == MIRType::Int64) {
    1743           0 :         MOZ_ASSERT(lhs->type() == MIRType::Int64);
    1744           0 :         ReorderCommutative(&lhs, &rhs, ins);
    1745           0 :         LAddI64* lir = new(alloc()) LAddI64;
    1746           0 :         lowerForALUInt64(lir, ins, lhs, rhs);
    1747           0 :         return;
    1748             :     }
    1749             : 
    1750           0 :     if (ins->specialization() == MIRType::Double) {
    1751           0 :         MOZ_ASSERT(lhs->type() == MIRType::Double);
    1752           0 :         ReorderCommutative(&lhs, &rhs, ins);
    1753           0 :         lowerForFPU(new(alloc()) LMathD(JSOP_ADD), ins, lhs, rhs);
    1754           0 :         return;
    1755             :     }
    1756             : 
    1757           0 :     if (ins->specialization() == MIRType::Float32) {
    1758           0 :         MOZ_ASSERT(lhs->type() == MIRType::Float32);
    1759           0 :         ReorderCommutative(&lhs, &rhs, ins);
    1760           0 :         lowerForFPU(new(alloc()) LMathF(JSOP_ADD), ins, lhs, rhs);
    1761           0 :         return;
    1762             :     }
    1763             : 
    1764           0 :     lowerBinaryV(JSOP_ADD, ins);
    1765             : }
    1766             : 
    1767             : void
    1768           0 : LIRGenerator::visitSub(MSub* ins)
    1769             : {
    1770           0 :     MDefinition* lhs = ins->lhs();
    1771           0 :     MDefinition* rhs = ins->rhs();
    1772             : 
    1773           0 :     MOZ_ASSERT(lhs->type() == rhs->type());
    1774             : 
    1775           0 :     if (ins->specialization() == MIRType::Int32) {
    1776           0 :         MOZ_ASSERT(lhs->type() == MIRType::Int32);
    1777             : 
    1778           0 :         LSubI* lir = new(alloc()) LSubI;
    1779           0 :         if (ins->fallible())
    1780           0 :             assignSnapshot(lir, Bailout_Overflow);
    1781             : 
    1782           0 :         lowerForALU(lir, ins, lhs, rhs);
    1783           0 :         MaybeSetRecoversInput(ins, lir);
    1784           0 :         return;
    1785             :     }
    1786             : 
    1787           0 :     if (ins->specialization() == MIRType::Int64) {
    1788           0 :         MOZ_ASSERT(lhs->type() == MIRType::Int64);
    1789           0 :         LSubI64* lir = new(alloc()) LSubI64;
    1790           0 :         lowerForALUInt64(lir, ins, lhs, rhs);
    1791           0 :         return;
    1792             :     }
    1793             : 
    1794           0 :     if (ins->specialization() == MIRType::Double) {
    1795           0 :         MOZ_ASSERT(lhs->type() == MIRType::Double);
    1796           0 :         lowerForFPU(new(alloc()) LMathD(JSOP_SUB), ins, lhs, rhs);
    1797           0 :         return;
    1798             :     }
    1799             : 
    1800           0 :     if (ins->specialization() == MIRType::Float32) {
    1801           0 :         MOZ_ASSERT(lhs->type() == MIRType::Float32);
    1802           0 :         lowerForFPU(new(alloc()) LMathF(JSOP_SUB), ins, lhs, rhs);
    1803           0 :         return;
    1804             :     }
    1805             : 
    1806           0 :     lowerBinaryV(JSOP_SUB, ins);
    1807             : }
    1808             : 
    1809             : void
    1810           0 : LIRGenerator::visitMul(MMul* ins)
    1811             : {
    1812           0 :     MDefinition* lhs = ins->lhs();
    1813           0 :     MDefinition* rhs = ins->rhs();
    1814           0 :     MOZ_ASSERT(lhs->type() == rhs->type());
    1815             : 
    1816           0 :     if (ins->specialization() == MIRType::Int32) {
    1817           0 :         MOZ_ASSERT(lhs->type() == MIRType::Int32);
    1818           0 :         ReorderCommutative(&lhs, &rhs, ins);
    1819             : 
    1820             :         // If our RHS is a constant -1 and we don't have to worry about
    1821             :         // overflow, we can optimize to an LNegI.
    1822           0 :         if (!ins->fallible() && rhs->isConstant() && rhs->toConstant()->toInt32() == -1)
    1823           0 :             defineReuseInput(new(alloc()) LNegI(useRegisterAtStart(lhs)), ins, 0);
    1824             :         else
    1825           0 :             lowerMulI(ins, lhs, rhs);
    1826           0 :         return;
    1827             :     }
    1828             : 
    1829           0 :     if (ins->specialization() == MIRType::Int64) {
    1830           0 :         MOZ_ASSERT(lhs->type() == MIRType::Int64);
    1831           0 :         ReorderCommutative(&lhs, &rhs, ins);
    1832           0 :         LMulI64* lir = new(alloc()) LMulI64;
    1833           0 :         lowerForMulInt64(lir, ins, lhs, rhs);
    1834           0 :         return;
    1835             :     }
    1836             : 
    1837           0 :     if (ins->specialization() == MIRType::Double) {
    1838           0 :         MOZ_ASSERT(lhs->type() == MIRType::Double);
    1839           0 :         ReorderCommutative(&lhs, &rhs, ins);
    1840             : 
    1841             :         // If our RHS is a constant -1.0, we can optimize to an LNegD.
    1842           0 :         if (!ins->mustPreserveNaN() && rhs->isConstant() && rhs->toConstant()->toDouble() == -1.0)
    1843           0 :             defineReuseInput(new(alloc()) LNegD(useRegisterAtStart(lhs)), ins, 0);
    1844             :         else
    1845           0 :             lowerForFPU(new(alloc()) LMathD(JSOP_MUL), ins, lhs, rhs);
    1846           0 :         return;
    1847             :     }
    1848             : 
    1849           0 :     if (ins->specialization() == MIRType::Float32) {
    1850           0 :         MOZ_ASSERT(lhs->type() == MIRType::Float32);
    1851           0 :         ReorderCommutative(&lhs, &rhs, ins);
    1852             : 
    1853             :         // We apply the same optimizations as for doubles
    1854           0 :         if (!ins->mustPreserveNaN() && rhs->isConstant() && rhs->toConstant()->toFloat32() == -1.0f)
    1855           0 :             defineReuseInput(new(alloc()) LNegF(useRegisterAtStart(lhs)), ins, 0);
    1856             :         else
    1857           0 :             lowerForFPU(new(alloc()) LMathF(JSOP_MUL), ins, lhs, rhs);
    1858           0 :         return;
    1859             :     }
    1860             : 
    1861           0 :     lowerBinaryV(JSOP_MUL, ins);
    1862             : }
    1863             : 
    1864             : void
    1865           0 : LIRGenerator::visitDiv(MDiv* ins)
    1866             : {
    1867           0 :     MDefinition* lhs = ins->lhs();
    1868           0 :     MDefinition* rhs = ins->rhs();
    1869           0 :     MOZ_ASSERT(lhs->type() == rhs->type());
    1870             : 
    1871           0 :     if (ins->specialization() == MIRType::Int32) {
    1872           0 :         MOZ_ASSERT(lhs->type() == MIRType::Int32);
    1873           0 :         lowerDivI(ins);
    1874           0 :         return;
    1875             :     }
    1876             : 
    1877           0 :     if (ins->specialization() == MIRType::Int64) {
    1878           0 :         MOZ_ASSERT(lhs->type() == MIRType::Int64);
    1879           0 :         lowerDivI64(ins);
    1880           0 :         return;
    1881             :     }
    1882             : 
    1883           0 :     if (ins->specialization() == MIRType::Double) {
    1884           0 :         MOZ_ASSERT(lhs->type() == MIRType::Double);
    1885           0 :         lowerForFPU(new(alloc()) LMathD(JSOP_DIV), ins, lhs, rhs);
    1886           0 :         return;
    1887             :     }
    1888             : 
    1889           0 :     if (ins->specialization() == MIRType::Float32) {
    1890           0 :         MOZ_ASSERT(lhs->type() == MIRType::Float32);
    1891           0 :         lowerForFPU(new(alloc()) LMathF(JSOP_DIV), ins, lhs, rhs);
    1892           0 :         return;
    1893             :     }
    1894             : 
    1895           0 :     lowerBinaryV(JSOP_DIV, ins);
    1896             : }
    1897             : 
    1898             : void
    1899           0 : LIRGenerator::visitMod(MMod* ins)
    1900             : {
    1901           0 :     MOZ_ASSERT(ins->lhs()->type() == ins->rhs()->type());
    1902             : 
    1903           0 :     if (ins->specialization() == MIRType::Int32) {
    1904           0 :         MOZ_ASSERT(ins->type() == MIRType::Int32);
    1905           0 :         MOZ_ASSERT(ins->lhs()->type() == MIRType::Int32);
    1906           0 :         lowerModI(ins);
    1907           0 :         return;
    1908             :     }
    1909             : 
    1910           0 :     if (ins->specialization() == MIRType::Int64) {
    1911           0 :         MOZ_ASSERT(ins->type() == MIRType::Int64);
    1912           0 :         MOZ_ASSERT(ins->lhs()->type() == MIRType::Int64);
    1913           0 :         lowerModI64(ins);
    1914           0 :         return;
    1915             :     }
    1916             : 
    1917           0 :     if (ins->specialization() == MIRType::Double) {
    1918           0 :         MOZ_ASSERT(ins->type() == MIRType::Double);
    1919           0 :         MOZ_ASSERT(ins->lhs()->type() == MIRType::Double);
    1920           0 :         MOZ_ASSERT(ins->rhs()->type() == MIRType::Double);
    1921             : 
    1922             :         // Ion does an unaligned ABI call and thus needs a temp register. Wasm
    1923             :         // doesn't.
    1924           0 :         LDefinition maybeTemp = gen->compilingWasm()
    1925             :                                 ? LDefinition::BogusTemp()
    1926           0 :                                 : tempFixed(CallTempReg0);
    1927             : 
    1928             :         // Note: useRegisterAtStart is safe here, the temp is not a FP register.
    1929           0 :         LModD* lir = new(alloc()) LModD(useRegisterAtStart(ins->lhs()),
    1930           0 :                                         useRegisterAtStart(ins->rhs()),
    1931           0 :                                         maybeTemp);
    1932           0 :         defineReturn(lir, ins);
    1933           0 :         return;
    1934             :     }
    1935             : 
    1936           0 :     lowerBinaryV(JSOP_MOD, ins);
    1937             : }
    1938             : 
    1939             : void
    1940           0 : LIRGenerator::lowerBinaryV(JSOp op, MBinaryInstruction* ins)
    1941             : {
    1942           0 :     MDefinition* lhs = ins->getOperand(0);
    1943           0 :     MDefinition* rhs = ins->getOperand(1);
    1944             : 
    1945           0 :     MOZ_ASSERT(lhs->type() == MIRType::Value);
    1946           0 :     MOZ_ASSERT(rhs->type() == MIRType::Value);
    1947             : 
    1948           0 :     LBinaryV* lir = new(alloc()) LBinaryV(op, useBoxAtStart(lhs), useBoxAtStart(rhs));
    1949           0 :     defineReturn(lir, ins);
    1950           0 :     assignSafepoint(lir, ins);
    1951           0 : }
    1952             : 
    1953             : void
    1954          12 : LIRGenerator::visitConcat(MConcat* ins)
    1955             : {
    1956          12 :     MDefinition* lhs = ins->getOperand(0);
    1957          12 :     MDefinition* rhs = ins->getOperand(1);
    1958             : 
    1959          12 :     MOZ_ASSERT(lhs->type() == MIRType::String);
    1960          12 :     MOZ_ASSERT(rhs->type() == MIRType::String);
    1961          12 :     MOZ_ASSERT(ins->type() == MIRType::String);
    1962             : 
    1963          36 :     LConcat* lir = new(alloc()) LConcat(useFixedAtStart(lhs, CallTempReg0),
    1964          24 :                                         useFixedAtStart(rhs, CallTempReg1),
    1965          24 :                                         tempFixed(CallTempReg0),
    1966          24 :                                         tempFixed(CallTempReg1),
    1967          24 :                                         tempFixed(CallTempReg2),
    1968          24 :                                         tempFixed(CallTempReg3),
    1969          84 :                                         tempFixed(CallTempReg4));
    1970          12 :     defineFixed(lir, ins, LAllocation(AnyRegister(CallTempReg5)));
    1971          12 :     assignSafepoint(lir, ins);
    1972          12 : }
    1973             : 
    1974             : void
    1975           2 : LIRGenerator::visitCharCodeAt(MCharCodeAt* ins)
    1976             : {
    1977           2 :     MDefinition* str = ins->getOperand(0);
    1978           2 :     MDefinition* idx = ins->getOperand(1);
    1979             : 
    1980           2 :     MOZ_ASSERT(str->type() == MIRType::String);
    1981           2 :     MOZ_ASSERT(idx->type() == MIRType::Int32);
    1982             : 
    1983           2 :     LCharCodeAt* lir = new(alloc()) LCharCodeAt(useRegister(str), useRegister(idx));
    1984           2 :     define(lir, ins);
    1985           2 :     assignSafepoint(lir, ins);
    1986           2 : }
    1987             : 
    1988             : void
    1989           2 : LIRGenerator::visitFromCharCode(MFromCharCode* ins)
    1990             : {
    1991           2 :     MDefinition* code = ins->getOperand(0);
    1992             : 
    1993           2 :     MOZ_ASSERT(code->type() == MIRType::Int32);
    1994             : 
    1995           2 :     LFromCharCode* lir = new(alloc()) LFromCharCode(useRegister(code));
    1996           2 :     define(lir, ins);
    1997           2 :     assignSafepoint(lir, ins);
    1998           2 : }
    1999             : 
    2000             : void
    2001           0 : LIRGenerator::visitFromCodePoint(MFromCodePoint* ins)
    2002             : {
    2003           0 :     MDefinition* codePoint = ins->getOperand(0);
    2004             : 
    2005           0 :     MOZ_ASSERT(codePoint->type() == MIRType::Int32);
    2006             : 
    2007           0 :     LFromCodePoint* lir = new(alloc()) LFromCodePoint(useRegister(codePoint), temp(), temp());
    2008           0 :     assignSnapshot(lir, Bailout_BoundsCheck);
    2009           0 :     define(lir, ins);
    2010           0 :     assignSafepoint(lir, ins);
    2011           0 : }
    2012             : 
    2013             : void
    2014          11 : LIRGenerator::visitStart(MStart* start)
    2015             : {
    2016          11 :     LStart* lir = new(alloc()) LStart;
    2017             : 
    2018             :     // Create a snapshot that captures the initial state of the function.
    2019          11 :     assignSnapshot(lir, Bailout_ArgumentCheck);
    2020          11 :     if (start->block()->graph().entryBlock() == start->block())
    2021           8 :         lirGraph_.setEntrySnapshot(lir->snapshot());
    2022             : 
    2023          11 :     add(lir);
    2024          11 : }
    2025             : 
    2026             : void
    2027          60 : LIRGenerator::visitNop(MNop* nop)
    2028             : {
    2029          60 : }
    2030             : 
    2031             : void
    2032           5 : LIRGenerator::visitLimitedTruncate(MLimitedTruncate* nop)
    2033             : {
    2034           5 :     redefine(nop, nop->input());
    2035           5 : }
    2036             : 
    2037             : void
    2038           3 : LIRGenerator::visitOsrEntry(MOsrEntry* entry)
    2039             : {
    2040           3 :     LOsrEntry* lir = new(alloc()) LOsrEntry(temp());
    2041           3 :     defineFixed(lir, entry, LAllocation(AnyRegister(OsrFrameReg)));
    2042           3 : }
    2043             : 
    2044             : void
    2045          42 : LIRGenerator::visitOsrValue(MOsrValue* value)
    2046             : {
    2047          42 :     LOsrValue* lir = new(alloc()) LOsrValue(useRegister(value->entry()));
    2048          42 :     defineBox(lir, value);
    2049          42 : }
    2050             : 
    2051             : void
    2052           3 : LIRGenerator::visitOsrReturnValue(MOsrReturnValue* value)
    2053             : {
    2054           3 :     LOsrReturnValue* lir = new(alloc()) LOsrReturnValue(useRegister(value->entry()));
    2055           3 :     defineBox(lir, value);
    2056           3 : }
    2057             : 
    2058             : void
    2059           2 : LIRGenerator::visitOsrEnvironmentChain(MOsrEnvironmentChain* object)
    2060             : {
    2061           2 :     LOsrEnvironmentChain* lir = new(alloc()) LOsrEnvironmentChain(useRegister(object->entry()));
    2062           2 :     define(lir, object);
    2063           2 : }
    2064             : 
    2065             : void
    2066           0 : LIRGenerator::visitOsrArgumentsObject(MOsrArgumentsObject* object)
    2067             : {
    2068           0 :     LOsrArgumentsObject* lir = new(alloc()) LOsrArgumentsObject(useRegister(object->entry()));
    2069           0 :     define(lir, object);
    2070           0 : }
    2071             : 
    2072             : void
    2073           0 : LIRGenerator::visitToDouble(MToDouble* convert)
    2074             : {
    2075           0 :     MDefinition* opd = convert->input();
    2076           0 :     mozilla::DebugOnly<MToFPInstruction::ConversionKind> conversion = convert->conversion();
    2077             : 
    2078           0 :     switch (opd->type()) {
    2079             :       case MIRType::Value:
    2080             :       {
    2081           0 :         LValueToDouble* lir = new(alloc()) LValueToDouble(useBox(opd));
    2082           0 :         assignSnapshot(lir, Bailout_NonPrimitiveInput);
    2083           0 :         define(lir, convert);
    2084           0 :         break;
    2085             :       }
    2086             : 
    2087             :       case MIRType::Null:
    2088           0 :         MOZ_ASSERT(conversion != MToFPInstruction::NumbersOnly &&
    2089             :                    conversion != MToFPInstruction::NonNullNonStringPrimitives);
    2090           0 :         lowerConstantDouble(0, convert);
    2091           0 :         break;
    2092             : 
    2093             :       case MIRType::Undefined:
    2094           0 :         MOZ_ASSERT(conversion != MToFPInstruction::NumbersOnly);
    2095           0 :         lowerConstantDouble(GenericNaN(), convert);
    2096           0 :         break;
    2097             : 
    2098             :       case MIRType::Boolean:
    2099           0 :         MOZ_ASSERT(conversion != MToFPInstruction::NumbersOnly);
    2100             :         MOZ_FALLTHROUGH;
    2101             : 
    2102             :       case MIRType::Int32:
    2103             :       {
    2104           0 :         LInt32ToDouble* lir = new(alloc()) LInt32ToDouble(useRegisterAtStart(opd));
    2105           0 :         define(lir, convert);
    2106           0 :         break;
    2107             :       }
    2108             : 
    2109             :       case MIRType::Float32:
    2110             :       {
    2111           0 :         LFloat32ToDouble* lir = new (alloc()) LFloat32ToDouble(useRegisterAtStart(opd));
    2112           0 :         define(lir, convert);
    2113           0 :         break;
    2114             :       }
    2115             : 
    2116             :       case MIRType::Double:
    2117           0 :         redefine(convert, opd);
    2118           0 :         break;
    2119             : 
    2120             :       default:
    2121             :         // Objects might be effectful. Symbols will throw.
    2122             :         // Strings are complicated - we don't handle them yet.
    2123           0 :         MOZ_CRASH("unexpected type");
    2124             :     }
    2125           0 : }
    2126             : 
    2127             : void
    2128           0 : LIRGenerator::visitToFloat32(MToFloat32* convert)
    2129             : {
    2130           0 :     MDefinition* opd = convert->input();
    2131           0 :     mozilla::DebugOnly<MToFloat32::ConversionKind> conversion = convert->conversion();
    2132             : 
    2133           0 :     switch (opd->type()) {
    2134             :       case MIRType::Value:
    2135             :       {
    2136           0 :         LValueToFloat32* lir = new(alloc()) LValueToFloat32(useBox(opd));
    2137           0 :         assignSnapshot(lir, Bailout_NonPrimitiveInput);
    2138           0 :         define(lir, convert);
    2139           0 :         break;
    2140             :       }
    2141             : 
    2142             :       case MIRType::Null:
    2143           0 :         MOZ_ASSERT(conversion != MToFPInstruction::NumbersOnly &&
    2144             :                    conversion != MToFPInstruction::NonNullNonStringPrimitives);
    2145           0 :         lowerConstantFloat32(0, convert);
    2146           0 :         break;
    2147             : 
    2148             :       case MIRType::Undefined:
    2149           0 :         MOZ_ASSERT(conversion != MToFPInstruction::NumbersOnly);
    2150           0 :         lowerConstantFloat32(GenericNaN(), convert);
    2151           0 :         break;
    2152             : 
    2153             :       case MIRType::Boolean:
    2154           0 :         MOZ_ASSERT(conversion != MToFPInstruction::NumbersOnly);
    2155             :         MOZ_FALLTHROUGH;
    2156             : 
    2157             :       case MIRType::Int32:
    2158             :       {
    2159           0 :         LInt32ToFloat32* lir = new(alloc()) LInt32ToFloat32(useRegisterAtStart(opd));
    2160           0 :         define(lir, convert);
    2161           0 :         break;
    2162             :       }
    2163             : 
    2164             :       case MIRType::Double:
    2165             :       {
    2166           0 :         LDoubleToFloat32* lir = new(alloc()) LDoubleToFloat32(useRegisterAtStart(opd));
    2167           0 :         define(lir, convert);
    2168           0 :         break;
    2169             :       }
    2170             : 
    2171             :       case MIRType::Float32:
    2172           0 :         redefine(convert, opd);
    2173           0 :         break;
    2174             : 
    2175             :       default:
    2176             :         // Objects might be effectful. Symbols will throw.
    2177             :         // Strings are complicated - we don't handle them yet.
    2178           0 :         MOZ_CRASH("unexpected type");
    2179             :     }
    2180           0 : }
    2181             : 
    2182             : void
    2183           1 : LIRGenerator::visitToInt32(MToInt32* convert)
    2184             : {
    2185           1 :     MDefinition* opd = convert->input();
    2186             : 
    2187           1 :     switch (opd->type()) {
    2188             :       case MIRType::Value:
    2189             :       {
    2190             :         LValueToInt32* lir =
    2191           1 :             new(alloc()) LValueToInt32(useBox(opd), tempDouble(), temp(), LValueToInt32::NORMAL);
    2192           1 :         assignSnapshot(lir, Bailout_NonPrimitiveInput);
    2193           1 :         define(lir, convert);
    2194           1 :         assignSafepoint(lir, convert);
    2195           1 :         break;
    2196             :       }
    2197             : 
    2198             :       case MIRType::Null:
    2199           0 :         MOZ_ASSERT(convert->conversion() == MacroAssembler::IntConversion_Any);
    2200           0 :         define(new(alloc()) LInteger(0), convert);
    2201           0 :         break;
    2202             : 
    2203             :       case MIRType::Boolean:
    2204           0 :         MOZ_ASSERT(convert->conversion() == MacroAssembler::IntConversion_Any ||
    2205             :                    convert->conversion() == MacroAssembler::IntConversion_NumbersOrBoolsOnly);
    2206           0 :         redefine(convert, opd);
    2207           0 :         break;
    2208             : 
    2209             :       case MIRType::Int32:
    2210           0 :         redefine(convert, opd);
    2211           0 :         break;
    2212             : 
    2213             :       case MIRType::Float32:
    2214             :       {
    2215           0 :         LFloat32ToInt32* lir = new(alloc()) LFloat32ToInt32(useRegister(opd));
    2216           0 :         assignSnapshot(lir, Bailout_PrecisionLoss);
    2217           0 :         define(lir, convert);
    2218           0 :         break;
    2219             :       }
    2220             : 
    2221             :       case MIRType::Double:
    2222             :       {
    2223           0 :         LDoubleToInt32* lir = new(alloc()) LDoubleToInt32(useRegister(opd));
    2224           0 :         assignSnapshot(lir, Bailout_PrecisionLoss);
    2225           0 :         define(lir, convert);
    2226           0 :         break;
    2227             :       }
    2228             : 
    2229             :       case MIRType::String:
    2230             :       case MIRType::Symbol:
    2231             :       case MIRType::Object:
    2232             :       case MIRType::Undefined:
    2233             :         // Objects might be effectful. Symbols throw. Undefined coerces to NaN, not int32.
    2234           0 :         MOZ_CRASH("ToInt32 invalid input type");
    2235             : 
    2236             :       default:
    2237           0 :         MOZ_CRASH("unexpected type");
    2238             :     }
    2239           1 : }
    2240             : 
    2241             : void
    2242           2 : LIRGenerator::visitTruncateToInt32(MTruncateToInt32* truncate)
    2243             : {
    2244           2 :     MDefinition* opd = truncate->input();
    2245             : 
    2246           2 :     switch (opd->type()) {
    2247             :       case MIRType::Value: {
    2248           5 :         LValueToInt32* lir = new(alloc()) LValueToInt32(useBox(opd), tempDouble(), temp(),
    2249           4 :                                                         LValueToInt32::TRUNCATE);
    2250           1 :         assignSnapshot(lir, Bailout_NonPrimitiveInput);
    2251           1 :         define(lir, truncate);
    2252           1 :         assignSafepoint(lir, truncate);
    2253           1 :         break;
    2254             :       }
    2255             : 
    2256             :       case MIRType::Null:
    2257             :       case MIRType::Undefined:
    2258           1 :         define(new(alloc()) LInteger(0), truncate);
    2259           1 :         break;
    2260             : 
    2261             :       case MIRType::Int32:
    2262             :       case MIRType::Boolean:
    2263           0 :         redefine(truncate, opd);
    2264           0 :         break;
    2265             : 
    2266             :       case MIRType::Double:
    2267             :         // May call into JS::ToInt32() on the slow OOL path.
    2268           0 :         gen->setNeedsStaticStackAlignment();
    2269           0 :         lowerTruncateDToInt32(truncate);
    2270           0 :         break;
    2271             : 
    2272             :       case MIRType::Float32:
    2273             :         // May call into JS::ToInt32() on the slow OOL path.
    2274           0 :         gen->setNeedsStaticStackAlignment();
    2275           0 :         lowerTruncateFToInt32(truncate);
    2276           0 :         break;
    2277             : 
    2278             :       default:
    2279             :         // Objects might be effectful. Symbols throw.
    2280             :         // Strings are complicated - we don't handle them yet.
    2281           0 :         MOZ_CRASH("unexpected type");
    2282             :     }
    2283           2 : }
    2284             : 
    2285             : void
    2286           0 : LIRGenerator::visitWasmTruncateToInt32(MWasmTruncateToInt32* ins)
    2287             : {
    2288           0 :     MDefinition* input = ins->input();
    2289           0 :     switch (input->type()) {
    2290             :       case MIRType::Double:
    2291             :       case MIRType::Float32: {
    2292           0 :         auto* lir = new(alloc()) LWasmTruncateToInt32(useRegisterAtStart(input));
    2293           0 :         define(lir, ins);
    2294           0 :         break;
    2295             :       }
    2296             :       default:
    2297           0 :         MOZ_CRASH("unexpected type in WasmTruncateToInt32");
    2298             :     }
    2299           0 : }
    2300             : 
    2301             : void
    2302           0 : LIRGenerator::visitWrapInt64ToInt32(MWrapInt64ToInt32* ins)
    2303             : {
    2304           0 :     define(new(alloc()) LWrapInt64ToInt32(useInt64AtStart(ins->input())), ins);
    2305           0 : }
    2306             : 
    2307             : void
    2308           4 : LIRGenerator::visitToString(MToString* ins)
    2309             : {
    2310           4 :     MDefinition* opd = ins->input();
    2311             : 
    2312           4 :     switch (opd->type()) {
    2313             :       case MIRType::Null: {
    2314           0 :         const JSAtomState& names = GetJitContext()->runtime->names();
    2315           0 :         LPointer* lir = new(alloc()) LPointer(names.null);
    2316           0 :         define(lir, ins);
    2317           0 :         break;
    2318             :       }
    2319             : 
    2320             :       case MIRType::Undefined: {
    2321           0 :         const JSAtomState& names = GetJitContext()->runtime->names();
    2322           0 :         LPointer* lir = new(alloc()) LPointer(names.undefined);
    2323           0 :         define(lir, ins);
    2324           0 :         break;
    2325             :       }
    2326             : 
    2327             :       case MIRType::Boolean: {
    2328           0 :         LBooleanToString* lir = new(alloc()) LBooleanToString(useRegister(opd));
    2329           0 :         define(lir, ins);
    2330           0 :         break;
    2331             :       }
    2332             : 
    2333             :       case MIRType::Double: {
    2334           0 :         LDoubleToString* lir = new(alloc()) LDoubleToString(useRegister(opd), temp());
    2335             : 
    2336           0 :         define(lir, ins);
    2337           0 :         assignSafepoint(lir, ins);
    2338           0 :         break;
    2339             :       }
    2340             : 
    2341             :       case MIRType::Int32: {
    2342           0 :         LIntToString* lir = new(alloc()) LIntToString(useRegister(opd));
    2343             : 
    2344           0 :         define(lir, ins);
    2345           0 :         assignSafepoint(lir, ins);
    2346           0 :         break;
    2347             :       }
    2348             : 
    2349             :       case MIRType::String:
    2350           0 :         redefine(ins, ins->input());
    2351           0 :         break;
    2352             : 
    2353             :       case MIRType::Value: {
    2354           4 :         LValueToString* lir = new(alloc()) LValueToString(useBox(opd), tempToUnbox());
    2355           4 :         if (ins->fallible())
    2356           0 :             assignSnapshot(lir, Bailout_NonPrimitiveInput);
    2357           4 :         define(lir, ins);
    2358           4 :         assignSafepoint(lir, ins);
    2359           4 :         break;
    2360             :       }
    2361             : 
    2362             :       default:
    2363             :         // Float32, symbols, and objects are not supported.
    2364           0 :         MOZ_CRASH("unexpected type");
    2365             :     }
    2366           4 : }
    2367             : 
    2368             : void
    2369           0 : LIRGenerator::visitToObjectOrNull(MToObjectOrNull* ins)
    2370             : {
    2371           0 :     MOZ_ASSERT(ins->input()->type() == MIRType::Value);
    2372             : 
    2373           0 :     LValueToObjectOrNull* lir = new(alloc()) LValueToObjectOrNull(useBox(ins->input()));
    2374           0 :     define(lir, ins);
    2375           0 :     assignSafepoint(lir, ins);
    2376           0 : }
    2377             : 
    2378             : void
    2379           0 : LIRGenerator::visitRegExp(MRegExp* ins)
    2380             : {
    2381           0 :     if (ins->mustClone()) {
    2382           0 :         LRegExp* lir = new(alloc()) LRegExp(temp());
    2383           0 :         define(lir, ins);
    2384           0 :         assignSafepoint(lir, ins);
    2385             :     } else {
    2386           0 :         RegExpObject* source = ins->source();
    2387           0 :         define(new(alloc()) LPointer(source), ins);
    2388             :     }
    2389           0 : }
    2390             : 
    2391             : void
    2392           0 : LIRGenerator::visitRegExpMatcher(MRegExpMatcher* ins)
    2393             : {
    2394           0 :     MOZ_ASSERT(ins->regexp()->type() == MIRType::Object);
    2395           0 :     MOZ_ASSERT(ins->string()->type() == MIRType::String);
    2396           0 :     MOZ_ASSERT(ins->lastIndex()->type() == MIRType::Int32);
    2397             : 
    2398           0 :     LRegExpMatcher* lir = new(alloc()) LRegExpMatcher(useFixedAtStart(ins->regexp(), RegExpMatcherRegExpReg),
    2399           0 :                                                       useFixedAtStart(ins->string(), RegExpMatcherStringReg),
    2400           0 :                                                       useFixedAtStart(ins->lastIndex(), RegExpMatcherLastIndexReg));
    2401           0 :     defineReturn(lir, ins);
    2402           0 :     assignSafepoint(lir, ins);
    2403           0 : }
    2404             : 
    2405             : void
    2406           0 : LIRGenerator::visitRegExpSearcher(MRegExpSearcher* ins)
    2407             : {
    2408           0 :     MOZ_ASSERT(ins->regexp()->type() == MIRType::Object);
    2409           0 :     MOZ_ASSERT(ins->string()->type() == MIRType::String);
    2410           0 :     MOZ_ASSERT(ins->lastIndex()->type() == MIRType::Int32);
    2411             : 
    2412           0 :     LRegExpSearcher* lir = new(alloc()) LRegExpSearcher(useFixedAtStart(ins->regexp(), RegExpTesterRegExpReg),
    2413           0 :                                                         useFixedAtStart(ins->string(), RegExpTesterStringReg),
    2414           0 :                                                         useFixedAtStart(ins->lastIndex(), RegExpTesterLastIndexReg));
    2415           0 :     defineReturn(lir, ins);
    2416           0 :     assignSafepoint(lir, ins);
    2417           0 : }
    2418             : 
    2419             : void
    2420           0 : LIRGenerator::visitRegExpTester(MRegExpTester* ins)
    2421             : {
    2422           0 :     MOZ_ASSERT(ins->regexp()->type() == MIRType::Object);
    2423           0 :     MOZ_ASSERT(ins->string()->type() == MIRType::String);
    2424           0 :     MOZ_ASSERT(ins->lastIndex()->type() == MIRType::Int32);
    2425             : 
    2426           0 :     LRegExpTester* lir = new(alloc()) LRegExpTester(useFixedAtStart(ins->regexp(), RegExpTesterRegExpReg),
    2427           0 :                                                     useFixedAtStart(ins->string(), RegExpTesterStringReg),
    2428           0 :                                                     useFixedAtStart(ins->lastIndex(), RegExpTesterLastIndexReg));
    2429           0 :     defineReturn(lir, ins);
    2430           0 :     assignSafepoint(lir, ins);
    2431           0 : }
    2432             : 
    2433             : void
    2434           0 : LIRGenerator::visitRegExpPrototypeOptimizable(MRegExpPrototypeOptimizable* ins)
    2435             : {
    2436           0 :     MOZ_ASSERT(ins->object()->type() == MIRType::Object);
    2437           0 :     MOZ_ASSERT(ins->type() == MIRType::Boolean);
    2438           0 :     LRegExpPrototypeOptimizable* lir = new(alloc()) LRegExpPrototypeOptimizable(useRegister(ins->object()),
    2439           0 :                                                                                 temp());
    2440           0 :     define(lir, ins);
    2441           0 : }
    2442             : 
    2443             : void
    2444           0 : LIRGenerator::visitRegExpInstanceOptimizable(MRegExpInstanceOptimizable* ins)
    2445             : {
    2446           0 :     MOZ_ASSERT(ins->object()->type() == MIRType::Object);
    2447           0 :     MOZ_ASSERT(ins->proto()->type() == MIRType::Object);
    2448           0 :     MOZ_ASSERT(ins->type() == MIRType::Boolean);
    2449           0 :     LRegExpInstanceOptimizable* lir = new(alloc()) LRegExpInstanceOptimizable(useRegister(ins->object()),
    2450           0 :                                                                               useRegister(ins->proto()),
    2451           0 :                                                                               temp());
    2452           0 :     define(lir, ins);
    2453           0 : }
    2454             : 
    2455             : void
    2456           0 : LIRGenerator::visitGetFirstDollarIndex(MGetFirstDollarIndex* ins)
    2457             : {
    2458           0 :     MOZ_ASSERT(ins->str()->type() == MIRType::String);
    2459           0 :     MOZ_ASSERT(ins->type() == MIRType::Int32);
    2460           0 :     LGetFirstDollarIndex* lir = new(alloc()) LGetFirstDollarIndex(useRegister(ins->str()),
    2461           0 :                                                                   temp(), temp(), temp());
    2462           0 :     define(lir, ins);
    2463           0 :     assignSafepoint(lir, ins);
    2464           0 : }
    2465             : 
    2466             : void
    2467           0 : LIRGenerator::visitStringReplace(MStringReplace* ins)
    2468             : {
    2469           0 :     MOZ_ASSERT(ins->pattern()->type() == MIRType::String);
    2470           0 :     MOZ_ASSERT(ins->string()->type() == MIRType::String);
    2471           0 :     MOZ_ASSERT(ins->replacement()->type() == MIRType::String);
    2472             : 
    2473           0 :     LStringReplace* lir = new(alloc()) LStringReplace(useRegisterOrConstantAtStart(ins->string()),
    2474           0 :                                                       useRegisterAtStart(ins->pattern()),
    2475           0 :                                                       useRegisterOrConstantAtStart(ins->replacement()));
    2476           0 :     defineReturn(lir, ins);
    2477           0 :     assignSafepoint(lir, ins);
    2478           0 : }
    2479             : 
    2480             : void
    2481           0 : LIRGenerator::visitBinarySharedStub(MBinarySharedStub* ins)
    2482             : {
    2483           0 :     MDefinition* lhs = ins->getOperand(0);
    2484           0 :     MDefinition* rhs = ins->getOperand(1);
    2485             : 
    2486           0 :     MOZ_ASSERT(ins->type() == MIRType::Value);
    2487           0 :     MOZ_ASSERT(ins->type() == MIRType::Value);
    2488             : 
    2489           0 :     LBinarySharedStub* lir = new(alloc()) LBinarySharedStub(useBoxFixedAtStart(lhs, R0),
    2490           0 :                                                             useBoxFixedAtStart(rhs, R1));
    2491           0 :     defineSharedStubReturn(lir, ins);
    2492           0 :     assignSafepoint(lir, ins);
    2493           0 : }
    2494             : 
    2495             : void
    2496           0 : LIRGenerator::visitUnarySharedStub(MUnarySharedStub* ins)
    2497             : {
    2498           0 :     MDefinition* input = ins->getOperand(0);
    2499           0 :     MOZ_ASSERT(ins->type() == MIRType::Value);
    2500             : 
    2501           0 :     LUnarySharedStub* lir = new(alloc()) LUnarySharedStub(useBoxFixedAtStart(input, R0));
    2502           0 :     defineSharedStubReturn(lir, ins);
    2503           0 :     assignSafepoint(lir, ins);
    2504           0 : }
    2505             : 
    2506             : void
    2507           0 : LIRGenerator::visitNullarySharedStub(MNullarySharedStub* ins)
    2508             : {
    2509           0 :     MOZ_ASSERT(ins->type() == MIRType::Value);
    2510             : 
    2511           0 :     LNullarySharedStub* lir = new(alloc()) LNullarySharedStub();
    2512             : 
    2513           0 :     defineSharedStubReturn(lir, ins);
    2514           0 :     assignSafepoint(lir, ins);
    2515           0 : }
    2516             : 
    2517             : void
    2518          10 : LIRGenerator::visitLambda(MLambda* ins)
    2519             : {
    2520          10 :     if (ins->info().singletonType || ins->info().useSingletonForClone) {
    2521             :         // If the function has a singleton type, this instruction will only be
    2522             :         // executed once so we don't bother inlining it.
    2523             :         //
    2524             :         // If UseSingletonForClone is true, we will assign a singleton type to
    2525             :         // the clone and we have to clone the script, we can't do that inline.
    2526           0 :         LLambdaForSingleton* lir = new(alloc())
    2527           0 :             LLambdaForSingleton(useRegisterAtStart(ins->environmentChain()));
    2528           0 :         defineReturn(lir, ins);
    2529           0 :         assignSafepoint(lir, ins);
    2530             :     } else {
    2531          10 :         LLambda* lir = new(alloc()) LLambda(useRegister(ins->environmentChain()), temp());
    2532          10 :         define(lir, ins);
    2533          10 :         assignSafepoint(lir, ins);
    2534             :     }
    2535          10 : }
    2536             : 
    2537             : void
    2538           0 : LIRGenerator::visitLambdaArrow(MLambdaArrow* ins)
    2539             : {
    2540           0 :     MOZ_ASSERT(ins->environmentChain()->type() == MIRType::Object);
    2541           0 :     MOZ_ASSERT(ins->newTargetDef()->type() == MIRType::Value);
    2542             : 
    2543           0 :     LLambdaArrow* lir = new(alloc()) LLambdaArrow(useRegister(ins->environmentChain()),
    2544           0 :                                                   useBox(ins->newTargetDef()));
    2545           0 :     define(lir, ins);
    2546           0 :     assignSafepoint(lir, ins);
    2547           0 : }
    2548             : 
    2549             : void
    2550           0 : LIRGenerator::visitSetFunName(MSetFunName* ins)
    2551             : {
    2552           0 :     MOZ_ASSERT(ins->fun()->type() == MIRType::Object);
    2553           0 :     MOZ_ASSERT(ins->name()->type() == MIRType::Value);
    2554             : 
    2555           0 :     LSetFunName* lir = new(alloc()) LSetFunName(useRegisterAtStart(ins->fun()),
    2556           0 :                                                 useBoxAtStart(ins->name()));
    2557           0 :     add(lir, ins);
    2558           0 :     assignSafepoint(lir, ins);
    2559           0 : }
    2560             : 
    2561             : void
    2562           0 : LIRGenerator::visitNewLexicalEnvironmentObject(MNewLexicalEnvironmentObject* ins)
    2563             : {
    2564           0 :     MDefinition* enclosing = ins->enclosing();
    2565           0 :     MOZ_ASSERT(enclosing->type() == MIRType::Object);
    2566             : 
    2567             :     LNewLexicalEnvironmentObject* lir =
    2568           0 :         new(alloc()) LNewLexicalEnvironmentObject(useRegisterAtStart(enclosing));
    2569             : 
    2570           0 :     defineReturn(lir, ins);
    2571           0 :     assignSafepoint(lir, ins);
    2572           0 : }
    2573             : 
    2574             : void
    2575           0 : LIRGenerator::visitCopyLexicalEnvironmentObject(MCopyLexicalEnvironmentObject* ins)
    2576             : {
    2577           0 :     MDefinition* env = ins->env();
    2578           0 :     MOZ_ASSERT(env->type() == MIRType::Object);
    2579             : 
    2580             :     LCopyLexicalEnvironmentObject* lir =
    2581           0 :         new(alloc()) LCopyLexicalEnvironmentObject(useRegisterAtStart(env));
    2582             : 
    2583           0 :     defineReturn(lir, ins);
    2584           0 :     assignSafepoint(lir, ins);
    2585           0 : }
    2586             : 
    2587             : void
    2588           2 : LIRGenerator::visitKeepAliveObject(MKeepAliveObject* ins)
    2589             : {
    2590           2 :     MDefinition* obj = ins->object();
    2591           2 :     MOZ_ASSERT(obj->type() == MIRType::Object);
    2592             : 
    2593           2 :     add(new(alloc()) LKeepAliveObject(useKeepalive(obj)), ins);
    2594           2 : }
    2595             : 
    2596             : void
    2597           7 : LIRGenerator::visitSlots(MSlots* ins)
    2598             : {
    2599           7 :     define(new(alloc()) LSlots(useRegisterAtStart(ins->object())), ins);
    2600           7 : }
    2601             : 
    2602             : void
    2603           7 : LIRGenerator::visitElements(MElements* ins)
    2604             : {
    2605           7 :     define(new(alloc()) LElements(useRegisterAtStart(ins->object())), ins);
    2606           7 : }
    2607             : 
    2608             : void
    2609           0 : LIRGenerator::visitConstantElements(MConstantElements* ins)
    2610             : {
    2611           0 :     define(new(alloc()) LPointer(ins->value().unwrap(/*safe - pointer does not flow back to C++*/),
    2612           0 :                                  LPointer::NON_GC_THING),
    2613           0 :            ins);
    2614           0 : }
    2615             : 
    2616             : void
    2617           0 : LIRGenerator::visitConvertElementsToDoubles(MConvertElementsToDoubles* ins)
    2618             : {
    2619           0 :     LInstruction* check = new(alloc()) LConvertElementsToDoubles(useRegister(ins->elements()));
    2620           0 :     add(check, ins);
    2621           0 :     assignSafepoint(check, ins);
    2622           0 : }
    2623             : 
    2624             : void
    2625           0 : LIRGenerator::visitMaybeToDoubleElement(MMaybeToDoubleElement* ins)
    2626             : {
    2627           0 :     MOZ_ASSERT(ins->elements()->type() == MIRType::Elements);
    2628           0 :     MOZ_ASSERT(ins->value()->type() == MIRType::Int32);
    2629             : 
    2630           0 :     LMaybeToDoubleElement* lir = new(alloc()) LMaybeToDoubleElement(useRegisterAtStart(ins->elements()),
    2631           0 :                                                                     useRegisterAtStart(ins->value()),
    2632           0 :                                                                     tempDouble());
    2633           0 :     defineBox(lir, ins);
    2634           0 : }
    2635             : 
    2636             : void
    2637           0 : LIRGenerator::visitMaybeCopyElementsForWrite(MMaybeCopyElementsForWrite* ins)
    2638             : {
    2639           0 :     LInstruction* check = new(alloc()) LMaybeCopyElementsForWrite(useRegister(ins->object()), temp());
    2640           0 :     add(check, ins);
    2641           0 :     assignSafepoint(check, ins);
    2642           0 : }
    2643             : 
    2644             : void
    2645           7 : LIRGenerator::visitLoadSlot(MLoadSlot* ins)
    2646             : {
    2647           7 :     switch (ins->type()) {
    2648             :       case MIRType::Value:
    2649           0 :         defineBox(new(alloc()) LLoadSlotV(useRegisterAtStart(ins->slots())), ins);
    2650           0 :         break;
    2651             : 
    2652             :       case MIRType::Undefined:
    2653             :       case MIRType::Null:
    2654           0 :         MOZ_CRASH("typed load must have a payload");
    2655             : 
    2656             :       default:
    2657           7 :         define(new(alloc()) LLoadSlotT(useRegisterForTypedLoad(ins->slots(), ins->type())), ins);
    2658           7 :         break;
    2659             :     }
    2660           7 : }
    2661             : 
    2662             : void
    2663           6 : LIRGenerator::visitFunctionEnvironment(MFunctionEnvironment* ins)
    2664             : {
    2665           6 :     define(new(alloc()) LFunctionEnvironment(useRegisterAtStart(ins->function())), ins);
    2666           6 : }
    2667             : 
    2668             : void
    2669           5 : LIRGenerator::visitInterruptCheck(MInterruptCheck* ins)
    2670             : {
    2671           5 :     LInstruction* lir = new(alloc()) LInterruptCheck(temp());
    2672           5 :     add(lir, ins);
    2673           5 :     assignSafepoint(lir, ins);
    2674           5 : }
    2675             : 
    2676             : void
    2677           0 : LIRGenerator::visitWasmTrap(MWasmTrap* ins)
    2678             : {
    2679           0 :     add(new(alloc()) LWasmTrap, ins);
    2680           0 : }
    2681             : 
    2682             : void
    2683           0 : LIRGenerator::visitWasmReinterpret(MWasmReinterpret* ins)
    2684             : {
    2685           0 :     if (ins->type() == MIRType::Int64)
    2686           0 :         defineInt64(new(alloc()) LWasmReinterpretToI64(useRegisterAtStart(ins->input())), ins);
    2687           0 :     else if (ins->input()->type() == MIRType::Int64)
    2688           0 :         define(new(alloc()) LWasmReinterpretFromI64(useInt64RegisterAtStart(ins->input())), ins);
    2689             :     else
    2690           0 :         define(new(alloc()) LWasmReinterpret(useRegisterAtStart(ins->input())), ins);
    2691           0 : }
    2692             : 
    2693             : void
    2694           0 : LIRGenerator::visitStoreSlot(MStoreSlot* ins)
    2695             : {
    2696             :     LInstruction* lir;
    2697             : 
    2698           0 :     switch (ins->value()->type()) {
    2699             :       case MIRType::Value:
    2700           0 :         lir = new(alloc()) LStoreSlotV(useRegister(ins->slots()), useBox(ins->value()));
    2701           0 :         add(lir, ins);
    2702           0 :         break;
    2703             : 
    2704             :       case MIRType::Double:
    2705           0 :         add(new(alloc()) LStoreSlotT(useRegister(ins->slots()), useRegister(ins->value())), ins);
    2706           0 :         break;
    2707             : 
    2708             :       case MIRType::Float32:
    2709           0 :         MOZ_CRASH("Float32 shouldn't be stored in a slot.");
    2710             : 
    2711             :       default:
    2712           0 :         add(new(alloc()) LStoreSlotT(useRegister(ins->slots()),
    2713           0 :                                      useRegisterOrConstant(ins->value())), ins);
    2714           0 :         break;
    2715             :     }
    2716           0 : }
    2717             : 
    2718             : void
    2719          10 : LIRGenerator::visitFilterTypeSet(MFilterTypeSet* ins)
    2720             : {
    2721          10 :     redefine(ins, ins->input());
    2722          10 : }
    2723             : 
    2724             : void
    2725         127 : LIRGenerator::visitTypeBarrier(MTypeBarrier* ins)
    2726             : {
    2727             :     // Requesting a non-GC pointer is safe here since we never re-enter C++
    2728             :     // from inside a type barrier test.
    2729             : 
    2730         127 :     const TemporaryTypeSet* types = ins->resultTypeSet();
    2731         127 :     bool needTemp = !types->unknownObject() && types->getObjectCount() > 0;
    2732             : 
    2733         127 :     MIRType inputType = ins->getOperand(0)->type();
    2734         127 :     MOZ_ASSERT(inputType == ins->type());
    2735             : 
    2736             :     // Handle typebarrier that will always bail.
    2737             :     // (Emit LBail for visibility).
    2738         127 :     if (ins->alwaysBails()) {
    2739           0 :         LBail* bail = new(alloc()) LBail();
    2740           0 :         assignSnapshot(bail, Bailout_Inevitable);
    2741           0 :         add(bail, ins);
    2742           0 :         redefine(ins, ins->input());
    2743           0 :         return;
    2744             :     }
    2745             : 
    2746             :     // Handle typebarrier with Value as input.
    2747         127 :     if (inputType == MIRType::Value) {
    2748          47 :         LDefinition tmp = needTemp ? temp() : tempToUnbox();
    2749          47 :         LTypeBarrierV* barrier = new(alloc()) LTypeBarrierV(useBox(ins->input()), tmp);
    2750          47 :         assignSnapshot(barrier, Bailout_TypeBarrierV);
    2751          47 :         add(barrier, ins);
    2752          47 :         redefine(ins, ins->input());
    2753          47 :         return;
    2754             :     }
    2755             : 
    2756             :     // The payload needs to be tested if it either might be null or might have
    2757             :     // an object that should be excluded from the barrier.
    2758          80 :     bool needsObjectBarrier = false;
    2759          80 :     if (inputType == MIRType::ObjectOrNull)
    2760           0 :         needsObjectBarrier = true;
    2761         101 :     if (inputType == MIRType::Object && !types->hasType(TypeSet::AnyObjectType()) &&
    2762          21 :         ins->barrierKind() != BarrierKind::TypeTagOnly)
    2763             :     {
    2764          21 :         needsObjectBarrier = true;
    2765             :     }
    2766             : 
    2767          80 :     if (needsObjectBarrier) {
    2768          21 :         LDefinition tmp = needTemp ? temp() : LDefinition::BogusTemp();
    2769          21 :         LTypeBarrierO* barrier = new(alloc()) LTypeBarrierO(useRegister(ins->getOperand(0)), tmp);
    2770          21 :         assignSnapshot(barrier, Bailout_TypeBarrierO);
    2771          21 :         add(barrier, ins);
    2772          21 :         redefine(ins, ins->getOperand(0));
    2773          21 :         return;
    2774             :     }
    2775             : 
    2776             :     // Handle remaining cases: No-op, unbox did everything.
    2777          59 :     redefine(ins, ins->getOperand(0));
    2778             : }
    2779             : 
    2780             : void
    2781           0 : LIRGenerator::visitMonitorTypes(MMonitorTypes* ins)
    2782             : {
    2783             :     // Requesting a non-GC pointer is safe here since we never re-enter C++
    2784             :     // from inside a type check.
    2785             : 
    2786           0 :     const TemporaryTypeSet* types = ins->typeSet();
    2787           0 :     bool needTemp = !types->unknownObject() && types->getObjectCount() > 0;
    2788           0 :     LDefinition tmp = needTemp ? temp() : tempToUnbox();
    2789             : 
    2790           0 :     LMonitorTypes* lir = new(alloc()) LMonitorTypes(useBox(ins->input()), tmp);
    2791           0 :     assignSnapshot(lir, Bailout_MonitorTypes);
    2792           0 :     add(lir, ins);
    2793           0 : }
    2794             : 
    2795             : // Returns true iff |def| is a constant that's either not a GC thing or is not
    2796             : // allocated in the nursery.
    2797             : static bool
    2798           8 : IsNonNurseryConstant(MDefinition* def)
    2799             : {
    2800           8 :     if (!def->isConstant())
    2801           6 :         return false;
    2802           2 :     Value v = def->toConstant()->toJSValue();
    2803           2 :     return !v.isGCThing() || !IsInsideNursery(v.toGCThing());
    2804             : }
    2805             : 
    2806             : void
    2807           2 : LIRGenerator::visitPostWriteBarrier(MPostWriteBarrier* ins)
    2808             : {
    2809           2 :     MOZ_ASSERT(ins->object()->type() == MIRType::Object);
    2810             : 
    2811             :     // LPostWriteBarrier assumes that if it has a constant object then that
    2812             :     // object is tenured, and does not need to be tested for being in the
    2813             :     // nursery. Ensure that assumption holds by lowering constant nursery
    2814             :     // objects to a register.
    2815           2 :     bool useConstantObject = IsNonNurseryConstant(ins->object());
    2816             : 
    2817           2 :     switch (ins->value()->type()) {
    2818             :       case MIRType::Object:
    2819             :       case MIRType::ObjectOrNull: {
    2820           1 :         LDefinition tmp = needTempForPostBarrier() ? temp() : LDefinition::BogusTemp();
    2821             :         LPostWriteBarrierO* lir =
    2822           1 :             new(alloc()) LPostWriteBarrierO(useConstantObject
    2823           3 :                                             ? useOrConstant(ins->object())
    2824           3 :                                             : useRegister(ins->object()),
    2825           2 :                                             useRegister(ins->value()), tmp);
    2826           1 :         add(lir, ins);
    2827           1 :         assignSafepoint(lir, ins);
    2828           1 :         break;
    2829             :       }
    2830             :       case MIRType::Value: {
    2831           1 :         LDefinition tmp = needTempForPostBarrier() ? temp() : LDefinition::BogusTemp();
    2832             :         LPostWriteBarrierV* lir =
    2833           1 :             new(alloc()) LPostWriteBarrierV(useConstantObject
    2834           3 :                                             ? useOrConstant(ins->object())
    2835           3 :                                             : useRegister(ins->object()),
    2836           2 :                                             useBox(ins->value()),
    2837           3 :                                             tmp);
    2838           1 :         add(lir, ins);
    2839           1 :         assignSafepoint(lir, ins);
    2840           1 :         break;
    2841             :       }
    2842             :       default:
    2843             :         // Currently, only objects can be in the nursery. Other instruction
    2844             :         // types cannot hold nursery pointers.
    2845           0 :         break;
    2846             :     }
    2847           2 : }
    2848             : 
    2849             : void
    2850           0 : LIRGenerator::visitPostWriteElementBarrier(MPostWriteElementBarrier* ins)
    2851             : {
    2852           0 :     MOZ_ASSERT(ins->object()->type() == MIRType::Object);
    2853           0 :     MOZ_ASSERT(ins->index()->type() == MIRType::Int32);
    2854             : 
    2855             :     // LPostWriteElementBarrier assumes that if it has a constant object then that
    2856             :     // object is tenured, and does not need to be tested for being in the
    2857             :     // nursery. Ensure that assumption holds by lowering constant nursery
    2858             :     // objects to a register.
    2859             :     bool useConstantObject =
    2860           0 :         ins->object()->isConstant() &&
    2861           0 :         !IsInsideNursery(&ins->object()->toConstant()->toObject());
    2862             : 
    2863           0 :     switch (ins->value()->type()) {
    2864             :       case MIRType::Object:
    2865             :       case MIRType::ObjectOrNull: {
    2866           0 :         LDefinition tmp = needTempForPostBarrier() ? temp() : LDefinition::BogusTemp();
    2867             :         LPostWriteElementBarrierO* lir =
    2868           0 :             new(alloc()) LPostWriteElementBarrierO(useConstantObject
    2869           0 :                                                    ? useOrConstant(ins->object())
    2870           0 :                                                    : useRegister(ins->object()),
    2871           0 :                                                    useRegister(ins->value()),
    2872           0 :                                                    useRegister(ins->index()),
    2873           0 :                                                    tmp);
    2874           0 :         add(lir, ins);
    2875           0 :         assignSafepoint(lir, ins);
    2876           0 :         break;
    2877             :       }
    2878             :       case MIRType::Value: {
    2879           0 :         LDefinition tmp = needTempForPostBarrier() ? temp() : LDefinition::BogusTemp();
    2880             :         LPostWriteElementBarrierV* lir =
    2881           0 :             new(alloc()) LPostWriteElementBarrierV(useConstantObject
    2882           0 :                                                    ? useOrConstant(ins->object())
    2883           0 :                                                    : useRegister(ins->object()),
    2884           0 :                                                    useRegister(ins->index()),
    2885           0 :                                                    useBox(ins->value()),
    2886           0 :                                                    tmp);
    2887           0 :         add(lir, ins);
    2888           0 :         assignSafepoint(lir, ins);
    2889           0 :         break;
    2890             :       }
    2891             :       default:
    2892             :         // Currently, only objects can be in the nursery. Other instruction
    2893             :         // types cannot hold nursery pointers.
    2894           0 :         break;
    2895             :     }
    2896           0 : }
    2897             : 
    2898             : void
    2899           2 : LIRGenerator::visitArrayLength(MArrayLength* ins)
    2900             : {
    2901           2 :     MOZ_ASSERT(ins->elements()->type() == MIRType::Elements);
    2902           2 :     define(new(alloc()) LArrayLength(useRegisterAtStart(ins->elements())), ins);
    2903           2 : }
    2904             : 
    2905             : void
    2906           0 : LIRGenerator::visitSetArrayLength(MSetArrayLength* ins)
    2907             : {
    2908           0 :     MOZ_ASSERT(ins->elements()->type() == MIRType::Elements);
    2909           0 :     MOZ_ASSERT(ins->index()->type() == MIRType::Int32);
    2910             : 
    2911           0 :     MOZ_ASSERT(ins->index()->isConstant());
    2912           0 :     add(new(alloc()) LSetArrayLength(useRegister(ins->elements()),
    2913           0 :                                      useRegisterOrConstant(ins->index())), ins);
    2914           0 : }
    2915             : 
    2916             : void
    2917           0 : LIRGenerator::visitGetNextEntryForIterator(MGetNextEntryForIterator* ins)
    2918             : {
    2919           0 :     MOZ_ASSERT(ins->iter()->type() == MIRType::Object);
    2920           0 :     MOZ_ASSERT(ins->result()->type() == MIRType::Object);
    2921           0 :     auto lir = new(alloc()) LGetNextEntryForIterator(useRegister(ins->iter()),
    2922           0 :                                                      useRegister(ins->result()),
    2923           0 :                                                      temp(), temp(), temp());
    2924           0 :     define(lir, ins);
    2925           0 :     assignSafepoint(lir, ins);
    2926           0 : }
    2927             : 
    2928             : void
    2929           0 : LIRGenerator::visitTypedArrayLength(MTypedArrayLength* ins)
    2930             : {
    2931           0 :     MOZ_ASSERT(ins->object()->type() == MIRType::Object);
    2932           0 :     define(new(alloc()) LTypedArrayLength(useRegisterAtStart(ins->object())), ins);
    2933           0 : }
    2934             : 
    2935             : void
    2936           0 : LIRGenerator::visitTypedArrayElements(MTypedArrayElements* ins)
    2937             : {
    2938           0 :     MOZ_ASSERT(ins->type() == MIRType::Elements);
    2939           0 :     define(new(alloc()) LTypedArrayElements(useRegisterAtStart(ins->object())), ins);
    2940           0 : }
    2941             : 
    2942             : void
    2943           0 : LIRGenerator::visitSetDisjointTypedElements(MSetDisjointTypedElements* ins)
    2944             : {
    2945           0 :     MOZ_ASSERT(ins->type() == MIRType::None);
    2946             : 
    2947           0 :     MDefinition* target = ins->target();
    2948           0 :     MOZ_ASSERT(target->type() == MIRType::Object);
    2949             : 
    2950           0 :     MDefinition* targetOffset = ins->targetOffset();
    2951           0 :     MOZ_ASSERT(targetOffset->type() == MIRType::Int32);
    2952             : 
    2953           0 :     MDefinition* source = ins->source();
    2954           0 :     MOZ_ASSERT(source->type() == MIRType::Object);
    2955             : 
    2956           0 :     auto lir = new(alloc()) LSetDisjointTypedElements(useRegister(target),
    2957           0 :                                                       useRegister(targetOffset),
    2958           0 :                                                       useRegister(source),
    2959           0 :                                                       temp());
    2960           0 :     add(lir, ins);
    2961           0 : }
    2962             : 
    2963             : void
    2964           0 : LIRGenerator::visitTypedObjectDescr(MTypedObjectDescr* ins)
    2965             : {
    2966           0 :     MOZ_ASSERT(ins->type() == MIRType::Object);
    2967           0 :     define(new(alloc()) LTypedObjectDescr(useRegisterAtStart(ins->object())), ins);
    2968           0 : }
    2969             : 
    2970             : void
    2971           0 : LIRGenerator::visitTypedObjectElements(MTypedObjectElements* ins)
    2972             : {
    2973           0 :     MOZ_ASSERT(ins->type() == MIRType::Elements);
    2974           0 :     define(new(alloc()) LTypedObjectElements(useRegister(ins->object())), ins);
    2975           0 : }
    2976             : 
    2977             : void
    2978           0 : LIRGenerator::visitSetTypedObjectOffset(MSetTypedObjectOffset* ins)
    2979             : {
    2980           0 :     add(new(alloc()) LSetTypedObjectOffset(useRegister(ins->object()),
    2981           0 :                                            useRegister(ins->offset()),
    2982           0 :                                            temp(), temp()),
    2983           0 :         ins);
    2984           0 : }
    2985             : 
    2986             : void
    2987           1 : LIRGenerator::visitInitializedLength(MInitializedLength* ins)
    2988             : {
    2989           1 :     MOZ_ASSERT(ins->elements()->type() == MIRType::Elements);
    2990           1 :     define(new(alloc()) LInitializedLength(useRegisterAtStart(ins->elements())), ins);
    2991           1 : }
    2992             : 
    2993             : void
    2994           4 : LIRGenerator::visitSetInitializedLength(MSetInitializedLength* ins)
    2995             : {
    2996           4 :     MOZ_ASSERT(ins->elements()->type() == MIRType::Elements);
    2997           4 :     MOZ_ASSERT(ins->index()->type() == MIRType::Int32);
    2998             : 
    2999           4 :     MOZ_ASSERT(ins->index()->isConstant());
    3000          16 :     add(new(alloc()) LSetInitializedLength(useRegister(ins->elements()),
    3001          12 :                                            useRegisterOrConstant(ins->index())), ins);
    3002           4 : }
    3003             : 
    3004             : void
    3005           0 : LIRGenerator::visitUnboxedArrayLength(MUnboxedArrayLength* ins)
    3006             : {
    3007           0 :     define(new(alloc()) LUnboxedArrayLength(useRegisterAtStart(ins->object())), ins);
    3008           0 : }
    3009             : 
    3010             : void
    3011           0 : LIRGenerator::visitUnboxedArrayInitializedLength(MUnboxedArrayInitializedLength* ins)
    3012             : {
    3013           0 :     define(new(alloc()) LUnboxedArrayInitializedLength(useRegisterAtStart(ins->object())), ins);
    3014           0 : }
    3015             : 
    3016             : void
    3017           0 : LIRGenerator::visitIncrementUnboxedArrayInitializedLength(MIncrementUnboxedArrayInitializedLength* ins)
    3018             : {
    3019           0 :     add(new(alloc()) LIncrementUnboxedArrayInitializedLength(useRegister(ins->object())), ins);
    3020           0 : }
    3021             : 
    3022             : void
    3023           0 : LIRGenerator::visitSetUnboxedArrayInitializedLength(MSetUnboxedArrayInitializedLength* ins)
    3024             : {
    3025           0 :     add(new(alloc()) LSetUnboxedArrayInitializedLength(useRegister(ins->object()),
    3026           0 :                                                        useRegisterOrConstant(ins->length()),
    3027           0 :                                                        temp()), ins);
    3028           0 : }
    3029             : 
    3030             : void
    3031           2 : LIRGenerator::visitNot(MNot* ins)
    3032             : {
    3033           2 :     MDefinition* op = ins->input();
    3034             : 
    3035             :     // String is converted to length of string in the type analysis phase (see
    3036             :     // TestPolicy).
    3037           2 :     MOZ_ASSERT(op->type() != MIRType::String);
    3038             : 
    3039             :     // - boolean: x xor 1
    3040             :     // - int32: LCompare(x, 0)
    3041             :     // - double: LCompare(x, 0)
    3042             :     // - null or undefined: true
    3043             :     // - object: false if it never emulates undefined, else LNotO(x)
    3044           2 :     switch (op->type()) {
    3045             :       case MIRType::Boolean: {
    3046           0 :         MConstant* cons = MConstant::New(alloc(), Int32Value(1));
    3047           0 :         ins->block()->insertBefore(ins, cons);
    3048           0 :         lowerForALU(new(alloc()) LBitOpI(JSOP_BITXOR), ins, op, cons);
    3049           0 :         break;
    3050             :       }
    3051             :       case MIRType::Int32:
    3052           0 :         define(new(alloc()) LNotI(useRegisterAtStart(op)), ins);
    3053           0 :         break;
    3054             :       case MIRType::Int64:
    3055           0 :         define(new(alloc()) LNotI64(useInt64RegisterAtStart(op)), ins);
    3056           0 :         break;
    3057             :       case MIRType::Double:
    3058           0 :         define(new(alloc()) LNotD(useRegister(op)), ins);
    3059           0 :         break;
    3060             :       case MIRType::Float32:
    3061           0 :         define(new(alloc()) LNotF(useRegister(op)), ins);
    3062           0 :         break;
    3063             :       case MIRType::Undefined:
    3064             :       case MIRType::Null:
    3065           0 :         define(new(alloc()) LInteger(1), ins);
    3066           0 :         break;
    3067             :       case MIRType::Symbol:
    3068           0 :         define(new(alloc()) LInteger(0), ins);
    3069           0 :         break;
    3070             :       case MIRType::Object:
    3071           0 :         if (!ins->operandMightEmulateUndefined()) {
    3072             :             // Objects that don't emulate undefined can be constant-folded.
    3073           0 :             define(new(alloc()) LInteger(0), ins);
    3074             :         } else {
    3075             :             // All others require further work.
    3076           0 :             define(new(alloc()) LNotO(useRegister(op)), ins);
    3077             :         }
    3078           0 :         break;
    3079             :       case MIRType::Value: {
    3080           2 :         LDefinition temp0, temp1;
    3081           2 :         if (ins->operandMightEmulateUndefined()) {
    3082           0 :             temp0 = temp();
    3083           0 :             temp1 = temp();
    3084             :         } else {
    3085           2 :             temp0 = LDefinition::BogusTemp();
    3086           2 :             temp1 = LDefinition::BogusTemp();
    3087             :         }
    3088             : 
    3089           2 :         LNotV* lir = new(alloc()) LNotV(useBox(op), tempDouble(), temp0, temp1);
    3090           2 :         define(lir, ins);
    3091           2 :         break;
    3092             :       }
    3093             : 
    3094             :       default:
    3095           0 :         MOZ_CRASH("Unexpected MIRType.");
    3096             :     }
    3097           2 : }
    3098             : 
    3099             : void
    3100           2 : LIRGenerator::visitBoundsCheck(MBoundsCheck* ins)
    3101             : {
    3102           2 :     MOZ_ASSERT(ins->index()->type() == MIRType::Int32);
    3103           2 :     MOZ_ASSERT(ins->length()->type() == MIRType::Int32);
    3104           2 :     MOZ_ASSERT(ins->type() == MIRType::Int32);
    3105             : 
    3106           2 :     if (!ins->fallible())
    3107           1 :         return;
    3108             : 
    3109             :     LInstruction* check;
    3110           1 :     if (ins->minimum() || ins->maximum()) {
    3111           0 :         check = new(alloc()) LBoundsCheckRange(useRegisterOrConstant(ins->index()),
    3112           0 :                                                useAny(ins->length()),
    3113           0 :                                                temp());
    3114             :     } else {
    3115           4 :         check = new(alloc()) LBoundsCheck(useRegisterOrConstant(ins->index()),
    3116           3 :                                           useAnyOrConstant(ins->length()));
    3117             :     }
    3118           1 :     assignSnapshot(check, Bailout_BoundsCheck);
    3119           1 :     add(check, ins);
    3120             : }
    3121             : 
    3122             : void
    3123           2 : LIRGenerator::visitBoundsCheckLower(MBoundsCheckLower* ins)
    3124             : {
    3125           2 :     MOZ_ASSERT(ins->index()->type() == MIRType::Int32);
    3126             : 
    3127           2 :     if (!ins->fallible())
    3128           0 :         return;
    3129             : 
    3130           2 :     LInstruction* check = new(alloc()) LBoundsCheckLower(useRegister(ins->index()));
    3131           2 :     assignSnapshot(check, Bailout_BoundsCheck);
    3132           2 :     add(check, ins);
    3133             : }
    3134             : 
    3135             : void
    3136           0 : LIRGenerator::visitInArray(MInArray* ins)
    3137             : {
    3138           0 :     MOZ_ASSERT(ins->elements()->type() == MIRType::Elements);
    3139           0 :     MOZ_ASSERT(ins->index()->type() == MIRType::Int32);
    3140           0 :     MOZ_ASSERT(ins->initLength()->type() == MIRType::Int32);
    3141           0 :     MOZ_ASSERT(ins->object()->type() == MIRType::Object);
    3142           0 :     MOZ_ASSERT(ins->type() == MIRType::Boolean);
    3143             : 
    3144           0 :     LAllocation object;
    3145           0 :     if (ins->needsNegativeIntCheck())
    3146           0 :         object = useRegister(ins->object());
    3147             : 
    3148           0 :     LInArray* lir = new(alloc()) LInArray(useRegister(ins->elements()),
    3149           0 :                                           useRegisterOrConstant(ins->index()),
    3150           0 :                                           useRegister(ins->initLength()),
    3151           0 :                                           object);
    3152           0 :     define(lir, ins);
    3153           0 :     assignSafepoint(lir, ins);
    3154           0 : }
    3155             : 
    3156             : void
    3157           1 : LIRGenerator::visitLoadElement(MLoadElement* ins)
    3158             : {
    3159           1 :     MOZ_ASSERT(IsValidElementsType(ins->elements(), ins->offsetAdjustment()));
    3160           1 :     MOZ_ASSERT(ins->index()->type() == MIRType::Int32);
    3161             : 
    3162           1 :     switch (ins->type()) {
    3163             :       case MIRType::Value:
    3164             :       {
    3165           0 :         LLoadElementV* lir = new(alloc()) LLoadElementV(useRegister(ins->elements()),
    3166           0 :                                                         useRegisterOrConstant(ins->index()));
    3167           0 :         if (ins->fallible())
    3168           0 :             assignSnapshot(lir, Bailout_Hole);
    3169           0 :         defineBox(lir, ins);
    3170           0 :         break;
    3171             :       }
    3172             :       case MIRType::Undefined:
    3173             :       case MIRType::Null:
    3174           0 :         MOZ_CRASH("typed load must have a payload");
    3175             : 
    3176             :       default:
    3177             :       {
    3178           3 :         LLoadElementT* lir = new(alloc()) LLoadElementT(useRegister(ins->elements()),
    3179           2 :                                                         useRegisterOrConstant(ins->index()));
    3180           1 :         if (ins->fallible())
    3181           0 :             assignSnapshot(lir, Bailout_Hole);
    3182           1 :         define(lir, ins);
    3183           1 :         break;
    3184             :       }
    3185             :     }
    3186           1 : }
    3187             : 
    3188             : void
    3189           0 : LIRGenerator::visitLoadElementHole(MLoadElementHole* ins)
    3190             : {
    3191           0 :     MOZ_ASSERT(ins->elements()->type() == MIRType::Elements);
    3192           0 :     MOZ_ASSERT(ins->index()->type() == MIRType::Int32);
    3193           0 :     MOZ_ASSERT(ins->initLength()->type() == MIRType::Int32);
    3194           0 :     MOZ_ASSERT(ins->type() == MIRType::Value);
    3195             : 
    3196           0 :     LLoadElementHole* lir = new(alloc()) LLoadElementHole(useRegister(ins->elements()),
    3197           0 :                                                           useRegisterOrConstant(ins->index()),
    3198           0 :                                                           useRegister(ins->initLength()));
    3199           0 :     if (ins->needsNegativeIntCheck())
    3200           0 :         assignSnapshot(lir, Bailout_NegativeIndex);
    3201           0 :     defineBox(lir, ins);
    3202           0 : }
    3203             : 
    3204             : void
    3205           0 : LIRGenerator::visitLoadUnboxedObjectOrNull(MLoadUnboxedObjectOrNull* ins)
    3206             : {
    3207           0 :     MOZ_ASSERT(IsValidElementsType(ins->elements(), ins->offsetAdjustment()));
    3208           0 :     MOZ_ASSERT(ins->index()->type() == MIRType::Int32);
    3209             : 
    3210           0 :     if (ins->type() == MIRType::Object || ins->type() == MIRType::ObjectOrNull) {
    3211           0 :         LLoadUnboxedPointerT* lir = new(alloc()) LLoadUnboxedPointerT(useRegister(ins->elements()),
    3212           0 :                                                                       useRegisterOrConstant(ins->index()));
    3213           0 :         if (ins->nullBehavior() == MLoadUnboxedObjectOrNull::BailOnNull)
    3214           0 :             assignSnapshot(lir, Bailout_TypeBarrierO);
    3215           0 :         define(lir, ins);
    3216             :     } else {
    3217           0 :         MOZ_ASSERT(ins->type() == MIRType::Value);
    3218           0 :         MOZ_ASSERT(ins->nullBehavior() != MLoadUnboxedObjectOrNull::BailOnNull);
    3219             : 
    3220           0 :         LLoadUnboxedPointerV* lir = new(alloc()) LLoadUnboxedPointerV(useRegister(ins->elements()),
    3221           0 :                                                                       useRegisterOrConstant(ins->index()));
    3222           0 :         defineBox(lir, ins);
    3223             :     }
    3224           0 : }
    3225             : 
    3226             : void
    3227           0 : LIRGenerator::visitLoadUnboxedString(MLoadUnboxedString* ins)
    3228             : {
    3229           0 :     MOZ_ASSERT(IsValidElementsType(ins->elements(), ins->offsetAdjustment()));
    3230           0 :     MOZ_ASSERT(ins->index()->type() == MIRType::Int32);
    3231           0 :     MOZ_ASSERT(ins->type() == MIRType::String);
    3232             : 
    3233           0 :     LLoadUnboxedPointerT* lir = new(alloc()) LLoadUnboxedPointerT(useRegister(ins->elements()),
    3234           0 :                                                                   useRegisterOrConstant(ins->index()));
    3235           0 :     define(lir, ins);
    3236           0 : }
    3237             : 
    3238             : void
    3239           4 : LIRGenerator::visitStoreElement(MStoreElement* ins)
    3240             : {
    3241           4 :     MOZ_ASSERT(IsValidElementsType(ins->elements(), ins->offsetAdjustment()));
    3242           4 :     MOZ_ASSERT(ins->index()->type() == MIRType::Int32);
    3243             : 
    3244           4 :     const LUse elements = useRegister(ins->elements());
    3245           4 :     const LAllocation index = useRegisterOrConstant(ins->index());
    3246             : 
    3247           4 :     switch (ins->value()->type()) {
    3248             :       case MIRType::Value:
    3249             :       {
    3250           0 :         LInstruction* lir = new(alloc()) LStoreElementV(elements, index, useBox(ins->value()));
    3251           0 :         if (ins->fallible())
    3252           0 :             assignSnapshot(lir, Bailout_Hole);
    3253           0 :         add(lir, ins);
    3254           0 :         break;
    3255             :       }
    3256             : 
    3257             :       default:
    3258             :       {
    3259           4 :         const LAllocation value = useRegisterOrNonDoubleConstant(ins->value());
    3260           4 :         LInstruction* lir = new(alloc()) LStoreElementT(elements, index, value);
    3261           4 :         if (ins->fallible())
    3262           0 :             assignSnapshot(lir, Bailout_Hole);
    3263           4 :         add(lir, ins);
    3264           4 :         break;
    3265             :       }
    3266             :     }
    3267           4 : }
    3268             : 
    3269             : void
    3270           1 : LIRGenerator::visitStoreElementHole(MStoreElementHole* ins)
    3271             : {
    3272           1 :     MOZ_ASSERT(ins->elements()->type() == MIRType::Elements);
    3273           1 :     MOZ_ASSERT(ins->index()->type() == MIRType::Int32);
    3274             : 
    3275           1 :     const LUse object = useRegister(ins->object());
    3276           1 :     const LUse elements = useRegister(ins->elements());
    3277           1 :     const LAllocation index = useRegisterOrConstant(ins->index());
    3278             : 
    3279             :     // Use a temp register when adding new elements to unboxed arrays.
    3280           1 :     LDefinition tempDef = LDefinition::BogusTemp();
    3281           1 :     if (ins->unboxedType() != JSVAL_TYPE_MAGIC)
    3282           0 :         tempDef = temp();
    3283             : 
    3284             :     LInstruction* lir;
    3285           1 :     switch (ins->value()->type()) {
    3286             :       case MIRType::Value:
    3287           0 :         lir = new(alloc()) LStoreElementHoleV(object, elements, index, useBox(ins->value()),
    3288           0 :                                               tempDef);
    3289           0 :         break;
    3290             : 
    3291             :       default:
    3292             :       {
    3293           1 :         const LAllocation value = useRegisterOrNonDoubleConstant(ins->value());
    3294           1 :         lir = new(alloc()) LStoreElementHoleT(object, elements, index, value, tempDef);
    3295           1 :         break;
    3296             :       }
    3297             :     }
    3298             : 
    3299           1 :     add(lir, ins);
    3300           1 :     assignSafepoint(lir, ins);
    3301           1 : }
    3302             : 
    3303             : void
    3304           0 : LIRGenerator::visitFallibleStoreElement(MFallibleStoreElement* ins)
    3305             : {
    3306           0 :     MOZ_ASSERT(ins->elements()->type() == MIRType::Elements);
    3307           0 :     MOZ_ASSERT(ins->index()->type() == MIRType::Int32);
    3308             : 
    3309           0 :     const LUse object = useRegister(ins->object());
    3310           0 :     const LUse elements = useRegister(ins->elements());
    3311           0 :     const LAllocation index = useRegisterOrConstant(ins->index());
    3312             : 
    3313             :     // Use a temp register when adding new elements to unboxed arrays.
    3314           0 :     LDefinition tempDef = LDefinition::BogusTemp();
    3315           0 :     if (ins->unboxedType() != JSVAL_TYPE_MAGIC)
    3316           0 :         tempDef = temp();
    3317             : 
    3318             :     LInstruction* lir;
    3319           0 :     switch (ins->value()->type()) {
    3320             :       case MIRType::Value:
    3321           0 :         lir = new(alloc()) LFallibleStoreElementV(object, elements, index, useBox(ins->value()),
    3322           0 :                                                   tempDef);
    3323           0 :         break;
    3324             :       default:
    3325           0 :         const LAllocation value = useRegisterOrNonDoubleConstant(ins->value());
    3326           0 :         lir = new(alloc()) LFallibleStoreElementT(object, elements, index, value, tempDef);
    3327           0 :         break;
    3328             :     }
    3329             : 
    3330           0 :     add(lir, ins);
    3331           0 :     assignSafepoint(lir, ins);
    3332           0 : }
    3333             : 
    3334             : 
    3335             : void
    3336           0 : LIRGenerator::visitStoreUnboxedObjectOrNull(MStoreUnboxedObjectOrNull* ins)
    3337             : {
    3338           0 :     MOZ_ASSERT(IsValidElementsType(ins->elements(), ins->offsetAdjustment()));
    3339           0 :     MOZ_ASSERT(ins->index()->type() == MIRType::Int32);
    3340           0 :     MOZ_ASSERT(ins->value()->type() == MIRType::Object ||
    3341             :                ins->value()->type() == MIRType::Null ||
    3342             :                ins->value()->type() == MIRType::ObjectOrNull);
    3343             : 
    3344           0 :     const LUse elements = useRegister(ins->elements());
    3345           0 :     const LAllocation index = useRegisterOrNonDoubleConstant(ins->index());
    3346           0 :     const LAllocation value = useRegisterOrNonDoubleConstant(ins->value());
    3347             : 
    3348           0 :     LInstruction* lir = new(alloc()) LStoreUnboxedPointer(elements, index, value);
    3349           0 :     add(lir, ins);
    3350           0 : }
    3351             : 
    3352             : void
    3353           0 : LIRGenerator::visitStoreUnboxedString(MStoreUnboxedString* ins)
    3354             : {
    3355           0 :     MOZ_ASSERT(IsValidElementsType(ins->elements(), ins->offsetAdjustment()));
    3356           0 :     MOZ_ASSERT(ins->index()->type() == MIRType::Int32);
    3357           0 :     MOZ_ASSERT(ins->value()->type() == MIRType::String);
    3358             : 
    3359           0 :     const LUse elements = useRegister(ins->elements());
    3360           0 :     const LAllocation index = useRegisterOrConstant(ins->index());
    3361           0 :     const LAllocation value = useRegisterOrNonDoubleConstant(ins->value());
    3362             : 
    3363           0 :     LInstruction* lir = new(alloc()) LStoreUnboxedPointer(elements, index, value);
    3364           0 :     add(lir, ins);
    3365           0 : }
    3366             : 
    3367             : void
    3368           0 : LIRGenerator::visitConvertUnboxedObjectToNative(MConvertUnboxedObjectToNative* ins)
    3369             : {
    3370           0 :     LInstruction* check = new(alloc()) LConvertUnboxedObjectToNative(useRegister(ins->object()));
    3371           0 :     add(check, ins);
    3372           0 :     assignSafepoint(check, ins);
    3373           0 : }
    3374             : 
    3375             : void
    3376           0 : LIRGenerator::visitEffectiveAddress(MEffectiveAddress* ins)
    3377             : {
    3378           0 :     define(new(alloc()) LEffectiveAddress(useRegister(ins->base()), useRegister(ins->index())), ins);
    3379           0 : }
    3380             : 
    3381             : void
    3382           0 : LIRGenerator::visitArrayPopShift(MArrayPopShift* ins)
    3383             : {
    3384           0 :     LUse object = useRegister(ins->object());
    3385             : 
    3386           0 :     switch (ins->type()) {
    3387             :       case MIRType::Value:
    3388             :       {
    3389           0 :         LArrayPopShiftV* lir = new(alloc()) LArrayPopShiftV(object, temp(), temp());
    3390           0 :         defineBox(lir, ins);
    3391           0 :         assignSafepoint(lir, ins);
    3392           0 :         break;
    3393             :       }
    3394             :       case MIRType::Undefined:
    3395             :       case MIRType::Null:
    3396           0 :         MOZ_CRASH("typed load must have a payload");
    3397             : 
    3398             :       default:
    3399             :       {
    3400           0 :         LArrayPopShiftT* lir = new(alloc()) LArrayPopShiftT(object, temp(), temp());
    3401           0 :         define(lir, ins);
    3402           0 :         assignSafepoint(lir, ins);
    3403           0 :         break;
    3404             :       }
    3405             :     }
    3406           0 : }
    3407             : 
    3408             : void
    3409           1 : LIRGenerator::visitArrayPush(MArrayPush* ins)
    3410             : {
    3411           1 :     MOZ_ASSERT(ins->type() == MIRType::Int32);
    3412             : 
    3413           1 :     LUse object = useRegister(ins->object());
    3414             : 
    3415           1 :     switch (ins->value()->type()) {
    3416             :       case MIRType::Value:
    3417             :       {
    3418           0 :         LArrayPushV* lir = new(alloc()) LArrayPushV(object, useBox(ins->value()), temp());
    3419           0 :         define(lir, ins);
    3420           0 :         assignSafepoint(lir, ins);
    3421           0 :         break;
    3422             :       }
    3423             : 
    3424             :       default:
    3425             :       {
    3426           1 :         const LAllocation value = useRegisterOrNonDoubleConstant(ins->value());
    3427           1 :         LArrayPushT* lir = new(alloc()) LArrayPushT(object, value, temp());
    3428           1 :         define(lir, ins);
    3429           1 :         assignSafepoint(lir, ins);
    3430           1 :         break;
    3431             :       }
    3432             :     }
    3433           1 : }
    3434             : 
    3435             : void
    3436           0 : LIRGenerator::visitArraySlice(MArraySlice* ins)
    3437             : {
    3438           0 :     MOZ_ASSERT(ins->type() == MIRType::Object);
    3439           0 :     MOZ_ASSERT(ins->object()->type() == MIRType::Object);
    3440           0 :     MOZ_ASSERT(ins->begin()->type() == MIRType::Int32);
    3441           0 :     MOZ_ASSERT(ins->end()->type() == MIRType::Int32);
    3442             : 
    3443           0 :     LArraySlice* lir = new(alloc()) LArraySlice(useFixedAtStart(ins->object(), CallTempReg0),
    3444           0 :                                                 useFixedAtStart(ins->begin(), CallTempReg1),
    3445           0 :                                                 useFixedAtStart(ins->end(), CallTempReg2),
    3446           0 :                                                 tempFixed(CallTempReg3),
    3447           0 :                                                 tempFixed(CallTempReg4));
    3448           0 :     defineReturn(lir, ins);
    3449           0 :     assignSafepoint(lir, ins);
    3450           0 : }
    3451             : 
    3452             : void
    3453           1 : LIRGenerator::visitArrayJoin(MArrayJoin* ins)
    3454             : {
    3455           1 :     MOZ_ASSERT(ins->type() == MIRType::String);
    3456           1 :     MOZ_ASSERT(ins->array()->type() == MIRType::Object);
    3457           1 :     MOZ_ASSERT(ins->sep()->type() == MIRType::String);
    3458             : 
    3459           3 :     LArrayJoin* lir = new(alloc()) LArrayJoin(useRegisterAtStart(ins->array()),
    3460           2 :                                               useRegisterAtStart(ins->sep()));
    3461           1 :     defineReturn(lir, ins);
    3462           1 :     assignSafepoint(lir, ins);
    3463           1 : }
    3464             : 
    3465             : void
    3466           0 : LIRGenerator::visitSinCos(MSinCos *ins)
    3467             : {
    3468           0 :     MOZ_ASSERT(ins->type() == MIRType::SinCosDouble);
    3469           0 :     MOZ_ASSERT(ins->input()->type() == MIRType::Double  ||
    3470             :                ins->input()->type() == MIRType::Float32 ||
    3471             :                ins->input()->type() == MIRType::Int32);
    3472             : 
    3473           0 :     LSinCos *lir = new (alloc()) LSinCos(useRegisterAtStart(ins->input()),
    3474           0 :                                          tempFixed(CallTempReg0),
    3475           0 :                                          temp());
    3476           0 :     defineSinCos(lir, ins);
    3477           0 : }
    3478             : 
    3479             : void
    3480           0 : LIRGenerator::visitStringSplit(MStringSplit* ins)
    3481             : {
    3482           0 :     MOZ_ASSERT(ins->type() == MIRType::Object);
    3483           0 :     MOZ_ASSERT(ins->string()->type() == MIRType::String);
    3484           0 :     MOZ_ASSERT(ins->separator()->type() == MIRType::String);
    3485             : 
    3486           0 :     LStringSplit* lir = new(alloc()) LStringSplit(useRegisterAtStart(ins->string()),
    3487           0 :                                                   useRegisterAtStart(ins->separator()));
    3488           0 :     defineReturn(lir, ins);
    3489           0 :     assignSafepoint(lir, ins);
    3490           0 : }
    3491             : 
    3492             : void
    3493           0 : LIRGenerator::visitLoadUnboxedScalar(MLoadUnboxedScalar* ins)
    3494             : {
    3495           0 :     MOZ_ASSERT(IsValidElementsType(ins->elements(), ins->offsetAdjustment()));
    3496           0 :     MOZ_ASSERT(ins->index()->type() == MIRType::Int32);
    3497             : 
    3498           0 :     const LUse elements = useRegister(ins->elements());
    3499           0 :     const LAllocation index = useRegisterOrConstant(ins->index());
    3500             : 
    3501           0 :     MOZ_ASSERT(IsNumberType(ins->type()) || IsSimdType(ins->type()) ||
    3502             :                ins->type() == MIRType::Boolean);
    3503             : 
    3504             :     // We need a temp register for Uint32Array with known double result.
    3505           0 :     LDefinition tempDef = LDefinition::BogusTemp();
    3506           0 :     if (ins->readType() == Scalar::Uint32 && IsFloatingPointType(ins->type()))
    3507           0 :         tempDef = temp();
    3508             : 
    3509           0 :     if (ins->requiresMemoryBarrier()) {
    3510           0 :         LMemoryBarrier* fence = new(alloc()) LMemoryBarrier(MembarBeforeLoad);
    3511           0 :         add(fence, ins);
    3512             :     }
    3513           0 :     LLoadUnboxedScalar* lir = new(alloc()) LLoadUnboxedScalar(elements, index, tempDef);
    3514           0 :     if (ins->fallible())
    3515           0 :         assignSnapshot(lir, Bailout_Overflow);
    3516           0 :     define(lir, ins);
    3517           0 :     if (ins->requiresMemoryBarrier()) {
    3518           0 :         LMemoryBarrier* fence = new(alloc()) LMemoryBarrier(MembarAfterLoad);
    3519           0 :         add(fence, ins);
    3520             :     }
    3521           0 : }
    3522             : 
    3523             : void
    3524           0 : LIRGenerator::visitClampToUint8(MClampToUint8* ins)
    3525             : {
    3526           0 :     MDefinition* in = ins->input();
    3527             : 
    3528           0 :     switch (in->type()) {
    3529             :       case MIRType::Boolean:
    3530           0 :         redefine(ins, in);
    3531           0 :         break;
    3532             : 
    3533             :       case MIRType::Int32:
    3534           0 :         defineReuseInput(new(alloc()) LClampIToUint8(useRegisterAtStart(in)), ins, 0);
    3535           0 :         break;
    3536             : 
    3537             :       case MIRType::Double:
    3538             :         // LClampDToUint8 clobbers its input register. Making it available as
    3539             :         // a temp copy describes this behavior to the register allocator.
    3540           0 :         define(new(alloc()) LClampDToUint8(useRegisterAtStart(in), tempCopy(in, 0)), ins);
    3541           0 :         break;
    3542             : 
    3543             :       case MIRType::Value:
    3544             :       {
    3545           0 :         LClampVToUint8* lir = new(alloc()) LClampVToUint8(useBox(in), tempDouble());
    3546           0 :         assignSnapshot(lir, Bailout_NonPrimitiveInput);
    3547           0 :         define(lir, ins);
    3548           0 :         assignSafepoint(lir, ins);
    3549           0 :         break;
    3550             :       }
    3551             : 
    3552             :       default:
    3553           0 :         MOZ_CRASH("unexpected type");
    3554             :     }
    3555           0 : }
    3556             : 
    3557             : void
    3558           0 : LIRGenerator::visitLoadTypedArrayElementHole(MLoadTypedArrayElementHole* ins)
    3559             : {
    3560           0 :     MOZ_ASSERT(ins->object()->type() == MIRType::Object);
    3561           0 :     MOZ_ASSERT(ins->index()->type() == MIRType::Int32);
    3562             : 
    3563           0 :     MOZ_ASSERT(ins->type() == MIRType::Value);
    3564             : 
    3565           0 :     const LUse object = useRegister(ins->object());
    3566           0 :     const LAllocation index = useRegisterOrConstant(ins->index());
    3567             : 
    3568           0 :     LLoadTypedArrayElementHole* lir = new(alloc()) LLoadTypedArrayElementHole(object, index);
    3569           0 :     if (ins->fallible())
    3570           0 :         assignSnapshot(lir, Bailout_Overflow);
    3571           0 :     defineBox(lir, ins);
    3572           0 :     assignSafepoint(lir, ins);
    3573           0 : }
    3574             : 
    3575             : void
    3576           0 : LIRGenerator::visitLoadTypedArrayElementStatic(MLoadTypedArrayElementStatic* ins)
    3577             : {
    3578             :     LLoadTypedArrayElementStatic* lir =
    3579           0 :         new(alloc()) LLoadTypedArrayElementStatic(useRegisterAtStart(ins->ptr()));
    3580             : 
    3581             :     // In case of out of bounds, may bail out, or may jump to ool code.
    3582           0 :     if (ins->fallible())
    3583           0 :         assignSnapshot(lir, Bailout_BoundsCheck);
    3584           0 :     define(lir, ins);
    3585           0 : }
    3586             : 
    3587             : void
    3588           0 : LIRGenerator::visitStoreUnboxedScalar(MStoreUnboxedScalar* ins)
    3589             : {
    3590           0 :     MOZ_ASSERT(IsValidElementsType(ins->elements(), ins->offsetAdjustment()));
    3591           0 :     MOZ_ASSERT(ins->index()->type() == MIRType::Int32);
    3592             : 
    3593           0 :     if (ins->isSimdWrite()) {
    3594           0 :         MOZ_ASSERT_IF(ins->writeType() == Scalar::Float32x4, ins->value()->type() == MIRType::Float32x4);
    3595           0 :         MOZ_ASSERT_IF(ins->writeType() == Scalar::Int8x16, ins->value()->type() == MIRType::Int8x16);
    3596           0 :         MOZ_ASSERT_IF(ins->writeType() == Scalar::Int16x8, ins->value()->type() == MIRType::Int16x8);
    3597           0 :         MOZ_ASSERT_IF(ins->writeType() == Scalar::Int32x4, ins->value()->type() == MIRType::Int32x4);
    3598           0 :     } else if (ins->isFloatWrite()) {
    3599           0 :         MOZ_ASSERT_IF(ins->writeType() == Scalar::Float32, ins->value()->type() == MIRType::Float32);
    3600           0 :         MOZ_ASSERT_IF(ins->writeType() == Scalar::Float64, ins->value()->type() == MIRType::Double);
    3601             :     } else {
    3602           0 :         MOZ_ASSERT(ins->value()->type() == MIRType::Int32);
    3603             :     }
    3604             : 
    3605           0 :     LUse elements = useRegister(ins->elements());
    3606           0 :     LAllocation index = useRegisterOrConstant(ins->index());
    3607           0 :     LAllocation value;
    3608             : 
    3609             :     // For byte arrays, the value has to be in a byte register on x86.
    3610           0 :     if (ins->isByteWrite())
    3611           0 :         value = useByteOpRegisterOrNonDoubleConstant(ins->value());
    3612             :     else
    3613           0 :         value = useRegisterOrNonDoubleConstant(ins->value());
    3614             : 
    3615             :     // Optimization opportunity for atomics: on some platforms there
    3616             :     // is a store instruction that incorporates the necessary
    3617             :     // barriers, and we could use that instead of separate barrier and
    3618             :     // store instructions.  See bug #1077027.
    3619           0 :     if (ins->requiresMemoryBarrier()) {
    3620           0 :         LMemoryBarrier* fence = new(alloc()) LMemoryBarrier(MembarBeforeStore);
    3621           0 :         add(fence, ins);
    3622             :     }
    3623           0 :     add(new(alloc()) LStoreUnboxedScalar(elements, index, value), ins);
    3624           0 :     if (ins->requiresMemoryBarrier()) {
    3625           0 :         LMemoryBarrier* fence = new(alloc()) LMemoryBarrier(MembarAfterStore);
    3626           0 :         add(fence, ins);
    3627             :     }
    3628           0 : }
    3629             : 
    3630             : void
    3631           0 : LIRGenerator::visitStoreTypedArrayElementHole(MStoreTypedArrayElementHole* ins)
    3632             : {
    3633           0 :     MOZ_ASSERT(ins->elements()->type() == MIRType::Elements);
    3634           0 :     MOZ_ASSERT(ins->index()->type() == MIRType::Int32);
    3635           0 :     MOZ_ASSERT(ins->length()->type() == MIRType::Int32);
    3636             : 
    3637           0 :     if (ins->isFloatWrite()) {
    3638           0 :         MOZ_ASSERT_IF(ins->arrayType() == Scalar::Float32, ins->value()->type() == MIRType::Float32);
    3639           0 :         MOZ_ASSERT_IF(ins->arrayType() == Scalar::Float64, ins->value()->type() == MIRType::Double);
    3640             :     } else {
    3641           0 :         MOZ_ASSERT(ins->value()->type() == MIRType::Int32);
    3642             :     }
    3643             : 
    3644           0 :     LUse elements = useRegister(ins->elements());
    3645           0 :     LAllocation length = useAnyOrConstant(ins->length());
    3646           0 :     LAllocation index = useRegisterOrConstant(ins->index());
    3647           0 :     LAllocation value;
    3648             : 
    3649             :     // For byte arrays, the value has to be in a byte register on x86.
    3650           0 :     if (ins->isByteWrite())
    3651           0 :         value = useByteOpRegisterOrNonDoubleConstant(ins->value());
    3652             :     else
    3653           0 :         value = useRegisterOrNonDoubleConstant(ins->value());
    3654           0 :     add(new(alloc()) LStoreTypedArrayElementHole(elements, length, index, value), ins);
    3655           0 : }
    3656             : 
    3657             : void
    3658          34 : LIRGenerator::visitLoadFixedSlot(MLoadFixedSlot* ins)
    3659             : {
    3660          34 :     MDefinition* obj = ins->object();
    3661          34 :     MOZ_ASSERT(obj->type() == MIRType::Object);
    3662             : 
    3663          34 :     MIRType type = ins->type();
    3664             : 
    3665          34 :     if (type == MIRType::Value) {
    3666          29 :         LLoadFixedSlotV* lir = new(alloc()) LLoadFixedSlotV(useRegisterAtStart(obj));
    3667          29 :         defineBox(lir, ins);
    3668             :     } else {
    3669           5 :         LLoadFixedSlotT* lir = new(alloc()) LLoadFixedSlotT(useRegisterForTypedLoad(obj, type));
    3670           5 :         define(lir, ins);
    3671             :     }
    3672          34 : }
    3673             : 
    3674             : void
    3675           1 : LIRGenerator::visitLoadFixedSlotAndUnbox(MLoadFixedSlotAndUnbox* ins)
    3676             : {
    3677           1 :     MDefinition* obj = ins->object();
    3678           1 :     MOZ_ASSERT(obj->type() == MIRType::Object);
    3679             : 
    3680           1 :     LLoadFixedSlotAndUnbox* lir = new(alloc()) LLoadFixedSlotAndUnbox(useRegisterAtStart(obj));
    3681           1 :     if (ins->fallible())
    3682           1 :         assignSnapshot(lir, ins->bailoutKind());
    3683             : 
    3684           1 :     define(lir, ins);
    3685           1 : }
    3686             : 
    3687             : void
    3688          32 : LIRGenerator::visitStoreFixedSlot(MStoreFixedSlot* ins)
    3689             : {
    3690          32 :     MOZ_ASSERT(ins->object()->type() == MIRType::Object);
    3691             : 
    3692          32 :     if (ins->value()->type() == MIRType::Value) {
    3693           3 :         LStoreFixedSlotV* lir = new(alloc()) LStoreFixedSlotV(useRegister(ins->object()),
    3694           2 :                                                               useBox(ins->value()));
    3695           1 :         add(lir, ins);
    3696             :     } else {
    3697          93 :         LStoreFixedSlotT* lir = new(alloc()) LStoreFixedSlotT(useRegister(ins->object()),
    3698          62 :                                                               useRegisterOrConstant(ins->value()));
    3699          31 :         add(lir, ins);
    3700             :     }
    3701          32 : }
    3702             : 
    3703             : void
    3704           4 : LIRGenerator::visitGetNameCache(MGetNameCache* ins)
    3705             : {
    3706           4 :     MOZ_ASSERT(ins->envObj()->type() == MIRType::Object);
    3707             : 
    3708             :     // Emit an overrecursed check: this is necessary because the cache can
    3709             :     // attach a scripted getter stub that calls this script recursively.
    3710           4 :     gen->setNeedsOverrecursedCheck();
    3711             : 
    3712           4 :     LGetNameCache* lir = new(alloc()) LGetNameCache(useRegister(ins->envObj()), temp());
    3713           4 :     defineBox(lir, ins);
    3714           4 :     assignSafepoint(lir, ins);
    3715           4 : }
    3716             : 
    3717             : void
    3718           1 : LIRGenerator::visitCallGetIntrinsicValue(MCallGetIntrinsicValue* ins)
    3719             : {
    3720           1 :     LCallGetIntrinsicValue* lir = new(alloc()) LCallGetIntrinsicValue();
    3721           1 :     defineReturn(lir, ins);
    3722           1 :     assignSafepoint(lir, ins);
    3723           1 : }
    3724             : 
    3725             : void
    3726          23 : LIRGenerator::visitGetPropertyCache(MGetPropertyCache* ins)
    3727             : {
    3728          23 :     MDefinition* value = ins->value();
    3729          23 :     MOZ_ASSERT(value->type() == MIRType::Object || value->type() == MIRType::Value);
    3730             : 
    3731          23 :     MDefinition* id = ins->idval();
    3732          23 :     MOZ_ASSERT(id->type() == MIRType::String ||
    3733             :                id->type() == MIRType::Symbol ||
    3734             :                id->type() == MIRType::Int32 ||
    3735             :                id->type() == MIRType::Value);
    3736             : 
    3737          23 :     if (ins->monitoredResult()) {
    3738             :         // Emit an overrecursed check: this is necessary because the cache can
    3739             :         // attach a scripted getter stub that calls this script recursively.
    3740          17 :         gen->setNeedsOverrecursedCheck();
    3741             :     }
    3742             : 
    3743             :     // If this is a GETPROP, the id is a constant string. Allow passing it as a
    3744             :     // constant to reduce register allocation pressure.
    3745          23 :     bool useConstId = id->type() == MIRType::String || id->type() == MIRType::Symbol;
    3746             : 
    3747             :     // We need a temp register if we can't use the output register as scratch.
    3748             :     // See IonIC::scratchRegisterForEntryJump.
    3749          23 :     LDefinition maybeTemp = LDefinition::BogusTemp();
    3750          23 :     if (ins->type() == MIRType::Double)
    3751           1 :         maybeTemp = temp();
    3752             : 
    3753          23 :     if (ins->type() == MIRType::Value) {
    3754             :         LGetPropertyCacheV* lir =
    3755          51 :             new(alloc()) LGetPropertyCacheV(useBoxOrTyped(value),
    3756          34 :                                             useBoxOrTypedOrConstant(id, useConstId),
    3757          51 :                                             maybeTemp);
    3758          17 :         defineBox(lir, ins);
    3759          17 :         assignSafepoint(lir, ins);
    3760             :     } else {
    3761             :         LGetPropertyCacheT* lir =
    3762          18 :             new(alloc()) LGetPropertyCacheT(useBoxOrTyped(value),
    3763          12 :                                             useBoxOrTypedOrConstant(id, useConstId),
    3764          18 :                                             maybeTemp);
    3765           6 :         define(lir, ins);
    3766           6 :         assignSafepoint(lir, ins);
    3767             :     }
    3768          23 : }
    3769             : 
    3770             : void
    3771           0 : LIRGenerator::visitGetPropertyPolymorphic(MGetPropertyPolymorphic* ins)
    3772             : {
    3773           0 :     MOZ_ASSERT(ins->object()->type() == MIRType::Object);
    3774             : 
    3775           0 :     if (ins->type() == MIRType::Value) {
    3776             :         LGetPropertyPolymorphicV* lir =
    3777           0 :             new(alloc()) LGetPropertyPolymorphicV(useRegister(ins->object()));
    3778           0 :         assignSnapshot(lir, Bailout_ShapeGuard);
    3779           0 :         defineBox(lir, ins);
    3780             :     } else {
    3781           0 :         LDefinition maybeTemp = (ins->type() == MIRType::Double) ? temp() : LDefinition::BogusTemp();
    3782             :         LGetPropertyPolymorphicT* lir =
    3783           0 :             new(alloc()) LGetPropertyPolymorphicT(useRegister(ins->object()), maybeTemp);
    3784           0 :         assignSnapshot(lir, Bailout_ShapeGuard);
    3785           0 :         define(lir, ins);
    3786             :     }
    3787           0 : }
    3788             : 
    3789             : void
    3790           0 : LIRGenerator::visitSetPropertyPolymorphic(MSetPropertyPolymorphic* ins)
    3791             : {
    3792           0 :     MOZ_ASSERT(ins->object()->type() == MIRType::Object);
    3793             : 
    3794           0 :     if (ins->value()->type() == MIRType::Value) {
    3795             :         LSetPropertyPolymorphicV* lir =
    3796           0 :             new(alloc()) LSetPropertyPolymorphicV(useRegister(ins->object()),
    3797           0 :                                                   useBox(ins->value()),
    3798           0 :                                                   temp());
    3799           0 :         assignSnapshot(lir, Bailout_ShapeGuard);
    3800           0 :         add(lir, ins);
    3801             :     } else {
    3802           0 :         LAllocation value = useRegisterOrConstant(ins->value());
    3803             :         LSetPropertyPolymorphicT* lir =
    3804           0 :             new(alloc()) LSetPropertyPolymorphicT(useRegister(ins->object()), value,
    3805           0 :                                                   ins->value()->type(), temp());
    3806           0 :         assignSnapshot(lir, Bailout_ShapeGuard);
    3807           0 :         add(lir, ins);
    3808             :     }
    3809           0 : }
    3810             : 
    3811             : void
    3812           0 : LIRGenerator::visitBindNameCache(MBindNameCache* ins)
    3813             : {
    3814           0 :     MOZ_ASSERT(ins->environmentChain()->type() == MIRType::Object);
    3815           0 :     MOZ_ASSERT(ins->type() == MIRType::Object);
    3816             : 
    3817           0 :     LBindNameCache* lir = new(alloc()) LBindNameCache(useRegister(ins->environmentChain()), temp());
    3818           0 :     define(lir, ins);
    3819           0 :     assignSafepoint(lir, ins);
    3820           0 : }
    3821             : 
    3822             : void
    3823           0 : LIRGenerator::visitCallBindVar(MCallBindVar* ins)
    3824             : {
    3825           0 :     MOZ_ASSERT(ins->environmentChain()->type() == MIRType::Object);
    3826           0 :     MOZ_ASSERT(ins->type() == MIRType::Object);
    3827             : 
    3828           0 :     LCallBindVar* lir = new(alloc()) LCallBindVar(useRegister(ins->environmentChain()));
    3829           0 :     define(lir, ins);
    3830           0 : }
    3831             : 
    3832             : void
    3833           0 : LIRGenerator::visitGuardObjectIdentity(MGuardObjectIdentity* ins)
    3834             : {
    3835           0 :     LGuardObjectIdentity* guard = new(alloc()) LGuardObjectIdentity(useRegister(ins->object()),
    3836           0 :                                                                     useRegister(ins->expected()));
    3837           0 :     assignSnapshot(guard, Bailout_ObjectIdentityOrTypeGuard);
    3838           0 :     add(guard, ins);
    3839           0 :     redefine(ins, ins->object());
    3840           0 : }
    3841             : 
    3842             : void
    3843           0 : LIRGenerator::visitGuardClass(MGuardClass* ins)
    3844             : {
    3845           0 :     LDefinition t = temp();
    3846           0 :     LGuardClass* guard = new(alloc()) LGuardClass(useRegister(ins->object()), t);
    3847           0 :     assignSnapshot(guard, Bailout_ObjectIdentityOrTypeGuard);
    3848           0 :     add(guard, ins);
    3849           0 : }
    3850             : 
    3851             : void
    3852           0 : LIRGenerator::visitGuardObject(MGuardObject* ins)
    3853             : {
    3854             :     // The type policy does all the work, so at this point the input
    3855             :     // is guaranteed to be an object.
    3856           0 :     MOZ_ASSERT(ins->input()->type() == MIRType::Object);
    3857           0 :     redefine(ins, ins->input());
    3858           0 : }
    3859             : 
    3860             : void
    3861           0 : LIRGenerator::visitGuardString(MGuardString* ins)
    3862             : {
    3863             :     // The type policy does all the work, so at this point the input
    3864             :     // is guaranteed to be a string.
    3865           0 :     MOZ_ASSERT(ins->input()->type() == MIRType::String);
    3866           0 :     redefine(ins, ins->input());
    3867           0 : }
    3868             : 
    3869             : void
    3870           0 : LIRGenerator::visitGuardSharedTypedArray(MGuardSharedTypedArray* ins)
    3871             : {
    3872           0 :     MOZ_ASSERT(ins->input()->type() == MIRType::Object);
    3873             :     LGuardSharedTypedArray* guard =
    3874           0 :         new(alloc()) LGuardSharedTypedArray(useRegister(ins->object()), temp());
    3875           0 :     assignSnapshot(guard, Bailout_NonSharedTypedArrayInput);
    3876           0 :     add(guard, ins);
    3877           0 : }
    3878             : 
    3879             : void
    3880           3 : LIRGenerator::visitPolyInlineGuard(MPolyInlineGuard* ins)
    3881             : {
    3882           3 :     MOZ_ASSERT(ins->input()->type() == MIRType::Object);
    3883           3 :     redefine(ins, ins->input());
    3884           3 : }
    3885             : 
    3886             : void
    3887           0 : LIRGenerator::visitGuardReceiverPolymorphic(MGuardReceiverPolymorphic* ins)
    3888             : {
    3889           0 :     MOZ_ASSERT(ins->object()->type() == MIRType::Object);
    3890           0 :     MOZ_ASSERT(ins->type() == MIRType::Object);
    3891             : 
    3892             :     LGuardReceiverPolymorphic* guard =
    3893           0 :         new(alloc()) LGuardReceiverPolymorphic(useRegister(ins->object()), temp());
    3894           0 :     assignSnapshot(guard, Bailout_ShapeGuard);
    3895           0 :     add(guard, ins);
    3896           0 :     redefine(ins, ins->object());
    3897           0 : }
    3898             : 
    3899             : void
    3900           0 : LIRGenerator::visitGuardUnboxedExpando(MGuardUnboxedExpando* ins)
    3901             : {
    3902             :     LGuardUnboxedExpando* guard =
    3903           0 :         new(alloc()) LGuardUnboxedExpando(useRegister(ins->object()));
    3904           0 :     assignSnapshot(guard, ins->bailoutKind());
    3905           0 :     add(guard, ins);
    3906           0 :     redefine(ins, ins->object());
    3907           0 : }
    3908             : 
    3909             : void
    3910           0 : LIRGenerator::visitLoadUnboxedExpando(MLoadUnboxedExpando* ins)
    3911             : {
    3912             :     LLoadUnboxedExpando* lir =
    3913           0 :         new(alloc()) LLoadUnboxedExpando(useRegisterAtStart(ins->object()));
    3914           0 :     define(lir, ins);
    3915           0 : }
    3916             : 
    3917             : void
    3918           0 : LIRGenerator::visitAssertRange(MAssertRange* ins)
    3919             : {
    3920           0 :     MDefinition* input = ins->input();
    3921           0 :     LInstruction* lir = nullptr;
    3922             : 
    3923           0 :     switch (input->type()) {
    3924             :       case MIRType::Boolean:
    3925             :       case MIRType::Int32:
    3926           0 :         lir = new(alloc()) LAssertRangeI(useRegisterAtStart(input));
    3927           0 :         break;
    3928             : 
    3929             :       case MIRType::Double:
    3930           0 :         lir = new(alloc()) LAssertRangeD(useRegister(input), tempDouble());
    3931           0 :         break;
    3932             : 
    3933             :       case MIRType::Float32:
    3934           0 :         lir = new(alloc()) LAssertRangeF(useRegister(input), tempDouble(), tempDouble());
    3935           0 :         break;
    3936             : 
    3937             :       case MIRType::Value:
    3938           0 :         lir = new(alloc()) LAssertRangeV(useBox(input), tempToUnbox(), tempDouble(), tempDouble());
    3939           0 :         break;
    3940             : 
    3941             :       default:
    3942           0 :         MOZ_CRASH("Unexpected Range for MIRType");
    3943             :         break;
    3944             :     }
    3945             : 
    3946           0 :     lir->setMir(ins);
    3947           0 :     add(lir);
    3948           0 : }
    3949             : 
    3950             : void
    3951           3 : LIRGenerator::visitCallGetProperty(MCallGetProperty* ins)
    3952             : {
    3953           3 :     LCallGetProperty* lir = new(alloc()) LCallGetProperty(useBoxAtStart(ins->value()));
    3954           3 :     defineReturn(lir, ins);
    3955           3 :     assignSafepoint(lir, ins);
    3956           3 : }
    3957             : 
    3958             : void
    3959           0 : LIRGenerator::visitCallGetElement(MCallGetElement* ins)
    3960             : {
    3961           0 :     MOZ_ASSERT(ins->lhs()->type() == MIRType::Value);
    3962           0 :     MOZ_ASSERT(ins->rhs()->type() == MIRType::Value);
    3963             : 
    3964           0 :     LCallGetElement* lir = new(alloc()) LCallGetElement(useBoxAtStart(ins->lhs()),
    3965           0 :                                                         useBoxAtStart(ins->rhs()));
    3966           0 :     defineReturn(lir, ins);
    3967           0 :     assignSafepoint(lir, ins);
    3968           0 : }
    3969             : 
    3970             : void
    3971           0 : LIRGenerator::visitCallSetProperty(MCallSetProperty* ins)
    3972             : {
    3973           0 :     LInstruction* lir = new(alloc()) LCallSetProperty(useRegisterAtStart(ins->object()),
    3974           0 :                                                       useBoxAtStart(ins->value()));
    3975           0 :     add(lir, ins);
    3976           0 :     assignSafepoint(lir, ins);
    3977           0 : }
    3978             : 
    3979             : void
    3980           0 : LIRGenerator::visitDeleteProperty(MDeleteProperty* ins)
    3981             : {
    3982           0 :     LCallDeleteProperty* lir = new(alloc()) LCallDeleteProperty(useBoxAtStart(ins->value()));
    3983           0 :     defineReturn(lir, ins);
    3984           0 :     assignSafepoint(lir, ins);
    3985           0 : }
    3986             : 
    3987             : void
    3988           0 : LIRGenerator::visitDeleteElement(MDeleteElement* ins)
    3989             : {
    3990           0 :     LCallDeleteElement* lir = new(alloc()) LCallDeleteElement(useBoxAtStart(ins->value()),
    3991           0 :                                                               useBoxAtStart(ins->index()));
    3992           0 :     defineReturn(lir, ins);
    3993           0 :     assignSafepoint(lir, ins);
    3994           0 : }
    3995             : 
    3996             : void
    3997           6 : LIRGenerator::visitSetPropertyCache(MSetPropertyCache* ins)
    3998             : {
    3999           6 :     MOZ_ASSERT(ins->object()->type() == MIRType::Object);
    4000             : 
    4001           6 :     MDefinition* id = ins->idval();
    4002           6 :     MOZ_ASSERT(id->type() == MIRType::String ||
    4003             :                id->type() == MIRType::Symbol ||
    4004             :                id->type() == MIRType::Int32 ||
    4005             :                id->type() == MIRType::Value);
    4006             : 
    4007             :     // If this is a SETPROP, the id is a constant string. Allow passing it as a
    4008             :     // constant to reduce register allocation pressure.
    4009           6 :     bool useConstId = id->type() == MIRType::String || id->type() == MIRType::Symbol;
    4010           6 :     bool useConstValue = IsNonNurseryConstant(ins->value());
    4011             : 
    4012             :     // Emit an overrecursed check: this is necessary because the cache can
    4013             :     // attach a scripted setter stub that calls this script recursively.
    4014           6 :     gen->setNeedsOverrecursedCheck();
    4015             : 
    4016             :     // We need a double/float32 temp register for typed array stubs if this is
    4017             :     // a SETELEM or INITELEM op.
    4018           6 :     LDefinition tempD = LDefinition::BogusTemp();
    4019           6 :     LDefinition tempF32 = LDefinition::BogusTemp();
    4020           6 :     if (IsElemPC(ins->resumePoint()->pc())) {
    4021           6 :         tempD = tempDouble();
    4022           6 :         tempF32 = hasUnaliasedDouble() ? tempFloat32() : LDefinition::BogusTemp();
    4023             :     }
    4024             : 
    4025             :     LInstruction* lir =
    4026          18 :         new(alloc()) LSetPropertyCache(useRegister(ins->object()),
    4027          12 :                                        useBoxOrTypedOrConstant(id, useConstId),
    4028          12 :                                        useBoxOrTypedOrConstant(ins->value(), useConstValue),
    4029          24 :                                        temp(), tempD, tempF32);
    4030           6 :     add(lir, ins);
    4031           6 :     assignSafepoint(lir, ins);
    4032           6 : }
    4033             : 
    4034             : void
    4035           0 : LIRGenerator::visitCallSetElement(MCallSetElement* ins)
    4036             : {
    4037           0 :     MOZ_ASSERT(ins->object()->type() == MIRType::Object);
    4038           0 :     MOZ_ASSERT(ins->index()->type() == MIRType::Value);
    4039           0 :     MOZ_ASSERT(ins->value()->type() == MIRType::Value);
    4040             : 
    4041           0 :     LCallSetElement* lir = new(alloc()) LCallSetElement(useRegisterAtStart(ins->object()),
    4042           0 :                                                         useBoxAtStart(ins->index()),
    4043           0 :                                                         useBoxAtStart(ins->value()));
    4044           0 :     add(lir, ins);
    4045           0 :     assignSafepoint(lir, ins);
    4046           0 : }
    4047             : 
    4048             : void
    4049           0 : LIRGenerator::visitCallInitElementArray(MCallInitElementArray* ins)
    4050             : {
    4051             :     LCallInitElementArray* lir =
    4052           0 :         new(alloc()) LCallInitElementArray(useRegisterAtStart(ins->object()),
    4053           0 :                                            useRegisterOrConstantAtStart(ins->index()),
    4054           0 :                                            useBoxAtStart(ins->value()));
    4055           0 :     add(lir, ins);
    4056           0 :     assignSafepoint(lir, ins);
    4057           0 : }
    4058             : 
    4059             : void
    4060           0 : LIRGenerator::visitIteratorStart(MIteratorStart* ins)
    4061             : {
    4062           0 :     if (ins->object()->type() == MIRType::Value) {
    4063           0 :         LCallIteratorStartV* lir = new(alloc()) LCallIteratorStartV(useBoxAtStart(ins->object()));
    4064           0 :         defineReturn(lir, ins);
    4065           0 :         assignSafepoint(lir, ins);
    4066           0 :         return;
    4067             :     }
    4068             : 
    4069           0 :     MOZ_ASSERT(ins->object()->type() == MIRType::Object);
    4070             : 
    4071             :     // Call a stub if this is not a simple for-in loop.
    4072           0 :     if (ins->flags() != JSITER_ENUMERATE) {
    4073           0 :         LCallIteratorStartO* lir = new(alloc()) LCallIteratorStartO(useRegisterAtStart(ins->object()));
    4074           0 :         defineReturn(lir, ins);
    4075           0 :         assignSafepoint(lir, ins);
    4076             :     } else {
    4077           0 :         LIteratorStartO* lir = new(alloc()) LIteratorStartO(useRegister(ins->object()), temp(), temp(), temp());
    4078           0 :         define(lir, ins);
    4079           0 :         assignSafepoint(lir, ins);
    4080             :     }
    4081             : }
    4082             : 
    4083             : void
    4084           0 : LIRGenerator::visitIteratorMore(MIteratorMore* ins)
    4085             : {
    4086           0 :     LIteratorMore* lir = new(alloc()) LIteratorMore(useRegister(ins->iterator()), temp());
    4087           0 :     defineBox(lir, ins);
    4088           0 :     assignSafepoint(lir, ins);
    4089           0 : }
    4090             : 
    4091             : void
    4092           0 : LIRGenerator::visitIsNoIter(MIsNoIter* ins)
    4093             : {
    4094           0 :     MOZ_ASSERT(ins->hasOneUse());
    4095           0 :     emitAtUses(ins);
    4096           0 : }
    4097             : 
    4098             : void
    4099           0 : LIRGenerator::visitIteratorEnd(MIteratorEnd* ins)
    4100             : {
    4101           0 :     LIteratorEnd* lir = new(alloc()) LIteratorEnd(useRegister(ins->iterator()), temp(), temp(), temp());
    4102           0 :     add(lir, ins);
    4103           0 :     assignSafepoint(lir, ins);
    4104           0 : }
    4105             : 
    4106             : void
    4107           8 : LIRGenerator::visitStringLength(MStringLength* ins)
    4108             : {
    4109           8 :     MOZ_ASSERT(ins->string()->type() == MIRType::String);
    4110           8 :     define(new(alloc()) LStringLength(useRegisterAtStart(ins->string())), ins);
    4111           8 : }
    4112             : 
    4113             : void
    4114           2 : LIRGenerator::visitArgumentsLength(MArgumentsLength* ins)
    4115             : {
    4116           2 :     define(new(alloc()) LArgumentsLength(), ins);
    4117           2 : }
    4118             : 
    4119             : void
    4120           1 : LIRGenerator::visitGetFrameArgument(MGetFrameArgument* ins)
    4121             : {
    4122           1 :     LGetFrameArgument* lir = new(alloc()) LGetFrameArgument(useRegisterOrConstant(ins->index()));
    4123           1 :     defineBox(lir, ins);
    4124           1 : }
    4125             : 
    4126             : void
    4127           0 : LIRGenerator::visitNewTarget(MNewTarget* ins)
    4128             : {
    4129           0 :     LNewTarget* lir = new(alloc()) LNewTarget();
    4130           0 :     defineBox(lir, ins);
    4131           0 : }
    4132             : 
    4133             : void
    4134           0 : LIRGenerator::visitSetFrameArgument(MSetFrameArgument* ins)
    4135             : {
    4136           0 :     MDefinition* input = ins->input();
    4137             : 
    4138           0 :     if (input->type() == MIRType::Value) {
    4139           0 :         LSetFrameArgumentV* lir = new(alloc()) LSetFrameArgumentV(useBox(input));
    4140           0 :         add(lir, ins);
    4141           0 :     } else if (input->type() == MIRType::Undefined || input->type() == MIRType::Null) {
    4142           0 :         Value val = input->type() == MIRType::Undefined ? UndefinedValue() : NullValue();
    4143           0 :         LSetFrameArgumentC* lir = new(alloc()) LSetFrameArgumentC(val);
    4144           0 :         add(lir, ins);
    4145             :     } else {
    4146           0 :         LSetFrameArgumentT* lir = new(alloc()) LSetFrameArgumentT(useRegister(input));
    4147           0 :         add(lir, ins);
    4148             :     }
    4149           0 : }
    4150             : 
    4151             : void
    4152           0 : LIRGenerator::visitRunOncePrologue(MRunOncePrologue* ins)
    4153             : {
    4154           0 :     LRunOncePrologue* lir = new(alloc()) LRunOncePrologue;
    4155           0 :     add(lir, ins);
    4156           0 :     assignSafepoint(lir, ins);
    4157           0 : }
    4158             : 
    4159             : void
    4160           1 : LIRGenerator::visitRest(MRest* ins)
    4161             : {
    4162           1 :     MOZ_ASSERT(ins->numActuals()->type() == MIRType::Int32);
    4163             : 
    4164           3 :     LRest* lir = new(alloc()) LRest(useFixedAtStart(ins->numActuals(), CallTempReg0),
    4165           2 :                                     tempFixed(CallTempReg1),
    4166           2 :                                     tempFixed(CallTempReg2),
    4167           4 :                                     tempFixed(CallTempReg3));
    4168           1 :     defineReturn(lir, ins);
    4169           1 :     assignSafepoint(lir, ins);
    4170           1 : }
    4171             : 
    4172             : void
    4173           1 : LIRGenerator::visitThrow(MThrow* ins)
    4174             : {
    4175           1 :     MDefinition* value = ins->getOperand(0);
    4176           1 :     MOZ_ASSERT(value->type() == MIRType::Value);
    4177             : 
    4178           1 :     LThrow* lir = new(alloc()) LThrow(useBoxAtStart(value));
    4179           1 :     add(lir, ins);
    4180           1 :     assignSafepoint(lir, ins);
    4181           1 : }
    4182             : 
    4183             : void
    4184           2 : LIRGenerator::visitInCache(MInCache* ins)
    4185             : {
    4186           2 :     MDefinition* lhs = ins->lhs();
    4187           2 :     MDefinition* rhs = ins->rhs();
    4188             : 
    4189           2 :     MOZ_ASSERT(lhs->type() == MIRType::String ||
    4190             :                lhs->type() == MIRType::Symbol ||
    4191             :                lhs->type() == MIRType::Int32 ||
    4192             :                lhs->type() == MIRType::Value);
    4193           2 :     MOZ_ASSERT(rhs->type() == MIRType::Object);
    4194             : 
    4195           2 :     LInCache* lir = new(alloc()) LInCache(useBoxOrTyped(lhs), useRegister(rhs), temp());
    4196           2 :     define(lir, ins);
    4197           2 :     assignSafepoint(lir, ins);
    4198           2 : }
    4199             : 
    4200             : void
    4201           0 : LIRGenerator::visitHasOwnCache(MHasOwnCache* ins)
    4202             : {
    4203           0 :     MDefinition* value = ins->value();
    4204           0 :     MOZ_ASSERT(value->type() == MIRType::Object || value->type() == MIRType::Value);
    4205             : 
    4206           0 :     MDefinition* id = ins->idval();
    4207           0 :     MOZ_ASSERT(id->type() == MIRType::String ||
    4208             :                id->type() == MIRType::Symbol ||
    4209             :                id->type() == MIRType::Int32 ||
    4210             :                id->type() == MIRType::Value);
    4211             : 
    4212             :     // Emit an overrecursed check: this is necessary because the cache can
    4213             :     // attach a scripted getter stub that calls this script recursively.
    4214           0 :     gen->setNeedsOverrecursedCheck();
    4215             : 
    4216           0 :     LHasOwnCache* lir = new(alloc()) LHasOwnCache(useBoxOrTyped(value), useBoxOrTyped(id));
    4217           0 :     define(lir, ins);
    4218           0 :     assignSafepoint(lir, ins);
    4219           0 : }
    4220             : 
    4221             : void
    4222           0 : LIRGenerator::visitInstanceOf(MInstanceOf* ins)
    4223             : {
    4224           0 :     MDefinition* lhs = ins->getOperand(0);
    4225             : 
    4226           0 :     MOZ_ASSERT(lhs->type() == MIRType::Value || lhs->type() == MIRType::Object);
    4227             : 
    4228           0 :     if (lhs->type() == MIRType::Object) {
    4229           0 :         LInstanceOfO* lir = new(alloc()) LInstanceOfO(useRegister(lhs));
    4230           0 :         define(lir, ins);
    4231           0 :         assignSafepoint(lir, ins);
    4232             :     } else {
    4233           0 :         LInstanceOfV* lir = new(alloc()) LInstanceOfV(useBox(lhs));
    4234           0 :         define(lir, ins);
    4235           0 :         assignSafepoint(lir, ins);
    4236             :     }
    4237           0 : }
    4238             : 
    4239             : void
    4240           0 : LIRGenerator::visitCallInstanceOf(MCallInstanceOf* ins)
    4241             : {
    4242           0 :     MDefinition* lhs = ins->lhs();
    4243           0 :     MDefinition* rhs = ins->rhs();
    4244             : 
    4245           0 :     MOZ_ASSERT(lhs->type() == MIRType::Value);
    4246           0 :     MOZ_ASSERT(rhs->type() == MIRType::Object);
    4247             : 
    4248           0 :     LCallInstanceOf* lir = new(alloc()) LCallInstanceOf(useBoxAtStart(lhs),
    4249           0 :                                                         useRegisterAtStart(rhs));
    4250           0 :     defineReturn(lir, ins);
    4251           0 :     assignSafepoint(lir, ins);
    4252           0 : }
    4253             : 
    4254             : void
    4255           0 : LIRGenerator::visitIsArray(MIsArray* ins)
    4256             : {
    4257           0 :     MOZ_ASSERT(ins->type() == MIRType::Boolean);
    4258             : 
    4259           0 :     if (ins->value()->type() == MIRType::Object) {
    4260           0 :         LIsArrayO* lir = new(alloc()) LIsArrayO(useRegister(ins->value()));
    4261           0 :         define(lir, ins);
    4262           0 :         assignSafepoint(lir, ins);
    4263             :     } else {
    4264           0 :         MOZ_ASSERT(ins->value()->type() == MIRType::Value);
    4265           0 :         LIsArrayV* lir = new(alloc()) LIsArrayV(useBox(ins->value()), temp());
    4266           0 :         define(lir, ins);
    4267           0 :         assignSafepoint(lir, ins);
    4268             :     }
    4269           0 : }
    4270             : 
    4271             : void
    4272           0 : LIRGenerator::visitIsCallable(MIsCallable* ins)
    4273             : {
    4274           0 :     MOZ_ASSERT(ins->object()->type() == MIRType::Object);
    4275           0 :     MOZ_ASSERT(ins->type() == MIRType::Boolean);
    4276           0 :     define(new(alloc()) LIsCallable(useRegister(ins->object())), ins);
    4277           0 : }
    4278             : 
    4279             : void
    4280           0 : LIRGenerator::visitIsConstructor(MIsConstructor* ins)
    4281             : {
    4282           0 :     MOZ_ASSERT(ins->object()->type() == MIRType::Object);
    4283           0 :     MOZ_ASSERT(ins->type() == MIRType::Boolean);
    4284           0 :     define(new(alloc()) LIsConstructor(useRegister(ins->object())), ins);
    4285           0 : }
    4286             : 
    4287             : static bool
    4288           0 : CanEmitIsObjectAtUses(MInstruction* ins)
    4289             : {
    4290           0 :     if (!ins->canEmitAtUses())
    4291           0 :         return false;
    4292             : 
    4293           0 :     MUseIterator iter(ins->usesBegin());
    4294           0 :     if (iter == ins->usesEnd())
    4295           0 :         return false;
    4296             : 
    4297           0 :     MNode* node = iter->consumer();
    4298           0 :     if (!node->isDefinition())
    4299           0 :         return false;
    4300             : 
    4301           0 :     if (!node->toDefinition()->isTest())
    4302           0 :         return false;
    4303             : 
    4304           0 :     iter++;
    4305           0 :     return iter == ins->usesEnd();
    4306             : }
    4307             : 
    4308             : void
    4309           0 : LIRGenerator::visitIsObject(MIsObject* ins)
    4310             : {
    4311           0 :     if (CanEmitIsObjectAtUses(ins)) {
    4312           0 :         emitAtUses(ins);
    4313           0 :         return;
    4314             :     }
    4315             : 
    4316           0 :     MDefinition* opd = ins->input();
    4317           0 :     MOZ_ASSERT(opd->type() == MIRType::Value);
    4318           0 :     LIsObject* lir = new(alloc()) LIsObject(useBoxAtStart(opd));
    4319           0 :     define(lir, ins);
    4320             : }
    4321             : 
    4322             : void
    4323           0 : LIRGenerator::visitHasClass(MHasClass* ins)
    4324             : {
    4325           0 :     MOZ_ASSERT(ins->object()->type() == MIRType::Object);
    4326           0 :     MOZ_ASSERT(ins->type() == MIRType::Boolean);
    4327           0 :     define(new(alloc()) LHasClass(useRegister(ins->object())), ins);
    4328           0 : }
    4329             : 
    4330             : void
    4331           0 : LIRGenerator::visitWasmAddOffset(MWasmAddOffset* ins)
    4332             : {
    4333           0 :     MOZ_ASSERT(ins->base()->type() == MIRType::Int32);
    4334           0 :     MOZ_ASSERT(ins->type() == MIRType::Int32);
    4335           0 :     define(new(alloc()) LWasmAddOffset(useRegisterAtStart(ins->base())), ins);
    4336           0 : }
    4337             : 
    4338             : void
    4339           0 : LIRGenerator::visitWasmLoadTls(MWasmLoadTls* ins)
    4340             : {
    4341             : #ifdef WASM_HUGE_MEMORY
    4342             :     // This will disappear once we remove HeapReg and replace it with a load
    4343             :     // from Tls, but in the mean time it keeps us sane.
    4344           0 :     MOZ_CRASH("No WasmLoadTls here at the moment");
    4345             : #endif
    4346             :     auto* lir = new(alloc()) LWasmLoadTls(useRegisterAtStart(ins->tlsPtr()));
    4347             :     define(lir, ins);
    4348             : }
    4349             : 
    4350             : void
    4351           0 : LIRGenerator::visitWasmBoundsCheck(MWasmBoundsCheck* ins)
    4352             : {
    4353             : #ifdef WASM_HUGE_MEMORY
    4354           0 :     MOZ_CRASH("No bounds checking on huge memory");
    4355             : #else
    4356             :     MOZ_ASSERT(!ins->isRedundant());
    4357             : 
    4358             :     MDefinition* index = ins->index();
    4359             :     MOZ_ASSERT(index->type() == MIRType::Int32);
    4360             : 
    4361             :     MDefinition* boundsCheckLimit = ins->boundsCheckLimit();
    4362             :     MOZ_ASSERT(boundsCheckLimit->type() == MIRType::Int32);
    4363             : 
    4364             :     auto* lir = new(alloc()) LWasmBoundsCheck(useRegisterAtStart(index),
    4365             :                                               useRegisterAtStart(boundsCheckLimit));
    4366             :     add(lir, ins);
    4367             : #endif
    4368             : }
    4369             : 
    4370             : void
    4371           0 : LIRGenerator::visitWasmLoadGlobalVar(MWasmLoadGlobalVar* ins)
    4372             : {
    4373           0 :     if (ins->type() == MIRType::Int64) {
    4374             : #ifdef JS_PUNBOX64
    4375           0 :         LAllocation tlsPtr = useRegisterAtStart(ins->tlsPtr());
    4376             : #else
    4377             :         LAllocation tlsPtr = useRegister(ins->tlsPtr());
    4378             : #endif
    4379           0 :         defineInt64(new(alloc()) LWasmLoadGlobalVarI64(tlsPtr), ins);
    4380             :     } else {
    4381           0 :         LAllocation tlsPtr = useRegisterAtStart(ins->tlsPtr());
    4382           0 :         define(new(alloc()) LWasmLoadGlobalVar(tlsPtr), ins);
    4383             :     }
    4384           0 : }
    4385             : 
    4386             : void
    4387           0 : LIRGenerator::visitWasmStoreGlobalVar(MWasmStoreGlobalVar* ins)
    4388             : {
    4389           0 :     MDefinition* value = ins->value();
    4390           0 :     if (value->type() == MIRType::Int64) {
    4391             : #ifdef JS_PUNBOX64
    4392           0 :         LAllocation tlsPtr = useRegisterAtStart(ins->tlsPtr());
    4393           0 :         LInt64Allocation valueAlloc = useInt64RegisterAtStart(value);
    4394             : #else
    4395             :         LAllocation tlsPtr = useRegister(ins->tlsPtr());
    4396             :         LInt64Allocation valueAlloc = useInt64Register(value);
    4397             : #endif
    4398           0 :         add(new(alloc()) LWasmStoreGlobalVarI64(valueAlloc, tlsPtr), ins);
    4399             :     } else {
    4400           0 :         LAllocation tlsPtr = useRegisterAtStart(ins->tlsPtr());
    4401           0 :         LAllocation valueAlloc = useRegisterAtStart(value);
    4402           0 :         add(new(alloc()) LWasmStoreGlobalVar(valueAlloc, tlsPtr), ins);
    4403             :     }
    4404           0 : }
    4405             : 
    4406             : void
    4407           0 : LIRGenerator::visitWasmParameter(MWasmParameter* ins)
    4408             : {
    4409           0 :     ABIArg abi = ins->abi();
    4410           0 :     if (abi.argInRegister()) {
    4411             : #if defined(JS_NUNBOX32)
    4412             :         if (abi.isGeneralRegPair()) {
    4413             :             defineInt64Fixed(new(alloc()) LWasmParameterI64, ins,
    4414             :                 LInt64Allocation(LAllocation(AnyRegister(abi.gpr64().high)),
    4415             :                                  LAllocation(AnyRegister(abi.gpr64().low))));
    4416             :             return;
    4417             :         }
    4418             : #endif
    4419           0 :         defineFixed(new(alloc()) LWasmParameter, ins, LAllocation(abi.reg()));
    4420           0 :         return;
    4421             :     }
    4422           0 :     if (ins->type() == MIRType::Int64) {
    4423           0 :         MOZ_ASSERT(!abi.argInRegister());
    4424           0 :         defineInt64Fixed(new(alloc()) LWasmParameterI64, ins,
    4425             : #if defined(JS_NUNBOX32)
    4426             :             LInt64Allocation(LArgument(abi.offsetFromArgBase() + INT64HIGH_OFFSET),
    4427             :                              LArgument(abi.offsetFromArgBase() + INT64LOW_OFFSET))
    4428             : #else
    4429           0 :             LInt64Allocation(LArgument(abi.offsetFromArgBase()))
    4430             : #endif
    4431           0 :         );
    4432             :     } else {
    4433           0 :         MOZ_ASSERT(IsNumberType(ins->type()) || IsSimdType(ins->type()));
    4434           0 :         defineFixed(new(alloc()) LWasmParameter, ins, LArgument(abi.offsetFromArgBase()));
    4435             :     }
    4436             : }
    4437             : 
    4438             : void
    4439           0 : LIRGenerator::visitWasmReturn(MWasmReturn* ins)
    4440             : {
    4441           0 :     MDefinition* rval = ins->getOperand(0);
    4442             : 
    4443           0 :     if (rval->type() == MIRType::Int64) {
    4444           0 :         add(new(alloc()) LWasmReturnI64(useInt64Fixed(rval, ReturnReg64)));
    4445           0 :         return;
    4446             :     }
    4447             : 
    4448           0 :     LWasmReturn* lir = new(alloc()) LWasmReturn;
    4449           0 :     if (rval->type() == MIRType::Float32)
    4450           0 :         lir->setOperand(0, useFixed(rval, ReturnFloat32Reg));
    4451           0 :     else if (rval->type() == MIRType::Double)
    4452           0 :         lir->setOperand(0, useFixed(rval, ReturnDoubleReg));
    4453           0 :     else if (IsSimdType(rval->type()))
    4454           0 :         lir->setOperand(0, useFixed(rval, ReturnSimd128Reg));
    4455           0 :     else if (rval->type() == MIRType::Int32)
    4456           0 :         lir->setOperand(0, useFixed(rval, ReturnReg));
    4457             :     else
    4458           0 :         MOZ_CRASH("Unexpected wasm return type");
    4459             : 
    4460           0 :     add(lir);
    4461             : }
    4462             : 
    4463             : void
    4464           0 : LIRGenerator::visitWasmReturnVoid(MWasmReturnVoid* ins)
    4465             : {
    4466           0 :     add(new(alloc()) LWasmReturnVoid);
    4467           0 : }
    4468             : 
    4469             : void
    4470           0 : LIRGenerator::visitWasmStackArg(MWasmStackArg* ins)
    4471             : {
    4472           0 :     if (ins->arg()->type() == MIRType::Int64) {
    4473           0 :         add(new(alloc()) LWasmStackArgI64(useInt64RegisterOrConstantAtStart(ins->arg())), ins);
    4474           0 :     } else if (IsFloatingPointType(ins->arg()->type()) || IsSimdType(ins->arg()->type())) {
    4475           0 :         MOZ_ASSERT(!ins->arg()->isEmittedAtUses());
    4476           0 :         add(new(alloc()) LWasmStackArg(useRegisterAtStart(ins->arg())), ins);
    4477             :     } else {
    4478           0 :         add(new(alloc()) LWasmStackArg(useRegisterOrConstantAtStart(ins->arg())), ins);
    4479             :     }
    4480           0 : }
    4481             : 
    4482             : void
    4483           0 : LIRGenerator::visitWasmCall(MWasmCall* ins)
    4484             : {
    4485           0 :     LAllocation* args = gen->allocate<LAllocation>(ins->numOperands());
    4486           0 :     if (!args) {
    4487           0 :         abort(AbortReason::Alloc, "Couldn't allocate for MWasmCall");
    4488           0 :         return;
    4489             :     }
    4490             : 
    4491           0 :     for (unsigned i = 0; i < ins->numArgs(); i++)
    4492           0 :         args[i] = useFixedAtStart(ins->getOperand(i), ins->registerForArg(i));
    4493             : 
    4494           0 :     bool needsBoundsCheck = true;
    4495           0 :     if (ins->callee().isTable()) {
    4496           0 :         MDefinition* index = ins->getOperand(ins->numArgs());
    4497             : 
    4498           0 :         if (ins->callee().which() == wasm::CalleeDesc::WasmTable && index->isConstant()) {
    4499           0 :             if (uint32_t(index->toConstant()->toInt32()) < ins->callee().wasmTableMinLength())
    4500           0 :                 needsBoundsCheck = false;
    4501             :         }
    4502             : 
    4503           0 :         args[ins->numArgs()] = useFixedAtStart(index, WasmTableCallIndexReg);
    4504             :     }
    4505             : 
    4506             :     LInstruction* lir;
    4507           0 :     if (ins->type() == MIRType::Int64)
    4508           0 :         lir = new(alloc()) LWasmCallI64(args, ins->numOperands(), needsBoundsCheck);
    4509             :     else
    4510           0 :         lir = new(alloc()) LWasmCall(args, ins->numOperands(), needsBoundsCheck);
    4511             : 
    4512           0 :     if (ins->type() == MIRType::None)
    4513           0 :         add(lir, ins);
    4514             :     else
    4515           0 :         defineReturn(lir, ins);
    4516             : }
    4517             : 
    4518             : void
    4519           0 : LIRGenerator::visitSetDOMProperty(MSetDOMProperty* ins)
    4520             : {
    4521           0 :     MDefinition* val = ins->value();
    4522             : 
    4523           0 :     Register cxReg, objReg, privReg, valueReg;
    4524           0 :     GetTempRegForIntArg(0, 0, &cxReg);
    4525           0 :     GetTempRegForIntArg(1, 0, &objReg);
    4526           0 :     GetTempRegForIntArg(2, 0, &privReg);
    4527           0 :     GetTempRegForIntArg(3, 0, &valueReg);
    4528             : 
    4529             :     // Keep using GetTempRegForIntArg, since we want to make sure we
    4530             :     // don't clobber registers we're already using.
    4531           0 :     Register tempReg1, tempReg2;
    4532           0 :     GetTempRegForIntArg(4, 0, &tempReg1);
    4533           0 :     mozilla::DebugOnly<bool> ok = GetTempRegForIntArg(5, 0, &tempReg2);
    4534           0 :     MOZ_ASSERT(ok, "How can we not have six temp registers?");
    4535             : 
    4536           0 :     LSetDOMProperty* lir = new(alloc()) LSetDOMProperty(tempFixed(cxReg),
    4537           0 :                                                         useFixedAtStart(ins->object(), objReg),
    4538           0 :                                                         useBoxFixedAtStart(val, tempReg1, tempReg2),
    4539           0 :                                                         tempFixed(privReg),
    4540           0 :                                                         tempFixed(valueReg));
    4541           0 :     add(lir, ins);
    4542           0 :     assignSafepoint(lir, ins);
    4543           0 : }
    4544             : 
    4545             : void
    4546           0 : LIRGenerator::visitGetDOMProperty(MGetDOMProperty* ins)
    4547             : {
    4548           0 :     Register cxReg, objReg, privReg, valueReg;
    4549           0 :     GetTempRegForIntArg(0, 0, &cxReg);
    4550           0 :     GetTempRegForIntArg(1, 0, &objReg);
    4551           0 :     GetTempRegForIntArg(2, 0, &privReg);
    4552           0 :     mozilla::DebugOnly<bool> ok = GetTempRegForIntArg(3, 0, &valueReg);
    4553           0 :     MOZ_ASSERT(ok, "How can we not have four temp registers?");
    4554           0 :     LGetDOMProperty* lir = new(alloc()) LGetDOMProperty(tempFixed(cxReg),
    4555           0 :                                                         useFixedAtStart(ins->object(), objReg),
    4556           0 :                                                         tempFixed(privReg),
    4557           0 :                                                         tempFixed(valueReg));
    4558             : 
    4559           0 :     defineReturn(lir, ins);
    4560           0 :     assignSafepoint(lir, ins);
    4561           0 : }
    4562             : 
    4563             : void
    4564           0 : LIRGenerator::visitGetDOMMember(MGetDOMMember* ins)
    4565             : {
    4566           0 :     MOZ_ASSERT(ins->isDomMovable(), "Members had better be movable");
    4567             :     // We wish we could assert that ins->domAliasSet() == JSJitInfo::AliasNone,
    4568             :     // but some MGetDOMMembers are for [Pure], not [Constant] properties, whose
    4569             :     // value can in fact change as a result of DOM setters and method calls.
    4570           0 :     MOZ_ASSERT(ins->domAliasSet() != JSJitInfo::AliasEverything,
    4571             :                "Member gets had better not alias the world");
    4572             : 
    4573           0 :     MDefinition* obj = ins->object();
    4574           0 :     MOZ_ASSERT(obj->type() == MIRType::Object);
    4575             : 
    4576           0 :     MIRType type = ins->type();
    4577             : 
    4578           0 :     if (type == MIRType::Value) {
    4579           0 :         LGetDOMMemberV* lir = new(alloc()) LGetDOMMemberV(useRegisterAtStart(obj));
    4580           0 :         defineBox(lir, ins);
    4581             :     } else {
    4582           0 :         LGetDOMMemberT* lir = new(alloc()) LGetDOMMemberT(useRegisterForTypedLoad(obj, type));
    4583           0 :         define(lir, ins);
    4584             :     }
    4585           0 : }
    4586             : 
    4587             : void
    4588           6 : LIRGenerator::visitRecompileCheck(MRecompileCheck* ins)
    4589             : {
    4590           6 :     LRecompileCheck* lir = new(alloc()) LRecompileCheck(temp());
    4591           6 :     add(lir, ins);
    4592           6 :     assignSafepoint(lir, ins);
    4593           6 : }
    4594             : 
    4595             : void
    4596           0 : LIRGenerator::visitSimdBox(MSimdBox* ins)
    4597             : {
    4598           0 :     MOZ_ASSERT(IsSimdType(ins->input()->type()));
    4599           0 :     LUse in = useRegister(ins->input());
    4600           0 :     LSimdBox* lir = new(alloc()) LSimdBox(in, temp());
    4601           0 :     define(lir, ins);
    4602           0 :     assignSafepoint(lir, ins);
    4603           0 : }
    4604             : 
    4605             : void
    4606           0 : LIRGenerator::visitSimdUnbox(MSimdUnbox* ins)
    4607             : {
    4608           0 :     MOZ_ASSERT(ins->input()->type() == MIRType::Object);
    4609           0 :     MOZ_ASSERT(IsSimdType(ins->type()));
    4610           0 :     LUse in = useRegister(ins->input());
    4611           0 :     LSimdUnbox* lir = new(alloc()) LSimdUnbox(in, temp());
    4612           0 :     assignSnapshot(lir, Bailout_UnexpectedSimdInput);
    4613           0 :     define(lir, ins);
    4614           0 : }
    4615             : 
    4616             : void
    4617           0 : LIRGenerator::visitSimdConstant(MSimdConstant* ins)
    4618             : {
    4619           0 :     MOZ_ASSERT(IsSimdType(ins->type()));
    4620             : 
    4621           0 :     switch (ins->type()) {
    4622             :       case MIRType::Int8x16:
    4623             :       case MIRType::Int16x8:
    4624             :       case MIRType::Int32x4:
    4625             :       case MIRType::Bool8x16:
    4626             :       case MIRType::Bool16x8:
    4627             :       case MIRType::Bool32x4:
    4628           0 :         define(new(alloc()) LSimd128Int(), ins);
    4629           0 :         break;
    4630             :       case MIRType::Float32x4:
    4631           0 :         define(new(alloc()) LSimd128Float(), ins);
    4632           0 :         break;
    4633             :       default:
    4634           0 :         MOZ_CRASH("Unknown SIMD kind when generating constant");
    4635             :     }
    4636           0 : }
    4637             : 
    4638             : void
    4639           0 : LIRGenerator::visitSimdConvert(MSimdConvert* ins)
    4640             : {
    4641           0 :     MOZ_ASSERT(IsSimdType(ins->type()));
    4642           0 :     MDefinition* input = ins->input();
    4643           0 :     LUse use = useRegister(input);
    4644           0 :     if (ins->type() == MIRType::Int32x4) {
    4645           0 :         MOZ_ASSERT(input->type() == MIRType::Float32x4);
    4646           0 :         switch (ins->signedness()) {
    4647             :           case SimdSign::Signed: {
    4648           0 :               LFloat32x4ToInt32x4* lir = new(alloc()) LFloat32x4ToInt32x4(use, temp());
    4649           0 :               if (!gen->compilingWasm())
    4650           0 :                   assignSnapshot(lir, Bailout_BoundsCheck);
    4651           0 :               define(lir, ins);
    4652           0 :               break;
    4653             :           }
    4654             :           case SimdSign::Unsigned: {
    4655             :               LFloat32x4ToUint32x4* lir =
    4656           0 :                 new (alloc()) LFloat32x4ToUint32x4(use, temp(), temp(LDefinition::SIMD128INT));
    4657           0 :               if (!gen->compilingWasm())
    4658           0 :                   assignSnapshot(lir, Bailout_BoundsCheck);
    4659           0 :               define(lir, ins);
    4660           0 :               break;
    4661             :           }
    4662             :           default:
    4663           0 :             MOZ_CRASH("Unexpected SimdConvert sign");
    4664             :         }
    4665           0 :     } else if (ins->type() == MIRType::Float32x4) {
    4666           0 :         MOZ_ASSERT(input->type() == MIRType::Int32x4);
    4667           0 :         MOZ_ASSERT(ins->signedness() == SimdSign::Signed, "Unexpected SimdConvert sign");
    4668           0 :         define(new(alloc()) LInt32x4ToFloat32x4(use), ins);
    4669             :     } else {
    4670           0 :         MOZ_CRASH("Unknown SIMD kind when generating constant");
    4671             :     }
    4672           0 : }
    4673             : 
    4674             : void
    4675           0 : LIRGenerator::visitSimdReinterpretCast(MSimdReinterpretCast* ins)
    4676             : {
    4677           0 :     MOZ_ASSERT(IsSimdType(ins->type()) && IsSimdType(ins->input()->type()));
    4678           0 :     MDefinition* input = ins->input();
    4679           0 :     LUse use = useRegisterAtStart(input);
    4680             :     // :TODO: (Bug 1132894) We have to allocate a different register as redefine
    4681             :     // and/or defineReuseInput are not yet capable of reusing the same register
    4682             :     // with a different register type.
    4683           0 :     define(new(alloc()) LSimdReinterpretCast(use), ins);
    4684           0 : }
    4685             : 
    4686             : void
    4687           0 : LIRGenerator::visitSimdAllTrue(MSimdAllTrue* ins)
    4688             : {
    4689           0 :     MDefinition* input = ins->input();
    4690           0 :     MOZ_ASSERT(IsBooleanSimdType(input->type()));
    4691             : 
    4692           0 :     LUse use = useRegisterAtStart(input);
    4693           0 :     define(new(alloc()) LSimdAllTrue(use), ins);
    4694           0 : }
    4695             : 
    4696             : void
    4697           0 : LIRGenerator::visitSimdAnyTrue(MSimdAnyTrue* ins)
    4698             : {
    4699           0 :     MDefinition* input = ins->input();
    4700           0 :     MOZ_ASSERT(IsBooleanSimdType(input->type()));
    4701             : 
    4702           0 :     LUse use = useRegisterAtStart(input);
    4703           0 :     define(new(alloc()) LSimdAnyTrue(use), ins);
    4704           0 : }
    4705             : 
    4706             : void
    4707           0 : LIRGenerator::visitSimdUnaryArith(MSimdUnaryArith* ins)
    4708             : {
    4709           0 :     MOZ_ASSERT(IsSimdType(ins->input()->type()));
    4710           0 :     MOZ_ASSERT(IsSimdType(ins->type()));
    4711             : 
    4712             :     // Cannot be at start, as the ouput is used as a temporary to store values.
    4713           0 :     LUse in = use(ins->input());
    4714             : 
    4715           0 :     switch (ins->type()) {
    4716             :       case MIRType::Int8x16:
    4717             :       case MIRType::Bool8x16:
    4718           0 :         define(new (alloc()) LSimdUnaryArithIx16(in), ins);
    4719           0 :         break;
    4720             :       case MIRType::Int16x8:
    4721             :       case MIRType::Bool16x8:
    4722           0 :         define(new (alloc()) LSimdUnaryArithIx8(in), ins);
    4723           0 :         break;
    4724             :       case MIRType::Int32x4:
    4725             :       case MIRType::Bool32x4:
    4726           0 :         define(new (alloc()) LSimdUnaryArithIx4(in), ins);
    4727           0 :         break;
    4728             :       case MIRType::Float32x4:
    4729           0 :         define(new (alloc()) LSimdUnaryArithFx4(in), ins);
    4730           0 :         break;
    4731             :       default:
    4732           0 :         MOZ_CRASH("Unknown SIMD kind for unary operation");
    4733             :     }
    4734           0 : }
    4735             : 
    4736             : void
    4737           0 : LIRGenerator::visitSimdBinaryComp(MSimdBinaryComp* ins)
    4738             : {
    4739           0 :     MOZ_ASSERT(IsSimdType(ins->lhs()->type()));
    4740           0 :     MOZ_ASSERT(IsSimdType(ins->rhs()->type()));
    4741           0 :     MOZ_ASSERT(IsBooleanSimdType(ins->type()));
    4742             : 
    4743           0 :     if (ShouldReorderCommutative(ins->lhs(), ins->rhs(), ins))
    4744           0 :         ins->reverse();
    4745             : 
    4746           0 :     switch (ins->specialization()) {
    4747             :       case MIRType::Int8x16: {
    4748           0 :           MOZ_ASSERT(ins->signedness() == SimdSign::Signed);
    4749           0 :           LSimdBinaryCompIx16* add = new (alloc()) LSimdBinaryCompIx16();
    4750           0 :           lowerForFPU(add, ins, ins->lhs(), ins->rhs());
    4751           0 :           return;
    4752             :       }
    4753             :       case MIRType::Int16x8: {
    4754           0 :           MOZ_ASSERT(ins->signedness() == SimdSign::Signed);
    4755           0 :           LSimdBinaryCompIx8* add = new (alloc()) LSimdBinaryCompIx8();
    4756           0 :           lowerForFPU(add, ins, ins->lhs(), ins->rhs());
    4757           0 :           return;
    4758             :       }
    4759             :       case MIRType::Int32x4: {
    4760           0 :           MOZ_ASSERT(ins->signedness() == SimdSign::Signed);
    4761           0 :           LSimdBinaryCompIx4* add = new (alloc()) LSimdBinaryCompIx4();
    4762           0 :           lowerForCompIx4(add, ins, ins->lhs(), ins->rhs());
    4763           0 :           return;
    4764             :       }
    4765             :       case MIRType::Float32x4: {
    4766           0 :           MOZ_ASSERT(ins->signedness() == SimdSign::NotApplicable);
    4767           0 :           LSimdBinaryCompFx4* add = new (alloc()) LSimdBinaryCompFx4();
    4768           0 :           lowerForCompFx4(add, ins, ins->lhs(), ins->rhs());
    4769           0 :           return;
    4770             :       }
    4771             :       default:
    4772           0 :         MOZ_CRASH("Unknown compare type when comparing values");
    4773             :     }
    4774             : }
    4775             : 
    4776             : void
    4777           0 : LIRGenerator::visitSimdBinaryBitwise(MSimdBinaryBitwise* ins)
    4778             : {
    4779           0 :     MOZ_ASSERT(IsSimdType(ins->lhs()->type()));
    4780           0 :     MOZ_ASSERT(IsSimdType(ins->rhs()->type()));
    4781           0 :     MOZ_ASSERT(IsSimdType(ins->type()));
    4782             : 
    4783           0 :     MDefinition* lhs = ins->lhs();
    4784           0 :     MDefinition* rhs = ins->rhs();
    4785           0 :     ReorderCommutative(&lhs, &rhs, ins);
    4786           0 :     LSimdBinaryBitwise* lir = new(alloc()) LSimdBinaryBitwise;
    4787           0 :     lowerForFPU(lir, ins, lhs, rhs);
    4788           0 : }
    4789             : 
    4790             : void
    4791           0 : LIRGenerator::visitSimdShift(MSimdShift* ins)
    4792             : {
    4793           0 :     MOZ_ASSERT(IsIntegerSimdType(ins->type()));
    4794           0 :     MOZ_ASSERT(ins->lhs()->type() == ins->type());
    4795           0 :     MOZ_ASSERT(ins->rhs()->type() == MIRType::Int32);
    4796             : 
    4797           0 :     LUse vector = useRegisterAtStart(ins->lhs());
    4798           0 :     LAllocation value = useRegisterOrConstant(ins->rhs());
    4799             :     // We need a temp register to mask the shift amount, but not if the shift
    4800             :     // amount is a constant.
    4801           0 :     LDefinition tempReg = value.isConstant() ? LDefinition::BogusTemp() : temp();
    4802           0 :     LSimdShift* lir = new(alloc()) LSimdShift(vector, value, tempReg);
    4803           0 :     defineReuseInput(lir, ins, 0);
    4804           0 : }
    4805             : 
    4806             : void
    4807           0 : LIRGenerator::visitLexicalCheck(MLexicalCheck* ins)
    4808             : {
    4809           0 :     MDefinition* input = ins->input();
    4810           0 :     MOZ_ASSERT(input->type() == MIRType::Value);
    4811           0 :     LLexicalCheck* lir = new(alloc()) LLexicalCheck(useBox(input));
    4812           0 :     assignSnapshot(lir, ins->bailoutKind());
    4813           0 :     add(lir, ins);
    4814           0 :     redefine(ins, input);
    4815           0 : }
    4816             : 
    4817             : void
    4818           0 : LIRGenerator::visitThrowRuntimeLexicalError(MThrowRuntimeLexicalError* ins)
    4819             : {
    4820           0 :     LThrowRuntimeLexicalError* lir = new(alloc()) LThrowRuntimeLexicalError();
    4821           0 :     add(lir, ins);
    4822           0 :     assignSafepoint(lir, ins);
    4823           0 : }
    4824             : 
    4825             : void
    4826           0 : LIRGenerator::visitGlobalNameConflictsCheck(MGlobalNameConflictsCheck* ins)
    4827             : {
    4828           0 :     LGlobalNameConflictsCheck* lir = new(alloc()) LGlobalNameConflictsCheck();
    4829           0 :     add(lir, ins);
    4830           0 :     assignSafepoint(lir, ins);
    4831           0 : }
    4832             : 
    4833             : void
    4834           0 : LIRGenerator::visitDebugger(MDebugger* ins)
    4835             : {
    4836           0 :     LDebugger* lir = new(alloc()) LDebugger(tempFixed(CallTempReg0), tempFixed(CallTempReg1));
    4837           0 :     assignSnapshot(lir, Bailout_Debugger);
    4838           0 :     add(lir, ins);
    4839           0 : }
    4840             : 
    4841             : void
    4842           0 : LIRGenerator::visitAtomicIsLockFree(MAtomicIsLockFree* ins)
    4843             : {
    4844           0 :     define(new(alloc()) LAtomicIsLockFree(useRegister(ins->input())), ins);
    4845           0 : }
    4846             : 
    4847             : void
    4848           0 : LIRGenerator::visitCheckReturn(MCheckReturn* ins)
    4849             : {
    4850           0 :     MDefinition* retVal = ins->returnValue();
    4851           0 :     MDefinition* thisVal = ins->thisValue();
    4852           0 :     MOZ_ASSERT(retVal->type() == MIRType::Value);
    4853           0 :     MOZ_ASSERT(thisVal->type() == MIRType::Value);
    4854             : 
    4855           0 :     LCheckReturn* lir = new(alloc()) LCheckReturn(useBoxAtStart(retVal), useBoxAtStart(thisVal));
    4856           0 :     assignSnapshot(lir, Bailout_BadDerivedConstructorReturn);
    4857           0 :     add(lir, ins);
    4858           0 :     redefine(ins, retVal);
    4859           0 : }
    4860             : 
    4861             : void
    4862           0 : LIRGenerator::visitCheckIsObj(MCheckIsObj* ins)
    4863             : {
    4864           0 :     MDefinition* checkVal = ins->checkValue();
    4865           0 :     MOZ_ASSERT(checkVal->type() == MIRType::Value);
    4866             : 
    4867           0 :     LCheckIsObj* lir = new(alloc()) LCheckIsObj(useBoxAtStart(checkVal));
    4868           0 :     redefine(ins, checkVal);
    4869           0 :     add(lir, ins);
    4870           0 :     assignSafepoint(lir, ins);
    4871           0 : }
    4872             : 
    4873             : void
    4874           0 : LIRGenerator::visitCheckIsCallable(MCheckIsCallable* ins)
    4875             : {
    4876           0 :     MDefinition* checkVal = ins->checkValue();
    4877           0 :     MOZ_ASSERT(checkVal->type() == MIRType::Value);
    4878             : 
    4879           0 :     LCheckIsCallable* lir = new(alloc()) LCheckIsCallable(useBox(checkVal),
    4880           0 :                                                           temp());
    4881           0 :     redefine(ins, checkVal);
    4882           0 :     add(lir, ins);
    4883           0 :     assignSafepoint(lir, ins);
    4884           0 : }
    4885             : 
    4886             : void
    4887           0 : LIRGenerator::visitCheckObjCoercible(MCheckObjCoercible* ins)
    4888             : {
    4889           0 :     MDefinition* checkVal = ins->checkValue();
    4890           0 :     MOZ_ASSERT(checkVal->type() == MIRType::Value);
    4891             : 
    4892           0 :     LCheckObjCoercible* lir = new(alloc()) LCheckObjCoercible(useBoxAtStart(checkVal));
    4893           0 :     redefine(ins, checkVal);
    4894           0 :     add(lir, ins);
    4895           0 :     assignSafepoint(lir, ins);
    4896           0 : }
    4897             : 
    4898             : void
    4899           0 : LIRGenerator::visitDebugCheckSelfHosted(MDebugCheckSelfHosted* ins)
    4900             : {
    4901           0 :     MDefinition* checkVal = ins->checkValue();
    4902           0 :     MOZ_ASSERT(checkVal->type() == MIRType::Value);
    4903             : 
    4904           0 :     LDebugCheckSelfHosted* lir = new (alloc()) LDebugCheckSelfHosted(useBoxAtStart(checkVal));
    4905           0 :     redefine(ins, checkVal);
    4906           0 :     add(lir, ins);
    4907           0 :     assignSafepoint(lir, ins);
    4908           0 : }
    4909             : 
    4910             : void
    4911           0 : LIRGenerator::visitFinishBoundFunctionInit(MFinishBoundFunctionInit* ins)
    4912             : {
    4913           0 :     auto lir = new(alloc()) LFinishBoundFunctionInit(useRegister(ins->bound()),
    4914           0 :                                                      useRegister(ins->target()),
    4915           0 :                                                      useRegister(ins->argCount()),
    4916           0 :                                                      temp(), temp());
    4917           0 :     add(lir, ins);
    4918           0 :     assignSafepoint(lir, ins);
    4919           0 : }
    4920             : 
    4921             : static void
    4922           0 : SpewResumePoint(MBasicBlock* block, MInstruction* ins, MResumePoint* resumePoint)
    4923             : {
    4924           0 :     Fprinter& out = JitSpewPrinter();
    4925           0 :     out.printf("Current resume point %p details:\n", (void*)resumePoint);
    4926           0 :     out.printf("    frame count: %u\n", resumePoint->frameCount());
    4927             : 
    4928           0 :     if (ins) {
    4929           0 :         out.printf("    taken after: ");
    4930           0 :         ins->printName(out);
    4931             :     } else {
    4932           0 :         out.printf("    taken at block %d entry", block->id());
    4933             :     }
    4934           0 :     out.printf("\n");
    4935             : 
    4936           0 :     out.printf("    pc: %p (script: %p, offset: %d)\n",
    4937           0 :             (void*)resumePoint->pc(),
    4938           0 :             (void*)resumePoint->block()->info().script(),
    4939           0 :             int(resumePoint->block()->info().script()->pcToOffset(resumePoint->pc())));
    4940             : 
    4941           0 :     for (size_t i = 0, e = resumePoint->numOperands(); i < e; i++) {
    4942           0 :         MDefinition* in = resumePoint->getOperand(i);
    4943           0 :         out.printf("    slot%u: ", (unsigned)i);
    4944           0 :         in->printName(out);
    4945           0 :         out.printf("\n");
    4946             :     }
    4947           0 : }
    4948             : 
    4949             : bool
    4950        1474 : LIRGenerator::visitInstruction(MInstruction* ins)
    4951             : {
    4952        1474 :     if (ins->isRecoveredOnBailout()) {
    4953          63 :         MOZ_ASSERT(!JitOptions.disableRecoverIns);
    4954          63 :         return true;
    4955             :     }
    4956             : 
    4957        1411 :     if (!gen->ensureBallast())
    4958           0 :         return false;
    4959        1411 :     ins->accept(this);
    4960             : 
    4961        1411 :     if (ins->possiblyCalls()) {
    4962          38 :         gen->setNeedsStaticStackAlignment();
    4963          38 :         gen->setNeedsOverrecursedCheck();
    4964             :     }
    4965             : 
    4966        1411 :     if (ins->resumePoint())
    4967         259 :         updateResumeState(ins);
    4968             : 
    4969             : #ifdef DEBUG
    4970        1411 :     ins->setInWorklistUnchecked();
    4971             : #endif
    4972             : 
    4973             :     // If no safepoint was created, there's no need for an OSI point.
    4974        1411 :     if (LOsiPoint* osiPoint = popOsiPoint())
    4975         134 :         add(osiPoint);
    4976             : 
    4977        1411 :     return !errored();
    4978             : }
    4979             : 
    4980             : void
    4981         403 : LIRGenerator::definePhis()
    4982             : {
    4983         403 :     size_t lirIndex = 0;
    4984         403 :     MBasicBlock* block = current->mir();
    4985         578 :     for (MPhiIterator phi(block->phisBegin()); phi != block->phisEnd(); phi++) {
    4986         175 :         if (phi->type() == MIRType::Value) {
    4987          86 :             defineUntypedPhi(*phi, lirIndex);
    4988          86 :             lirIndex += BOX_PIECES;
    4989          89 :         } else if (phi->type() == MIRType::Int64) {
    4990           0 :             defineInt64Phi(*phi, lirIndex);
    4991           0 :             lirIndex += INT64_PIECES;
    4992             :         } else {
    4993          89 :             defineTypedPhi(*phi, lirIndex);
    4994          89 :             lirIndex += 1;
    4995             :         }
    4996             :     }
    4997         403 : }
    4998             : 
    4999             : void
    5000         259 : LIRGenerator::updateResumeState(MInstruction* ins)
    5001             : {
    5002         259 :     lastResumePoint_ = ins->resumePoint();
    5003         259 :     if (JitSpewEnabled(JitSpew_IonSnapshots) && lastResumePoint_)
    5004           0 :         SpewResumePoint(nullptr, ins, lastResumePoint_);
    5005         259 : }
    5006             : 
    5007             : void
    5008         403 : LIRGenerator::updateResumeState(MBasicBlock* block)
    5009             : {
    5010             :     // As Value Numbering phase can remove edges from the entry basic block to a
    5011             :     // code paths reachable from the OSR entry point, we have to add fixup
    5012             :     // blocks to keep the dominator tree organized the same way. These fixup
    5013             :     // blocks are flaged as unreachable, and should only exist iff the graph has
    5014             :     // an OSR block.
    5015             :     //
    5016             :     // Note: RangeAnalysis can flag blocks as unreachable, but they are only
    5017             :     // removed iff GVN (including UCE) is enabled.
    5018         403 :     MOZ_ASSERT_IF(!mir()->compilingWasm() && !block->unreachable(), block->entryResumePoint());
    5019         403 :     MOZ_ASSERT_IF(block->unreachable(), block->graph().osrBlock() ||
    5020             :                   !mir()->optimizationInfo().gvnEnabled());
    5021         403 :     lastResumePoint_ = block->entryResumePoint();
    5022         403 :     if (JitSpewEnabled(JitSpew_IonSnapshots) && lastResumePoint_)
    5023           0 :         SpewResumePoint(block, nullptr, lastResumePoint_);
    5024         403 : }
    5025             : 
    5026             : bool
    5027         403 : LIRGenerator::visitBlock(MBasicBlock* block)
    5028             : {
    5029         403 :     current = block->lir();
    5030         403 :     updateResumeState(block);
    5031             : 
    5032         403 :     definePhis();
    5033             : 
    5034             :     // See fixup blocks added by Value Numbering, to keep the dominator relation
    5035             :     // modified by the presence of the OSR block.
    5036         403 :     MOZ_ASSERT_IF(block->unreachable(), *block->begin() == block->lastIns() ||
    5037             :                   !mir()->optimizationInfo().gvnEnabled());
    5038         403 :     MOZ_ASSERT_IF(block->unreachable(), block->graph().osrBlock() ||
    5039             :                   !mir()->optimizationInfo().gvnEnabled());
    5040        1474 :     for (MInstructionIterator iter = block->begin(); *iter != block->lastIns(); iter++) {
    5041        1071 :         if (!visitInstruction(*iter))
    5042           0 :             return false;
    5043             :     }
    5044             : 
    5045         403 :     if (block->successorWithPhis()) {
    5046             :         // If we have a successor with phis, lower the phi input now that we
    5047             :         // are approaching the join point.
    5048         134 :         MBasicBlock* successor = block->successorWithPhis();
    5049         134 :         uint32_t position = block->positionInPhiSuccessor();
    5050         134 :         size_t lirIndex = 0;
    5051         564 :         for (MPhiIterator phi(successor->phisBegin()); phi != successor->phisEnd(); phi++) {
    5052         430 :             if (!gen->ensureBallast())
    5053           0 :                 return false;
    5054             : 
    5055         430 :             MDefinition* opd = phi->getOperand(position);
    5056         430 :             ensureDefined(opd);
    5057             : 
    5058         430 :             MOZ_ASSERT(opd->type() == phi->type());
    5059             : 
    5060         430 :             if (phi->type() == MIRType::Value) {
    5061         222 :                 lowerUntypedPhiInput(*phi, position, successor->lir(), lirIndex);
    5062         222 :                 lirIndex += BOX_PIECES;
    5063         208 :             } else if (phi->type() == MIRType::Int64) {
    5064           0 :                 lowerInt64PhiInput(*phi, position, successor->lir(), lirIndex);
    5065           0 :                 lirIndex += INT64_PIECES;
    5066             :             } else {
    5067         208 :                 lowerTypedPhiInput(*phi, position, successor->lir(), lirIndex);
    5068         208 :                 lirIndex += 1;
    5069             :             }
    5070             :         }
    5071             :     }
    5072             : 
    5073             :     // Now emit the last instruction, which is some form of branch.
    5074         403 :     if (!visitInstruction(block->lastIns()))
    5075           0 :         return false;
    5076             : 
    5077         403 :     return true;
    5078             : }
    5079             : 
    5080             : void
    5081           0 : LIRGenerator::visitNaNToZero(MNaNToZero *ins)
    5082             : {
    5083           0 :     MDefinition* input = ins->input();
    5084             : 
    5085           0 :     if (ins->operandIsNeverNaN() && ins->operandIsNeverNegativeZero()) {
    5086           0 :         redefine(ins, input);
    5087           0 :         return;
    5088             :     }
    5089           0 :     LNaNToZero* lir = new(alloc()) LNaNToZero(useRegisterAtStart(input), tempDouble());
    5090           0 :     defineReuseInput(lir, ins, 0);
    5091             : }
    5092             : 
    5093             : bool
    5094           8 : LIRGenerator::generate()
    5095             : {
    5096             :     // Create all blocks and prep all phis beforehand.
    5097         411 :     for (ReversePostorderIterator block(graph.rpoBegin()); block != graph.rpoEnd(); block++) {
    5098         403 :         if (gen->shouldCancel("Lowering (preparation loop)"))
    5099           0 :             return false;
    5100             : 
    5101         403 :         if (!lirGraph_.initBlock(*block))
    5102           0 :             return false;
    5103             :     }
    5104             : 
    5105         822 :     for (ReversePostorderIterator block(graph.rpoBegin()); block != graph.rpoEnd(); block++) {
    5106         403 :         if (gen->shouldCancel("Lowering (main loop)"))
    5107           0 :             return false;
    5108             : 
    5109         403 :         if (!visitBlock(*block))
    5110           0 :             return false;
    5111             :     }
    5112             : 
    5113           8 :     lirGraph_.setArgumentSlotCount(maxargslots_);
    5114           8 :     return true;
    5115             : }
    5116             : 
    5117             : void
    5118           0 : LIRGenerator::visitPhi(MPhi* phi)
    5119             : {
    5120             :     // Phi nodes are not lowered because they are only meaningful for the register allocator.
    5121           0 :     MOZ_CRASH("Unexpected Phi node during Lowering.");
    5122             : }
    5123             : 
    5124             : void
    5125           0 : LIRGenerator::visitBeta(MBeta* beta)
    5126             : {
    5127             :     // Beta nodes are supposed to be removed before because they are
    5128             :     // only used to carry the range information for Range analysis
    5129           0 :     MOZ_CRASH("Unexpected Beta node during Lowering.");
    5130             : }
    5131             : 
    5132             : void
    5133           0 : LIRGenerator::visitObjectState(MObjectState* objState)
    5134             : {
    5135             :     // ObjectState nodes are always recovered on bailouts
    5136           0 :     MOZ_CRASH("Unexpected ObjectState node during Lowering.");
    5137             : }
    5138             : 
    5139             : void
    5140           0 : LIRGenerator::visitArrayState(MArrayState* objState)
    5141             : {
    5142             :     // ArrayState nodes are always recovered on bailouts
    5143           0 :     MOZ_CRASH("Unexpected ArrayState node during Lowering.");
    5144             : }
    5145             : 
    5146             : void
    5147           0 : LIRGenerator::visitUnknownValue(MUnknownValue* ins)
    5148             : {
    5149           0 :     MOZ_CRASH("Can not lower unknown value.");
    5150             : }

Generated by: LCOV version 1.13