js/src/jit/Lowering.cpp

Sat, 03 Jan 2015 20:18:00 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Sat, 03 Jan 2015 20:18:00 +0100
branch
TOR_BUG_3246
changeset 7
129ffea94266
permissions
-rw-r--r--

Conditionally enable double key logic according to:
private browsing mode or privacy.thirdparty.isolate preference and
implement in GetCookieStringCommon and FindCookie where it counts...
With some reservations of how to convince FindCookie users to test
condition and pass a nullptr when disabling double key logic.

     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/. */
     7 #include "jit/Lowering.h"
     9 #include "mozilla/DebugOnly.h"
    11 #include "jsanalyze.h"
    13 #include "jit/IonSpewer.h"
    14 #include "jit/LIR.h"
    15 #include "jit/MIR.h"
    16 #include "jit/MIRGraph.h"
    18 #include "jsinferinlines.h"
    19 #include "jsobjinlines.h"
    20 #include "jsopcodeinlines.h"
    22 #include "jit/shared/Lowering-shared-inl.h"
    24 using namespace js;
    25 using namespace jit;
    27 using mozilla::DebugOnly;
    28 using JS::GenericNaN;
    30 bool
    31 LIRGenerator::visitCloneLiteral(MCloneLiteral *ins)
    32 {
    33     JS_ASSERT(ins->type() == MIRType_Object);
    34     JS_ASSERT(ins->input()->type() == MIRType_Object);
    36     LCloneLiteral *lir = new(alloc()) LCloneLiteral(useRegisterAtStart(ins->input()));
    37     return defineReturn(lir, ins) && assignSafepoint(lir, ins);
    38 }
    40 bool
    41 LIRGenerator::visitParameter(MParameter *param)
    42 {
    43     ptrdiff_t offset;
    44     if (param->index() == MParameter::THIS_SLOT)
    45         offset = THIS_FRAME_ARGSLOT;
    46     else
    47         offset = 1 + param->index();
    49     LParameter *ins = new(alloc()) LParameter;
    50     if (!defineBox(ins, param, LDefinition::PRESET))
    51         return false;
    53     offset *= sizeof(Value);
    54 #if defined(JS_NUNBOX32)
    55 # if defined(IS_BIG_ENDIAN)
    56     ins->getDef(0)->setOutput(LArgument(offset));
    57     ins->getDef(1)->setOutput(LArgument(offset + 4));
    58 # else
    59     ins->getDef(0)->setOutput(LArgument(offset + 4));
    60     ins->getDef(1)->setOutput(LArgument(offset));
    61 # endif
    62 #elif defined(JS_PUNBOX64)
    63     ins->getDef(0)->setOutput(LArgument(offset));
    64 #endif
    66     return true;
    67 }
    69 bool
    70 LIRGenerator::visitCallee(MCallee *ins)
    71 {
    72     return define(new(alloc()) LCallee(), ins);
    73 }
    75 bool
    76 LIRGenerator::visitGoto(MGoto *ins)
    77 {
    78     return add(new(alloc()) LGoto(ins->target()));
    79 }
    81 bool
    82 LIRGenerator::visitTableSwitch(MTableSwitch *tableswitch)
    83 {
    84     MDefinition *opd = tableswitch->getOperand(0);
    86     // There should be at least 1 successor. The default case!
    87     JS_ASSERT(tableswitch->numSuccessors() > 0);
    89     // If there are no cases, the default case is always taken.
    90     if (tableswitch->numSuccessors() == 1)
    91         return add(new(alloc()) LGoto(tableswitch->getDefault()));
    93     // If we don't know the type.
    94     if (opd->type() == MIRType_Value) {
    95         LTableSwitchV *lir = newLTableSwitchV(tableswitch);
    96         if (!useBox(lir, LTableSwitchV::InputValue, opd))
    97             return false;
    98         return add(lir);
    99     }
   101     // Case indices are numeric, so other types will always go to the default case.
   102     if (opd->type() != MIRType_Int32 && opd->type() != MIRType_Double)
   103         return add(new(alloc()) LGoto(tableswitch->getDefault()));
   105     // Return an LTableSwitch, capable of handling either an integer or
   106     // floating-point index.
   107     LAllocation index;
   108     LDefinition tempInt;
   109     if (opd->type() == MIRType_Int32) {
   110         index = useRegisterAtStart(opd);
   111         tempInt = tempCopy(opd, 0);
   112     } else {
   113         index = useRegister(opd);
   114         tempInt = temp(LDefinition::GENERAL);
   115     }
   116     return add(newLTableSwitch(index, tempInt, tableswitch));
   117 }
   119 bool
   120 LIRGenerator::visitCheckOverRecursed(MCheckOverRecursed *ins)
   121 {
   122     LCheckOverRecursed *lir = new(alloc()) LCheckOverRecursed();
   124     if (!add(lir, ins))
   125         return false;
   126     if (!assignSafepoint(lir, ins))
   127         return false;
   129     return true;
   130 }
   132 bool
   133 LIRGenerator::visitCheckOverRecursedPar(MCheckOverRecursedPar *ins)
   134 {
   135     LCheckOverRecursedPar *lir =
   136         new(alloc()) LCheckOverRecursedPar(useRegister(ins->forkJoinContext()), temp());
   137     if (!add(lir, ins))
   138         return false;
   139     if (!assignSafepoint(lir, ins))
   140         return false;
   141     return true;
   142 }
   144 bool
   145 LIRGenerator::visitDefVar(MDefVar *ins)
   146 {
   147     LDefVar *lir = new(alloc()) LDefVar(useRegisterAtStart(ins->scopeChain()));
   148     if (!add(lir, ins))
   149         return false;
   150     if (!assignSafepoint(lir, ins))
   151         return false;
   153     return true;
   154 }
   156 bool
   157 LIRGenerator::visitDefFun(MDefFun *ins)
   158 {
   159     LDefFun *lir = new(alloc()) LDefFun(useRegisterAtStart(ins->scopeChain()));
   160     return add(lir, ins) && assignSafepoint(lir, ins);
   161 }
   163 bool
   164 LIRGenerator::visitNewSlots(MNewSlots *ins)
   165 {
   166     // No safepoint needed, since we don't pass a cx.
   167     LNewSlots *lir = new(alloc()) LNewSlots(tempFixed(CallTempReg0), tempFixed(CallTempReg1),
   168                                             tempFixed(CallTempReg2));
   169     if (!assignSnapshot(lir))
   170         return false;
   171     return defineReturn(lir, ins);
   172 }
   174 bool
   175 LIRGenerator::visitNewArray(MNewArray *ins)
   176 {
   177     LNewArray *lir = new(alloc()) LNewArray(temp());
   178     return define(lir, ins) && assignSafepoint(lir, ins);
   179 }
   181 bool
   182 LIRGenerator::visitNewObject(MNewObject *ins)
   183 {
   184     LNewObject *lir = new(alloc()) LNewObject(temp());
   185     return define(lir, ins) && assignSafepoint(lir, ins);
   186 }
   188 bool
   189 LIRGenerator::visitNewDeclEnvObject(MNewDeclEnvObject *ins)
   190 {
   191     LNewDeclEnvObject *lir = new(alloc()) LNewDeclEnvObject(temp());
   192     return define(lir, ins) && assignSafepoint(lir, ins);
   193 }
   195 bool
   196 LIRGenerator::visitNewCallObject(MNewCallObject *ins)
   197 {
   198     LAllocation slots;
   199     if (ins->slots()->type() == MIRType_Slots)
   200         slots = useRegister(ins->slots());
   201     else
   202         slots = LConstantIndex::Bogus();
   204     LInstruction *lir;
   205     if (ins->templateObject()->hasSingletonType()) {
   206         LNewSingletonCallObject *singletonLir = new(alloc()) LNewSingletonCallObject(slots);
   207         if (!define(singletonLir, ins))
   208             return false;
   209         lir = singletonLir;
   210     } else {
   211         LNewCallObject *normalLir = new(alloc()) LNewCallObject(slots, temp());
   212         if (!define(normalLir, ins))
   213             return false;
   214         lir = normalLir;
   215     }
   217     if (!assignSafepoint(lir, ins))
   218         return false;
   220     return true;
   221 }
   223 bool
   224 LIRGenerator::visitNewRunOnceCallObject(MNewRunOnceCallObject *ins)
   225 {
   226     LAllocation slots;
   227     if (ins->slots()->type() == MIRType_Slots)
   228         slots = useRegister(ins->slots());
   229     else
   230         slots = LConstantIndex::Bogus();
   232     LNewSingletonCallObject *lir = new(alloc()) LNewSingletonCallObject(slots);
   233     if (!define(lir, ins))
   234         return false;
   236     if (!assignSafepoint(lir, ins))
   237         return false;
   239     return true;
   240 }
   242 bool
   243 LIRGenerator::visitNewDerivedTypedObject(MNewDerivedTypedObject *ins)
   244 {
   245     LNewDerivedTypedObject *lir =
   246         new(alloc()) LNewDerivedTypedObject(useRegisterAtStart(ins->type()),
   247                                             useRegisterAtStart(ins->owner()),
   248                                             useRegisterAtStart(ins->offset()));
   249     return defineReturn(lir, ins) && assignSafepoint(lir, ins);
   250 }
   252 bool
   253 LIRGenerator::visitNewCallObjectPar(MNewCallObjectPar *ins)
   254 {
   255     const LAllocation &parThreadContext = useRegister(ins->forkJoinContext());
   256     const LDefinition &temp1 = temp();
   257     const LDefinition &temp2 = temp();
   259     LNewCallObjectPar *lir;
   260     if (ins->slots()->type() == MIRType_Slots) {
   261         const LAllocation &slots = useRegister(ins->slots());
   262         lir = LNewCallObjectPar::NewWithSlots(alloc(), parThreadContext, slots, temp1, temp2);
   263     } else {
   264         lir = LNewCallObjectPar::NewSansSlots(alloc(), parThreadContext, temp1, temp2);
   265     }
   267     return define(lir, ins);
   268 }
   270 bool
   271 LIRGenerator::visitNewStringObject(MNewStringObject *ins)
   272 {
   273     JS_ASSERT(ins->input()->type() == MIRType_String);
   275     LNewStringObject *lir = new(alloc()) LNewStringObject(useRegister(ins->input()), temp());
   276     return define(lir, ins) && assignSafepoint(lir, ins);
   277 }
   279 bool
   280 LIRGenerator::visitAbortPar(MAbortPar *ins)
   281 {
   282     LAbortPar *lir = new(alloc()) LAbortPar();
   283     return add(lir, ins);
   284 }
   286 bool
   287 LIRGenerator::visitInitElem(MInitElem *ins)
   288 {
   289     LInitElem *lir = new(alloc()) LInitElem(useRegisterAtStart(ins->getObject()));
   290     if (!useBoxAtStart(lir, LInitElem::IdIndex, ins->getId()))
   291         return false;
   292     if (!useBoxAtStart(lir, LInitElem::ValueIndex, ins->getValue()))
   293         return false;
   295     return add(lir, ins) && assignSafepoint(lir, ins);
   296 }
   298 bool
   299 LIRGenerator::visitInitElemGetterSetter(MInitElemGetterSetter *ins)
   300 {
   301     LInitElemGetterSetter *lir =
   302         new(alloc()) LInitElemGetterSetter(useRegisterAtStart(ins->object()),
   303                                            useRegisterAtStart(ins->value()));
   304     if (!useBoxAtStart(lir, LInitElemGetterSetter::IdIndex, ins->idValue()))
   305         return false;
   307     return add(lir, ins) && assignSafepoint(lir, ins);
   308 }
   310 bool
   311 LIRGenerator::visitMutateProto(MMutateProto *ins)
   312 {
   313     LMutateProto *lir = new(alloc()) LMutateProto(useRegisterAtStart(ins->getObject()));
   314     if (!useBoxAtStart(lir, LMutateProto::ValueIndex, ins->getValue()))
   315         return false;
   317     return add(lir, ins) && assignSafepoint(lir, ins);
   318 }
   320 bool
   321 LIRGenerator::visitInitProp(MInitProp *ins)
   322 {
   323     LInitProp *lir = new(alloc()) LInitProp(useRegisterAtStart(ins->getObject()));
   324     if (!useBoxAtStart(lir, LInitProp::ValueIndex, ins->getValue()))
   325         return false;
   327     return add(lir, ins) && assignSafepoint(lir, ins);
   328 }
   330 bool
   331 LIRGenerator::visitInitPropGetterSetter(MInitPropGetterSetter *ins)
   332 {
   333     LInitPropGetterSetter *lir =
   334         new(alloc()) LInitPropGetterSetter(useRegisterAtStart(ins->object()),
   335                                            useRegisterAtStart(ins->value()));
   336     return add(lir, ins) && assignSafepoint(lir, ins);
   337 }
   339 bool
   340 LIRGenerator::visitCreateThisWithTemplate(MCreateThisWithTemplate *ins)
   341 {
   342     LCreateThisWithTemplate *lir = new(alloc()) LCreateThisWithTemplate(temp());
   343     return define(lir, ins) && assignSafepoint(lir, ins);
   344 }
   346 bool
   347 LIRGenerator::visitCreateThisWithProto(MCreateThisWithProto *ins)
   348 {
   349     LCreateThisWithProto *lir =
   350         new(alloc()) LCreateThisWithProto(useRegisterOrConstantAtStart(ins->getCallee()),
   351                                           useRegisterOrConstantAtStart(ins->getPrototype()));
   352     return defineReturn(lir, ins) && assignSafepoint(lir, ins);
   353 }
   355 bool
   356 LIRGenerator::visitCreateThis(MCreateThis *ins)
   357 {
   358     LCreateThis *lir = new(alloc()) LCreateThis(useRegisterOrConstantAtStart(ins->getCallee()));
   359     return defineReturn(lir, ins) && assignSafepoint(lir, ins);
   360 }
   362 bool
   363 LIRGenerator::visitCreateArgumentsObject(MCreateArgumentsObject *ins)
   364 {
   365     // LAllocation callObj = useRegisterAtStart(ins->getCallObject());
   366     LAllocation callObj = useFixed(ins->getCallObject(), CallTempReg0);
   367     LCreateArgumentsObject *lir = new(alloc()) LCreateArgumentsObject(callObj, tempFixed(CallTempReg1));
   368     return defineReturn(lir, ins) && assignSafepoint(lir, ins);
   369 }
   371 bool
   372 LIRGenerator::visitGetArgumentsObjectArg(MGetArgumentsObjectArg *ins)
   373 {
   374     LAllocation argsObj = useRegister(ins->getArgsObject());
   375     LGetArgumentsObjectArg *lir = new(alloc()) LGetArgumentsObjectArg(argsObj, temp());
   376     return defineBox(lir, ins);
   377 }
   379 bool
   380 LIRGenerator::visitSetArgumentsObjectArg(MSetArgumentsObjectArg *ins)
   381 {
   382     LAllocation argsObj = useRegister(ins->getArgsObject());
   383     LSetArgumentsObjectArg *lir = new(alloc()) LSetArgumentsObjectArg(argsObj, temp());
   384     if (!useBox(lir, LSetArgumentsObjectArg::ValueIndex, ins->getValue()))
   385         return false;
   387     return add(lir, ins);
   388 }
   390 bool
   391 LIRGenerator::visitReturnFromCtor(MReturnFromCtor *ins)
   392 {
   393     LReturnFromCtor *lir = new(alloc()) LReturnFromCtor(useRegister(ins->getObject()));
   394     if (!useBox(lir, LReturnFromCtor::ValueIndex, ins->getValue()))
   395         return false;
   397     return define(lir, ins);
   398 }
   400 bool
   401 LIRGenerator::visitComputeThis(MComputeThis *ins)
   402 {
   403     JS_ASSERT(ins->type() == MIRType_Object);
   404     JS_ASSERT(ins->input()->type() == MIRType_Value);
   406     LComputeThis *lir = new(alloc()) LComputeThis();
   408     // Don't use useBoxAtStart because ComputeThis has a safepoint and needs to
   409     // have its inputs in different registers than its return value so that
   410     // they aren't clobbered.
   411     if (!useBox(lir, LComputeThis::ValueIndex, ins->input()))
   412         return false;
   414     return define(lir, ins) && assignSafepoint(lir, ins);
   415 }
   417 bool
   418 LIRGenerator::visitLoadArrowThis(MLoadArrowThis *ins)
   419 {
   420     JS_ASSERT(ins->type() == MIRType_Value);
   421     JS_ASSERT(ins->callee()->type() == MIRType_Object);
   423     LLoadArrowThis *lir = new(alloc()) LLoadArrowThis(useRegister(ins->callee()));
   424     return defineBox(lir, ins);
   425 }
   427 bool
   428 LIRGenerator::lowerCallArguments(MCall *call)
   429 {
   430     uint32_t argc = call->numStackArgs();
   431     if (argc > maxargslots_)
   432         maxargslots_ = argc;
   434     for (size_t i = 0; i < argc; i++) {
   435         MDefinition *arg = call->getArg(i);
   436         uint32_t argslot = argc - i;
   438         // Values take a slow path.
   439         if (arg->type() == MIRType_Value) {
   440             LStackArgV *stack = new(alloc()) LStackArgV(argslot);
   441             if (!useBox(stack, 0, arg) || !add(stack))
   442                 return false;
   443         } else {
   444             // Known types can move constant types and/or payloads.
   445             LStackArgT *stack = new(alloc()) LStackArgT(argslot, arg->type(), useRegisterOrConstant(arg));
   446             if (!add(stack))
   447                 return false;
   448         }
   449     }
   451     return true;
   452 }
   454 bool
   455 LIRGenerator::visitCall(MCall *call)
   456 {
   457     JS_ASSERT(CallTempReg0 != CallTempReg1);
   458     JS_ASSERT(CallTempReg0 != ArgumentsRectifierReg);
   459     JS_ASSERT(CallTempReg1 != ArgumentsRectifierReg);
   460     JS_ASSERT(call->getFunction()->type() == MIRType_Object);
   462     if (!lowerCallArguments(call))
   463         return false;
   465     // Height of the current argument vector.
   466     JSFunction *target = call->getSingleTarget();
   468     // Call DOM functions.
   469     if (call->isCallDOMNative()) {
   470         JS_ASSERT(target && target->isNative());
   471         Register cxReg, objReg, privReg, argsReg;
   472         GetTempRegForIntArg(0, 0, &cxReg);
   473         GetTempRegForIntArg(1, 0, &objReg);
   474         GetTempRegForIntArg(2, 0, &privReg);
   475         mozilla::DebugOnly<bool> ok = GetTempRegForIntArg(3, 0, &argsReg);
   476         MOZ_ASSERT(ok, "How can we not have four temp registers?");
   477         LCallDOMNative *lir = new(alloc()) LCallDOMNative(tempFixed(cxReg), tempFixed(objReg),
   478                                                           tempFixed(privReg), tempFixed(argsReg));
   479         return defineReturn(lir, call) && assignSafepoint(lir, call);
   480     }
   482     // Call known functions.
   483     if (target) {
   484         if (target->isNative()) {
   485             Register cxReg, numReg, vpReg, tmpReg;
   486             GetTempRegForIntArg(0, 0, &cxReg);
   487             GetTempRegForIntArg(1, 0, &numReg);
   488             GetTempRegForIntArg(2, 0, &vpReg);
   490             // Even though this is just a temp reg, use the same API to avoid
   491             // register collisions.
   492             mozilla::DebugOnly<bool> ok = GetTempRegForIntArg(3, 0, &tmpReg);
   493             MOZ_ASSERT(ok, "How can we not have four temp registers?");
   495             LCallNative *lir = new(alloc()) LCallNative(tempFixed(cxReg), tempFixed(numReg),
   496                                                         tempFixed(vpReg), tempFixed(tmpReg));
   497             return defineReturn(lir, call) && assignSafepoint(lir, call);
   498         }
   500         LCallKnown *lir = new(alloc()) LCallKnown(useFixed(call->getFunction(), CallTempReg0),
   501                                                   tempFixed(CallTempReg2));
   502         return defineReturn(lir, call) && assignSafepoint(lir, call);
   503     }
   505     // Call anything, using the most generic code.
   506     LCallGeneric *lir = new(alloc()) LCallGeneric(useFixed(call->getFunction(), CallTempReg0),
   507                                                   tempFixed(ArgumentsRectifierReg),
   508                                                   tempFixed(CallTempReg2));
   509     return defineReturn(lir, call) && assignSafepoint(lir, call);
   510 }
   512 bool
   513 LIRGenerator::visitApplyArgs(MApplyArgs *apply)
   514 {
   515     JS_ASSERT(apply->getFunction()->type() == MIRType_Object);
   517     // Assert if we cannot build a rectifier frame.
   518     JS_ASSERT(CallTempReg0 != ArgumentsRectifierReg);
   519     JS_ASSERT(CallTempReg1 != ArgumentsRectifierReg);
   521     // Assert if the return value is already erased.
   522     JS_ASSERT(CallTempReg2 != JSReturnReg_Type);
   523     JS_ASSERT(CallTempReg2 != JSReturnReg_Data);
   525     LApplyArgsGeneric *lir = new(alloc()) LApplyArgsGeneric(
   526         useFixed(apply->getFunction(), CallTempReg3),
   527         useFixed(apply->getArgc(), CallTempReg0),
   528         tempFixed(CallTempReg1),  // object register
   529         tempFixed(CallTempReg2)); // copy register
   531     MDefinition *self = apply->getThis();
   532     if (!useBoxFixed(lir, LApplyArgsGeneric::ThisIndex, self, CallTempReg4, CallTempReg5))
   533         return false;
   535     // Bailout is only needed in the case of possible non-JSFunction callee.
   536     if (!apply->getSingleTarget() && !assignSnapshot(lir))
   537         return false;
   539     if (!defineReturn(lir, apply))
   540         return false;
   541     if (!assignSafepoint(lir, apply))
   542         return false;
   543     return true;
   544 }
   546 bool
   547 LIRGenerator::visitBail(MBail *bail)
   548 {
   549     LBail *lir = new(alloc()) LBail();
   550     return assignSnapshot(lir) && add(lir, bail);
   551 }
   553 bool
   554 LIRGenerator::visitAssertFloat32(MAssertFloat32 *assertion)
   555 {
   556     MIRType type = assertion->input()->type();
   557     DebugOnly<bool> checkIsFloat32 = assertion->mustBeFloat32();
   559     if (!allowFloat32Optimizations())
   560         return true;
   562     if (type != MIRType_Value && !js_JitOptions.eagerCompilation) {
   563         JS_ASSERT_IF(checkIsFloat32, type == MIRType_Float32);
   564         JS_ASSERT_IF(!checkIsFloat32, type != MIRType_Float32);
   565     }
   566     return true;
   567 }
   569 bool
   570 LIRGenerator::visitArraySplice(MArraySplice *ins)
   571 {
   572     LArraySplice *lir = new(alloc()) LArraySplice(useRegisterAtStart(ins->object()),
   573                                                   useRegisterAtStart(ins->start()),
   574                                                   useRegisterAtStart(ins->deleteCount()));
   575     return add(lir, ins) && assignSafepoint(lir, ins);
   576 }
   578 bool
   579 LIRGenerator::visitGetDynamicName(MGetDynamicName *ins)
   580 {
   581     MDefinition *scopeChain = ins->getScopeChain();
   582     JS_ASSERT(scopeChain->type() == MIRType_Object);
   584     MDefinition *name = ins->getName();
   585     JS_ASSERT(name->type() == MIRType_String);
   587     LGetDynamicName *lir = new(alloc()) LGetDynamicName(useFixed(scopeChain, CallTempReg0),
   588                                                         useFixed(name, CallTempReg1),
   589                                                         tempFixed(CallTempReg2),
   590                                                         tempFixed(CallTempReg3),
   591                                                         tempFixed(CallTempReg4));
   593     return assignSnapshot(lir) && defineReturn(lir, ins);
   594 }
   596 bool
   597 LIRGenerator::visitFilterArgumentsOrEval(MFilterArgumentsOrEval *ins)
   598 {
   599     MDefinition *string = ins->getString();
   600     MOZ_ASSERT(string->type() == MIRType_String || string->type() == MIRType_Value);
   602     LInstruction *lir;
   603     if (string->type() == MIRType_String) {
   604         lir = new(alloc()) LFilterArgumentsOrEvalS(useFixed(string, CallTempReg0),
   605                                                    tempFixed(CallTempReg1),
   606                                                    tempFixed(CallTempReg2));
   607     } else {
   608         lir = new(alloc()) LFilterArgumentsOrEvalV(tempFixed(CallTempReg0),
   609                                                    tempFixed(CallTempReg1),
   610                                                    tempFixed(CallTempReg2));
   611         if (!useBoxFixed(lir, LFilterArgumentsOrEvalV::Input, string,
   612                          CallTempReg3, CallTempReg4))
   613         {
   614             return false;
   615         }
   616     }
   618     return assignSnapshot(lir) && add(lir, ins) && assignSafepoint(lir, ins);
   619 }
   621 bool
   622 LIRGenerator::visitCallDirectEval(MCallDirectEval *ins)
   623 {
   624     MDefinition *scopeChain = ins->getScopeChain();
   625     JS_ASSERT(scopeChain->type() == MIRType_Object);
   627     MDefinition *string = ins->getString();
   628     JS_ASSERT(string->type() == MIRType_String || string->type() == MIRType_Value);
   630     MDefinition *thisValue = ins->getThisValue();
   633     LInstruction *lir;
   634     if (string->type() == MIRType_String) {
   635         lir = new(alloc()) LCallDirectEvalS(useRegisterAtStart(scopeChain),
   636                                             useRegisterAtStart(string));
   637     } else {
   638         lir = new(alloc()) LCallDirectEvalV(useRegisterAtStart(scopeChain));
   639         if (!useBoxAtStart(lir, LCallDirectEvalV::Argument, string))
   640             return false;
   641     }
   643     if (string->type() == MIRType_String) {
   644         if (!useBoxAtStart(lir, LCallDirectEvalS::ThisValue, thisValue))
   645             return false;
   646     } else {
   647         if (!useBoxAtStart(lir, LCallDirectEvalV::ThisValue, thisValue))
   648             return false;
   649     }
   651     return defineReturn(lir, ins) && assignSafepoint(lir, ins);
   652 }
   654 static JSOp
   655 ReorderComparison(JSOp op, MDefinition **lhsp, MDefinition **rhsp)
   656 {
   657     MDefinition *lhs = *lhsp;
   658     MDefinition *rhs = *rhsp;
   660     if (lhs->isConstant()) {
   661         *rhsp = lhs;
   662         *lhsp = rhs;
   663         return ReverseCompareOp(op);
   664     }
   665     return op;
   666 }
   668 static void
   669 ReorderCommutative(MDefinition **lhsp, MDefinition **rhsp)
   670 {
   671     MDefinition *lhs = *lhsp;
   672     MDefinition *rhs = *rhsp;
   674     // Ensure that if there is a constant, then it is in rhs.
   675     // In addition, since clobbering binary operations clobber the left
   676     // operand, prefer a non-constant lhs operand with no further uses.
   678     if (rhs->isConstant())
   679         return;
   681     // lhs and rhs are used by the commutative operator. If they have any
   682     // *other* uses besides, try to reorder to avoid clobbering them. To
   683     // be fully precise, we should check whether this is the *last* use,
   684     // but checking hasOneDefUse() is a decent approximation which doesn't
   685     // require any extra analysis.
   686     JS_ASSERT(lhs->defUseCount() > 0);
   687     JS_ASSERT(rhs->defUseCount() > 0);
   688     if (lhs->isConstant() || (rhs->hasOneDefUse() && !lhs->hasOneDefUse())) {
   689         *rhsp = lhs;
   690         *lhsp = rhs;
   691     }
   692 }
   694 bool
   695 LIRGenerator::visitTest(MTest *test)
   696 {
   697     MDefinition *opd = test->getOperand(0);
   698     MBasicBlock *ifTrue = test->ifTrue();
   699     MBasicBlock *ifFalse = test->ifFalse();
   701     // String is converted to length of string in the type analysis phase (see
   702     // TestPolicy).
   703     JS_ASSERT(opd->type() != MIRType_String);
   705     if (opd->type() == MIRType_Value) {
   706         LDefinition temp0, temp1;
   707         if (test->operandMightEmulateUndefined()) {
   708             temp0 = temp();
   709             temp1 = temp();
   710         } else {
   711             temp0 = LDefinition::BogusTemp();
   712             temp1 = LDefinition::BogusTemp();
   713         }
   714         LTestVAndBranch *lir = new(alloc()) LTestVAndBranch(ifTrue, ifFalse, tempDouble(), temp0, temp1);
   715         if (!useBox(lir, LTestVAndBranch::Input, opd))
   716             return false;
   717         return add(lir, test);
   718     }
   720     if (opd->type() == MIRType_Object) {
   721         // If the object might emulate undefined, we have to test for that.
   722         if (test->operandMightEmulateUndefined())
   723             return add(new(alloc()) LTestOAndBranch(useRegister(opd), ifTrue, ifFalse, temp()), test);
   725         // Otherwise we know it's truthy.
   726         return add(new(alloc()) LGoto(ifTrue));
   727     }
   729     // These must be explicitly sniffed out since they are constants and have
   730     // no payload.
   731     if (opd->type() == MIRType_Undefined || opd->type() == MIRType_Null)
   732         return add(new(alloc()) LGoto(ifFalse));
   734     // Constant Double operand.
   735     if (opd->type() == MIRType_Double && opd->isConstant()) {
   736         bool result = opd->toConstant()->valueToBoolean();
   737         return add(new(alloc()) LGoto(result ? ifTrue : ifFalse));
   738     }
   740     // Constant Float32 operand.
   741     if (opd->type() == MIRType_Float32 && opd->isConstant()) {
   742         bool result = opd->toConstant()->valueToBoolean();
   743         return add(new(alloc()) LGoto(result ? ifTrue : ifFalse));
   744     }
   746     // Constant Int32 operand.
   747     if (opd->type() == MIRType_Int32 && opd->isConstant()) {
   748         int32_t num = opd->toConstant()->value().toInt32();
   749         return add(new(alloc()) LGoto(num ? ifTrue : ifFalse));
   750     }
   752     // Constant Boolean operand.
   753     if (opd->type() == MIRType_Boolean && opd->isConstant()) {
   754         bool result = opd->toConstant()->value().toBoolean();
   755         return add(new(alloc()) LGoto(result ? ifTrue : ifFalse));
   756     }
   758     // Check if the operand for this test is a compare operation. If it is, we want
   759     // to emit an LCompare*AndBranch rather than an LTest*AndBranch, to fuse the
   760     // compare and jump instructions.
   761     if (opd->isCompare() && opd->isEmittedAtUses()) {
   762         MCompare *comp = opd->toCompare();
   763         MDefinition *left = comp->lhs();
   764         MDefinition *right = comp->rhs();
   766         // Try to fold the comparison so that we don't have to handle all cases.
   767         bool result;
   768         if (comp->tryFold(&result))
   769             return add(new(alloc()) LGoto(result ? ifTrue : ifFalse));
   771         // Emit LCompare*AndBranch.
   773         // Compare and branch null/undefined.
   774         // The second operand has known null/undefined type,
   775         // so just test the first operand.
   776         if (comp->compareType() == MCompare::Compare_Null ||
   777             comp->compareType() == MCompare::Compare_Undefined)
   778         {
   779             if (left->type() == MIRType_Object) {
   780                 MOZ_ASSERT(comp->operandMightEmulateUndefined(),
   781                            "MCompare::tryFold should handle the never-emulates-undefined case");
   783                 LEmulatesUndefinedAndBranch *lir =
   784                     new(alloc()) LEmulatesUndefinedAndBranch(comp, useRegister(left),
   785                                                              ifTrue, ifFalse, temp());
   786                 return add(lir, test);
   787             }
   789             LDefinition tmp, tmpToUnbox;
   790             if (comp->operandMightEmulateUndefined()) {
   791                 tmp = temp();
   792                 tmpToUnbox = tempToUnbox();
   793             } else {
   794                 tmp = LDefinition::BogusTemp();
   795                 tmpToUnbox = LDefinition::BogusTemp();
   796             }
   798             LIsNullOrLikeUndefinedAndBranch *lir =
   799                 new(alloc()) LIsNullOrLikeUndefinedAndBranch(comp, ifTrue, ifFalse,
   800                                                              tmp, tmpToUnbox);
   801             if (!useBox(lir, LIsNullOrLikeUndefinedAndBranch::Value, left))
   802                 return false;
   803             return add(lir, test);
   804         }
   806         // Compare and branch booleans.
   807         if (comp->compareType() == MCompare::Compare_Boolean) {
   808             JS_ASSERT(left->type() == MIRType_Value);
   809             JS_ASSERT(right->type() == MIRType_Boolean);
   811             LAllocation rhs = useRegisterOrConstant(right);
   812             LCompareBAndBranch *lir = new(alloc()) LCompareBAndBranch(comp, rhs, ifTrue, ifFalse);
   813             if (!useBox(lir, LCompareBAndBranch::Lhs, left))
   814                 return false;
   815             return add(lir, test);
   816         }
   818         // Compare and branch Int32 or Object pointers.
   819         if (comp->isInt32Comparison() ||
   820             comp->compareType() == MCompare::Compare_UInt32 ||
   821             comp->compareType() == MCompare::Compare_Object)
   822         {
   823             JSOp op = ReorderComparison(comp->jsop(), &left, &right);
   824             LAllocation lhs = useRegister(left);
   825             LAllocation rhs;
   826             if (comp->isInt32Comparison() || comp->compareType() == MCompare::Compare_UInt32)
   827                 rhs = useAnyOrConstant(right);
   828             else
   829                 rhs = useRegister(right);
   830             LCompareAndBranch *lir = new(alloc()) LCompareAndBranch(comp, op, lhs, rhs,
   831                                                                     ifTrue, ifFalse);
   832             return add(lir, test);
   833         }
   835         // Compare and branch doubles.
   836         if (comp->isDoubleComparison()) {
   837             LAllocation lhs = useRegister(left);
   838             LAllocation rhs = useRegister(right);
   839             LCompareDAndBranch *lir = new(alloc()) LCompareDAndBranch(comp, lhs, rhs,
   840                                                                       ifTrue, ifFalse);
   841             return add(lir, test);
   842         }
   844         // Compare and branch floats.
   845         if (comp->isFloat32Comparison()) {
   846             LAllocation lhs = useRegister(left);
   847             LAllocation rhs = useRegister(right);
   848             LCompareFAndBranch *lir = new(alloc()) LCompareFAndBranch(comp, lhs, rhs,
   849                                                                       ifTrue, ifFalse);
   850             return add(lir, test);
   851         }
   853         // Compare values.
   854         if (comp->compareType() == MCompare::Compare_Value) {
   855             LCompareVAndBranch *lir = new(alloc()) LCompareVAndBranch(comp, ifTrue, ifFalse);
   856             if (!useBoxAtStart(lir, LCompareVAndBranch::LhsInput, left))
   857                 return false;
   858             if (!useBoxAtStart(lir, LCompareVAndBranch::RhsInput, right))
   859                 return false;
   860             return add(lir, test);
   861         }
   862     }
   864     // Check if the operand for this test is a bitand operation. If it is, we want
   865     // to emit an LBitAndAndBranch rather than an LTest*AndBranch.
   866     if (opd->isBitAnd() && opd->isEmittedAtUses()) {
   867         MDefinition *lhs = opd->getOperand(0);
   868         MDefinition *rhs = opd->getOperand(1);
   869         if (lhs->type() == MIRType_Int32 && rhs->type() == MIRType_Int32) {
   870             ReorderCommutative(&lhs, &rhs);
   871             return lowerForBitAndAndBranch(new(alloc()) LBitAndAndBranch(ifTrue, ifFalse), test, lhs, rhs);
   872         }
   873     }
   875     if (opd->type() == MIRType_Double)
   876         return add(new(alloc()) LTestDAndBranch(useRegister(opd), ifTrue, ifFalse));
   878     if (opd->type() == MIRType_Float32)
   879         return add(new(alloc()) LTestFAndBranch(useRegister(opd), ifTrue, ifFalse));
   881     JS_ASSERT(opd->type() == MIRType_Int32 || opd->type() == MIRType_Boolean);
   882     return add(new(alloc()) LTestIAndBranch(useRegister(opd), ifTrue, ifFalse));
   883 }
   885 bool
   886 LIRGenerator::visitFunctionDispatch(MFunctionDispatch *ins)
   887 {
   888     LFunctionDispatch *lir = new(alloc()) LFunctionDispatch(useRegister(ins->input()));
   889     return add(lir, ins);
   890 }
   892 bool
   893 LIRGenerator::visitTypeObjectDispatch(MTypeObjectDispatch *ins)
   894 {
   895     LTypeObjectDispatch *lir = new(alloc()) LTypeObjectDispatch(useRegister(ins->input()), temp());
   896     return add(lir, ins);
   897 }
   899 static inline bool
   900 CanEmitCompareAtUses(MInstruction *ins)
   901 {
   902     if (!ins->canEmitAtUses())
   903         return false;
   905     bool foundTest = false;
   906     for (MUseIterator iter(ins->usesBegin()); iter != ins->usesEnd(); iter++) {
   907         MNode *node = iter->consumer();
   908         if (!node->isDefinition())
   909             return false;
   910         if (!node->toDefinition()->isTest())
   911             return false;
   912         if (foundTest)
   913             return false;
   914         foundTest = true;
   915     }
   916     return true;
   917 }
   919 bool
   920 LIRGenerator::visitCompare(MCompare *comp)
   921 {
   922     MDefinition *left = comp->lhs();
   923     MDefinition *right = comp->rhs();
   925     // Try to fold the comparison so that we don't have to handle all cases.
   926     bool result;
   927     if (comp->tryFold(&result))
   928         return define(new(alloc()) LInteger(result), comp);
   930     // Move below the emitAtUses call if we ever implement
   931     // LCompareSAndBranch. Doing this now wouldn't be wrong, but doesn't
   932     // make sense and avoids confusion.
   933     if (comp->compareType() == MCompare::Compare_String) {
   934         LCompareS *lir = new(alloc()) LCompareS(useRegister(left), useRegister(right), temp());
   935         if (!define(lir, comp))
   936             return false;
   937         return assignSafepoint(lir, comp);
   938     }
   940     // Strict compare between value and string
   941     if (comp->compareType() == MCompare::Compare_StrictString) {
   942         JS_ASSERT(left->type() == MIRType_Value);
   943         JS_ASSERT(right->type() == MIRType_String);
   945         LCompareStrictS *lir = new(alloc()) LCompareStrictS(useRegister(right), temp(), tempToUnbox());
   946         if (!useBox(lir, LCompareStrictS::Lhs, left))
   947             return false;
   948         if (!define(lir, comp))
   949             return false;
   950         return assignSafepoint(lir, comp);
   951     }
   953     // Unknown/unspecialized compare use a VM call.
   954     if (comp->compareType() == MCompare::Compare_Unknown) {
   955         LCompareVM *lir = new(alloc()) LCompareVM();
   956         if (!useBoxAtStart(lir, LCompareVM::LhsInput, left))
   957             return false;
   958         if (!useBoxAtStart(lir, LCompareVM::RhsInput, right))
   959             return false;
   960         return defineReturn(lir, comp) && assignSafepoint(lir, comp);
   961     }
   963     // Sniff out if the output of this compare is used only for a branching.
   964     // If it is, then we will emit an LCompare*AndBranch instruction in place
   965     // of this compare and any test that uses this compare. Thus, we can
   966     // ignore this Compare.
   967     if (CanEmitCompareAtUses(comp))
   968         return emitAtUses(comp);
   970     // Compare Null and Undefined.
   971     if (comp->compareType() == MCompare::Compare_Null ||
   972         comp->compareType() == MCompare::Compare_Undefined)
   973     {
   974         if (left->type() == MIRType_Object) {
   975             MOZ_ASSERT(comp->operandMightEmulateUndefined(),
   976                        "MCompare::tryFold should have folded this away");
   978             return define(new(alloc()) LEmulatesUndefined(useRegister(left)), comp);
   979         }
   981         LDefinition tmp, tmpToUnbox;
   982         if (comp->operandMightEmulateUndefined()) {
   983             tmp = temp();
   984             tmpToUnbox = tempToUnbox();
   985         } else {
   986             tmp = LDefinition::BogusTemp();
   987             tmpToUnbox = LDefinition::BogusTemp();
   988         }
   990         LIsNullOrLikeUndefined *lir = new(alloc()) LIsNullOrLikeUndefined(tmp, tmpToUnbox);
   991         if (!useBox(lir, LIsNullOrLikeUndefined::Value, left))
   992             return false;
   993         return define(lir, comp);
   994     }
   996     // Compare booleans.
   997     if (comp->compareType() == MCompare::Compare_Boolean) {
   998         JS_ASSERT(left->type() == MIRType_Value);
   999         JS_ASSERT(right->type() == MIRType_Boolean);
  1001         LCompareB *lir = new(alloc()) LCompareB(useRegisterOrConstant(right));
  1002         if (!useBox(lir, LCompareB::Lhs, left))
  1003             return false;
  1004         return define(lir, comp);
  1007     // Compare Int32 or Object pointers.
  1008     if (comp->isInt32Comparison() ||
  1009         comp->compareType() == MCompare::Compare_UInt32 ||
  1010         comp->compareType() == MCompare::Compare_Object)
  1012         JSOp op = ReorderComparison(comp->jsop(), &left, &right);
  1013         LAllocation lhs = useRegister(left);
  1014         LAllocation rhs;
  1015         if (comp->isInt32Comparison() ||
  1016             comp->compareType() == MCompare::Compare_UInt32)
  1018             rhs = useAnyOrConstant(right);
  1019         } else {
  1020             rhs = useRegister(right);
  1022         return define(new(alloc()) LCompare(op, lhs, rhs), comp);
  1025     // Compare doubles.
  1026     if (comp->isDoubleComparison())
  1027         return define(new(alloc()) LCompareD(useRegister(left), useRegister(right)), comp);
  1029     // Compare float32.
  1030     if (comp->isFloat32Comparison())
  1031         return define(new(alloc()) LCompareF(useRegister(left), useRegister(right)), comp);
  1033     // Compare values.
  1034     if (comp->compareType() == MCompare::Compare_Value) {
  1035         LCompareV *lir = new(alloc()) LCompareV();
  1036         if (!useBoxAtStart(lir, LCompareV::LhsInput, left))
  1037             return false;
  1038         if (!useBoxAtStart(lir, LCompareV::RhsInput, right))
  1039             return false;
  1040         return define(lir, comp);
  1043     MOZ_ASSUME_UNREACHABLE("Unrecognized compare type.");
  1046 bool
  1047 LIRGenerator::lowerBitOp(JSOp op, MInstruction *ins)
  1049     MDefinition *lhs = ins->getOperand(0);
  1050     MDefinition *rhs = ins->getOperand(1);
  1052     if (lhs->type() == MIRType_Int32 && rhs->type() == MIRType_Int32) {
  1053         ReorderCommutative(&lhs, &rhs);
  1054         return lowerForALU(new(alloc()) LBitOpI(op), ins, lhs, rhs);
  1057     LBitOpV *lir = new(alloc()) LBitOpV(op);
  1058     if (!useBoxAtStart(lir, LBitOpV::LhsInput, lhs))
  1059         return false;
  1060     if (!useBoxAtStart(lir, LBitOpV::RhsInput, rhs))
  1061         return false;
  1063     return defineReturn(lir, ins) && assignSafepoint(lir, ins);
  1066 bool
  1067 LIRGenerator::visitTypeOf(MTypeOf *ins)
  1069     MDefinition *opd = ins->input();
  1070     JS_ASSERT(opd->type() == MIRType_Value);
  1072     LTypeOfV *lir = new(alloc()) LTypeOfV(tempToUnbox());
  1073     if (!useBox(lir, LTypeOfV::Input, opd))
  1074         return false;
  1075     return define(lir, ins);
  1078 bool
  1079 LIRGenerator::visitToId(MToId *ins)
  1081     LToIdV *lir = new(alloc()) LToIdV(tempDouble());
  1082     if (!useBox(lir, LToIdV::Object, ins->lhs()))
  1083         return false;
  1084     if (!useBox(lir, LToIdV::Index, ins->rhs()))
  1085         return false;
  1086     return defineBox(lir, ins) && assignSafepoint(lir, ins);
  1089 bool
  1090 LIRGenerator::visitBitNot(MBitNot *ins)
  1092     MDefinition *input = ins->getOperand(0);
  1094     if (input->type() == MIRType_Int32)
  1095         return lowerForALU(new(alloc()) LBitNotI(), ins, input);
  1097     LBitNotV *lir = new(alloc()) LBitNotV;
  1098     if (!useBoxAtStart(lir, LBitNotV::Input, input))
  1099         return false;
  1100     if (!defineReturn(lir, ins))
  1101         return false;
  1102     return assignSafepoint(lir, ins);
  1105 static bool
  1106 CanEmitBitAndAtUses(MInstruction *ins)
  1108     if (!ins->canEmitAtUses())
  1109         return false;
  1111     if (ins->getOperand(0)->type() != MIRType_Int32 || ins->getOperand(1)->type() != MIRType_Int32)
  1112         return false;
  1114     MUseIterator iter(ins->usesBegin());
  1115     if (iter == ins->usesEnd())
  1116         return false;
  1118     MNode *node = iter->consumer();
  1119     if (!node->isDefinition())
  1120         return false;
  1122     if (!node->toDefinition()->isTest())
  1123         return false;
  1125     iter++;
  1126     return iter == ins->usesEnd();
  1129 bool
  1130 LIRGenerator::visitBitAnd(MBitAnd *ins)
  1132     // Sniff out if the output of this bitand is used only for a branching.
  1133     // If it is, then we will emit an LBitAndAndBranch instruction in place
  1134     // of this bitand and any test that uses this bitand. Thus, we can
  1135     // ignore this BitAnd.
  1136     if (CanEmitBitAndAtUses(ins))
  1137         return emitAtUses(ins);
  1139     return lowerBitOp(JSOP_BITAND, ins);
  1142 bool
  1143 LIRGenerator::visitBitOr(MBitOr *ins)
  1145     return lowerBitOp(JSOP_BITOR, ins);
  1148 bool
  1149 LIRGenerator::visitBitXor(MBitXor *ins)
  1151     return lowerBitOp(JSOP_BITXOR, ins);
  1154 bool
  1155 LIRGenerator::lowerShiftOp(JSOp op, MShiftInstruction *ins)
  1157     MDefinition *lhs = ins->getOperand(0);
  1158     MDefinition *rhs = ins->getOperand(1);
  1160     if (lhs->type() == MIRType_Int32 && rhs->type() == MIRType_Int32) {
  1161         if (ins->type() == MIRType_Double) {
  1162             JS_ASSERT(op == JSOP_URSH);
  1163             return lowerUrshD(ins->toUrsh());
  1166         LShiftI *lir = new(alloc()) LShiftI(op);
  1167         if (op == JSOP_URSH) {
  1168             if (ins->toUrsh()->fallible() && !assignSnapshot(lir, Bailout_BaselineInfo))
  1169                 return false;
  1171         return lowerForShift(lir, ins, lhs, rhs);
  1174     JS_ASSERT(ins->specialization() == MIRType_None);
  1176     if (op == JSOP_URSH) {
  1177         // Result is either int32 or double so we have to use BinaryV.
  1178         return lowerBinaryV(JSOP_URSH, ins);
  1181     LBitOpV *lir = new(alloc()) LBitOpV(op);
  1182     if (!useBoxAtStart(lir, LBitOpV::LhsInput, lhs))
  1183         return false;
  1184     if (!useBoxAtStart(lir, LBitOpV::RhsInput, rhs))
  1185         return false;
  1186     return defineReturn(lir, ins) && assignSafepoint(lir, ins);
  1189 bool
  1190 LIRGenerator::visitLsh(MLsh *ins)
  1192     return lowerShiftOp(JSOP_LSH, ins);
  1195 bool
  1196 LIRGenerator::visitRsh(MRsh *ins)
  1198     return lowerShiftOp(JSOP_RSH, ins);
  1201 bool
  1202 LIRGenerator::visitUrsh(MUrsh *ins)
  1204     return lowerShiftOp(JSOP_URSH, ins);
  1207 bool
  1208 LIRGenerator::visitFloor(MFloor *ins)
  1210     MIRType type = ins->num()->type();
  1211     JS_ASSERT(IsFloatingPointType(type));
  1213     if (type == MIRType_Double) {
  1214         LFloor *lir = new(alloc()) LFloor(useRegister(ins->num()));
  1215         if (!assignSnapshot(lir))
  1216             return false;
  1217         return define(lir, ins);
  1220     LFloorF *lir = new(alloc()) LFloorF(useRegister(ins->num()));
  1221     if (!assignSnapshot(lir))
  1222         return false;
  1223     return define(lir, ins);
  1226 bool
  1227 LIRGenerator::visitRound(MRound *ins)
  1229     MIRType type = ins->num()->type();
  1230     JS_ASSERT(IsFloatingPointType(type));
  1232     if (type == MIRType_Double) {
  1233         LRound *lir = new (alloc()) LRound(useRegister(ins->num()), tempDouble());
  1234         if (!assignSnapshot(lir))
  1235             return false;
  1236         return define(lir, ins);
  1239     LRoundF *lir = new (alloc()) LRoundF(useRegister(ins->num()), tempDouble());
  1240     if (!assignSnapshot(lir))
  1241         return false;
  1242     return define(lir, ins);
  1245 bool
  1246 LIRGenerator::visitMinMax(MMinMax *ins)
  1248     MDefinition *first = ins->getOperand(0);
  1249     MDefinition *second = ins->getOperand(1);
  1251     ReorderCommutative(&first, &second);
  1253     if (ins->specialization() == MIRType_Int32) {
  1254         LMinMaxI *lir = new(alloc()) LMinMaxI(useRegisterAtStart(first), useRegisterOrConstant(second));
  1255         return defineReuseInput(lir, ins, 0);
  1258     LMinMaxD *lir = new(alloc()) LMinMaxD(useRegisterAtStart(first), useRegister(second));
  1259     return defineReuseInput(lir, ins, 0);
  1262 bool
  1263 LIRGenerator::visitAbs(MAbs *ins)
  1265     MDefinition *num = ins->num();
  1266     JS_ASSERT(IsNumberType(num->type()));
  1268     if (num->type() == MIRType_Int32) {
  1269         LAbsI *lir = new(alloc()) LAbsI(useRegisterAtStart(num));
  1270         // needed to handle abs(INT32_MIN)
  1271         if (ins->fallible() && !assignSnapshot(lir))
  1272             return false;
  1273         return defineReuseInput(lir, ins, 0);
  1275     if (num->type() == MIRType_Float32) {
  1276         LAbsF *lir = new(alloc()) LAbsF(useRegisterAtStart(num));
  1277         return defineReuseInput(lir, ins, 0);
  1280     LAbsD *lir = new(alloc()) LAbsD(useRegisterAtStart(num));
  1281     return defineReuseInput(lir, ins, 0);
  1284 bool
  1285 LIRGenerator::visitSqrt(MSqrt *ins)
  1287     MDefinition *num = ins->num();
  1288     JS_ASSERT(IsFloatingPointType(num->type()));
  1289     if (num->type() == MIRType_Double) {
  1290         LSqrtD *lir = new(alloc()) LSqrtD(useRegisterAtStart(num));
  1291         return define(lir, ins);
  1294     LSqrtF *lir = new(alloc()) LSqrtF(useRegisterAtStart(num));
  1295     return define(lir, ins);
  1298 bool
  1299 LIRGenerator::visitAtan2(MAtan2 *ins)
  1301     MDefinition *y = ins->y();
  1302     JS_ASSERT(y->type() == MIRType_Double);
  1304     MDefinition *x = ins->x();
  1305     JS_ASSERT(x->type() == MIRType_Double);
  1307     LAtan2D *lir = new(alloc()) LAtan2D(useRegisterAtStart(y), useRegisterAtStart(x), tempFixed(CallTempReg0));
  1308     return defineReturn(lir, ins);
  1311 bool
  1312 LIRGenerator::visitHypot(MHypot *ins)
  1314     MDefinition *x = ins->x();
  1315     JS_ASSERT(x->type() == MIRType_Double);
  1317     MDefinition *y = ins->y();
  1318     JS_ASSERT(y->type() == MIRType_Double);
  1320     LHypot *lir = new(alloc()) LHypot(useRegisterAtStart(x), useRegisterAtStart(y), tempFixed(CallTempReg0));
  1321     return defineReturn(lir, ins);
  1324 bool
  1325 LIRGenerator::visitPow(MPow *ins)
  1327     MDefinition *input = ins->input();
  1328     JS_ASSERT(input->type() == MIRType_Double);
  1330     MDefinition *power = ins->power();
  1331     JS_ASSERT(power->type() == MIRType_Int32 || power->type() == MIRType_Double);
  1333     if (power->type() == MIRType_Int32) {
  1334         // Note: useRegisterAtStart here is safe, the temp is a GP register so
  1335         // it will never get the same register.
  1336         LPowI *lir = new(alloc()) LPowI(useRegisterAtStart(input), useFixed(power, CallTempReg1),
  1337                                         tempFixed(CallTempReg0));
  1338         return defineReturn(lir, ins);
  1341     LPowD *lir = new(alloc()) LPowD(useRegisterAtStart(input), useRegisterAtStart(power),
  1342                                     tempFixed(CallTempReg0));
  1343     return defineReturn(lir, ins);
  1346 bool
  1347 LIRGenerator::visitRandom(MRandom *ins)
  1349     LRandom *lir = new(alloc()) LRandom(tempFixed(CallTempReg0), tempFixed(CallTempReg1));
  1350     return defineReturn(lir, ins);
  1353 bool
  1354 LIRGenerator::visitMathFunction(MMathFunction *ins)
  1356     JS_ASSERT(IsFloatingPointType(ins->type()));
  1357     JS_ASSERT_IF(ins->type() == MIRType_Double, ins->input()->type() == MIRType_Double);
  1358     JS_ASSERT_IF(ins->type() == MIRType_Float32, ins->input()->type() == MIRType_Float32);
  1360     if (ins->type() == MIRType_Double) {
  1361         // Note: useRegisterAtStart is safe here, the temp is not a FP register.
  1362         LMathFunctionD *lir = new(alloc()) LMathFunctionD(useRegisterAtStart(ins->input()),
  1363                                                           tempFixed(CallTempReg0));
  1364         return defineReturn(lir, ins);
  1367     LMathFunctionF *lir = new(alloc()) LMathFunctionF(useRegisterAtStart(ins->input()),
  1368                                                       tempFixed(CallTempReg0));
  1369     return defineReturn(lir, ins);
  1372 // Try to mark an add or sub instruction as able to recover its input when
  1373 // bailing out.
  1374 template <typename S, typename T>
  1375 static void
  1376 MaybeSetRecoversInput(S *mir, T *lir)
  1378     JS_ASSERT(lir->mirRaw() == mir);
  1379     if (!mir->fallible())
  1380         return;
  1382     if (lir->output()->policy() != LDefinition::MUST_REUSE_INPUT)
  1383         return;
  1385     // The original operands to an add or sub can't be recovered if they both
  1386     // use the same register.
  1387     if (lir->lhs()->isUse() && lir->rhs()->isUse() &&
  1388         lir->lhs()->toUse()->virtualRegister() == lir->rhs()->toUse()->virtualRegister())
  1390         return;
  1393     // Add instructions that are on two different values can recover
  1394     // the input they clobbered via MUST_REUSE_INPUT. Thus, a copy
  1395     // of that input does not need to be kept alive in the snapshot
  1396     // for the instruction.
  1398     lir->setRecoversInput();
  1400     const LUse *input = lir->getOperand(lir->output()->getReusedInput())->toUse();
  1401     lir->snapshot()->rewriteRecoveredInput(*input);
  1404 bool
  1405 LIRGenerator::visitAdd(MAdd *ins)
  1407     MDefinition *lhs = ins->getOperand(0);
  1408     MDefinition *rhs = ins->getOperand(1);
  1410     JS_ASSERT(lhs->type() == rhs->type());
  1412     if (ins->specialization() == MIRType_Int32) {
  1413         JS_ASSERT(lhs->type() == MIRType_Int32);
  1414         ReorderCommutative(&lhs, &rhs);
  1415         LAddI *lir = new(alloc()) LAddI;
  1417         if (ins->fallible() && !assignSnapshot(lir, Bailout_BaselineInfo))
  1418             return false;
  1420         if (!lowerForALU(lir, ins, lhs, rhs))
  1421             return false;
  1423         MaybeSetRecoversInput(ins, lir);
  1424         return true;
  1427     if (ins->specialization() == MIRType_Double) {
  1428         JS_ASSERT(lhs->type() == MIRType_Double);
  1429         ReorderCommutative(&lhs, &rhs);
  1430         return lowerForFPU(new(alloc()) LMathD(JSOP_ADD), ins, lhs, rhs);
  1433     if (ins->specialization() == MIRType_Float32) {
  1434         JS_ASSERT(lhs->type() == MIRType_Float32);
  1435         ReorderCommutative(&lhs, &rhs);
  1436         return lowerForFPU(new(alloc()) LMathF(JSOP_ADD), ins, lhs, rhs);
  1439     return lowerBinaryV(JSOP_ADD, ins);
  1442 bool
  1443 LIRGenerator::visitSub(MSub *ins)
  1445     MDefinition *lhs = ins->lhs();
  1446     MDefinition *rhs = ins->rhs();
  1448     JS_ASSERT(lhs->type() == rhs->type());
  1450     if (ins->specialization() == MIRType_Int32) {
  1451         JS_ASSERT(lhs->type() == MIRType_Int32);
  1453         LSubI *lir = new(alloc()) LSubI;
  1454         if (ins->fallible() && !assignSnapshot(lir))
  1455             return false;
  1457         if (!lowerForALU(lir, ins, lhs, rhs))
  1458             return false;
  1460         MaybeSetRecoversInput(ins, lir);
  1461         return true;
  1463     if (ins->specialization() == MIRType_Double) {
  1464         JS_ASSERT(lhs->type() == MIRType_Double);
  1465         return lowerForFPU(new(alloc()) LMathD(JSOP_SUB), ins, lhs, rhs);
  1467     if (ins->specialization() == MIRType_Float32) {
  1468         JS_ASSERT(lhs->type() == MIRType_Float32);
  1469         return lowerForFPU(new(alloc()) LMathF(JSOP_SUB), ins, lhs, rhs);
  1472     return lowerBinaryV(JSOP_SUB, ins);
  1475 bool
  1476 LIRGenerator::visitMul(MMul *ins)
  1478     MDefinition *lhs = ins->lhs();
  1479     MDefinition *rhs = ins->rhs();
  1480     JS_ASSERT(lhs->type() == rhs->type());
  1482     if (ins->specialization() == MIRType_Int32) {
  1483         JS_ASSERT(lhs->type() == MIRType_Int32);
  1484         ReorderCommutative(&lhs, &rhs);
  1486         // If our RHS is a constant -1 and we don't have to worry about
  1487         // overflow, we can optimize to an LNegI.
  1488         if (!ins->fallible() && rhs->isConstant() && rhs->toConstant()->value() == Int32Value(-1))
  1489             return defineReuseInput(new(alloc()) LNegI(useRegisterAtStart(lhs)), ins, 0);
  1491         return lowerMulI(ins, lhs, rhs);
  1493     if (ins->specialization() == MIRType_Double) {
  1494         JS_ASSERT(lhs->type() == MIRType_Double);
  1495         ReorderCommutative(&lhs, &rhs);
  1497         // If our RHS is a constant -1.0, we can optimize to an LNegD.
  1498         if (rhs->isConstant() && rhs->toConstant()->value() == DoubleValue(-1.0))
  1499             return defineReuseInput(new(alloc()) LNegD(useRegisterAtStart(lhs)), ins, 0);
  1501         return lowerForFPU(new(alloc()) LMathD(JSOP_MUL), ins, lhs, rhs);
  1503     if (ins->specialization() == MIRType_Float32) {
  1504         JS_ASSERT(lhs->type() == MIRType_Float32);
  1505         ReorderCommutative(&lhs, &rhs);
  1507         // We apply the same optimizations as for doubles
  1508         if (rhs->isConstant() && rhs->toConstant()->value() == Float32Value(-1.0f))
  1509             return defineReuseInput(new(alloc()) LNegF(useRegisterAtStart(lhs)), ins, 0);
  1511         return lowerForFPU(new(alloc()) LMathF(JSOP_MUL), ins, lhs, rhs);
  1514     return lowerBinaryV(JSOP_MUL, ins);
  1517 bool
  1518 LIRGenerator::visitDiv(MDiv *ins)
  1520     MDefinition *lhs = ins->lhs();
  1521     MDefinition *rhs = ins->rhs();
  1522     JS_ASSERT(lhs->type() == rhs->type());
  1524     if (ins->specialization() == MIRType_Int32) {
  1525         JS_ASSERT(lhs->type() == MIRType_Int32);
  1526         return lowerDivI(ins);
  1528     if (ins->specialization() == MIRType_Double) {
  1529         JS_ASSERT(lhs->type() == MIRType_Double);
  1530         return lowerForFPU(new(alloc()) LMathD(JSOP_DIV), ins, lhs, rhs);
  1532     if (ins->specialization() == MIRType_Float32) {
  1533         JS_ASSERT(lhs->type() == MIRType_Float32);
  1534         return lowerForFPU(new(alloc()) LMathF(JSOP_DIV), ins, lhs, rhs);
  1537     return lowerBinaryV(JSOP_DIV, ins);
  1540 bool
  1541 LIRGenerator::visitMod(MMod *ins)
  1543     JS_ASSERT(ins->lhs()->type() == ins->rhs()->type());
  1545     if (ins->specialization() == MIRType_Int32) {
  1546         JS_ASSERT(ins->type() == MIRType_Int32);
  1547         JS_ASSERT(ins->lhs()->type() == MIRType_Int32);
  1548         return lowerModI(ins);
  1551     if (ins->specialization() == MIRType_Double) {
  1552         JS_ASSERT(ins->type() == MIRType_Double);
  1553         JS_ASSERT(ins->lhs()->type() == MIRType_Double);
  1554         JS_ASSERT(ins->rhs()->type() == MIRType_Double);
  1556         // Note: useRegisterAtStart is safe here, the temp is not a FP register.
  1557         LModD *lir = new(alloc()) LModD(useRegisterAtStart(ins->lhs()), useRegisterAtStart(ins->rhs()),
  1558                                         tempFixed(CallTempReg0));
  1559         return defineReturn(lir, ins);
  1562     return lowerBinaryV(JSOP_MOD, ins);
  1565 bool
  1566 LIRGenerator::lowerBinaryV(JSOp op, MBinaryInstruction *ins)
  1568     MDefinition *lhs = ins->getOperand(0);
  1569     MDefinition *rhs = ins->getOperand(1);
  1571     JS_ASSERT(lhs->type() == MIRType_Value);
  1572     JS_ASSERT(rhs->type() == MIRType_Value);
  1574     LBinaryV *lir = new(alloc()) LBinaryV(op);
  1575     if (!useBoxAtStart(lir, LBinaryV::LhsInput, lhs))
  1576         return false;
  1577     if (!useBoxAtStart(lir, LBinaryV::RhsInput, rhs))
  1578         return false;
  1579     if (!defineReturn(lir, ins))
  1580         return false;
  1581     return assignSafepoint(lir, ins);
  1584 bool
  1585 LIRGenerator::visitConcat(MConcat *ins)
  1587     MDefinition *lhs = ins->getOperand(0);
  1588     MDefinition *rhs = ins->getOperand(1);
  1590     JS_ASSERT(lhs->type() == MIRType_String);
  1591     JS_ASSERT(rhs->type() == MIRType_String);
  1592     JS_ASSERT(ins->type() == MIRType_String);
  1594     LConcat *lir = new(alloc()) LConcat(useFixedAtStart(lhs, CallTempReg0),
  1595                                         useFixedAtStart(rhs, CallTempReg1),
  1596                                         tempFixed(CallTempReg0),
  1597                                         tempFixed(CallTempReg1),
  1598                                         tempFixed(CallTempReg2),
  1599                                         tempFixed(CallTempReg3),
  1600                                         tempFixed(CallTempReg4));
  1601     if (!defineFixed(lir, ins, LAllocation(AnyRegister(CallTempReg5))))
  1602         return false;
  1603     return assignSafepoint(lir, ins);
  1606 bool
  1607 LIRGenerator::visitConcatPar(MConcatPar *ins)
  1609     MDefinition *cx = ins->forkJoinContext();
  1610     MDefinition *lhs = ins->lhs();
  1611     MDefinition *rhs = ins->rhs();
  1613     JS_ASSERT(lhs->type() == MIRType_String);
  1614     JS_ASSERT(rhs->type() == MIRType_String);
  1615     JS_ASSERT(ins->type() == MIRType_String);
  1617     LConcatPar *lir = new(alloc()) LConcatPar(useFixed(cx, CallTempReg4),
  1618                                               useFixedAtStart(lhs, CallTempReg0),
  1619                                               useFixedAtStart(rhs, CallTempReg1),
  1620                                               tempFixed(CallTempReg0),
  1621                                               tempFixed(CallTempReg1),
  1622                                               tempFixed(CallTempReg2),
  1623                                               tempFixed(CallTempReg3));
  1624     if (!defineFixed(lir, ins, LAllocation(AnyRegister(CallTempReg5))))
  1625         return false;
  1626     return assignSafepoint(lir, ins);
  1629 bool
  1630 LIRGenerator::visitCharCodeAt(MCharCodeAt *ins)
  1632     MDefinition *str = ins->getOperand(0);
  1633     MDefinition *idx = ins->getOperand(1);
  1635     JS_ASSERT(str->type() == MIRType_String);
  1636     JS_ASSERT(idx->type() == MIRType_Int32);
  1638     LCharCodeAt *lir = new(alloc()) LCharCodeAt(useRegister(str), useRegister(idx));
  1639     if (!define(lir, ins))
  1640         return false;
  1641     return assignSafepoint(lir, ins);
  1644 bool
  1645 LIRGenerator::visitFromCharCode(MFromCharCode *ins)
  1647     MDefinition *code = ins->getOperand(0);
  1649     JS_ASSERT(code->type() == MIRType_Int32);
  1651     LFromCharCode *lir = new(alloc()) LFromCharCode(useRegister(code));
  1652     if (!define(lir, ins))
  1653         return false;
  1654     return assignSafepoint(lir, ins);
  1657 bool
  1658 LIRGenerator::visitStart(MStart *start)
  1660     // Create a snapshot that captures the initial state of the function.
  1661     LStart *lir = new(alloc()) LStart;
  1662     if (!assignSnapshot(lir))
  1663         return false;
  1665     if (start->startType() == MStart::StartType_Default)
  1666         lirGraph_.setEntrySnapshot(lir->snapshot());
  1667     return add(lir);
  1670 bool
  1671 LIRGenerator::visitNop(MNop *nop)
  1673     return true;
  1676 bool
  1677 LIRGenerator::visitOsrEntry(MOsrEntry *entry)
  1679     LOsrEntry *lir = new(alloc()) LOsrEntry;
  1680     return defineFixed(lir, entry, LAllocation(AnyRegister(OsrFrameReg)));
  1683 bool
  1684 LIRGenerator::visitOsrValue(MOsrValue *value)
  1686     LOsrValue *lir = new(alloc()) LOsrValue(useRegister(value->entry()));
  1687     return defineBox(lir, value);
  1690 bool
  1691 LIRGenerator::visitOsrReturnValue(MOsrReturnValue *value)
  1693     LOsrReturnValue *lir = new(alloc()) LOsrReturnValue(useRegister(value->entry()));
  1694     return defineBox(lir, value);
  1697 bool
  1698 LIRGenerator::visitOsrScopeChain(MOsrScopeChain *object)
  1700     LOsrScopeChain *lir = new(alloc()) LOsrScopeChain(useRegister(object->entry()));
  1701     return define(lir, object);
  1704 bool
  1705 LIRGenerator::visitOsrArgumentsObject(MOsrArgumentsObject *object)
  1707     LOsrArgumentsObject *lir = new(alloc()) LOsrArgumentsObject(useRegister(object->entry()));
  1708     return define(lir, object);
  1711 bool
  1712 LIRGenerator::visitToDouble(MToDouble *convert)
  1714     MDefinition *opd = convert->input();
  1715     mozilla::DebugOnly<MToDouble::ConversionKind> conversion = convert->conversion();
  1717     switch (opd->type()) {
  1718       case MIRType_Value:
  1720         LValueToDouble *lir = new(alloc()) LValueToDouble();
  1721         if (!useBox(lir, LValueToDouble::Input, opd))
  1722             return false;
  1723         return assignSnapshot(lir) && define(lir, convert);
  1726       case MIRType_Null:
  1727         JS_ASSERT(conversion != MToDouble::NumbersOnly && conversion != MToDouble::NonNullNonStringPrimitives);
  1728         return lowerConstantDouble(0, convert);
  1730       case MIRType_Undefined:
  1731         JS_ASSERT(conversion != MToDouble::NumbersOnly);
  1732         return lowerConstantDouble(GenericNaN(), convert);
  1734       case MIRType_Boolean:
  1735         JS_ASSERT(conversion != MToDouble::NumbersOnly);
  1736         /* FALLTHROUGH */
  1738       case MIRType_Int32:
  1740         LInt32ToDouble *lir = new(alloc()) LInt32ToDouble(useRegister(opd));
  1741         return define(lir, convert);
  1744       case MIRType_Float32:
  1746         LFloat32ToDouble *lir = new(alloc()) LFloat32ToDouble(useRegisterAtStart(opd));
  1747         return define(lir, convert);
  1750       case MIRType_Double:
  1751         return redefine(convert, opd);
  1753       default:
  1754         // Objects might be effectful.
  1755         // Strings are complicated - we don't handle them yet.
  1756         MOZ_ASSUME_UNREACHABLE("unexpected type");
  1760 bool
  1761 LIRGenerator::visitToFloat32(MToFloat32 *convert)
  1763     MDefinition *opd = convert->input();
  1764     mozilla::DebugOnly<MToFloat32::ConversionKind> conversion = convert->conversion();
  1766     switch (opd->type()) {
  1767       case MIRType_Value:
  1769         LValueToFloat32 *lir = new(alloc()) LValueToFloat32();
  1770         if (!useBox(lir, LValueToFloat32::Input, opd))
  1771             return false;
  1772         return assignSnapshot(lir) && define(lir, convert);
  1775       case MIRType_Null:
  1776         JS_ASSERT(conversion != MToFloat32::NonStringPrimitives);
  1777         return lowerConstantFloat32(0, convert);
  1779       case MIRType_Undefined:
  1780         JS_ASSERT(conversion != MToFloat32::NumbersOnly);
  1781         return lowerConstantFloat32(GenericNaN(), convert);
  1783       case MIRType_Boolean:
  1784         JS_ASSERT(conversion != MToFloat32::NumbersOnly);
  1785         /* FALLTHROUGH */
  1787       case MIRType_Int32:
  1789         LInt32ToFloat32 *lir = new(alloc()) LInt32ToFloat32(useRegister(opd));
  1790         return define(lir, convert);
  1793       case MIRType_Double:
  1795         LDoubleToFloat32 *lir = new(alloc()) LDoubleToFloat32(useRegister(opd));
  1796         return define(lir, convert);
  1799       case MIRType_Float32:
  1800         return redefine(convert, opd);
  1802       default:
  1803         // Objects might be effectful.
  1804         // Strings are complicated - we don't handle them yet.
  1805         MOZ_ASSUME_UNREACHABLE("unexpected type");
  1806         return false;
  1810 bool
  1811 LIRGenerator::visitToInt32(MToInt32 *convert)
  1813     MDefinition *opd = convert->input();
  1815     switch (opd->type()) {
  1816       case MIRType_Value:
  1818         LValueToInt32 *lir = new(alloc()) LValueToInt32(tempDouble(), temp(), LValueToInt32::NORMAL);
  1819         if (!useBox(lir, LValueToInt32::Input, opd))
  1820             return false;
  1821         return assignSnapshot(lir) && define(lir, convert) && assignSafepoint(lir, convert);
  1824       case MIRType_Null:
  1825         return define(new(alloc()) LInteger(0), convert);
  1827       case MIRType_Int32:
  1828       case MIRType_Boolean:
  1829         return redefine(convert, opd);
  1831       case MIRType_Float32:
  1833         LFloat32ToInt32 *lir = new(alloc()) LFloat32ToInt32(useRegister(opd));
  1834         return assignSnapshot(lir) && define(lir, convert);
  1837       case MIRType_Double:
  1839         LDoubleToInt32 *lir = new(alloc()) LDoubleToInt32(useRegister(opd));
  1840         return assignSnapshot(lir) && define(lir, convert);
  1843       case MIRType_String:
  1844       case MIRType_Object:
  1845       case MIRType_Undefined:
  1846         // Objects might be effectful. Undefined coerces to NaN, not int32.
  1847         MOZ_ASSUME_UNREACHABLE("ToInt32 invalid input type");
  1848         return false;
  1850       default:
  1851         MOZ_ASSUME_UNREACHABLE("unexpected type");
  1855 bool
  1856 LIRGenerator::visitTruncateToInt32(MTruncateToInt32 *truncate)
  1858     MDefinition *opd = truncate->input();
  1860     switch (opd->type()) {
  1861       case MIRType_Value:
  1863         LValueToInt32 *lir = new(alloc()) LValueToInt32(tempDouble(), temp(), LValueToInt32::TRUNCATE);
  1864         if (!useBox(lir, LValueToInt32::Input, opd))
  1865             return false;
  1866         return assignSnapshot(lir) && define(lir, truncate) && assignSafepoint(lir, truncate);
  1869       case MIRType_Null:
  1870       case MIRType_Undefined:
  1871         return define(new(alloc()) LInteger(0), truncate);
  1873       case MIRType_Int32:
  1874       case MIRType_Boolean:
  1875         return redefine(truncate, opd);
  1877       case MIRType_Double:
  1878         return lowerTruncateDToInt32(truncate);
  1880       case MIRType_Float32:
  1881         return lowerTruncateFToInt32(truncate);
  1883       default:
  1884         // Objects might be effectful.
  1885         // Strings are complicated - we don't handle them yet.
  1886         MOZ_ASSUME_UNREACHABLE("unexpected type");
  1890 bool
  1891 LIRGenerator::visitToString(MToString *ins)
  1893     MDefinition *opd = ins->input();
  1895     switch (opd->type()) {
  1896       case MIRType_Null: {
  1897         const JSAtomState &names = GetIonContext()->runtime->names();
  1898         LPointer *lir = new(alloc()) LPointer(names.null);
  1899         return define(lir, ins);
  1902       case MIRType_Undefined: {
  1903         const JSAtomState &names = GetIonContext()->runtime->names();
  1904         LPointer *lir = new(alloc()) LPointer(names.undefined);
  1905         return define(lir, ins);
  1908       case MIRType_Boolean: {
  1909         LBooleanToString *lir = new(alloc()) LBooleanToString(useRegister(opd));
  1910         return define(lir, ins);
  1913       case MIRType_Double: {
  1914         LDoubleToString *lir = new(alloc()) LDoubleToString(useRegister(opd), temp());
  1916         if (!define(lir, ins))
  1917             return false;
  1918         return assignSafepoint(lir, ins);
  1921       case MIRType_Int32: {
  1922         LIntToString *lir = new(alloc()) LIntToString(useRegister(opd));
  1924         if (!define(lir, ins))
  1925             return false;
  1926         return assignSafepoint(lir, ins);
  1929       case MIRType_Value: {
  1930         JS_ASSERT(!opd->mightBeType(MIRType_Object));
  1931         LPrimitiveToString *lir = new(alloc()) LPrimitiveToString(tempToUnbox());
  1932         if (!useBox(lir, LPrimitiveToString::Input, opd))
  1933             return false;
  1934         if (!define(lir, ins))
  1935             return false;
  1936         return assignSafepoint(lir, ins);
  1939       default:
  1940         // Objects might be effectful. (see ToPrimitive)
  1941         MOZ_ASSUME_UNREACHABLE("unexpected type");
  1945 static bool
  1946 MustCloneRegExpForCall(MCall *call, uint32_t useIndex)
  1948     // We have a regex literal flowing into a call. Return |false| iff
  1949     // this is a native call that does not let the regex escape.
  1951     JSFunction *target = call->getSingleTarget();
  1952     if (!target || !target->isNative())
  1953         return true;
  1955     if (useIndex == MCall::IndexOfThis() &&
  1956         (target->native() == regexp_exec || target->native() == regexp_test))
  1958         return false;
  1961     if (useIndex == MCall::IndexOfArgument(0) &&
  1962         (target->native() == str_split ||
  1963          target->native() == str_replace ||
  1964          target->native() == str_match ||
  1965          target->native() == str_search))
  1967         return false;
  1970     return true;
  1974 static bool
  1975 MustCloneRegExp(MRegExp *regexp)
  1977     if (regexp->mustClone())
  1978         return true;
  1980     // If this regex literal only flows into known natives that don't let
  1981     // it escape, we don't have to clone it.
  1983     for (MUseIterator iter(regexp->usesBegin()); iter != regexp->usesEnd(); iter++) {
  1984         MNode *node = iter->consumer();
  1985         if (!node->isDefinition())
  1986             return true;
  1988         MDefinition *def = node->toDefinition();
  1989         if (def->isRegExpTest() && iter->index() == 1) {
  1990             // Optimized RegExp.prototype.test.
  1991             JS_ASSERT(def->toRegExpTest()->regexp() == regexp);
  1992             continue;
  1995         if (def->isCall() && !MustCloneRegExpForCall(def->toCall(), iter->index()))
  1996             continue;
  1998         return true;
  2000     return false;
  2003 bool
  2004 LIRGenerator::visitRegExp(MRegExp *ins)
  2006     if (!MustCloneRegExp(ins)) {
  2007         RegExpObject *source = ins->source();
  2008         return define(new(alloc()) LPointer(source), ins);
  2011     LRegExp *lir = new(alloc()) LRegExp();
  2012     return defineReturn(lir, ins) && assignSafepoint(lir, ins);
  2015 bool
  2016 LIRGenerator::visitRegExpExec(MRegExpExec *ins)
  2018     JS_ASSERT(ins->regexp()->type() == MIRType_Object);
  2019     JS_ASSERT(ins->string()->type() == MIRType_String);
  2021     LRegExpExec *lir = new(alloc()) LRegExpExec(useRegisterAtStart(ins->regexp()),
  2022                                                 useRegisterAtStart(ins->string()));
  2023     return defineReturn(lir, ins) && assignSafepoint(lir, ins);
  2026 bool
  2027 LIRGenerator::visitRegExpTest(MRegExpTest *ins)
  2029     JS_ASSERT(ins->regexp()->type() == MIRType_Object);
  2030     JS_ASSERT(ins->string()->type() == MIRType_String);
  2032     LRegExpTest *lir = new(alloc()) LRegExpTest(useRegisterAtStart(ins->regexp()),
  2033                                                 useRegisterAtStart(ins->string()));
  2034     return defineReturn(lir, ins) && assignSafepoint(lir, ins);
  2037 bool
  2038 LIRGenerator::visitRegExpReplace(MRegExpReplace *ins)
  2040     JS_ASSERT(ins->pattern()->type() == MIRType_Object);
  2041     JS_ASSERT(ins->string()->type() == MIRType_String);
  2042     JS_ASSERT(ins->replacement()->type() == MIRType_String);
  2044     LRegExpReplace *lir = new(alloc()) LRegExpReplace(useRegisterOrConstantAtStart(ins->string()),
  2045                                                       useRegisterAtStart(ins->pattern()),
  2046                                                       useRegisterOrConstantAtStart(ins->replacement()));
  2047     return defineReturn(lir, ins) && assignSafepoint(lir, ins);
  2050 bool
  2051 LIRGenerator::visitStringReplace(MStringReplace *ins)
  2053     JS_ASSERT(ins->pattern()->type() == MIRType_String);
  2054     JS_ASSERT(ins->string()->type() == MIRType_String);
  2055     JS_ASSERT(ins->replacement()->type() == MIRType_String);
  2057     LStringReplace *lir = new(alloc()) LStringReplace(useRegisterOrConstantAtStart(ins->string()),
  2058                                                       useRegisterAtStart(ins->pattern()),
  2059                                                       useRegisterOrConstantAtStart(ins->replacement()));
  2060     return defineReturn(lir, ins) && assignSafepoint(lir, ins);
  2063 bool
  2064 LIRGenerator::visitLambda(MLambda *ins)
  2066     if (ins->info().singletonType || ins->info().useNewTypeForClone) {
  2067         // If the function has a singleton type, this instruction will only be
  2068         // executed once so we don't bother inlining it.
  2069         //
  2070         // If UseNewTypeForClone is true, we will assign a singleton type to
  2071         // the clone and we have to clone the script, we can't do that inline.
  2072         LLambdaForSingleton *lir = new(alloc()) LLambdaForSingleton(useRegisterAtStart(ins->scopeChain()));
  2073         return defineReturn(lir, ins) && assignSafepoint(lir, ins);
  2076     LLambda *lir = new(alloc()) LLambda(useRegister(ins->scopeChain()), temp());
  2077     return define(lir, ins) && assignSafepoint(lir, ins);
  2080 bool
  2081 LIRGenerator::visitLambdaArrow(MLambdaArrow *ins)
  2083     MOZ_ASSERT(ins->scopeChain()->type() == MIRType_Object);
  2084     MOZ_ASSERT(ins->thisDef()->type() == MIRType_Value);
  2086     LLambdaArrow *lir = new(alloc()) LLambdaArrow(useRegister(ins->scopeChain()), temp());
  2087     if (!useBox(lir, LLambdaArrow::ThisValue, ins->thisDef()))
  2088         return false;
  2089     return define(lir, ins) && assignSafepoint(lir, ins);
  2092 bool
  2093 LIRGenerator::visitLambdaPar(MLambdaPar *ins)
  2095     JS_ASSERT(!ins->info().singletonType);
  2096     JS_ASSERT(!ins->info().useNewTypeForClone);
  2097     LLambdaPar *lir = new(alloc()) LLambdaPar(useRegister(ins->forkJoinContext()),
  2098                                               useRegister(ins->scopeChain()),
  2099                                               temp(), temp());
  2100     return define(lir, ins);
  2103 bool
  2104 LIRGenerator::visitImplicitThis(MImplicitThis *ins)
  2106     JS_ASSERT(ins->callee()->type() == MIRType_Object);
  2108     LImplicitThis *lir = new(alloc()) LImplicitThis(useRegister(ins->callee()));
  2109     return assignSnapshot(lir) && defineBox(lir, ins);
  2112 bool
  2113 LIRGenerator::visitSlots(MSlots *ins)
  2115     return define(new(alloc()) LSlots(useRegisterAtStart(ins->object())), ins);
  2118 bool
  2119 LIRGenerator::visitElements(MElements *ins)
  2121     return define(new(alloc()) LElements(useRegisterAtStart(ins->object())), ins);
  2124 bool
  2125 LIRGenerator::visitConstantElements(MConstantElements *ins)
  2127     return define(new(alloc()) LPointer(ins->value(), LPointer::NON_GC_THING), ins);
  2130 bool
  2131 LIRGenerator::visitConvertElementsToDoubles(MConvertElementsToDoubles *ins)
  2133     LInstruction *check = new(alloc()) LConvertElementsToDoubles(useRegister(ins->elements()));
  2134     return add(check, ins) && assignSafepoint(check, ins);
  2137 bool
  2138 LIRGenerator::visitMaybeToDoubleElement(MMaybeToDoubleElement *ins)
  2140     JS_ASSERT(ins->elements()->type() == MIRType_Elements);
  2141     JS_ASSERT(ins->value()->type() == MIRType_Int32);
  2143     LMaybeToDoubleElement *lir = new(alloc()) LMaybeToDoubleElement(useRegisterAtStart(ins->elements()),
  2144                                                                     useRegisterAtStart(ins->value()),
  2145                                                                     tempDouble());
  2146     return defineBox(lir, ins);
  2149 bool
  2150 LIRGenerator::visitLoadSlot(MLoadSlot *ins)
  2152     switch (ins->type()) {
  2153       case MIRType_Value:
  2154         return defineBox(new(alloc()) LLoadSlotV(useRegister(ins->slots())), ins);
  2156       case MIRType_Undefined:
  2157       case MIRType_Null:
  2158         MOZ_ASSUME_UNREACHABLE("typed load must have a payload");
  2160       default:
  2161         return define(new(alloc()) LLoadSlotT(useRegister(ins->slots())), ins);
  2165 bool
  2166 LIRGenerator::visitFunctionEnvironment(MFunctionEnvironment *ins)
  2168     return define(new(alloc()) LFunctionEnvironment(useRegisterAtStart(ins->function())), ins);
  2171 bool
  2172 LIRGenerator::visitForkJoinContext(MForkJoinContext *ins)
  2174     LForkJoinContext *lir = new(alloc()) LForkJoinContext(tempFixed(CallTempReg0));
  2175     return defineReturn(lir, ins);
  2178 bool
  2179 LIRGenerator::visitGuardThreadExclusive(MGuardThreadExclusive *ins)
  2181     // FIXME (Bug 956281) -- For now, we always generate the most
  2182     // general form of write guard check. we could employ TI feedback
  2183     // to optimize this if we know that the object being tested is a
  2184     // typed object or know that it is definitely NOT a typed object.
  2185     LGuardThreadExclusive *lir =
  2186         new(alloc()) LGuardThreadExclusive(useFixed(ins->forkJoinContext(), CallTempReg0),
  2187                                            useFixed(ins->object(), CallTempReg1),
  2188                                            tempFixed(CallTempReg2));
  2189     lir->setMir(ins);
  2190     return add(lir, ins);
  2193 bool
  2194 LIRGenerator::visitInterruptCheck(MInterruptCheck *ins)
  2196     // Implicit interrupt checks require asm.js signal handlers to be
  2197     // installed. ARM does not yet use implicit interrupt checks, see
  2198     // bug 864220.
  2199 #ifndef JS_CODEGEN_ARM
  2200     if (GetIonContext()->runtime->signalHandlersInstalled()) {
  2201         LInterruptCheckImplicit *lir = new(alloc()) LInterruptCheckImplicit();
  2202         return add(lir, ins) && assignSafepoint(lir, ins);
  2204 #endif
  2206     LInterruptCheck *lir = new(alloc()) LInterruptCheck();
  2207     return add(lir, ins) && assignSafepoint(lir, ins);
  2210 bool
  2211 LIRGenerator::visitInterruptCheckPar(MInterruptCheckPar *ins)
  2213     LInterruptCheckPar *lir =
  2214         new(alloc()) LInterruptCheckPar(useRegister(ins->forkJoinContext()), temp());
  2215     if (!add(lir, ins))
  2216         return false;
  2217     if (!assignSafepoint(lir, ins))
  2218         return false;
  2219     return true;
  2222 bool
  2223 LIRGenerator::visitNewPar(MNewPar *ins)
  2225     LNewPar *lir = new(alloc()) LNewPar(useRegister(ins->forkJoinContext()), temp(), temp());
  2226     return define(lir, ins);
  2229 bool
  2230 LIRGenerator::visitNewDenseArrayPar(MNewDenseArrayPar *ins)
  2232     LNewDenseArrayPar *lir =
  2233         new(alloc()) LNewDenseArrayPar(useFixed(ins->forkJoinContext(), CallTempReg0),
  2234                                        useFixed(ins->length(), CallTempReg1),
  2235                                        tempFixed(CallTempReg2),
  2236                                        tempFixed(CallTempReg3),
  2237                                        tempFixed(CallTempReg4));
  2238     return defineReturn(lir, ins);
  2241 bool
  2242 LIRGenerator::visitStoreSlot(MStoreSlot *ins)
  2244     LInstruction *lir;
  2246     switch (ins->value()->type()) {
  2247       case MIRType_Value:
  2248         lir = new(alloc()) LStoreSlotV(useRegister(ins->slots()));
  2249         if (!useBox(lir, LStoreSlotV::Value, ins->value()))
  2250             return false;
  2251         return add(lir, ins);
  2253       case MIRType_Double:
  2254         return add(new(alloc()) LStoreSlotT(useRegister(ins->slots()), useRegister(ins->value())), ins);
  2256       case MIRType_Float32:
  2257         MOZ_ASSUME_UNREACHABLE("Float32 shouldn't be stored in a slot.");
  2259       default:
  2260         return add(new(alloc()) LStoreSlotT(useRegister(ins->slots()), useRegisterOrConstant(ins->value())),
  2261                    ins);
  2264     return true;
  2267 bool
  2268 LIRGenerator::visitFilterTypeSet(MFilterTypeSet *ins)
  2270     return redefine(ins, ins->input());
  2273 bool
  2274 LIRGenerator::visitTypeBarrier(MTypeBarrier *ins)
  2276     // Requesting a non-GC pointer is safe here since we never re-enter C++
  2277     // from inside a type barrier test.
  2279     const types::TemporaryTypeSet *types = ins->resultTypeSet();
  2280     bool needTemp = !types->unknownObject() && types->getObjectCount() > 0;
  2282     MIRType inputType = ins->getOperand(0)->type();
  2283     DebugOnly<MIRType> outputType = ins->type();
  2285     JS_ASSERT(inputType == outputType);
  2287     // Handle typebarrier that will always bail.
  2288     // (Emit LBail for visibility).
  2289     if (ins->alwaysBails()) {
  2290         LBail *bail = new(alloc()) LBail();
  2291         if (!assignSnapshot(bail))
  2292             return false;
  2293         return redefine(ins, ins->input()) && add(bail, ins);
  2296     // Handle typebarrier with Value as input.
  2297     if (inputType == MIRType_Value) {
  2298         LDefinition tmp = needTemp ? temp() : tempToUnbox();
  2299         LTypeBarrierV *barrier = new(alloc()) LTypeBarrierV(tmp);
  2300         if (!useBox(barrier, LTypeBarrierV::Input, ins->input()))
  2301             return false;
  2302         if (!assignSnapshot(barrier))
  2303             return false;
  2304         return redefine(ins, ins->input()) && add(barrier, ins);
  2307     // Handle typebarrier with specific TypeObject/SingleObjects.
  2308     if (inputType == MIRType_Object && !types->hasType(types::Type::AnyObjectType()))
  2310         LDefinition tmp = needTemp ? temp() : LDefinition::BogusTemp();
  2311         LTypeBarrierO *barrier = new(alloc()) LTypeBarrierO(useRegister(ins->getOperand(0)), tmp);
  2312         if (!assignSnapshot(barrier))
  2313             return false;
  2314         return redefine(ins, ins->getOperand(0)) && add(barrier, ins);
  2317     // Handle remaining cases: No-op, unbox did everything.
  2318     return redefine(ins, ins->getOperand(0));
  2321 bool
  2322 LIRGenerator::visitMonitorTypes(MMonitorTypes *ins)
  2324     // Requesting a non-GC pointer is safe here since we never re-enter C++
  2325     // from inside a type check.
  2327     const types::TemporaryTypeSet *types = ins->typeSet();
  2328     bool needTemp = !types->unknownObject() && types->getObjectCount() > 0;
  2329     LDefinition tmp = needTemp ? temp() : tempToUnbox();
  2331     LMonitorTypes *lir = new(alloc()) LMonitorTypes(tmp);
  2332     if (!useBox(lir, LMonitorTypes::Input, ins->input()))
  2333         return false;
  2334     return assignSnapshot(lir, Bailout_Normal) && add(lir, ins);
  2337 bool
  2338 LIRGenerator::visitPostWriteBarrier(MPostWriteBarrier *ins)
  2340 #ifdef JSGC_GENERATIONAL
  2341     switch (ins->value()->type()) {
  2342       case MIRType_Object: {
  2343         LDefinition tmp = needTempForPostBarrier() ? temp() : LDefinition::BogusTemp();
  2344         LPostWriteBarrierO *lir =
  2345             new(alloc()) LPostWriteBarrierO(useRegisterOrConstant(ins->object()),
  2346                                             useRegister(ins->value()), tmp);
  2347         return add(lir, ins) && assignSafepoint(lir, ins);
  2349       case MIRType_Value: {
  2350         LDefinition tmp = needTempForPostBarrier() ? temp() : LDefinition::BogusTemp();
  2351         LPostWriteBarrierV *lir =
  2352             new(alloc()) LPostWriteBarrierV(useRegisterOrConstant(ins->object()), tmp);
  2353         if (!useBox(lir, LPostWriteBarrierV::Input, ins->value()))
  2354             return false;
  2355         return add(lir, ins) && assignSafepoint(lir, ins);
  2357       default:
  2358         // Currently, only objects can be in the nursery. Other instruction
  2359         // types cannot hold nursery pointers.
  2360         return true;
  2362 #endif // JSGC_GENERATIONAL
  2363     return true;
  2366 bool
  2367 LIRGenerator::visitArrayLength(MArrayLength *ins)
  2369     JS_ASSERT(ins->elements()->type() == MIRType_Elements);
  2370     return define(new(alloc()) LArrayLength(useRegisterAtStart(ins->elements())), ins);
  2373 bool
  2374 LIRGenerator::visitSetArrayLength(MSetArrayLength *ins)
  2376     JS_ASSERT(ins->elements()->type() == MIRType_Elements);
  2377     JS_ASSERT(ins->index()->type() == MIRType_Int32);
  2379     JS_ASSERT(ins->index()->isConstant());
  2380     return add(new(alloc()) LSetArrayLength(useRegister(ins->elements()),
  2381                                             useRegisterOrConstant(ins->index())), ins);
  2384 bool
  2385 LIRGenerator::visitTypedArrayLength(MTypedArrayLength *ins)
  2387     JS_ASSERT(ins->object()->type() == MIRType_Object);
  2388     return define(new(alloc()) LTypedArrayLength(useRegisterAtStart(ins->object())), ins);
  2391 bool
  2392 LIRGenerator::visitTypedArrayElements(MTypedArrayElements *ins)
  2394     JS_ASSERT(ins->type() == MIRType_Elements);
  2395     return define(new(alloc()) LTypedArrayElements(useRegisterAtStart(ins->object())), ins);
  2398 bool
  2399 LIRGenerator::visitTypedObjectElements(MTypedObjectElements *ins)
  2401     JS_ASSERT(ins->type() == MIRType_Elements);
  2402     return define(new(alloc()) LTypedObjectElements(useRegisterAtStart(ins->object())), ins);
  2405 bool
  2406 LIRGenerator::visitSetTypedObjectOffset(MSetTypedObjectOffset *ins)
  2408     return add(new(alloc()) LSetTypedObjectOffset(
  2409                    useRegister(ins->object()),
  2410                    useRegister(ins->offset()),
  2411                    temp()),
  2412                ins);
  2415 bool
  2416 LIRGenerator::visitInitializedLength(MInitializedLength *ins)
  2418     JS_ASSERT(ins->elements()->type() == MIRType_Elements);
  2419     return define(new(alloc()) LInitializedLength(useRegisterAtStart(ins->elements())), ins);
  2422 bool
  2423 LIRGenerator::visitSetInitializedLength(MSetInitializedLength *ins)
  2425     JS_ASSERT(ins->elements()->type() == MIRType_Elements);
  2426     JS_ASSERT(ins->index()->type() == MIRType_Int32);
  2428     JS_ASSERT(ins->index()->isConstant());
  2429     return add(new(alloc()) LSetInitializedLength(useRegister(ins->elements()),
  2430                                                   useRegisterOrConstant(ins->index())), ins);
  2433 bool
  2434 LIRGenerator::visitNot(MNot *ins)
  2436     MDefinition *op = ins->operand();
  2438     // String is converted to length of string in the type analysis phase (see
  2439     // TestPolicy).
  2440     JS_ASSERT(op->type() != MIRType_String);
  2442     // - boolean: x xor 1
  2443     // - int32: LCompare(x, 0)
  2444     // - double: LCompare(x, 0)
  2445     // - null or undefined: true
  2446     // - object: false if it never emulates undefined, else LNotO(x)
  2447     switch (op->type()) {
  2448       case MIRType_Boolean: {
  2449         MConstant *cons = MConstant::New(alloc(), Int32Value(1));
  2450         ins->block()->insertBefore(ins, cons);
  2451         return lowerForALU(new(alloc()) LBitOpI(JSOP_BITXOR), ins, op, cons);
  2453       case MIRType_Int32: {
  2454         return define(new(alloc()) LNotI(useRegisterAtStart(op)), ins);
  2456       case MIRType_Double:
  2457         return define(new(alloc()) LNotD(useRegister(op)), ins);
  2458       case MIRType_Float32:
  2459         return define(new(alloc()) LNotF(useRegister(op)), ins);
  2460       case MIRType_Undefined:
  2461       case MIRType_Null:
  2462         return define(new(alloc()) LInteger(1), ins);
  2463       case MIRType_Object: {
  2464         // Objects that don't emulate undefined can be constant-folded.
  2465         if (!ins->operandMightEmulateUndefined())
  2466             return define(new(alloc()) LInteger(0), ins);
  2467         // All others require further work.
  2468         return define(new(alloc()) LNotO(useRegister(op)), ins);
  2470       case MIRType_Value: {
  2471         LDefinition temp0, temp1;
  2472         if (ins->operandMightEmulateUndefined()) {
  2473             temp0 = temp();
  2474             temp1 = temp();
  2475         } else {
  2476             temp0 = LDefinition::BogusTemp();
  2477             temp1 = LDefinition::BogusTemp();
  2480         LNotV *lir = new(alloc()) LNotV(tempDouble(), temp0, temp1);
  2481         if (!useBox(lir, LNotV::Input, op))
  2482             return false;
  2483         return define(lir, ins);
  2486       default:
  2487         MOZ_ASSUME_UNREACHABLE("Unexpected MIRType.");
  2491 bool
  2492 LIRGenerator::visitNeuterCheck(MNeuterCheck *ins)
  2494     LNeuterCheck *chk = new(alloc()) LNeuterCheck(useRegister(ins->object()),
  2495                                                   temp());
  2496     if (!assignSnapshot(chk, Bailout_BoundsCheck))
  2497         return false;
  2498     return redefine(ins, ins->input()) && add(chk, ins);
  2501 bool
  2502 LIRGenerator::visitBoundsCheck(MBoundsCheck *ins)
  2504     LInstruction *check;
  2505     if (ins->minimum() || ins->maximum()) {
  2506         check = new(alloc()) LBoundsCheckRange(useRegisterOrConstant(ins->index()),
  2507                                                useAny(ins->length()),
  2508                                                temp());
  2509     } else {
  2510         check = new(alloc()) LBoundsCheck(useRegisterOrConstant(ins->index()),
  2511                                           useAnyOrConstant(ins->length()));
  2513     return assignSnapshot(check, Bailout_BoundsCheck) && add(check, ins);
  2516 bool
  2517 LIRGenerator::visitBoundsCheckLower(MBoundsCheckLower *ins)
  2519     if (!ins->fallible())
  2520         return true;
  2522     LInstruction *check = new(alloc()) LBoundsCheckLower(useRegister(ins->index()));
  2523     return assignSnapshot(check, Bailout_BoundsCheck) && add(check, ins);
  2526 bool
  2527 LIRGenerator::visitInArray(MInArray *ins)
  2529     JS_ASSERT(ins->elements()->type() == MIRType_Elements);
  2530     JS_ASSERT(ins->index()->type() == MIRType_Int32);
  2531     JS_ASSERT(ins->initLength()->type() == MIRType_Int32);
  2532     JS_ASSERT(ins->object()->type() == MIRType_Object);
  2533     JS_ASSERT(ins->type() == MIRType_Boolean);
  2535     LAllocation object;
  2536     if (ins->needsNegativeIntCheck())
  2537         object = useRegister(ins->object());
  2538     else
  2539         object = LConstantIndex::Bogus();
  2541     LInArray *lir = new(alloc()) LInArray(useRegister(ins->elements()),
  2542                                           useRegisterOrConstant(ins->index()),
  2543                                           useRegister(ins->initLength()),
  2544                                           object);
  2545     return define(lir, ins) && assignSafepoint(lir, ins);
  2548 bool
  2549 LIRGenerator::visitLoadElement(MLoadElement *ins)
  2551     JS_ASSERT(ins->elements()->type() == MIRType_Elements);
  2552     JS_ASSERT(ins->index()->type() == MIRType_Int32);
  2554     switch (ins->type()) {
  2555       case MIRType_Value:
  2557         LLoadElementV *lir = new(alloc()) LLoadElementV(useRegister(ins->elements()),
  2558                                                useRegisterOrConstant(ins->index()));
  2559         if (ins->fallible() && !assignSnapshot(lir))
  2560             return false;
  2561         return defineBox(lir, ins);
  2563       case MIRType_Undefined:
  2564       case MIRType_Null:
  2565         MOZ_ASSUME_UNREACHABLE("typed load must have a payload");
  2567       default:
  2569         LLoadElementT *lir = new(alloc()) LLoadElementT(useRegister(ins->elements()),
  2570                                                useRegisterOrConstant(ins->index()));
  2571         if (ins->fallible() && !assignSnapshot(lir))
  2572             return false;
  2573         return define(lir, ins);
  2578 bool
  2579 LIRGenerator::visitLoadElementHole(MLoadElementHole *ins)
  2581     JS_ASSERT(ins->elements()->type() == MIRType_Elements);
  2582     JS_ASSERT(ins->index()->type() == MIRType_Int32);
  2583     JS_ASSERT(ins->initLength()->type() == MIRType_Int32);
  2584     JS_ASSERT(ins->type() == MIRType_Value);
  2586     LLoadElementHole *lir = new(alloc()) LLoadElementHole(useRegister(ins->elements()),
  2587                                                           useRegisterOrConstant(ins->index()),
  2588                                                           useRegister(ins->initLength()));
  2589     if (ins->needsNegativeIntCheck() && !assignSnapshot(lir))
  2590         return false;
  2591     return defineBox(lir, ins);
  2594 bool
  2595 LIRGenerator::visitStoreElement(MStoreElement *ins)
  2597     JS_ASSERT(ins->elements()->type() == MIRType_Elements);
  2598     JS_ASSERT(ins->index()->type() == MIRType_Int32);
  2600     const LUse elements = useRegister(ins->elements());
  2601     const LAllocation index = useRegisterOrConstant(ins->index());
  2603     switch (ins->value()->type()) {
  2604       case MIRType_Value:
  2606         LInstruction *lir = new(alloc()) LStoreElementV(elements, index);
  2607         if (ins->fallible() && !assignSnapshot(lir))
  2608             return false;
  2609         if (!useBox(lir, LStoreElementV::Value, ins->value()))
  2610             return false;
  2611         return add(lir, ins);
  2614       default:
  2616         const LAllocation value = useRegisterOrNonDoubleConstant(ins->value());
  2617         LInstruction *lir = new(alloc()) LStoreElementT(elements, index, value);
  2618         if (ins->fallible() && !assignSnapshot(lir))
  2619             return false;
  2620         return add(lir, ins);
  2625 bool
  2626 LIRGenerator::visitStoreElementHole(MStoreElementHole *ins)
  2628     JS_ASSERT(ins->elements()->type() == MIRType_Elements);
  2629     JS_ASSERT(ins->index()->type() == MIRType_Int32);
  2631     const LUse object = useRegister(ins->object());
  2632     const LUse elements = useRegister(ins->elements());
  2633     const LAllocation index = useRegisterOrConstant(ins->index());
  2635     LInstruction *lir;
  2636     switch (ins->value()->type()) {
  2637       case MIRType_Value:
  2638         lir = new(alloc()) LStoreElementHoleV(object, elements, index);
  2639         if (!useBox(lir, LStoreElementHoleV::Value, ins->value()))
  2640             return false;
  2641         break;
  2643       default:
  2645         const LAllocation value = useRegisterOrNonDoubleConstant(ins->value());
  2646         lir = new(alloc()) LStoreElementHoleT(object, elements, index, value);
  2647         break;
  2651     return add(lir, ins) && assignSafepoint(lir, ins);
  2654 bool
  2655 LIRGenerator::visitEffectiveAddress(MEffectiveAddress *ins)
  2657     return define(new(alloc()) LEffectiveAddress(useRegister(ins->base()), useRegister(ins->index())), ins);
  2660 bool
  2661 LIRGenerator::visitArrayPopShift(MArrayPopShift *ins)
  2663     LUse object = useRegister(ins->object());
  2665     switch (ins->type()) {
  2666       case MIRType_Value:
  2668         LArrayPopShiftV *lir = new(alloc()) LArrayPopShiftV(object, temp(), temp());
  2669         return defineBox(lir, ins) && assignSafepoint(lir, ins);
  2671       case MIRType_Undefined:
  2672       case MIRType_Null:
  2673         MOZ_ASSUME_UNREACHABLE("typed load must have a payload");
  2675       default:
  2677         LArrayPopShiftT *lir = new(alloc()) LArrayPopShiftT(object, temp(), temp());
  2678         return define(lir, ins) && assignSafepoint(lir, ins);
  2683 bool
  2684 LIRGenerator::visitArrayPush(MArrayPush *ins)
  2686     JS_ASSERT(ins->type() == MIRType_Int32);
  2688     LUse object = useRegister(ins->object());
  2690     switch (ins->value()->type()) {
  2691       case MIRType_Value:
  2693         LArrayPushV *lir = new(alloc()) LArrayPushV(object, temp());
  2694         if (!useBox(lir, LArrayPushV::Value, ins->value()))
  2695             return false;
  2696         return define(lir, ins) && assignSafepoint(lir, ins);
  2699       default:
  2701         const LAllocation value = useRegisterOrNonDoubleConstant(ins->value());
  2702         LArrayPushT *lir = new(alloc()) LArrayPushT(object, value, temp());
  2703         return define(lir, ins) && assignSafepoint(lir, ins);
  2708 bool
  2709 LIRGenerator::visitArrayConcat(MArrayConcat *ins)
  2711     JS_ASSERT(ins->type() == MIRType_Object);
  2712     JS_ASSERT(ins->lhs()->type() == MIRType_Object);
  2713     JS_ASSERT(ins->rhs()->type() == MIRType_Object);
  2715     LArrayConcat *lir = new(alloc()) LArrayConcat(useFixed(ins->lhs(), CallTempReg1),
  2716                                                   useFixed(ins->rhs(), CallTempReg2),
  2717                                                   tempFixed(CallTempReg3),
  2718                                                   tempFixed(CallTempReg4));
  2719     return defineReturn(lir, ins) && assignSafepoint(lir, ins);
  2722 bool
  2723 LIRGenerator::visitStringSplit(MStringSplit *ins)
  2725     JS_ASSERT(ins->type() == MIRType_Object);
  2726     JS_ASSERT(ins->string()->type() == MIRType_String);
  2727     JS_ASSERT(ins->separator()->type() == MIRType_String);
  2729     LStringSplit *lir = new(alloc()) LStringSplit(useRegisterAtStart(ins->string()),
  2730                                                   useRegisterAtStart(ins->separator()));
  2731     return defineReturn(lir, ins) && assignSafepoint(lir, ins);
  2734 bool
  2735 LIRGenerator::visitLoadTypedArrayElement(MLoadTypedArrayElement *ins)
  2737     JS_ASSERT(ins->elements()->type() == MIRType_Elements);
  2738     JS_ASSERT(ins->index()->type() == MIRType_Int32);
  2740     const LUse elements = useRegister(ins->elements());
  2741     const LAllocation index = useRegisterOrConstant(ins->index());
  2743     JS_ASSERT(IsNumberType(ins->type()));
  2745     // We need a temp register for Uint32Array with known double result.
  2746     LDefinition tempDef = LDefinition::BogusTemp();
  2747     if (ins->arrayType() == ScalarTypeDescr::TYPE_UINT32 && IsFloatingPointType(ins->type()))
  2748         tempDef = temp();
  2750     LLoadTypedArrayElement *lir = new(alloc()) LLoadTypedArrayElement(elements, index, tempDef);
  2751     if (ins->fallible() && !assignSnapshot(lir))
  2752         return false;
  2753     return define(lir, ins);
  2756 bool
  2757 LIRGenerator::visitClampToUint8(MClampToUint8 *ins)
  2759     MDefinition *in = ins->input();
  2761     switch (in->type()) {
  2762       case MIRType_Boolean:
  2763         return redefine(ins, in);
  2765       case MIRType_Int32:
  2766         return defineReuseInput(new(alloc()) LClampIToUint8(useRegisterAtStart(in)), ins, 0);
  2768       case MIRType_Double:
  2769         return define(new(alloc()) LClampDToUint8(useRegisterAtStart(in), tempCopy(in, 0)), ins);
  2771       case MIRType_Value:
  2773         LClampVToUint8 *lir = new(alloc()) LClampVToUint8(tempDouble());
  2774         if (!useBox(lir, LClampVToUint8::Input, in))
  2775             return false;
  2776         return assignSnapshot(lir) && define(lir, ins) && assignSafepoint(lir, ins);
  2779       default:
  2780         MOZ_ASSUME_UNREACHABLE("unexpected type");
  2784 bool
  2785 LIRGenerator::visitLoadTypedArrayElementHole(MLoadTypedArrayElementHole *ins)
  2787     JS_ASSERT(ins->object()->type() == MIRType_Object);
  2788     JS_ASSERT(ins->index()->type() == MIRType_Int32);
  2790     JS_ASSERT(ins->type() == MIRType_Value);
  2792     const LUse object = useRegister(ins->object());
  2793     const LAllocation index = useRegisterOrConstant(ins->index());
  2795     LLoadTypedArrayElementHole *lir = new(alloc()) LLoadTypedArrayElementHole(object, index);
  2796     if (ins->fallible() && !assignSnapshot(lir))
  2797         return false;
  2798     return defineBox(lir, ins) && assignSafepoint(lir, ins);
  2801 bool
  2802 LIRGenerator::visitLoadTypedArrayElementStatic(MLoadTypedArrayElementStatic *ins)
  2804     LLoadTypedArrayElementStatic *lir =
  2805         new(alloc()) LLoadTypedArrayElementStatic(useRegisterAtStart(ins->ptr()));
  2807     if (ins->fallible() && !assignSnapshot(lir))
  2808         return false;
  2809     return define(lir, ins);
  2812 bool
  2813 LIRGenerator::visitStoreTypedArrayElement(MStoreTypedArrayElement *ins)
  2815     JS_ASSERT(ins->elements()->type() == MIRType_Elements);
  2816     JS_ASSERT(ins->index()->type() == MIRType_Int32);
  2818     if (ins->isFloatArray()) {
  2819         DebugOnly<bool> optimizeFloat32 = allowFloat32Optimizations();
  2820         JS_ASSERT_IF(optimizeFloat32 && ins->arrayType() == ScalarTypeDescr::TYPE_FLOAT32,
  2821                      ins->value()->type() == MIRType_Float32);
  2822         JS_ASSERT_IF(!optimizeFloat32 || ins->arrayType() == ScalarTypeDescr::TYPE_FLOAT64,
  2823                      ins->value()->type() == MIRType_Double);
  2824     } else {
  2825         JS_ASSERT(ins->value()->type() == MIRType_Int32);
  2828     LUse elements = useRegister(ins->elements());
  2829     LAllocation index = useRegisterOrConstant(ins->index());
  2830     LAllocation value;
  2832     // For byte arrays, the value has to be in a byte register on x86.
  2833     if (ins->isByteArray())
  2834         value = useByteOpRegisterOrNonDoubleConstant(ins->value());
  2835     else
  2836         value = useRegisterOrNonDoubleConstant(ins->value());
  2837     return add(new(alloc()) LStoreTypedArrayElement(elements, index, value), ins);
  2840 bool
  2841 LIRGenerator::visitStoreTypedArrayElementHole(MStoreTypedArrayElementHole *ins)
  2843     JS_ASSERT(ins->elements()->type() == MIRType_Elements);
  2844     JS_ASSERT(ins->index()->type() == MIRType_Int32);
  2845     JS_ASSERT(ins->length()->type() == MIRType_Int32);
  2847     if (ins->isFloatArray()) {
  2848         DebugOnly<bool> optimizeFloat32 = allowFloat32Optimizations();
  2849         JS_ASSERT_IF(optimizeFloat32 && ins->arrayType() == ScalarTypeDescr::TYPE_FLOAT32,
  2850                      ins->value()->type() == MIRType_Float32);
  2851         JS_ASSERT_IF(!optimizeFloat32 || ins->arrayType() == ScalarTypeDescr::TYPE_FLOAT64,
  2852                      ins->value()->type() == MIRType_Double);
  2853     } else {
  2854         JS_ASSERT(ins->value()->type() == MIRType_Int32);
  2857     LUse elements = useRegister(ins->elements());
  2858     LAllocation length = useAnyOrConstant(ins->length());
  2859     LAllocation index = useRegisterOrConstant(ins->index());
  2860     LAllocation value;
  2862     // For byte arrays, the value has to be in a byte register on x86.
  2863     if (ins->isByteArray())
  2864         value = useByteOpRegisterOrNonDoubleConstant(ins->value());
  2865     else
  2866         value = useRegisterOrNonDoubleConstant(ins->value());
  2867     return add(new(alloc()) LStoreTypedArrayElementHole(elements, length, index, value), ins);
  2870 bool
  2871 LIRGenerator::visitLoadFixedSlot(MLoadFixedSlot *ins)
  2873     JS_ASSERT(ins->object()->type() == MIRType_Object);
  2875     if (ins->type() == MIRType_Value) {
  2876         LLoadFixedSlotV *lir = new(alloc()) LLoadFixedSlotV(useRegister(ins->object()));
  2877         return defineBox(lir, ins);
  2880     LLoadFixedSlotT *lir = new(alloc()) LLoadFixedSlotT(useRegister(ins->object()));
  2881     return define(lir, ins);
  2884 bool
  2885 LIRGenerator::visitStoreFixedSlot(MStoreFixedSlot *ins)
  2887     JS_ASSERT(ins->object()->type() == MIRType_Object);
  2889     if (ins->value()->type() == MIRType_Value) {
  2890         LStoreFixedSlotV *lir = new(alloc()) LStoreFixedSlotV(useRegister(ins->object()));
  2892         if (!useBox(lir, LStoreFixedSlotV::Value, ins->value()))
  2893             return false;
  2894         return add(lir, ins);
  2897     LStoreFixedSlotT *lir = new(alloc()) LStoreFixedSlotT(useRegister(ins->object()),
  2898                                                           useRegisterOrConstant(ins->value()));
  2899     return add(lir, ins);
  2902 bool
  2903 LIRGenerator::visitGetNameCache(MGetNameCache *ins)
  2905     JS_ASSERT(ins->scopeObj()->type() == MIRType_Object);
  2907     LGetNameCache *lir = new(alloc()) LGetNameCache(useRegister(ins->scopeObj()));
  2908     if (!defineBox(lir, ins))
  2909         return false;
  2910     return assignSafepoint(lir, ins);
  2913 bool
  2914 LIRGenerator::visitCallGetIntrinsicValue(MCallGetIntrinsicValue *ins)
  2916     LCallGetIntrinsicValue *lir = new(alloc()) LCallGetIntrinsicValue();
  2917     if (!defineReturn(lir, ins))
  2918         return false;
  2919     return assignSafepoint(lir, ins);
  2922 bool
  2923 LIRGenerator::visitCallsiteCloneCache(MCallsiteCloneCache *ins)
  2925     JS_ASSERT(ins->callee()->type() == MIRType_Object);
  2927     LCallsiteCloneCache *lir = new(alloc()) LCallsiteCloneCache(useRegister(ins->callee()));
  2928     if (!define(lir, ins))
  2929         return false;
  2930     return assignSafepoint(lir, ins);
  2933 bool
  2934 LIRGenerator::visitGetPropertyCache(MGetPropertyCache *ins)
  2936     JS_ASSERT(ins->object()->type() == MIRType_Object);
  2937     if (ins->type() == MIRType_Value) {
  2938         LGetPropertyCacheV *lir = new(alloc()) LGetPropertyCacheV(useRegister(ins->object()));
  2939         if (!defineBox(lir, ins))
  2940             return false;
  2941         return assignSafepoint(lir, ins);
  2944     LGetPropertyCacheT *lir = new(alloc()) LGetPropertyCacheT(useRegister(ins->object()),
  2945                                                               tempForDispatchCache(ins->type()));
  2946     if (!define(lir, ins))
  2947         return false;
  2948     return assignSafepoint(lir, ins);
  2951 bool
  2952 LIRGenerator::visitGetPropertyPolymorphic(MGetPropertyPolymorphic *ins)
  2954     JS_ASSERT(ins->obj()->type() == MIRType_Object);
  2956     if (ins->type() == MIRType_Value) {
  2957         LGetPropertyPolymorphicV *lir = new(alloc()) LGetPropertyPolymorphicV(useRegister(ins->obj()));
  2958         return assignSnapshot(lir, Bailout_ShapeGuard) && defineBox(lir, ins);
  2961     LDefinition maybeTemp = (ins->type() == MIRType_Double) ? temp() : LDefinition::BogusTemp();
  2962     LGetPropertyPolymorphicT *lir = new(alloc()) LGetPropertyPolymorphicT(useRegister(ins->obj()), maybeTemp);
  2963     return assignSnapshot(lir, Bailout_ShapeGuard) && define(lir, ins);
  2966 bool
  2967 LIRGenerator::visitSetPropertyPolymorphic(MSetPropertyPolymorphic *ins)
  2969     JS_ASSERT(ins->obj()->type() == MIRType_Object);
  2971     if (ins->value()->type() == MIRType_Value) {
  2972         LSetPropertyPolymorphicV *lir = new(alloc()) LSetPropertyPolymorphicV(useRegister(ins->obj()), temp());
  2973         if (!useBox(lir, LSetPropertyPolymorphicV::Value, ins->value()))
  2974             return false;
  2975         return assignSnapshot(lir, Bailout_ShapeGuard) && add(lir, ins);
  2978     LAllocation value = useRegisterOrConstant(ins->value());
  2979     LSetPropertyPolymorphicT *lir =
  2980         new(alloc()) LSetPropertyPolymorphicT(useRegister(ins->obj()), value, ins->value()->type(), temp());
  2981     return assignSnapshot(lir, Bailout_ShapeGuard) && add(lir, ins);
  2984 bool
  2985 LIRGenerator::visitGetElementCache(MGetElementCache *ins)
  2987     JS_ASSERT(ins->object()->type() == MIRType_Object);
  2989     if (ins->type() == MIRType_Value) {
  2990         JS_ASSERT(ins->index()->type() == MIRType_Value);
  2991         LGetElementCacheV *lir = new(alloc()) LGetElementCacheV(useRegister(ins->object()));
  2992         if (!useBox(lir, LGetElementCacheV::Index, ins->index()))
  2993             return false;
  2994         return defineBox(lir, ins) && assignSafepoint(lir, ins);
  2997     JS_ASSERT(ins->index()->type() == MIRType_Int32);
  2998     LGetElementCacheT *lir = new(alloc()) LGetElementCacheT(useRegister(ins->object()),
  2999                                                             useRegister(ins->index()),
  3000                                                             tempForDispatchCache(ins->type()));
  3001     return define(lir, ins) && assignSafepoint(lir, ins);
  3004 bool
  3005 LIRGenerator::visitBindNameCache(MBindNameCache *ins)
  3007     JS_ASSERT(ins->scopeChain()->type() == MIRType_Object);
  3008     JS_ASSERT(ins->type() == MIRType_Object);
  3010     LBindNameCache *lir = new(alloc()) LBindNameCache(useRegister(ins->scopeChain()));
  3011     return define(lir, ins) && assignSafepoint(lir, ins);
  3014 bool
  3015 LIRGenerator::visitGuardObjectIdentity(MGuardObjectIdentity *ins)
  3017     LGuardObjectIdentity *guard = new(alloc()) LGuardObjectIdentity(useRegister(ins->obj()));
  3018     return assignSnapshot(guard) && add(guard, ins) && redefine(ins, ins->obj());
  3021 bool
  3022 LIRGenerator::visitGuardClass(MGuardClass *ins)
  3024     LDefinition t = temp();
  3025     LGuardClass *guard = new(alloc()) LGuardClass(useRegister(ins->obj()), t);
  3026     return assignSnapshot(guard) && add(guard, ins);
  3029 bool
  3030 LIRGenerator::visitGuardObject(MGuardObject *ins)
  3032     // The type policy does all the work, so at this point the input
  3033     // is guaranteed to be an object.
  3034     JS_ASSERT(ins->input()->type() == MIRType_Object);
  3035     return redefine(ins, ins->input());
  3038 bool
  3039 LIRGenerator::visitGuardString(MGuardString *ins)
  3041     // The type policy does all the work, so at this point the input
  3042     // is guaranteed to be a string.
  3043     JS_ASSERT(ins->input()->type() == MIRType_String);
  3044     return redefine(ins, ins->input());
  3047 bool
  3048 LIRGenerator::visitAssertRange(MAssertRange *ins)
  3050     MDefinition *input = ins->input();
  3051     LInstruction *lir = nullptr;
  3053     switch (input->type()) {
  3054       case MIRType_Boolean:
  3055       case MIRType_Int32:
  3056         lir = new(alloc()) LAssertRangeI(useRegisterAtStart(input));
  3057         break;
  3059       case MIRType_Double:
  3060         lir = new(alloc()) LAssertRangeD(useRegister(input), tempDouble());
  3061         break;
  3063       case MIRType_Float32:
  3064         lir = new(alloc()) LAssertRangeF(useRegister(input), tempFloat32());
  3065         break;
  3067       case MIRType_Value:
  3068         lir = new(alloc()) LAssertRangeV(tempToUnbox(), tempDouble(), tempDouble());
  3069         if (!useBox(lir, LAssertRangeV::Input, input))
  3070             return false;
  3071         break;
  3073       default:
  3074         MOZ_ASSUME_UNREACHABLE("Unexpected Range for MIRType");
  3075         break;
  3078     lir->setMir(ins);
  3079     return add(lir);
  3082 bool
  3083 LIRGenerator::visitCallGetProperty(MCallGetProperty *ins)
  3085     LCallGetProperty *lir = new(alloc()) LCallGetProperty();
  3086     if (!useBoxAtStart(lir, LCallGetProperty::Value, ins->value()))
  3087         return false;
  3088     return defineReturn(lir, ins) && assignSafepoint(lir, ins);
  3091 bool
  3092 LIRGenerator::visitCallGetElement(MCallGetElement *ins)
  3094     JS_ASSERT(ins->lhs()->type() == MIRType_Value);
  3095     JS_ASSERT(ins->rhs()->type() == MIRType_Value);
  3097     LCallGetElement *lir = new(alloc()) LCallGetElement();
  3098     if (!useBoxAtStart(lir, LCallGetElement::LhsInput, ins->lhs()))
  3099         return false;
  3100     if (!useBoxAtStart(lir, LCallGetElement::RhsInput, ins->rhs()))
  3101         return false;
  3102     if (!defineReturn(lir, ins))
  3103         return false;
  3104     return assignSafepoint(lir, ins);
  3107 bool
  3108 LIRGenerator::visitCallSetProperty(MCallSetProperty *ins)
  3110     LInstruction *lir = new(alloc()) LCallSetProperty(useRegisterAtStart(ins->object()));
  3111     if (!useBoxAtStart(lir, LCallSetProperty::Value, ins->value()))
  3112         return false;
  3113     if (!add(lir, ins))
  3114         return false;
  3115     return assignSafepoint(lir, ins);
  3118 bool
  3119 LIRGenerator::visitDeleteProperty(MDeleteProperty *ins)
  3121     LCallDeleteProperty *lir = new(alloc()) LCallDeleteProperty();
  3122     if(!useBoxAtStart(lir, LCallDeleteProperty::Value, ins->value()))
  3123         return false;
  3124     return defineReturn(lir, ins) && assignSafepoint(lir, ins);
  3127 bool
  3128 LIRGenerator::visitDeleteElement(MDeleteElement *ins)
  3130     LCallDeleteElement *lir = new(alloc()) LCallDeleteElement();
  3131     if(!useBoxAtStart(lir, LCallDeleteElement::Value, ins->value()))
  3132         return false;
  3133     if(!useBoxAtStart(lir, LCallDeleteElement::Index, ins->index()))
  3134         return false;
  3135     return defineReturn(lir, ins) && assignSafepoint(lir, ins);
  3138 bool
  3139 LIRGenerator::visitSetPropertyCache(MSetPropertyCache *ins)
  3141     LUse obj = useRegisterAtStart(ins->object());
  3142     LDefinition slots = tempCopy(ins->object(), 0);
  3143     LDefinition dispatchTemp = tempForDispatchCache();
  3145     LInstruction *lir;
  3146     if (ins->value()->type() == MIRType_Value) {
  3147         lir = new(alloc()) LSetPropertyCacheV(obj, slots, dispatchTemp);
  3148         if (!useBox(lir, LSetPropertyCacheV::Value, ins->value()))
  3149             return false;
  3150     } else {
  3151         LAllocation value = useRegisterOrConstant(ins->value());
  3152         lir = new(alloc()) LSetPropertyCacheT(obj, slots, value, dispatchTemp, ins->value()->type());
  3155     if (!add(lir, ins))
  3156         return false;
  3158     return assignSafepoint(lir, ins);
  3161 bool
  3162 LIRGenerator::visitSetElementCache(MSetElementCache *ins)
  3164     JS_ASSERT(ins->object()->type() == MIRType_Object);
  3165     JS_ASSERT(ins->index()->type() == MIRType_Value);
  3167     // Due to lack of registers on x86, we reuse the object register as a
  3168     // temporary. This register may be used in a 1-byte store, which on x86
  3169     // again has constraints; thus the use of |useByteOpRegister| over
  3170     // |useRegister| below.
  3171     LInstruction *lir;
  3172     if (ins->value()->type() == MIRType_Value) {
  3173         lir = new(alloc()) LSetElementCacheV(useByteOpRegister(ins->object()), tempToUnbox(),
  3174                                              temp(), tempDouble());
  3176         if (!useBox(lir, LSetElementCacheV::Index, ins->index()))
  3177             return false;
  3178         if (!useBox(lir, LSetElementCacheV::Value, ins->value()))
  3179             return false;
  3180     } else {
  3181         lir = new(alloc()) LSetElementCacheT(useByteOpRegister(ins->object()),
  3182                                              useRegisterOrConstant(ins->value()),
  3183                                              tempToUnbox(), temp(), tempDouble());
  3185         if (!useBox(lir, LSetElementCacheT::Index, ins->index()))
  3186             return false;
  3189     return add(lir, ins) && assignSafepoint(lir, ins);
  3192 bool
  3193 LIRGenerator::visitCallSetElement(MCallSetElement *ins)
  3195     JS_ASSERT(ins->object()->type() == MIRType_Object);
  3196     JS_ASSERT(ins->index()->type() == MIRType_Value);
  3197     JS_ASSERT(ins->value()->type() == MIRType_Value);
  3199     LCallSetElement *lir = new(alloc()) LCallSetElement();
  3200     lir->setOperand(0, useRegisterAtStart(ins->object()));
  3201     if (!useBoxAtStart(lir, LCallSetElement::Index, ins->index()))
  3202         return false;
  3203     if (!useBoxAtStart(lir, LCallSetElement::Value, ins->value()))
  3204         return false;
  3205     return add(lir, ins) && assignSafepoint(lir, ins);
  3208 bool
  3209 LIRGenerator::visitCallInitElementArray(MCallInitElementArray *ins)
  3211     LCallInitElementArray *lir = new(alloc()) LCallInitElementArray();
  3212     lir->setOperand(0, useRegisterAtStart(ins->object()));
  3213     if (!useBoxAtStart(lir, LCallInitElementArray::Value, ins->value()))
  3214         return false;
  3215     return add(lir, ins) && assignSafepoint(lir, ins);
  3218 bool
  3219 LIRGenerator::visitIteratorStart(MIteratorStart *ins)
  3221     // Call a stub if this is not a simple for-in loop.
  3222     if (ins->flags() != JSITER_ENUMERATE) {
  3223         LCallIteratorStart *lir = new(alloc()) LCallIteratorStart(useRegisterAtStart(ins->object()));
  3224         return defineReturn(lir, ins) && assignSafepoint(lir, ins);
  3227     LIteratorStart *lir = new(alloc()) LIteratorStart(useRegister(ins->object()), temp(), temp(), temp());
  3228     return define(lir, ins) && assignSafepoint(lir, ins);
  3231 bool
  3232 LIRGenerator::visitIteratorNext(MIteratorNext *ins)
  3234     LIteratorNext *lir = new(alloc()) LIteratorNext(useRegister(ins->iterator()), temp());
  3235     return defineBox(lir, ins) && assignSafepoint(lir, ins);
  3238 bool
  3239 LIRGenerator::visitIteratorMore(MIteratorMore *ins)
  3241     LIteratorMore *lir = new(alloc()) LIteratorMore(useRegister(ins->iterator()), temp());
  3242     return define(lir, ins) && assignSafepoint(lir, ins);
  3245 bool
  3246 LIRGenerator::visitIteratorEnd(MIteratorEnd *ins)
  3248     LIteratorEnd *lir = new(alloc()) LIteratorEnd(useRegister(ins->iterator()), temp(), temp(), temp());
  3249     return add(lir, ins) && assignSafepoint(lir, ins);
  3252 bool
  3253 LIRGenerator::visitStringLength(MStringLength *ins)
  3255     JS_ASSERT(ins->string()->type() == MIRType_String);
  3256     return define(new(alloc()) LStringLength(useRegisterAtStart(ins->string())), ins);
  3259 bool
  3260 LIRGenerator::visitArgumentsLength(MArgumentsLength *ins)
  3262     return define(new(alloc()) LArgumentsLength(), ins);
  3265 bool
  3266 LIRGenerator::visitGetFrameArgument(MGetFrameArgument *ins)
  3268     LGetFrameArgument *lir = new(alloc()) LGetFrameArgument(useRegisterOrConstant(ins->index()));
  3269     return defineBox(lir, ins);
  3272 bool
  3273 LIRGenerator::visitSetFrameArgument(MSetFrameArgument *ins)
  3275     MDefinition *input = ins->input();
  3277     if (input->type() == MIRType_Value) {
  3278         LSetFrameArgumentV *lir = new(alloc()) LSetFrameArgumentV();
  3279         if (!useBox(lir, LSetFrameArgumentV::Input, input))
  3280             return false;
  3281         return add(lir, ins);
  3284     if (input->type() == MIRType_Undefined || input->type() == MIRType_Null) {
  3285         Value val = input->type() == MIRType_Undefined ? UndefinedValue() : NullValue();
  3286         LSetFrameArgumentC *lir = new(alloc()) LSetFrameArgumentC(val);
  3287         return add(lir, ins);
  3290     LSetFrameArgumentT *lir = new(alloc()) LSetFrameArgumentT(useRegister(input));
  3291     return add(lir, ins);
  3294 bool
  3295 LIRGenerator::visitRunOncePrologue(MRunOncePrologue *ins)
  3297     LRunOncePrologue *lir = new(alloc()) LRunOncePrologue;
  3298     return add(lir, ins) && assignSafepoint(lir, ins);
  3301 bool
  3302 LIRGenerator::visitRest(MRest *ins)
  3304     JS_ASSERT(ins->numActuals()->type() == MIRType_Int32);
  3306     LRest *lir = new(alloc()) LRest(useFixed(ins->numActuals(), CallTempReg0),
  3307                                     tempFixed(CallTempReg1),
  3308                                     tempFixed(CallTempReg2),
  3309                                     tempFixed(CallTempReg3));
  3310     return defineReturn(lir, ins) && assignSafepoint(lir, ins);
  3313 bool
  3314 LIRGenerator::visitRestPar(MRestPar *ins)
  3316     JS_ASSERT(ins->numActuals()->type() == MIRType_Int32);
  3318     LRestPar *lir = new(alloc()) LRestPar(useFixed(ins->forkJoinContext(), CallTempReg0),
  3319                                           useFixed(ins->numActuals(), CallTempReg1),
  3320                                           tempFixed(CallTempReg2),
  3321                                           tempFixed(CallTempReg3),
  3322                                           tempFixed(CallTempReg4));
  3323     return defineReturn(lir, ins) && assignSafepoint(lir, ins);
  3326 bool
  3327 LIRGenerator::visitThrow(MThrow *ins)
  3329     MDefinition *value = ins->getOperand(0);
  3330     JS_ASSERT(value->type() == MIRType_Value);
  3332     LThrow *lir = new(alloc()) LThrow;
  3333     if (!useBoxAtStart(lir, LThrow::Value, value))
  3334         return false;
  3335     return add(lir, ins) && assignSafepoint(lir, ins);
  3338 bool
  3339 LIRGenerator::visitIn(MIn *ins)
  3341     MDefinition *lhs = ins->lhs();
  3342     MDefinition *rhs = ins->rhs();
  3344     JS_ASSERT(lhs->type() == MIRType_Value);
  3345     JS_ASSERT(rhs->type() == MIRType_Object);
  3347     LIn *lir = new(alloc()) LIn(useRegisterAtStart(rhs));
  3348     if (!useBoxAtStart(lir, LIn::LHS, lhs))
  3349         return false;
  3350     return defineReturn(lir, ins) && assignSafepoint(lir, ins);
  3353 bool
  3354 LIRGenerator::visitInstanceOf(MInstanceOf *ins)
  3356     MDefinition *lhs = ins->getOperand(0);
  3358     JS_ASSERT(lhs->type() == MIRType_Value || lhs->type() == MIRType_Object);
  3360     if (lhs->type() == MIRType_Object) {
  3361         LInstanceOfO *lir = new(alloc()) LInstanceOfO(useRegister(lhs));
  3362         return define(lir, ins) && assignSafepoint(lir, ins);
  3365     LInstanceOfV *lir = new(alloc()) LInstanceOfV();
  3366     return useBox(lir, LInstanceOfV::LHS, lhs) && define(lir, ins) && assignSafepoint(lir, ins);
  3369 bool
  3370 LIRGenerator::visitCallInstanceOf(MCallInstanceOf *ins)
  3372     MDefinition *lhs = ins->lhs();
  3373     MDefinition *rhs = ins->rhs();
  3375     JS_ASSERT(lhs->type() == MIRType_Value);
  3376     JS_ASSERT(rhs->type() == MIRType_Object);
  3378     LCallInstanceOf *lir = new(alloc()) LCallInstanceOf(useRegisterAtStart(rhs));
  3379     if (!useBoxAtStart(lir, LCallInstanceOf::LHS, lhs))
  3380         return false;
  3381     return defineReturn(lir, ins) && assignSafepoint(lir, ins);
  3384 bool
  3385 LIRGenerator::visitProfilerStackOp(MProfilerStackOp *ins)
  3387     LProfilerStackOp *lir = new(alloc()) LProfilerStackOp(temp());
  3388     if (!add(lir, ins))
  3389         return false;
  3390     // If slow assertions are enabled, then this node will result in a callVM
  3391     // out to a C++ function for the assertions, so we will need a safepoint.
  3392     return !gen->options.spsSlowAssertionsEnabled() || assignSafepoint(lir, ins);
  3395 bool
  3396 LIRGenerator::visitIsCallable(MIsCallable *ins)
  3398     JS_ASSERT(ins->object()->type() == MIRType_Object);
  3399     JS_ASSERT(ins->type() == MIRType_Boolean);
  3400     return define(new(alloc()) LIsCallable(useRegister(ins->object())), ins);
  3403 bool
  3404 LIRGenerator::visitHaveSameClass(MHaveSameClass *ins)
  3406     MDefinition *lhs = ins->lhs();
  3407     MDefinition *rhs = ins->rhs();
  3409     JS_ASSERT(lhs->type() == MIRType_Object);
  3410     JS_ASSERT(rhs->type() == MIRType_Object);
  3412     return define(new(alloc()) LHaveSameClass(useRegister(lhs), useRegister(rhs), temp()), ins);
  3415 bool
  3416 LIRGenerator::visitHasClass(MHasClass *ins)
  3418     JS_ASSERT(ins->object()->type() == MIRType_Object);
  3419     JS_ASSERT(ins->type() == MIRType_Boolean);
  3420     return define(new(alloc()) LHasClass(useRegister(ins->object())), ins);
  3423 bool
  3424 LIRGenerator::visitAsmJSLoadGlobalVar(MAsmJSLoadGlobalVar *ins)
  3426     return define(new(alloc()) LAsmJSLoadGlobalVar, ins);
  3429 bool
  3430 LIRGenerator::visitAsmJSStoreGlobalVar(MAsmJSStoreGlobalVar *ins)
  3432     return add(new(alloc()) LAsmJSStoreGlobalVar(useRegisterAtStart(ins->value())), ins);
  3435 bool
  3436 LIRGenerator::visitAsmJSLoadFFIFunc(MAsmJSLoadFFIFunc *ins)
  3438     return define(new(alloc()) LAsmJSLoadFFIFunc, ins);
  3441 bool
  3442 LIRGenerator::visitAsmJSParameter(MAsmJSParameter *ins)
  3444     ABIArg abi = ins->abi();
  3445     if (abi.argInRegister())
  3446         return defineFixed(new(alloc()) LAsmJSParameter, ins, LAllocation(abi.reg()));
  3448     JS_ASSERT(IsNumberType(ins->type()));
  3449     return defineFixed(new(alloc()) LAsmJSParameter, ins, LArgument(abi.offsetFromArgBase()));
  3452 bool
  3453 LIRGenerator::visitAsmJSReturn(MAsmJSReturn *ins)
  3455     MDefinition *rval = ins->getOperand(0);
  3456     LAsmJSReturn *lir = new(alloc()) LAsmJSReturn;
  3457     if (IsFloatingPointType(rval->type()))
  3458         lir->setOperand(0, useFixed(rval, ReturnFloatReg));
  3459     else if (rval->type() == MIRType_Int32)
  3460         lir->setOperand(0, useFixed(rval, ReturnReg));
  3461     else
  3462         MOZ_ASSUME_UNREACHABLE("Unexpected asm.js return type");
  3463     return add(lir);
  3466 bool
  3467 LIRGenerator::visitAsmJSVoidReturn(MAsmJSVoidReturn *ins)
  3469     return add(new(alloc()) LAsmJSVoidReturn);
  3472 bool
  3473 LIRGenerator::visitAsmJSPassStackArg(MAsmJSPassStackArg *ins)
  3475     if (IsFloatingPointType(ins->arg()->type())) {
  3476         JS_ASSERT(!ins->arg()->isEmittedAtUses());
  3477         return add(new(alloc()) LAsmJSPassStackArg(useRegisterAtStart(ins->arg())), ins);
  3480     return add(new(alloc()) LAsmJSPassStackArg(useRegisterOrConstantAtStart(ins->arg())), ins);
  3483 bool
  3484 LIRGenerator::visitAsmJSCall(MAsmJSCall *ins)
  3486     gen->setPerformsAsmJSCall();
  3488     LAllocation *args = gen->allocate<LAllocation>(ins->numOperands());
  3489     if (!args)
  3490         return false;
  3492     for (unsigned i = 0; i < ins->numArgs(); i++)
  3493         args[i] = useFixed(ins->getOperand(i), ins->registerForArg(i));
  3495     if (ins->callee().which() == MAsmJSCall::Callee::Dynamic)
  3496         args[ins->dynamicCalleeOperandIndex()] = useFixed(ins->callee().dynamic(), CallTempReg0);
  3498     LInstruction *lir = new(alloc()) LAsmJSCall(args, ins->numOperands());
  3499     if (ins->type() == MIRType_None) {
  3500         return add(lir, ins);
  3502     return defineReturn(lir, ins);
  3505 bool
  3506 LIRGenerator::visitSetDOMProperty(MSetDOMProperty *ins)
  3508     MDefinition *val = ins->value();
  3510     Register cxReg, objReg, privReg, valueReg;
  3511     GetTempRegForIntArg(0, 0, &cxReg);
  3512     GetTempRegForIntArg(1, 0, &objReg);
  3513     GetTempRegForIntArg(2, 0, &privReg);
  3514     GetTempRegForIntArg(3, 0, &valueReg);
  3515     LSetDOMProperty *lir = new(alloc()) LSetDOMProperty(tempFixed(cxReg),
  3516                                                         useFixed(ins->object(), objReg),
  3517                                                         tempFixed(privReg),
  3518                                                         tempFixed(valueReg));
  3520     // Keep using GetTempRegForIntArg, since we want to make sure we
  3521     // don't clobber registers we're already using.
  3522     Register tempReg1, tempReg2;
  3523     GetTempRegForIntArg(4, 0, &tempReg1);
  3524     mozilla::DebugOnly<bool> ok = GetTempRegForIntArg(5, 0, &tempReg2);
  3525     MOZ_ASSERT(ok, "How can we not have six temp registers?");
  3526     if (!useBoxFixed(lir, LSetDOMProperty::Value, val, tempReg1, tempReg2))
  3527         return false;
  3529     return add(lir, ins) && assignSafepoint(lir, ins);
  3532 bool
  3533 LIRGenerator::visitGetDOMProperty(MGetDOMProperty *ins)
  3535     Register cxReg, objReg, privReg, valueReg;
  3536     GetTempRegForIntArg(0, 0, &cxReg);
  3537     GetTempRegForIntArg(1, 0, &objReg);
  3538     GetTempRegForIntArg(2, 0, &privReg);
  3539     mozilla::DebugOnly<bool> ok = GetTempRegForIntArg(3, 0, &valueReg);
  3540     MOZ_ASSERT(ok, "How can we not have four temp registers?");
  3541     LGetDOMProperty *lir = new(alloc()) LGetDOMProperty(tempFixed(cxReg),
  3542                                                         useFixed(ins->object(), objReg),
  3543                                                         tempFixed(privReg),
  3544                                                         tempFixed(valueReg));
  3546     return defineReturn(lir, ins) && assignSafepoint(lir, ins);
  3549 bool
  3550 LIRGenerator::visitGetDOMMember(MGetDOMMember *ins)
  3552     MOZ_ASSERT(ins->isDomMovable(), "Members had better be movable");
  3553     // We wish we could assert that ins->domAliasSet() == JSJitInfo::AliasNone,
  3554     // but some MGetDOMMembers are for [Pure], not [Constant] properties, whose
  3555     // value can in fact change as a result of DOM setters and method calls.
  3556     MOZ_ASSERT(ins->domAliasSet() != JSJitInfo::AliasEverything,
  3557                "Member gets had better not alias the world");
  3558     LGetDOMMember *lir =
  3559         new(alloc()) LGetDOMMember(useRegister(ins->object()));
  3560     return defineBox(lir, ins);
  3563 bool
  3564 LIRGenerator::visitRecompileCheck(MRecompileCheck *ins)
  3566     LRecompileCheck *lir = new(alloc()) LRecompileCheck(temp());
  3567     if (!add(lir, ins))
  3568         return false;
  3569     return assignSafepoint(lir, ins);
  3572 static void
  3573 SpewResumePoint(MBasicBlock *block, MInstruction *ins, MResumePoint *resumePoint)
  3575     fprintf(IonSpewFile, "Current resume point %p details:\n", (void *)resumePoint);
  3576     fprintf(IonSpewFile, "    frame count: %u\n", resumePoint->frameCount());
  3578     if (ins) {
  3579         fprintf(IonSpewFile, "    taken after: ");
  3580         ins->printName(IonSpewFile);
  3581     } else {
  3582         fprintf(IonSpewFile, "    taken at block %d entry", block->id());
  3584     fprintf(IonSpewFile, "\n");
  3586     fprintf(IonSpewFile, "    pc: %p (script: %p, offset: %d)\n",
  3587             (void *)resumePoint->pc(),
  3588             (void *)resumePoint->block()->info().script(),
  3589             int(resumePoint->block()->info().script()->pcToOffset(resumePoint->pc())));
  3591     for (size_t i = 0, e = resumePoint->numOperands(); i < e; i++) {
  3592         MDefinition *in = resumePoint->getOperand(i);
  3593         fprintf(IonSpewFile, "    slot%u: ", (unsigned)i);
  3594         in->printName(IonSpewFile);
  3595         fprintf(IonSpewFile, "\n");
  3599 bool
  3600 LIRGenerator::visitInstruction(MInstruction *ins)
  3602     if (!gen->ensureBallast())
  3603         return false;
  3604     if (!ins->accept(this))
  3605         return false;
  3607     if (ins->possiblyCalls())
  3608         gen->setPerformsCall();
  3610     if (ins->resumePoint())
  3611         updateResumeState(ins);
  3613     if (gen->errored())
  3614         return false;
  3615 #ifdef DEBUG
  3616     ins->setInWorklistUnchecked();
  3617 #endif
  3619     // If no safepoint was created, there's no need for an OSI point.
  3620     if (LOsiPoint *osiPoint = popOsiPoint()) {
  3621         if (!add(osiPoint))
  3622             return false;
  3625     return true;
  3628 bool
  3629 LIRGenerator::definePhis()
  3631     size_t lirIndex = 0;
  3632     MBasicBlock *block = current->mir();
  3633     for (MPhiIterator phi(block->phisBegin()); phi != block->phisEnd(); phi++) {
  3634         if (phi->type() == MIRType_Value) {
  3635             if (!defineUntypedPhi(*phi, lirIndex))
  3636                 return false;
  3637             lirIndex += BOX_PIECES;
  3638         } else {
  3639             if (!defineTypedPhi(*phi, lirIndex))
  3640                 return false;
  3641             lirIndex += 1;
  3644     return true;
  3647 void
  3648 LIRGenerator::updateResumeState(MInstruction *ins)
  3650     lastResumePoint_ = ins->resumePoint();
  3651     if (IonSpewEnabled(IonSpew_Snapshots) && lastResumePoint_)
  3652         SpewResumePoint(nullptr, ins, lastResumePoint_);
  3655 void
  3656 LIRGenerator::updateResumeState(MBasicBlock *block)
  3658     lastResumePoint_ = block->entryResumePoint();
  3659     if (IonSpewEnabled(IonSpew_Snapshots) && lastResumePoint_)
  3660         SpewResumePoint(block, nullptr, lastResumePoint_);
  3663 bool
  3664 LIRGenerator::visitBlock(MBasicBlock *block)
  3666     current = block->lir();
  3667     updateResumeState(block);
  3669     if (!definePhis())
  3670         return false;
  3672     if (gen->optimizationInfo().registerAllocator() == RegisterAllocator_LSRA) {
  3673         if (!add(new(alloc()) LLabel()))
  3674             return false;
  3677     for (MInstructionIterator iter = block->begin(); *iter != block->lastIns(); iter++) {
  3678         if (!visitInstruction(*iter))
  3679             return false;
  3682     if (block->successorWithPhis()) {
  3683         // If we have a successor with phis, lower the phi input now that we
  3684         // are approaching the join point.
  3685         MBasicBlock *successor = block->successorWithPhis();
  3686         uint32_t position = block->positionInPhiSuccessor();
  3687         size_t lirIndex = 0;
  3688         for (MPhiIterator phi(successor->phisBegin()); phi != successor->phisEnd(); phi++) {
  3689             MDefinition *opd = phi->getOperand(position);
  3690             if (!ensureDefined(opd))
  3691                 return false;
  3693             JS_ASSERT(opd->type() == phi->type());
  3695             if (phi->type() == MIRType_Value) {
  3696                 lowerUntypedPhiInput(*phi, position, successor->lir(), lirIndex);
  3697                 lirIndex += BOX_PIECES;
  3698             } else {
  3699                 lowerTypedPhiInput(*phi, position, successor->lir(), lirIndex);
  3700                 lirIndex += 1;
  3705     // Now emit the last instruction, which is some form of branch.
  3706     if (!visitInstruction(block->lastIns()))
  3707         return false;
  3709     return true;
  3712 bool
  3713 LIRGenerator::precreatePhi(LBlock *block, MPhi *phi)
  3715     LPhi *lir = LPhi::New(gen, phi);
  3716     if (!lir)
  3717         return false;
  3718     if (!block->addPhi(lir))
  3719         return false;
  3720     return true;
  3723 bool
  3724 LIRGenerator::generate()
  3726     // Create all blocks and prep all phis beforehand.
  3727     for (ReversePostorderIterator block(graph.rpoBegin()); block != graph.rpoEnd(); block++) {
  3728         if (gen->shouldCancel("Lowering (preparation loop)"))
  3729             return false;
  3731         current = LBlock::New(alloc(), *block);
  3732         if (!current)
  3733             return false;
  3734         if (!lirGraph_.addBlock(current))
  3735             return false;
  3736         block->assignLir(current);
  3738         // For each MIR phi, add LIR phis as appropriate. We'll fill in their
  3739         // operands on each incoming edge, and set their definitions at the
  3740         // start of their defining block.
  3741         for (MPhiIterator phi(block->phisBegin()); phi != block->phisEnd(); phi++) {
  3742             int numPhis = (phi->type() == MIRType_Value) ? BOX_PIECES : 1;
  3743             for (int i = 0; i < numPhis; i++) {
  3744                 if (!precreatePhi(block->lir(), *phi))
  3745                     return false;
  3750     for (ReversePostorderIterator block(graph.rpoBegin()); block != graph.rpoEnd(); block++) {
  3751         if (gen->shouldCancel("Lowering (main loop)"))
  3752             return false;
  3754         if (!visitBlock(*block))
  3755             return false;
  3758     if (graph.osrBlock())
  3759         lirGraph_.setOsrBlock(graph.osrBlock()->lir());
  3761     lirGraph_.setArgumentSlotCount(maxargslots_);
  3762     return true;

mercurial