Fix snapshot bug with emitted-at-use operands (bug 723496, r=dvander)
authorJan de Mooij <jdemooij@mozilla.com>
Fri, 03 Feb 2012 20:37:03 +0100
changeset 105710 e60822f61ea7e80e9140a15d302e3f23b0c36972
parent 105709 43b55878da4625751bc635fc425816e95583cf2f
child 105711 f6b54f8e87b2e66334c279c98314ba9de02b6ee9
push id14706
push usereakhgari@mozilla.com
push dateTue, 11 Sep 2012 20:39:52 +0000
treeherdermozilla-inbound@d50bf1edaabe [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersdvander
bugs723496
milestone13.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Fix snapshot bug with emitted-at-use operands (bug 723496, r=dvander)
js/src/ion/Lowering.cpp
js/src/ion/arm/Lowering-arm.cpp
js/src/ion/shared/Lowering-shared-inl.h
js/src/ion/shared/Lowering-shared.cpp
js/src/ion/x64/Lowering-x64.cpp
js/src/ion/x86/Lowering-x86.cpp
--- a/js/src/ion/Lowering.cpp
+++ b/js/src/ion/Lowering.cpp
@@ -167,19 +167,19 @@ LIRGenerator::visitCall(MCall *call)
     uint32 argslot = getArgumentSlotForCall();
 
     // A call is entirely stateful, depending upon arguments already being
     // stored in an argument vector. Therefore visitCall() may be generic.
     LCallGeneric *ins = new LCallGeneric(useFixed(call->getFunction(), CallTempReg1),
                                          argslot,
                                          tempFixed(ArgumentsRectifierReg),
                                          tempFixed(CallTempReg2));
-    if (!defineReturn(ins, call))
+    if (!assignSnapshot(ins))
         return false;
-    if (!assignSnapshot(ins))
+    if (!defineReturn(ins, call))
         return false;
     if (!assignSafepoint(ins, call))
         return false;
 
     freeArguments(argc);
     return true;
 }
 
@@ -560,17 +560,17 @@ LIRGenerator::visitToDouble(MToDouble *c
     MDefinition *opd = convert->input();
 
     switch (opd->type()) {
       case MIRType_Value:
       {
         LValueToDouble *lir = new LValueToDouble();
         if (!useBox(lir, LValueToDouble::Input, opd))
             return false;
-        return define(lir, convert) && assignSnapshot(lir);
+        return assignSnapshot(lir) && define(lir, convert);
       }
 
       case MIRType_Null:
         return lowerConstantDouble(0, convert);
 
       case MIRType_Undefined:
         return lowerConstantDouble(js_NaN, convert);
 
@@ -598,30 +598,30 @@ LIRGenerator::visitToInt32(MToInt32 *con
     MDefinition *opd = convert->input();
 
     switch (opd->type()) {
       case MIRType_Value:
       {
         LValueToInt32 *lir = new LValueToInt32(tempFloat(), LValueToInt32::NORMAL);
         if (!useBox(lir, LValueToInt32::Input, opd))
             return false;
-        return define(lir, convert) && assignSnapshot(lir);
+        return assignSnapshot(lir) && define(lir, convert);
       }
 
       case MIRType_Null:
         return define(new LInteger(0), convert);
 
       case MIRType_Int32:
       case MIRType_Boolean:
         return redefine(convert, opd);
 
       case MIRType_Double:
       {
         LDoubleToInt32 *lir = new LDoubleToInt32(use(opd));
-        return define(lir, convert) && assignSnapshot(lir);
+        return assignSnapshot(lir) && define(lir, convert);
       }
 
       default:
         // Undefined coerces to NaN, not int32.
         // Objects might be effectful.
         // Strings are complicated - we don't handle them yet.
         JS_NOT_REACHED("unexpected type");
     }
@@ -635,31 +635,31 @@ LIRGenerator::visitTruncateToInt32(MTrun
     MDefinition *opd = truncate->input();
 
     switch (opd->type()) {
       case MIRType_Value:
       {
         LValueToInt32 *lir = new LValueToInt32(tempFloat(), LValueToInt32::TRUNCATE);
         if (!useBox(lir, LValueToInt32::Input, opd))
             return false;
-        return define(lir, truncate) && assignSnapshot(lir);
+        return assignSnapshot(lir) && define(lir, truncate);
       }
 
       case MIRType_Null:
       case MIRType_Undefined:
         return define(new LInteger(0), truncate);
 
       case MIRType_Int32:
       case MIRType_Boolean:
         return redefine(truncate, opd);
 
       case MIRType_Double:
       {
         LTruncateDToInt32 *lir = new LTruncateDToInt32(useRegister(opd));
-        return define(lir, truncate) && assignSnapshot(lir);
+        return assignSnapshot(lir) && define(lir, truncate);
       }
 
       default:
         // Objects might be effectful.
         // Strings are complicated - we don't handle them yet.
         JS_NOT_REACHED("unexpected type");
     }
 
--- a/js/src/ion/arm/Lowering-arm.cpp
+++ b/js/src/ion/arm/Lowering-arm.cpp
@@ -273,17 +273,17 @@ LIRGeneratorARM::lowerForShift(LInstruct
 }
 
 bool
 LIRGeneratorARM::lowerDivI(MDiv *div)
 {
     LDivI *lir = new LDivI(useFixed(div->lhs(), r0), use(div->rhs(), r1),
                            tempFixed(r2), tempFixed(r3)/*, tempFixed(lr)*/);
 
-    return defineFixed(lir, div, LAllocation(AnyRegister(r0))) && assignSnapshot(lir);
+    return assignSnapshot(lir) && defineFixed(lir, div, LAllocation(AnyRegister(r0)));
 }
 
 bool
 LIRGeneratorARM::lowerMulI(MMul *mul, MDefinition *lhs, MDefinition *rhs)
 {
     LMulI *lir = new LMulI;
     if (mul->fallible() && !assignSnapshot(lir))
         return false;
--- a/js/src/ion/shared/Lowering-shared-inl.h
+++ b/js/src/ion/shared/Lowering-shared-inl.h
@@ -400,16 +400,18 @@ VirtualRegisterOfPayload(MDefinition *mi
     if (mir->isBox()) {
         MDefinition *inner = mir->toBox()->getOperand(0);
         if (!inner->isConstant() && inner->type() != MIRType_Double)
             return inner->id();
     }
     return mir->id() + VREG_DATA_OFFSET;
 }
 
+// Note: always call ensureDefined before calling useType/usePayload,
+// so that emitted-at-use operands are handled correctly.
 LUse
 LIRGeneratorShared::useType(MDefinition *mir, LUse::Policy policy)
 {
     JS_ASSERT(mir->type() == MIRType_Value);
 
     return LUse(mir->virtualRegister() + VREG_TYPE_OFFSET, policy);
 }
 
--- a/js/src/ion/shared/Lowering-shared.cpp
+++ b/js/src/ion/shared/Lowering-shared.cpp
@@ -122,16 +122,18 @@ LIRGeneratorShared::buildSnapshot(LInstr
             // since we can recover the same information, much cleaner, from MIR.
             if (ins->isConstant() || ins->isUnused()) {
                 *type = LConstantIndex::Bogus();
                 *payload = LConstantIndex::Bogus();
             } else if (ins->type() != MIRType_Value) {
                 *type = LConstantIndex::Bogus();
                 *payload = use(ins, LUse::KEEPALIVE);
             } else {
+                if (!ensureDefined(ins))
+                    return NULL;
                 *type = useType(ins, LUse::KEEPALIVE);
                 *payload = usePayload(ins, LUse::KEEPALIVE);
             }
         }
     }
 
     return snapshot;
 }
@@ -171,16 +173,20 @@ LIRGeneratorShared::buildSnapshot(LInstr
 
     return snapshot;
 }
 #endif
 
 bool
 LIRGeneratorShared::assignSnapshot(LInstruction *ins, BailoutKind kind)
 {
+    // assignSnapshot must be called before define/add, since
+    // it may add new instructions for emitted-at-use operands.
+    JS_ASSERT(ins->id() == 0);
+
     LSnapshot *snapshot = buildSnapshot(ins, lastResumePoint_, kind);
     if (!snapshot)
         return false;
 
     ins->assignSnapshot(snapshot);
     return true;
 }
 
--- a/js/src/ion/x64/Lowering-x64.cpp
+++ b/js/src/ion/x64/Lowering-x64.cpp
@@ -169,24 +169,24 @@ LIRGeneratorX64::lowerUntypedPhiInput(MP
 {
     lowerTypedPhiInput(phi, inputPosition, block, lirIndex);
 }
 
 bool
 LIRGeneratorX64::lowerDivI(MDiv *div)
 {
     LDivI *lir = new LDivI(useFixed(div->lhs(), rax), useRegister(div->rhs()), tempFixed(rdx));
-    return defineFixed(lir, div, LAllocation(AnyRegister(rax))) && assignSnapshot(lir);
+    return assignSnapshot(lir) && defineFixed(lir, div, LAllocation(AnyRegister(rax)));
 }
 
 bool
 LIRGeneratorX64::lowerModI(MMod *mod)
 {
     LModI *lir = new LModI(useFixed(mod->lhs(), rax), useRegister(mod->rhs()));
-    return defineFixed(lir, mod, LAllocation(AnyRegister(rdx))) && assignSnapshot(lir);
+    return assignSnapshot(lir) && defineFixed(lir, mod, LAllocation(AnyRegister(rdx)));
 }
 
 bool
 LIRGeneratorX64::visitGuardShape(MGuardShape *ins)
 {
     LGuardShape *guard = new LGuardShape(useRegister(ins->obj()));
     return assignSnapshot(guard) && add(guard, ins);
 }
--- a/js/src/ion/x86/Lowering-x86.cpp
+++ b/js/src/ion/x86/Lowering-x86.cpp
@@ -242,24 +242,24 @@ LIRGeneratorX86::lowerUntypedPhiInput(MP
     type->setOperand(inputPosition, LUse(operand->virtualRegister() + VREG_TYPE_OFFSET, LUse::ANY));
     payload->setOperand(inputPosition, LUse(VirtualRegisterOfPayload(operand), LUse::ANY));
 }
 
 bool
 LIRGeneratorX86::lowerDivI(MDiv *div)
 {
     LDivI *lir = new LDivI(useFixed(div->lhs(), eax), useRegister(div->rhs()), tempFixed(edx));
-    return defineFixed(lir, div, LAllocation(AnyRegister(eax))) && assignSnapshot(lir);
+    return assignSnapshot(lir) && defineFixed(lir, div, LAllocation(AnyRegister(eax)));
 }
 
 bool
 LIRGeneratorX86::lowerModI(MMod *mod)
 {
     LModI *lir = new LModI(useFixed(mod->lhs(), eax), useRegister(mod->rhs()));
-    return defineFixed(lir, mod, LAllocation(AnyRegister(edx))) && assignSnapshot(lir);
+    return assignSnapshot(lir) && defineFixed(lir, mod, LAllocation(AnyRegister(edx)));
 }
 
 bool
 LIRGeneratorX86::visitGuardShape(MGuardShape *ins)
 {
     LGuardShape *guard = new LGuardShape(useRegister(ins->obj()));
     return assignSnapshot(guard) && add(guard, ins);
 }