Bug 1248007 part 1 - Refactor useBox and friends to work more like useRegister. r=nbp
authorJan de Mooij <jdemooij@mozilla.com>
Fri, 19 Feb 2016 09:48:00 +0100
changeset 284840 1b752ce8f7befcce0130a3d6d20684483f1b2703
parent 284839 c372f284cdd70ad987e15b1521113d33d1dac6ef
child 284841 cc1f785b9187a881d06bd3258b1c60a47d4ee820
push id30015
push userphilringnalda@gmail.com
push dateSun, 21 Feb 2016 01:23:31 +0000
treeherdermozilla-central@7bfe45ec123a [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersnbp
bugs1248007
milestone47.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
Bug 1248007 part 1 - Refactor useBox and friends to work more like useRegister. r=nbp
js/src/jit/CodeGenerator.cpp
js/src/jit/LIR.h
js/src/jit/Lowering.cpp
js/src/jit/Lowering.h
js/src/jit/arm/LIR-arm.h
js/src/jit/arm/Lowering-arm.cpp
js/src/jit/arm/Lowering-arm.h
js/src/jit/arm64/LIR-arm64.h
js/src/jit/arm64/Lowering-arm64.cpp
js/src/jit/arm64/Lowering-arm64.h
js/src/jit/mips-shared/LIR-mips-shared.h
js/src/jit/mips-shared/Lowering-mips-shared.cpp
js/src/jit/mips32/LIR-mips32.h
js/src/jit/mips32/Lowering-mips32.cpp
js/src/jit/mips32/Lowering-mips32.h
js/src/jit/mips64/Lowering-mips64.cpp
js/src/jit/mips64/Lowering-mips64.h
js/src/jit/none/Lowering-none.h
js/src/jit/shared/LIR-shared.h
js/src/jit/shared/Lowering-shared-inl.h
js/src/jit/shared/Lowering-shared.h
js/src/jit/x64/Lowering-x64.cpp
js/src/jit/x64/Lowering-x64.h
js/src/jit/x86-shared/LIR-x86-shared.h
js/src/jit/x86-shared/Lowering-x86-shared.cpp
js/src/jit/x86/LIR-x86.h
js/src/jit/x86/Lowering-x86.cpp
js/src/jit/x86/Lowering-x86.h
--- a/js/src/jit/CodeGenerator.cpp
+++ b/js/src/jit/CodeGenerator.cpp
@@ -9448,33 +9448,33 @@ typedef bool (*ToIdFn)(JSContext*, Handl
 static const VMFunction ToIdInfo = FunctionInfo<ToIdFn>(ToIdOperation);
 
 void
 CodeGenerator::visitToIdV(LToIdV* lir)
 {
     Label notInt32;
     FloatRegister temp = ToFloatRegister(lir->tempFloat());
     const ValueOperand out = ToOutValue(lir);
-    ValueOperand index = ToValue(lir, LToIdV::Index);
+    ValueOperand input = ToValue(lir, LToIdV::Input);
 
     OutOfLineCode* ool = oolCallVM(ToIdInfo, lir,
                                    ArgList(ImmGCPtr(current->mir()->info().script()),
                                            ImmPtr(lir->mir()->resumePoint()->pc()),
-                                           ToValue(lir, LToIdV::Index)),
+                                           ToValue(lir, LToIdV::Input)),
                                    StoreValueTo(out));
 
-    Register tag = masm.splitTagForTest(index);
+    Register tag = masm.splitTagForTest(input);
 
     masm.branchTestInt32(Assembler::NotEqual, tag, &notInt32);
-    masm.moveValue(index, out);
+    masm.moveValue(input, out);
     masm.jump(ool->rejoin());
 
     masm.bind(&notInt32);
     masm.branchTestDouble(Assembler::NotEqual, tag, ool->entry());
-    masm.unboxDouble(index, temp);
+    masm.unboxDouble(input, temp);
     masm.convertDoubleToInt32(temp, out.scratchReg(), ool->entry(), true);
     masm.tagValue(JSVAL_TYPE_INT32, out.scratchReg(), out);
 
     masm.bind(ool->rejoin());
 }
 
 template<typename T>
 void
--- a/js/src/jit/LIR.h
+++ b/js/src/jit/LIR.h
@@ -286,16 +286,38 @@ class LUse : public LAllocation
     }
     bool usedAtStart() const {
         return !!((data() >> USED_AT_START_SHIFT) & USED_AT_START_MASK);
     }
 };
 
 static const uint32_t MAX_VIRTUAL_REGISTERS = LUse::VREG_MASK;
 
+class LBoxAllocation
+{
+#ifdef JS_NUNBOX32
+    LAllocation type_;
+    LAllocation payload_;
+#else
+    LAllocation value_;
+#endif
+
+  public:
+#ifdef JS_NUNBOX32
+    LBoxAllocation(LAllocation type, LAllocation payload) : type_(type), payload_(payload) {}
+
+    LAllocation type() const { return type_; }
+    LAllocation payload() const { return payload_; }
+#else
+    explicit LBoxAllocation(LAllocation value) : value_(value) {}
+
+    LAllocation value() const { return value_; }
+#endif
+};
+
 class LGeneralReg : public LAllocation
 {
   public:
     explicit LGeneralReg(Register reg)
       : LAllocation(GPR, reg.code())
     { }
 
     Register reg() const {
@@ -1045,16 +1067,24 @@ class LInstructionHelper : public detail
         return Operands;
     }
     LAllocation* getOperand(size_t index) final override {
         return &operands_[index];
     }
     void setOperand(size_t index, const LAllocation& a) final override {
         operands_[index] = a;
     }
+    void setBoxOperand(size_t index, const LBoxAllocation& alloc) {
+#ifdef JS_NUNBOX32
+        operands_[index] = alloc.type();
+        operands_[index + 1] = alloc.payload();
+#else
+        operands_[index] = alloc.value();
+#endif
+    }
 };
 
 template<size_t Defs, size_t Temps>
 class LVariadicInstruction : public details::LInstructionFixedDefsTempsHelper<Defs, Temps>
 {
     FixedList<LAllocation> operands_;
 
   public:
--- a/js/src/jit/Lowering.cpp
+++ b/js/src/jit/Lowering.cpp
@@ -19,32 +19,32 @@
 #include "jit/shared/Lowering-shared-inl.h"
 
 using namespace js;
 using namespace jit;
 
 using mozilla::DebugOnly;
 using JS::GenericNaN;
 
-void
-LIRGenerator::useBoxAtStart(LInstruction* lir, size_t n, MDefinition* mir, LUse::Policy policy)
-{
-    return useBox(lir, n, mir, policy, true);
-}
-
-void
-LIRGenerator::useBoxFixedAtStart(LInstruction* lir, size_t n, MDefinition* mir, ValueOperand op)
+LBoxAllocation
+LIRGenerator::useBoxFixedAtStart(MDefinition* mir, ValueOperand op)
 {
 #if defined(JS_NUNBOX32)
-    return useBoxFixed(lir, n, mir, op.typeReg(), op.payloadReg(), true);
+    return useBoxFixed(mir, op.typeReg(), op.payloadReg(), true);
 #elif defined(JS_PUNBOX64)
-    return useBoxFixed(lir, n, mir, op.valueReg(), op.scratchReg(), true);
+    return useBoxFixed(mir, op.valueReg(), op.scratchReg(), true);
 #endif
 }
 
+LBoxAllocation
+LIRGenerator::useBoxAtStart(MDefinition* mir, LUse::Policy policy)
+{
+    return useBox(mir, policy, /* useAtStart = */ true);
+}
+
 void
 LIRGenerator::visitCloneLiteral(MCloneLiteral* ins)
 {
     MOZ_ASSERT(ins->type() == MIRType_Object);
     MOZ_ASSERT(ins->input()->type() == MIRType_Object);
 
     LCloneLiteral* lir = new(alloc()) LCloneLiteral(useRegisterAtStart(ins->input()));
     defineReturn(lir, ins);
@@ -150,17 +150,16 @@ LIRGenerator::visitTableSwitch(MTableSwi
     if (tableswitch->numSuccessors() == 1) {
         add(new(alloc()) LGoto(tableswitch->getDefault()));
         return;
     }
 
     // If we don't know the type.
     if (opd->type() == MIRType_Value) {
         LTableSwitchV* lir = newLTableSwitchV(tableswitch);
-        useBox(lir, LTableSwitchV::InputValue, opd);
         add(lir);
         return;
     }
 
     // Case indices are numeric, so other types will always go to the default case.
     if (opd->type() != MIRType_Int32 && opd->type() != MIRType_Double) {
         add(new(alloc()) LGoto(tableswitch->getDefault()));
         return;
@@ -307,48 +306,48 @@ LIRGenerator::visitNewStringObject(MNewS
     LNewStringObject* lir = new(alloc()) LNewStringObject(useRegister(ins->input()), temp());
     define(lir, ins);
     assignSafepoint(lir, ins);
 }
 
 void
 LIRGenerator::visitInitElem(MInitElem* ins)
 {
-    LInitElem* lir = new(alloc()) LInitElem(useRegisterAtStart(ins->getObject()));
-    useBoxAtStart(lir, LInitElem::IdIndex, ins->getId());
-    useBoxAtStart(lir, LInitElem::ValueIndex, ins->getValue());
+    LInitElem* lir = new(alloc()) LInitElem(useRegisterAtStart(ins->getObject()),
+                                            useBoxAtStart(ins->getId()),
+                                            useBoxAtStart(ins->getValue()));
     add(lir, ins);
     assignSafepoint(lir, ins);
 }
 
 void
 LIRGenerator::visitInitElemGetterSetter(MInitElemGetterSetter* ins)
 {
     LInitElemGetterSetter* lir =
         new(alloc()) LInitElemGetterSetter(useRegisterAtStart(ins->object()),
+                                           useBoxAtStart(ins->idValue()),
                                            useRegisterAtStart(ins->value()));
-    useBoxAtStart(lir, LInitElemGetterSetter::IdIndex, ins->idValue());
     add(lir, ins);
     assignSafepoint(lir, ins);
 }
 
 void
 LIRGenerator::visitMutateProto(MMutateProto* ins)
 {
-    LMutateProto* lir = new(alloc()) LMutateProto(useRegisterAtStart(ins->getObject()));
-    useBoxAtStart(lir, LMutateProto::ValueIndex, ins->getValue());
+    LMutateProto* lir = new(alloc()) LMutateProto(useRegisterAtStart(ins->getObject()),
+                                                  useBoxAtStart(ins->getValue()));
     add(lir, ins);
     assignSafepoint(lir, ins);
 }
 
 void
 LIRGenerator::visitInitProp(MInitProp* ins)
 {
-    LInitProp* lir = new(alloc()) LInitProp(useRegisterAtStart(ins->getObject()));
-    useBoxAtStart(lir, LInitProp::ValueIndex, ins->getValue());
+    LInitProp* lir = new(alloc()) LInitProp(useRegisterAtStart(ins->getObject()),
+                                            useBoxAtStart(ins->getValue()));
     add(lir, ins);
     assignSafepoint(lir, ins);
 }
 
 void
 LIRGenerator::visitInitPropGetterSetter(MInitPropGetterSetter* ins)
 {
     LInitPropGetterSetter* lir =
@@ -403,42 +402,39 @@ LIRGenerator::visitGetArgumentsObjectArg
     LGetArgumentsObjectArg* lir = new(alloc()) LGetArgumentsObjectArg(argsObj, temp());
     defineBox(lir, ins);
 }
 
 void
 LIRGenerator::visitSetArgumentsObjectArg(MSetArgumentsObjectArg* ins)
 {
     LAllocation argsObj = useRegister(ins->getArgsObject());
-    LSetArgumentsObjectArg* lir = new(alloc()) LSetArgumentsObjectArg(argsObj, temp());
-    useBox(lir, LSetArgumentsObjectArg::ValueIndex, ins->getValue());
+    LSetArgumentsObjectArg* lir =
+        new(alloc()) LSetArgumentsObjectArg(argsObj, useBox(ins->getValue()), temp());
     add(lir, ins);
 }
 
 void
 LIRGenerator::visitReturnFromCtor(MReturnFromCtor* ins)
 {
-    LReturnFromCtor* lir = new(alloc()) LReturnFromCtor(useRegister(ins->getObject()));
-    useBox(lir, LReturnFromCtor::ValueIndex, ins->getValue());
+    LReturnFromCtor* lir = new(alloc()) LReturnFromCtor(useBox(ins->getValue()),
+                                                        useRegister(ins->getObject()));
     define(lir, ins);
 }
 
 void
 LIRGenerator::visitComputeThis(MComputeThis* ins)
 {
     MOZ_ASSERT(ins->type() == MIRType_Value);
     MOZ_ASSERT(ins->input()->type() == MIRType_Value);
 
-    LComputeThis* lir = new(alloc()) LComputeThis();
-
     // Don't use useBoxAtStart because ComputeThis has a safepoint and needs to
     // have its inputs in different registers than its return value so that
     // they aren't clobbered.
-    useBox(lir, LComputeThis::ValueIndex, ins->input());
-
+    LComputeThis* lir = new(alloc()) LComputeThis(useBox(ins->input()));
     defineBox(lir, ins);
     assignSafepoint(lir, ins);
 }
 
 void
 LIRGenerator::visitArrowNewTarget(MArrowNewTarget* ins)
 {
     MOZ_ASSERT(ins->type() == MIRType_Value);
@@ -467,18 +463,17 @@ LIRGenerator::lowerCallArguments(MCall* 
         maxargslots_ = baseSlot;
 
     for (size_t i = 0; i < argc; i++) {
         MDefinition* arg = call->getArg(i);
         uint32_t argslot = baseSlot - i;
 
         // Values take a slow path.
         if (arg->type() == MIRType_Value) {
-            LStackArgV* stack = new(alloc()) LStackArgV(argslot);
-            useBox(stack, 0, arg);
+            LStackArgV* stack = new(alloc()) LStackArgV(argslot, useBox(arg));
             add(stack);
         } else {
             // Known types can move constant types and/or payloads.
             LStackArgT* stack = new(alloc()) LStackArgT(argslot, arg->type(), useRegisterOrConstant(arg));
             add(stack);
         }
     }
 }
@@ -549,22 +544,20 @@ LIRGenerator::visitApplyArgs(MApplyArgs*
 
     // Assert if the return value is already erased.
     MOZ_ASSERT(CallTempReg2 != JSReturnReg_Type);
     MOZ_ASSERT(CallTempReg2 != JSReturnReg_Data);
 
     LApplyArgsGeneric* lir = new(alloc()) LApplyArgsGeneric(
         useFixed(apply->getFunction(), CallTempReg3),
         useFixed(apply->getArgc(), CallTempReg0),
+        useBoxFixed(apply->getThis(), CallTempReg4, CallTempReg5),
         tempFixed(CallTempReg1),  // object register
         tempFixed(CallTempReg2)); // stack counter register
 
-    MDefinition* self = apply->getThis();
-    useBoxFixed(lir, LApplyArgsGeneric::ThisIndex, self, CallTempReg4, CallTempReg5);
-
     // Bailout is only needed in the case of possible non-JSFunction callee.
     if (!apply->getSingleTarget())
         assignSnapshot(lir, Bailout_NonJSFunctionCallee);
 
     defineReturn(lir, apply);
     assignSafepoint(lir, apply);
 }
 
@@ -579,22 +572,20 @@ LIRGenerator::visitApplyArray(MApplyArra
 
     // Assert if the return value is already erased.
     MOZ_ASSERT(CallTempReg2 != JSReturnReg_Type);
     MOZ_ASSERT(CallTempReg2 != JSReturnReg_Data);
 
     LApplyArrayGeneric* lir = new(alloc()) LApplyArrayGeneric(
         useFixedAtStart(apply->getFunction(), CallTempReg3),
         useFixedAtStart(apply->getElements(), CallTempReg0),
+        useBoxFixed(apply->getThis(), CallTempReg4, CallTempReg5),
         tempFixed(CallTempReg1),  // object register
         tempFixed(CallTempReg2)); // stack counter register
 
-    MDefinition* self = apply->getThis();
-    useBoxFixed(lir, LApplyArrayGeneric::ThisIndex, self, CallTempReg4, CallTempReg5);
-
     // Bailout is needed in the case of possible non-JSFunction callee,
     // too many values in the array, or empty space at the end of the
     // array.  I'm going to use NonJSFunctionCallee for the code even
     // if that is not an adequate description.
     assignSnapshot(lir, Bailout_NonJSFunctionCallee);
 
     defineReturn(lir, apply);
     assignSafepoint(lir, apply);
@@ -677,19 +668,18 @@ LIRGenerator::visitCallDirectEval(MCallD
     MOZ_ASSERT(scopeChain->type() == MIRType_Object);
 
     MDefinition* string = ins->getString();
     MOZ_ASSERT(string->type() == MIRType_String);
 
     MDefinition* newTargetValue = ins->getNewTargetValue();
 
     LInstruction* lir = new(alloc()) LCallDirectEval(useRegisterAtStart(scopeChain),
-                                                     useRegisterAtStart(string));
-    useBoxAtStart(lir, LCallDirectEval::NewTarget, newTargetValue);
-
+                                                     useRegisterAtStart(string),
+                                                     useBoxAtStart(newTargetValue));
     defineReturn(lir, ins);
     assignSafepoint(lir, ins);
 }
 
 static JSOp
 ReorderComparison(JSOp op, MDefinition** lhsp, MDefinition** rhsp)
 {
     MDefinition* lhs = *lhsp;
@@ -728,18 +718,17 @@ LIRGenerator::visitTest(MTest* test)
         if (test->operandMightEmulateUndefined()) {
             temp0 = temp();
             temp1 = temp();
         } else {
             temp0 = LDefinition::BogusTemp();
             temp1 = LDefinition::BogusTemp();
         }
         LTestVAndBranch* lir =
-            new(alloc()) LTestVAndBranch(ifTrue, ifFalse, tempDouble(), temp0, temp1);
-        useBox(lir, LTestVAndBranch::Input, opd);
+            new(alloc()) LTestVAndBranch(ifTrue, ifFalse, useBox(opd), tempDouble(), temp0, temp1);
         add(lir, test);
         return;
     }
 
     if (opd->type() == MIRType_ObjectOrNull) {
         LDefinition temp0 = test->operandMightEmulateUndefined() ? temp() : LDefinition::BogusTemp();
         add(new(alloc()) LTestOAndBranch(useRegister(opd), ifTrue, ifFalse, temp0), test);
         return;
@@ -809,31 +798,30 @@ LIRGenerator::visitTest(MTest* test)
                 tmp = temp();
                 tmpToUnbox = tempToUnbox();
             } else {
                 tmp = LDefinition::BogusTemp();
                 tmpToUnbox = LDefinition::BogusTemp();
             }
 
             LIsNullOrLikeUndefinedAndBranchV* lir =
-                new(alloc()) LIsNullOrLikeUndefinedAndBranchV(comp, ifTrue, ifFalse,
+                new(alloc()) LIsNullOrLikeUndefinedAndBranchV(comp, ifTrue, ifFalse, useBox(left),
                                                               tmp, tmpToUnbox);
-            useBox(lir, LIsNullOrLikeUndefinedAndBranchV::Value, left);
             add(lir, test);
             return;
         }
 
         // Compare and branch booleans.
         if (comp->compareType() == MCompare::Compare_Boolean) {
             MOZ_ASSERT(left->type() == MIRType_Value);
             MOZ_ASSERT(right->type() == MIRType_Boolean);
 
-            LAllocation rhs = useRegisterOrConstant(right);
-            LCompareBAndBranch* lir = new(alloc()) LCompareBAndBranch(comp, rhs, ifTrue, ifFalse);
-            useBox(lir, LCompareBAndBranch::Lhs, left);
+            LCompareBAndBranch* lir = new(alloc()) LCompareBAndBranch(comp, useBox(left),
+                                                                      useRegisterOrConstant(right),
+                                                                      ifTrue, ifFalse);
             add(lir, test);
             return;
         }
 
         // Compare and branch Int32 or Object pointers.
         if (comp->isInt32Comparison() ||
             comp->compareType() == MCompare::Compare_UInt32 ||
             comp->compareType() == MCompare::Compare_Object)
@@ -869,19 +857,19 @@ LIRGenerator::visitTest(MTest* test)
                                                                       ifTrue, ifFalse);
             add(lir, test);
             return;
         }
 
         // Compare values.
         if (comp->compareType() == MCompare::Compare_Bitwise) {
             LCompareBitwiseAndBranch* lir =
-                new(alloc()) LCompareBitwiseAndBranch(comp, ifTrue, ifFalse);
-            useBoxAtStart(lir, LCompareBitwiseAndBranch::LhsInput, left);
-            useBoxAtStart(lir, LCompareBitwiseAndBranch::RhsInput, right);
+                new(alloc()) LCompareBitwiseAndBranch(comp, ifTrue, ifFalse,
+                                                      useBoxAtStart(left),
+                                                      useBoxAtStart(right));
             add(lir, test);
             return;
         }
     }
 
     // Check if the operand for this test is a bitand operation. If it is, we want
     // to emit an LBitAndAndBranch rather than an LTest*AndBranch.
     if (opd->isBitAnd() && opd->isEmittedAtUses()) {
@@ -893,30 +881,30 @@ LIRGenerator::visitTest(MTest* test)
             return;
         }
     }
 
     if (opd->isIsObject() && opd->isEmittedAtUses()) {
         MDefinition* input = opd->toIsObject()->input();
         MOZ_ASSERT(input->type() == MIRType_Value);
 
-        LIsObjectAndBranch* lir = new(alloc()) LIsObjectAndBranch(ifTrue, ifFalse);
-        useBoxAtStart(lir, LIsObjectAndBranch::Input, input);
+        LIsObjectAndBranch* lir = new(alloc()) LIsObjectAndBranch(ifTrue, ifFalse,
+                                                                  useBoxAtStart(input));
         add(lir, test);
         return;
     }
 
     if (opd->isIsNoIter()) {
         MOZ_ASSERT(opd->isEmittedAtUses());
 
         MDefinition* input = opd->toIsNoIter()->input();
         MOZ_ASSERT(input->type() == MIRType_Value);
 
-        LIsNoIterAndBranch* lir = new(alloc()) LIsNoIterAndBranch(ifTrue, ifFalse);
-        useBox(lir, LIsNoIterAndBranch::Input, input);
+        LIsNoIterAndBranch* lir = new(alloc()) LIsNoIterAndBranch(ifTrue, ifFalse,
+                                                                  useBox(input));
         add(lir, test);
         return;
     }
 
     switch (opd->type()) {
       case MIRType_Double:
         add(new(alloc()) LTestDAndBranch(useRegister(opd), ifTrue, ifFalse));
         break;
@@ -995,28 +983,26 @@ LIRGenerator::visitCompare(MCompare* com
         return;
     }
 
     // Strict compare between value and string
     if (comp->compareType() == MCompare::Compare_StrictString) {
         MOZ_ASSERT(left->type() == MIRType_Value);
         MOZ_ASSERT(right->type() == MIRType_String);
 
-        LCompareStrictS* lir = new(alloc()) LCompareStrictS(useRegister(right), tempToUnbox());
-        useBox(lir, LCompareStrictS::Lhs, left);
+        LCompareStrictS* lir = new(alloc()) LCompareStrictS(useBox(left), useRegister(right),
+                                                            tempToUnbox());
         define(lir, comp);
         assignSafepoint(lir, comp);
         return;
     }
 
     // Unknown/unspecialized compare use a VM call.
     if (comp->compareType() == MCompare::Compare_Unknown) {
-        LCompareVM* lir = new(alloc()) LCompareVM();
-        useBoxAtStart(lir, LCompareVM::LhsInput, left);
-        useBoxAtStart(lir, LCompareVM::RhsInput, right);
+        LCompareVM* lir = new(alloc()) LCompareVM(useBoxAtStart(left), useBoxAtStart(right));
         defineReturn(lir, comp);
         assignSafepoint(lir, comp);
         return;
     }
 
     // Sniff out if the output of this compare is used only for a branching.
     // If it is, then we will emit an LCompare*AndBranch instruction in place
     // of this compare and any test that uses this compare. Thus, we can
@@ -1043,29 +1029,28 @@ LIRGenerator::visitCompare(MCompare* com
         if (comp->operandMightEmulateUndefined()) {
             tmp = temp();
             tmpToUnbox = tempToUnbox();
         } else {
             tmp = LDefinition::BogusTemp();
             tmpToUnbox = LDefinition::BogusTemp();
         }
 
-        LIsNullOrLikeUndefinedV* lir = new(alloc()) LIsNullOrLikeUndefinedV(tmp, tmpToUnbox);
-        useBox(lir, LIsNullOrLikeUndefinedV::Value, left);
+        LIsNullOrLikeUndefinedV* lir = new(alloc()) LIsNullOrLikeUndefinedV(useBox(left),
+                                                                            tmp, tmpToUnbox);
         define(lir, comp);
         return;
     }
 
     // Compare booleans.
     if (comp->compareType() == MCompare::Compare_Boolean) {
         MOZ_ASSERT(left->type() == MIRType_Value);
         MOZ_ASSERT(right->type() == MIRType_Boolean);
 
-        LCompareB* lir = new(alloc()) LCompareB(useRegisterOrConstant(right));
-        useBox(lir, LCompareB::Lhs, left);
+        LCompareB* lir = new(alloc()) LCompareB(useBox(left), useRegisterOrConstant(right));
         define(lir, comp);
         return;
     }
 
     // Compare Int32 or Object pointers.
     if (comp->isInt32Comparison() ||
         comp->compareType() == MCompare::Compare_UInt32 ||
         comp->compareType() == MCompare::Compare_Object)
@@ -1093,19 +1078,18 @@ LIRGenerator::visitCompare(MCompare* com
     // Compare float32.
     if (comp->isFloat32Comparison()) {
         define(new(alloc()) LCompareF(useRegister(left), useRegister(right)), comp);
         return;
     }
 
     // Compare values.
     if (comp->compareType() == MCompare::Compare_Bitwise) {
-        LCompareBitwise* lir = new(alloc()) LCompareBitwise();
-        useBoxAtStart(lir, LCompareBitwise::LhsInput, left);
-        useBoxAtStart(lir, LCompareBitwise::RhsInput, right);
+        LCompareBitwise* lir = new(alloc()) LCompareBitwise(useBoxAtStart(left),
+                                                            useBoxAtStart(right));
         define(lir, comp);
         return;
     }
 
     MOZ_CRASH("Unrecognized compare type.");
 }
 
 void
@@ -1115,55 +1099,50 @@ LIRGenerator::lowerBitOp(JSOp op, MInstr
     MDefinition* rhs = ins->getOperand(1);
 
     if (lhs->type() == MIRType_Int32 && rhs->type() == MIRType_Int32) {
         ReorderCommutative(&lhs, &rhs, ins);
         lowerForALU(new(alloc()) LBitOpI(op), ins, lhs, rhs);
         return;
     }
 
-    LBitOpV* lir = new(alloc()) LBitOpV(op);
-    useBoxAtStart(lir, LBitOpV::LhsInput, lhs);
-    useBoxAtStart(lir, LBitOpV::RhsInput, rhs);
+    LBitOpV* lir = new(alloc()) LBitOpV(op, useBoxAtStart(lhs), useBoxAtStart(rhs));
     defineReturn(lir, ins);
     assignSafepoint(lir, ins);
 }
 
 void
 LIRGenerator::visitTypeOf(MTypeOf* ins)
 {
     MDefinition* opd = ins->input();
     MOZ_ASSERT(opd->type() == MIRType_Value);
 
-    LTypeOfV* lir = new(alloc()) LTypeOfV(tempToUnbox());
-    useBox(lir, LTypeOfV::Input, opd);
+    LTypeOfV* lir = new(alloc()) LTypeOfV(useBox(opd), tempToUnbox());
     define(lir, ins);
 }
 
 void
 LIRGenerator::visitToId(MToId* ins)
 {
-    LToIdV* lir = new(alloc()) LToIdV(tempDouble());
-    useBox(lir, LToIdV::Index, ins->input());
+    LToIdV* lir = new(alloc()) LToIdV(useBox(ins->input()), tempDouble());
     defineBox(lir, ins);
     assignSafepoint(lir, ins);
 }
 
 void
 LIRGenerator::visitBitNot(MBitNot* ins)
 {
     MDefinition* input = ins->getOperand(0);
 
     if (input->type() == MIRType_Int32) {
         lowerForALU(new(alloc()) LBitNotI(), ins, input);
         return;
     }
 
-    LBitNotV* lir = new(alloc()) LBitNotV;
-    useBoxAtStart(lir, LBitNotV::Input, input);
+    LBitNotV* lir = new(alloc()) LBitNotV(useBoxAtStart(input));
     defineReturn(lir, ins);
     assignSafepoint(lir, ins);
 }
 
 static bool
 CanEmitBitAndAtUses(MInstruction* ins)
 {
     if (!ins->canEmitAtUses())
@@ -1237,19 +1216,17 @@ LIRGenerator::lowerShiftOp(JSOp op, MShi
     MOZ_ASSERT(ins->specialization() == MIRType_None);
 
     if (op == JSOP_URSH) {
         // Result is either int32 or double so we have to use BinaryV.
         lowerBinaryV(JSOP_URSH, ins);
         return;
     }
 
-    LBitOpV* lir = new(alloc()) LBitOpV(op);
-    useBoxAtStart(lir, LBitOpV::LhsInput, lhs);
-    useBoxAtStart(lir, LBitOpV::RhsInput, rhs);
+    LBitOpV* lir = new(alloc()) LBitOpV(op, useBoxAtStart(lhs), useBoxAtStart(rhs));
     defineReturn(lir, ins);
     assignSafepoint(lir, ins);
 }
 
 void
 LIRGenerator::visitLsh(MLsh* ins)
 {
     lowerShiftOp(JSOP_LSH, ins);
@@ -1671,19 +1648,17 @@ void
 LIRGenerator::lowerBinaryV(JSOp op, MBinaryInstruction* ins)
 {
     MDefinition* lhs = ins->getOperand(0);
     MDefinition* rhs = ins->getOperand(1);
 
     MOZ_ASSERT(lhs->type() == MIRType_Value);
     MOZ_ASSERT(rhs->type() == MIRType_Value);
 
-    LBinaryV* lir = new(alloc()) LBinaryV(op);
-    useBoxAtStart(lir, LBinaryV::LhsInput, lhs);
-    useBoxAtStart(lir, LBinaryV::RhsInput, rhs);
+    LBinaryV* lir = new(alloc()) LBinaryV(op, useBoxAtStart(lhs), useBoxAtStart(rhs));
     defineReturn(lir, ins);
     assignSafepoint(lir, ins);
 }
 
 void
 LIRGenerator::visitConcat(MConcat* ins)
 {
     MDefinition* lhs = ins->getOperand(0);
@@ -1792,18 +1767,17 @@ void
 LIRGenerator::visitToDouble(MToDouble* convert)
 {
     MDefinition* opd = convert->input();
     mozilla::DebugOnly<MToFPInstruction::ConversionKind> conversion = convert->conversion();
 
     switch (opd->type()) {
       case MIRType_Value:
       {
-        LValueToDouble* lir = new(alloc()) LValueToDouble();
-        useBox(lir, LValueToDouble::Input, opd);
+        LValueToDouble* lir = new(alloc()) LValueToDouble(useBox(opd));
         assignSnapshot(lir, Bailout_NonPrimitiveInput);
         define(lir, convert);
         break;
       }
 
       case MIRType_Null:
         MOZ_ASSERT(conversion != MToFPInstruction::NumbersOnly &&
                    conversion != MToFPInstruction::NonNullNonStringPrimitives);
@@ -1848,18 +1822,17 @@ void
 LIRGenerator::visitToFloat32(MToFloat32* convert)
 {
     MDefinition* opd = convert->input();
     mozilla::DebugOnly<MToFloat32::ConversionKind> conversion = convert->conversion();
 
     switch (opd->type()) {
       case MIRType_Value:
       {
-        LValueToFloat32* lir = new(alloc()) LValueToFloat32();
-        useBox(lir, LValueToFloat32::Input, opd);
+        LValueToFloat32* lir = new(alloc()) LValueToFloat32(useBox(opd));
         assignSnapshot(lir, Bailout_NonPrimitiveInput);
         define(lir, convert);
         break;
       }
 
       case MIRType_Null:
         MOZ_ASSERT(conversion != MToFPInstruction::NumbersOnly &&
                    conversion != MToFPInstruction::NonNullNonStringPrimitives);
@@ -1904,18 +1877,17 @@ void
 LIRGenerator::visitToInt32(MToInt32* convert)
 {
     MDefinition* opd = convert->input();
 
     switch (opd->type()) {
       case MIRType_Value:
       {
         LValueToInt32* lir =
-            new(alloc()) LValueToInt32(tempDouble(), temp(), LValueToInt32::NORMAL);
-        useBox(lir, LValueToInt32::Input, opd);
+            new(alloc()) LValueToInt32(useBox(opd), tempDouble(), temp(), LValueToInt32::NORMAL);
         assignSnapshot(lir, Bailout_NonPrimitiveInput);
         define(lir, convert);
         assignSafepoint(lir, convert);
         break;
       }
 
       case MIRType_Null:
         MOZ_ASSERT(convert->conversion() == MacroAssembler::IntConversion_Any);
@@ -1963,19 +1935,18 @@ LIRGenerator::visitToInt32(MToInt32* con
 void
 LIRGenerator::visitTruncateToInt32(MTruncateToInt32* truncate)
 {
     MDefinition* opd = truncate->input();
 
     switch (opd->type()) {
       case MIRType_Value:
       {
-        LValueToInt32* lir = new(alloc()) LValueToInt32(tempDouble(), temp(),
+        LValueToInt32* lir = new(alloc()) LValueToInt32(useBox(opd), tempDouble(), temp(),
                                                         LValueToInt32::TRUNCATE);
-        useBox(lir, LValueToInt32::Input, opd);
         assignSnapshot(lir, Bailout_NonPrimitiveInput);
         define(lir, truncate);
         assignSafepoint(lir, truncate);
         break;
       }
 
       case MIRType_Null:
       case MIRType_Undefined:
@@ -2044,18 +2015,17 @@ LIRGenerator::visitToString(MToString* i
         break;
       }
 
       case MIRType_String:
         redefine(ins, ins->input());
         break;
 
       case MIRType_Value: {
-        LValueToString* lir = new(alloc()) LValueToString(tempToUnbox());
-        useBox(lir, LValueToString::Input, opd);
+        LValueToString* lir = new(alloc()) LValueToString(useBox(opd), tempToUnbox());
         if (ins->fallible())
             assignSnapshot(lir, Bailout_NonPrimitiveInput);
         define(lir, ins);
         assignSafepoint(lir, ins);
         break;
       }
 
       default:
@@ -2064,18 +2034,17 @@ LIRGenerator::visitToString(MToString* i
     }
 }
 
 void
 LIRGenerator::visitToObjectOrNull(MToObjectOrNull* ins)
 {
     MOZ_ASSERT(ins->input()->type() == MIRType_Value);
 
-    LValueToObjectOrNull* lir = new(alloc()) LValueToObjectOrNull();
-    useBox(lir, LValueToString::Input, ins->input());
+    LValueToObjectOrNull* lir = new(alloc()) LValueToObjectOrNull(useBox(ins->input()));
     define(lir, ins);
     assignSafepoint(lir, ins);
 }
 
 static bool
 MustCloneRegExpForCall(MCall* call, uint32_t useIndex)
 {
     // We have a regex literal flowing into a call. Return |false| iff
@@ -2215,35 +2184,29 @@ void
 LIRGenerator::visitBinarySharedStub(MBinarySharedStub* ins)
 {
     MDefinition* lhs = ins->getOperand(0);
     MDefinition* rhs = ins->getOperand(1);
 
     MOZ_ASSERT(ins->type() == MIRType_Value);
     MOZ_ASSERT(ins->type() == MIRType_Value);
 
-    LBinarySharedStub* lir = new(alloc()) LBinarySharedStub();
-
-    useBoxFixedAtStart(lir, LBinarySharedStub::LhsInput, lhs, R0);
-    useBoxFixedAtStart(lir, LBinarySharedStub::RhsInput, rhs, R1);
-
+    LBinarySharedStub* lir = new(alloc()) LBinarySharedStub(useBoxFixedAtStart(lhs, R0),
+                                                            useBoxFixedAtStart(rhs, R1));
     defineSharedStubReturn(lir, ins);
     assignSafepoint(lir, ins);
 }
 
 void
 LIRGenerator::visitUnarySharedStub(MUnarySharedStub* ins)
 {
     MDefinition* input = ins->getOperand(0);
     MOZ_ASSERT(ins->type() == MIRType_Value);
 
-    LUnarySharedStub* lir = new(alloc()) LUnarySharedStub();
-
-    useBoxFixedAtStart(lir, LUnarySharedStub::Input, input, R0);
-
+    LUnarySharedStub* lir = new(alloc()) LUnarySharedStub(useBoxFixedAtStart(input, R0));
     defineSharedStubReturn(lir, ins);
     assignSafepoint(lir, ins);
 }
 
 void
 LIRGenerator::visitLambda(MLambda* ins)
 {
     if (ins->info().singletonType || ins->info().useSingletonForClone) {
@@ -2263,18 +2226,18 @@ LIRGenerator::visitLambda(MLambda* ins)
 }
 
 void
 LIRGenerator::visitLambdaArrow(MLambdaArrow* ins)
 {
     MOZ_ASSERT(ins->scopeChain()->type() == MIRType_Object);
     MOZ_ASSERT(ins->newTargetDef()->type() == MIRType_Value);
 
-    LLambdaArrow* lir = new(alloc()) LLambdaArrow(useRegister(ins->scopeChain()));
-    useBox(lir, LLambdaArrow::NewTargetValue, ins->newTargetDef());
+    LLambdaArrow* lir = new(alloc()) LLambdaArrow(useRegister(ins->scopeChain()),
+                                                  useBox(ins->newTargetDef()));
     define(lir, ins);
     assignSafepoint(lir, ins);
 }
 
 void
 LIRGenerator::visitKeepAliveObject(MKeepAliveObject* ins)
 {
     MDefinition* obj = ins->object();
@@ -2372,18 +2335,17 @@ LIRGenerator::visitAsmJSInterruptCheck(M
 
 void
 LIRGenerator::visitStoreSlot(MStoreSlot* ins)
 {
     LInstruction* lir;
 
     switch (ins->value()->type()) {
       case MIRType_Value:
-        lir = new(alloc()) LStoreSlotV(useRegister(ins->slots()));
-        useBox(lir, LStoreSlotV::Value, ins->value());
+        lir = new(alloc()) LStoreSlotV(useRegister(ins->slots()), useBox(ins->value()));
         add(lir, ins);
         break;
 
       case MIRType_Double:
         add(new(alloc()) LStoreSlotT(useRegister(ins->slots()), useRegister(ins->value())), ins);
         break;
 
       case MIRType_Float32:
@@ -2424,18 +2386,17 @@ LIRGenerator::visitTypeBarrier(MTypeBarr
         add(bail, ins);
         redefine(ins, ins->input());
         return;
     }
 
     // Handle typebarrier with Value as input.
     if (inputType == MIRType_Value) {
         LDefinition tmp = needTemp ? temp() : tempToUnbox();
-        LTypeBarrierV* barrier = new(alloc()) LTypeBarrierV(tmp);
-        useBox(barrier, LTypeBarrierV::Input, ins->input());
+        LTypeBarrierV* barrier = new(alloc()) LTypeBarrierV(useBox(ins->input()), tmp);
         assignSnapshot(barrier, Bailout_TypeBarrierV);
         add(barrier, ins);
         redefine(ins, ins->input());
         return;
     }
 
     // The payload needs to be tested if it either might be null or might have
     // an object that should be excluded from the barrier.
@@ -2466,18 +2427,17 @@ LIRGenerator::visitMonitorTypes(MMonitor
 {
     // Requesting a non-GC pointer is safe here since we never re-enter C++
     // from inside a type check.
 
     const TemporaryTypeSet* types = ins->typeSet();
     bool needTemp = !types->unknownObject() && types->getObjectCount() > 0;
     LDefinition tmp = needTemp ? temp() : tempToUnbox();
 
-    LMonitorTypes* lir = new(alloc()) LMonitorTypes(tmp);
-    useBox(lir, LMonitorTypes::Input, ins->input());
+    LMonitorTypes* lir = new(alloc()) LMonitorTypes(useBox(ins->input()), tmp);
     assignSnapshot(lir, Bailout_MonitorTypes);
     add(lir, ins);
 }
 
 // Returns true iff |def| is a constant that's either not a GC thing or is not
 // allocated in the nursery.
 static bool
 IsNonNurseryConstant(MDefinition* def)
@@ -2513,18 +2473,18 @@ LIRGenerator::visitPostWriteBarrier(MPos
         break;
       }
       case MIRType_Value: {
         LDefinition tmp = needTempForPostBarrier() ? temp() : LDefinition::BogusTemp();
         LPostWriteBarrierV* lir =
             new(alloc()) LPostWriteBarrierV(useConstantObject
                                             ? useOrConstant(ins->object())
                                             : useRegister(ins->object()),
+                                            useBox(ins->value()),
                                             tmp);
-        useBox(lir, LPostWriteBarrierV::Input, ins->value());
         add(lir, ins);
         assignSafepoint(lir, ins);
         break;
       }
       default:
         // Currently, only objects can be in the nursery. Other instruction
         // types cannot hold nursery pointers.
         break;
@@ -2562,18 +2522,18 @@ LIRGenerator::visitPostWriteElementBarri
       }
       case MIRType_Value: {
         LDefinition tmp = needTempForPostBarrier() ? temp() : LDefinition::BogusTemp();
         LPostWriteElementBarrierV* lir =
             new(alloc()) LPostWriteElementBarrierV(useConstantObject
                                                    ? useOrConstant(ins->object())
                                                    : useRegister(ins->object()),
                                                    useRegister(ins->index()),
+                                                   useBox(ins->value()),
                                                    tmp);
-        useBox(lir, LPostWriteElementBarrierV::Input, ins->value());
         add(lir, ins);
         assignSafepoint(lir, ins);
         break;
       }
       default:
         // Currently, only objects can be in the nursery. Other instruction
         // types cannot hold nursery pointers.
         break;
@@ -2751,18 +2711,17 @@ LIRGenerator::visitNot(MNot* ins)
         if (ins->operandMightEmulateUndefined()) {
             temp0 = temp();
             temp1 = temp();
         } else {
             temp0 = LDefinition::BogusTemp();
             temp1 = LDefinition::BogusTemp();
         }
 
-        LNotV* lir = new(alloc()) LNotV(tempDouble(), temp0, temp1);
-        useBox(lir, LNotV::Input, op);
+        LNotV* lir = new(alloc()) LNotV(useBox(op), tempDouble(), temp0, temp1);
         define(lir, ins);
         break;
       }
 
       default:
         MOZ_CRASH("Unexpected MIRType.");
     }
 }
@@ -2907,20 +2866,19 @@ LIRGenerator::visitStoreElement(MStoreEl
     MOZ_ASSERT(ins->index()->type() == MIRType_Int32);
 
     const LUse elements = useRegister(ins->elements());
     const LAllocation index = useRegisterOrConstant(ins->index());
 
     switch (ins->value()->type()) {
       case MIRType_Value:
       {
-        LInstruction* lir = new(alloc()) LStoreElementV(elements, index);
+        LInstruction* lir = new(alloc()) LStoreElementV(elements, index, useBox(ins->value()));
         if (ins->fallible())
             assignSnapshot(lir, Bailout_Hole);
-        useBox(lir, LStoreElementV::Value, ins->value());
         add(lir, ins);
         break;
       }
 
       default:
       {
         const LAllocation value = useRegisterOrNonDoubleConstant(ins->value());
         LInstruction* lir = new(alloc()) LStoreElementT(elements, index, value);
@@ -2945,18 +2903,18 @@ LIRGenerator::visitStoreElementHole(MSto
     // Use a temp register when adding new elements to unboxed arrays.
     LDefinition tempDef = LDefinition::BogusTemp();
     if (ins->unboxedType() != JSVAL_TYPE_MAGIC)
         tempDef = temp();
 
     LInstruction* lir;
     switch (ins->value()->type()) {
       case MIRType_Value:
-        lir = new(alloc()) LStoreElementHoleV(object, elements, index, tempDef);
-        useBox(lir, LStoreElementHoleV::Value, ins->value());
+        lir = new(alloc()) LStoreElementHoleV(object, elements, index, useBox(ins->value()),
+                                              tempDef);
         break;
 
       default:
       {
         const LAllocation value = useRegisterOrNonDoubleConstant(ins->value());
         lir = new(alloc()) LStoreElementHoleT(object, elements, index, value, tempDef);
         break;
       }
@@ -3044,18 +3002,17 @@ LIRGenerator::visitArrayPush(MArrayPush*
 {
     MOZ_ASSERT(ins->type() == MIRType_Int32);
 
     LUse object = useRegister(ins->object());
 
     switch (ins->value()->type()) {
       case MIRType_Value:
       {
-        LArrayPushV* lir = new(alloc()) LArrayPushV(object, temp());
-        useBox(lir, LArrayPushV::Value, ins->value());
+        LArrayPushV* lir = new(alloc()) LArrayPushV(object, useBox(ins->value()), temp());
         define(lir, ins);
         assignSafepoint(lir, ins);
         break;
       }
 
       default:
       {
         const LAllocation value = useRegisterOrNonDoubleConstant(ins->value());
@@ -3187,18 +3144,17 @@ LIRGenerator::visitClampToUint8(MClampTo
       case MIRType_Double:
         // LClampDToUint8 clobbers its input register. Making it available as
         // a temp copy describes this behavior to the register allocator.
         define(new(alloc()) LClampDToUint8(useRegisterAtStart(in), tempCopy(in, 0)), ins);
         break;
 
       case MIRType_Value:
       {
-        LClampVToUint8* lir = new(alloc()) LClampVToUint8(tempDouble());
-        useBox(lir, LClampVToUint8::Input, in);
+        LClampVToUint8* lir = new(alloc()) LClampVToUint8(useBox(in), tempDouble());
         assignSnapshot(lir, Bailout_NonPrimitiveInput);
         define(lir, ins);
         assignSafepoint(lir, ins);
         break;
       }
 
       default:
         MOZ_CRASH("unexpected type");
@@ -3334,18 +3290,18 @@ LIRGenerator::visitLoadFixedSlotAndUnbox
 }
 
 void
 LIRGenerator::visitStoreFixedSlot(MStoreFixedSlot* ins)
 {
     MOZ_ASSERT(ins->object()->type() == MIRType_Object);
 
     if (ins->value()->type() == MIRType_Value) {
-        LStoreFixedSlotV* lir = new(alloc()) LStoreFixedSlotV(useRegister(ins->object()));
-        useBox(lir, LStoreFixedSlotV::Value, ins->value());
+        LStoreFixedSlotV* lir = new(alloc()) LStoreFixedSlotV(useRegister(ins->object()),
+                                                              useBox(ins->value()));
         add(lir, ins);
     } else {
         LStoreFixedSlotT* lir = new(alloc()) LStoreFixedSlotT(useRegister(ins->object()),
                                                               useRegisterOrConstant(ins->value()));
         add(lir, ins);
     }
 }
 
@@ -3390,23 +3346,25 @@ LIRGenerator::visitGetPropertyCache(MGet
         gen->setPerformsCall();
     }
 
     // If this is a GETPROP, the id is a constant string. Allow passing it as a
     // constant to reduce register allocation pressure.
     bool useConstId = id->type() == MIRType_String || id->type() == MIRType_Symbol;
 
     if (ins->type() == MIRType_Value) {
-        LGetPropertyCacheV* lir = new(alloc()) LGetPropertyCacheV(useRegister(ins->object()));
-        useBoxOrTypedOrConstant(lir, LGetPropertyCacheV::Id, id, useConstId);
+        LGetPropertyCacheV* lir =
+            new(alloc()) LGetPropertyCacheV(useRegister(ins->object()),
+                                            useBoxOrTypedOrConstant(id, useConstId));
         defineBox(lir, ins);
         assignSafepoint(lir, ins);
     } else {
-        LGetPropertyCacheT* lir = new(alloc()) LGetPropertyCacheT(useRegister(ins->object()));
-        useBoxOrTypedOrConstant(lir, LGetPropertyCacheT::Id, id, useConstId);
+        LGetPropertyCacheT* lir =
+            new(alloc()) LGetPropertyCacheT(useRegister(ins->object()),
+                                            useBoxOrTypedOrConstant(id, useConstId));
         define(lir, ins);
         assignSafepoint(lir, ins);
     }
 }
 
 void
 LIRGenerator::visitGetPropertyPolymorphic(MGetPropertyPolymorphic* ins)
 {
@@ -3428,18 +3386,19 @@ LIRGenerator::visitGetPropertyPolymorphi
 
 void
 LIRGenerator::visitSetPropertyPolymorphic(MSetPropertyPolymorphic* ins)
 {
     MOZ_ASSERT(ins->obj()->type() == MIRType_Object);
 
     if (ins->value()->type() == MIRType_Value) {
         LSetPropertyPolymorphicV* lir =
-            new(alloc()) LSetPropertyPolymorphicV(useRegister(ins->obj()), temp());
-        useBox(lir, LSetPropertyPolymorphicV::Value, ins->value());
+            new(alloc()) LSetPropertyPolymorphicV(useRegister(ins->obj()),
+                                                  useBox(ins->value()),
+                                                  temp());
         assignSnapshot(lir, Bailout_ShapeGuard);
         add(lir, ins);
     } else {
         LAllocation value = useRegisterOrConstant(ins->value());
         LSetPropertyPolymorphicT* lir =
             new(alloc()) LSetPropertyPolymorphicT(useRegister(ins->obj()), value,
                                                   ins->value()->type(), temp());
         assignSnapshot(lir, Bailout_ShapeGuard);
@@ -3570,75 +3529,70 @@ LIRGenerator::visitAssertRange(MAssertRa
         break;
 
       case MIRType_Float32: {
         LDefinition armtemp = hasMultiAlias() ? tempDouble() : LDefinition::BogusTemp();
         lir = new(alloc()) LAssertRangeF(useRegister(input), tempDouble(), armtemp);
         break;
       }
       case MIRType_Value:
-        lir = new(alloc()) LAssertRangeV(tempToUnbox(), tempDouble(), tempDouble());
-        useBox(lir, LAssertRangeV::Input, input);
+        lir = new(alloc()) LAssertRangeV(useBox(input), tempToUnbox(), tempDouble(), tempDouble());
         break;
 
       default:
         MOZ_CRASH("Unexpected Range for MIRType");
         break;
     }
 
     lir->setMir(ins);
     add(lir);
 }
 
 void
 LIRGenerator::visitCallGetProperty(MCallGetProperty* ins)
 {
-    LCallGetProperty* lir = new(alloc()) LCallGetProperty();
-    useBoxAtStart(lir, LCallGetProperty::Value, ins->value());
+    LCallGetProperty* lir = new(alloc()) LCallGetProperty(useBoxAtStart(ins->value()));
     defineReturn(lir, ins);
     assignSafepoint(lir, ins);
 }
 
 void
 LIRGenerator::visitCallGetElement(MCallGetElement* ins)
 {
     MOZ_ASSERT(ins->lhs()->type() == MIRType_Value);
     MOZ_ASSERT(ins->rhs()->type() == MIRType_Value);
 
-    LCallGetElement* lir = new(alloc()) LCallGetElement();
-    useBoxAtStart(lir, LCallGetElement::LhsInput, ins->lhs());
-    useBoxAtStart(lir, LCallGetElement::RhsInput, ins->rhs());
+    LCallGetElement* lir = new(alloc()) LCallGetElement(useBoxAtStart(ins->lhs()),
+                                                        useBoxAtStart(ins->rhs()));
     defineReturn(lir, ins);
     assignSafepoint(lir, ins);
 }
 
 void
 LIRGenerator::visitCallSetProperty(MCallSetProperty* ins)
 {
-    LInstruction* lir = new(alloc()) LCallSetProperty(useRegisterAtStart(ins->object()));
-    useBoxAtStart(lir, LCallSetProperty::Value, ins->value());
+    LInstruction* lir = new(alloc()) LCallSetProperty(useRegisterAtStart(ins->object()),
+                                                      useBoxAtStart(ins->value()));
     add(lir, ins);
     assignSafepoint(lir, ins);
 }
 
 void
 LIRGenerator::visitDeleteProperty(MDeleteProperty* ins)
 {
-    LCallDeleteProperty* lir = new(alloc()) LCallDeleteProperty();
-    useBoxAtStart(lir, LCallDeleteProperty::Value, ins->value());
+    LCallDeleteProperty* lir = new(alloc()) LCallDeleteProperty(useBoxAtStart(ins->value()));
     defineReturn(lir, ins);
     assignSafepoint(lir, ins);
 }
 
 void
 LIRGenerator::visitDeleteElement(MDeleteElement* ins)
 {
-    LCallDeleteElement* lir = new(alloc()) LCallDeleteElement();
-    useBoxAtStart(lir, LCallDeleteElement::Value, ins->value());
-    useBoxAtStart(lir, LCallDeleteElement::Index, ins->index());
+    LCallDeleteElement* lir = new(alloc()) LCallDeleteElement(useBoxAtStart(ins->value()),
+                                                              useBoxAtStart(ins->index()));
     defineReturn(lir, ins);
     assignSafepoint(lir, ins);
 }
 
 void
 LIRGenerator::visitSetPropertyCache(MSetPropertyCache* ins)
 {
     MOZ_ASSERT(ins->object()->type() == MIRType_Object);
@@ -3667,46 +3621,45 @@ LIRGenerator::visitSetPropertyCache(MSet
 
     if (id->mightBeType(MIRType_Int32)) {
         if (id->type() != MIRType_Int32)
             tempToUnboxIndex = tempToUnbox();
         tempD = tempDouble();
         tempF32 = hasUnaliasedDouble() ? tempFloat32() : LDefinition::BogusTemp();
     }
 
-    LInstruction* lir = new(alloc()) LSetPropertyCache(useRegister(ins->object()), temp(),
-                                                       tempToUnboxIndex, tempD, tempF32);
-    useBoxOrTypedOrConstant(lir, LSetPropertyCache::Id, id, useConstId);
-    useBoxOrTypedOrConstant(lir, LSetPropertyCache::Value, ins->value(), useConstValue);
-
+    LInstruction* lir =
+        new(alloc()) LSetPropertyCache(useRegister(ins->object()),
+                                       useBoxOrTypedOrConstant(id, useConstId),
+                                       useBoxOrTypedOrConstant(ins->value(), useConstValue),
+                                       temp(),
+                                       tempToUnboxIndex, tempD, tempF32);
     add(lir, ins);
     assignSafepoint(lir, ins);
 }
 
 void
 LIRGenerator::visitCallSetElement(MCallSetElement* ins)
 {
     MOZ_ASSERT(ins->object()->type() == MIRType_Object);
     MOZ_ASSERT(ins->index()->type() == MIRType_Value);
     MOZ_ASSERT(ins->value()->type() == MIRType_Value);
 
-    LCallSetElement* lir = new(alloc()) LCallSetElement();
-    lir->setOperand(0, useRegisterAtStart(ins->object()));
-    useBoxAtStart(lir, LCallSetElement::Index, ins->index());
-    useBoxAtStart(lir, LCallSetElement::Value, ins->value());
+    LCallSetElement* lir = new(alloc()) LCallSetElement(useRegisterAtStart(ins->object()),
+                                                        useBoxAtStart(ins->index()),
+                                                        useBoxAtStart(ins->value()));
     add(lir, ins);
     assignSafepoint(lir, ins);
 }
 
 void
 LIRGenerator::visitCallInitElementArray(MCallInitElementArray* ins)
 {
-    LCallInitElementArray* lir = new(alloc()) LCallInitElementArray();
-    lir->setOperand(0, useRegisterAtStart(ins->object()));
-    useBoxAtStart(lir, LCallInitElementArray::Value, ins->value());
+    LCallInitElementArray* lir = new(alloc()) LCallInitElementArray(useRegisterAtStart(ins->object()),
+                                                                    useBoxAtStart(ins->value()));
     add(lir, ins);
     assignSafepoint(lir, ins);
 }
 
 void
 LIRGenerator::visitIteratorStart(MIteratorStart* ins)
 {
     // Call a stub if this is not a simple for-in loop.
@@ -3772,18 +3725,17 @@ LIRGenerator::visitNewTarget(MNewTarget*
 }
 
 void
 LIRGenerator::visitSetFrameArgument(MSetFrameArgument* ins)
 {
     MDefinition* input = ins->input();
 
     if (input->type() == MIRType_Value) {
-        LSetFrameArgumentV* lir = new(alloc()) LSetFrameArgumentV();
-        useBox(lir, LSetFrameArgumentV::Input, input);
+        LSetFrameArgumentV* lir = new(alloc()) LSetFrameArgumentV(useBox(input));
         add(lir, ins);
     } else if (input->type() == MIRType_Undefined || input->type() == MIRType_Null) {
         Value val = input->type() == MIRType_Undefined ? UndefinedValue() : NullValue();
         LSetFrameArgumentC* lir = new(alloc()) LSetFrameArgumentC(val);
         add(lir, ins);
     } else {
         LSetFrameArgumentT* lir = new(alloc()) LSetFrameArgumentT(useRegister(input));
         add(lir, ins);
@@ -3812,67 +3764,64 @@ LIRGenerator::visitRest(MRest* ins)
 }
 
 void
 LIRGenerator::visitThrow(MThrow* ins)
 {
     MDefinition* value = ins->getOperand(0);
     MOZ_ASSERT(value->type() == MIRType_Value);
 
-    LThrow* lir = new(alloc()) LThrow;
-    useBoxAtStart(lir, LThrow::Value, value);
+    LThrow* lir = new(alloc()) LThrow(useBoxAtStart(value));
     add(lir, ins);
     assignSafepoint(lir, ins);
 }
 
 void
 LIRGenerator::visitIn(MIn* ins)
 {
     MDefinition* lhs = ins->lhs();
     MDefinition* rhs = ins->rhs();
 
     MOZ_ASSERT(lhs->type() == MIRType_Value);
     MOZ_ASSERT(rhs->type() == MIRType_Object);
 
-    LIn* lir = new(alloc()) LIn(useRegisterAtStart(rhs));
-    useBoxAtStart(lir, LIn::LHS, lhs);
+    LIn* lir = new(alloc()) LIn(useBoxAtStart(lhs), useRegisterAtStart(rhs));
     defineReturn(lir, ins);
     assignSafepoint(lir, ins);
 }
 
 void
 LIRGenerator::visitInstanceOf(MInstanceOf* ins)
 {
     MDefinition* lhs = ins->getOperand(0);
 
     MOZ_ASSERT(lhs->type() == MIRType_Value || lhs->type() == MIRType_Object);
 
     if (lhs->type() == MIRType_Object) {
         LInstanceOfO* lir = new(alloc()) LInstanceOfO(useRegister(lhs));
         define(lir, ins);
         assignSafepoint(lir, ins);
     } else {
-        LInstanceOfV* lir = new(alloc()) LInstanceOfV();
-        useBox(lir, LInstanceOfV::LHS, lhs);
+        LInstanceOfV* lir = new(alloc()) LInstanceOfV(useBox(lhs));
         define(lir, ins);
         assignSafepoint(lir, ins);
     }
 }
 
 void
 LIRGenerator::visitCallInstanceOf(MCallInstanceOf* ins)
 {
     MDefinition* lhs = ins->lhs();
     MDefinition* rhs = ins->rhs();
 
     MOZ_ASSERT(lhs->type() == MIRType_Value);
     MOZ_ASSERT(rhs->type() == MIRType_Object);
 
-    LCallInstanceOf* lir = new(alloc()) LCallInstanceOf(useRegisterAtStart(rhs));
-    useBoxAtStart(lir, LCallInstanceOf::LHS, lhs);
+    LCallInstanceOf* lir = new(alloc()) LCallInstanceOf(useBoxAtStart(lhs),
+                                                        useRegisterAtStart(rhs));
     defineReturn(lir, ins);
     assignSafepoint(lir, ins);
 }
 
 void
 LIRGenerator::visitIsCallable(MIsCallable* ins)
 {
     MOZ_ASSERT(ins->object()->type() == MIRType_Object);
@@ -3906,18 +3855,17 @@ LIRGenerator::visitIsObject(MIsObject* i
 {
     if (CanEmitIsObjectAtUses(ins)) {
         emitAtUses(ins);
         return;
     }
 
     MDefinition* opd = ins->input();
     MOZ_ASSERT(opd->type() == MIRType_Value);
-    LIsObject* lir = new(alloc()) LIsObject();
-    useBoxAtStart(lir, LIsObject::Input, opd);
+    LIsObject* lir = new(alloc()) LIsObject(useBoxAtStart(opd));
     define(lir, ins);
 }
 
 void
 LIRGenerator::visitHasClass(MHasClass* ins)
 {
     MOZ_ASSERT(ins->object()->type() == MIRType_Object);
     MOZ_ASSERT(ins->type() == MIRType_Boolean);
@@ -4018,28 +3966,29 @@ LIRGenerator::visitSetDOMProperty(MSetDO
 {
     MDefinition* val = ins->value();
 
     Register cxReg, objReg, privReg, valueReg;
     GetTempRegForIntArg(0, 0, &cxReg);
     GetTempRegForIntArg(1, 0, &objReg);
     GetTempRegForIntArg(2, 0, &privReg);
     GetTempRegForIntArg(3, 0, &valueReg);
-    LSetDOMProperty* lir = new(alloc()) LSetDOMProperty(tempFixed(cxReg),
-                                                        useFixed(ins->object(), objReg),
-                                                        tempFixed(privReg),
-                                                        tempFixed(valueReg));
 
     // Keep using GetTempRegForIntArg, since we want to make sure we
     // don't clobber registers we're already using.
     Register tempReg1, tempReg2;
     GetTempRegForIntArg(4, 0, &tempReg1);
     mozilla::DebugOnly<bool> ok = GetTempRegForIntArg(5, 0, &tempReg2);
     MOZ_ASSERT(ok, "How can we not have six temp registers?");
-    useBoxFixed(lir, LSetDOMProperty::Value, val, tempReg1, tempReg2);
+
+    LSetDOMProperty* lir = new(alloc()) LSetDOMProperty(tempFixed(cxReg),
+                                                        useFixed(ins->object(), objReg),
+                                                        useBoxFixed(val, tempReg1, tempReg2),
+                                                        tempFixed(privReg),
+                                                        tempFixed(valueReg));
     add(lir, ins);
     assignSafepoint(lir, ins);
 }
 
 void
 LIRGenerator::visitGetDOMProperty(MGetDOMProperty* ins)
 {
     Register cxReg, objReg, privReg, valueReg;
@@ -4426,18 +4375,17 @@ LIRGenerator::visitSimdShift(MSimdShift*
     defineReuseInput(lir, ins, 0);
 }
 
 void
 LIRGenerator::visitLexicalCheck(MLexicalCheck* ins)
 {
     MDefinition* input = ins->input();
     MOZ_ASSERT(input->type() == MIRType_Value);
-    LLexicalCheck* lir = new(alloc()) LLexicalCheck();
-    useBox(lir, LLexicalCheck::Input, input);
+    LLexicalCheck* lir = new(alloc()) LLexicalCheck(useBox(input));
     assignSnapshot(lir, ins->bailoutKind());
     add(lir, ins);
     redefine(ins, input);
 }
 
 void
 LIRGenerator::visitThrowRuntimeLexicalError(MThrowRuntimeLexicalError* ins)
 {
@@ -4471,45 +4419,41 @@ LIRGenerator::visitAtomicIsLockFree(MAto
 void
 LIRGenerator::visitCheckReturn(MCheckReturn* ins)
 {
     MDefinition* retVal = ins->returnValue();
     MDefinition* thisVal = ins->thisValue();
     MOZ_ASSERT(retVal->type() == MIRType_Value);
     MOZ_ASSERT(thisVal->type() == MIRType_Value);
 
-    LCheckReturn* lir = new(alloc()) LCheckReturn();
-    useBoxAtStart(lir, LCheckReturn::ReturnValue, retVal);
-    useBoxAtStart(lir, LCheckReturn::ThisValue, thisVal);
+    LCheckReturn* lir = new(alloc()) LCheckReturn(useBoxAtStart(retVal), useBoxAtStart(thisVal));
     assignSnapshot(lir, Bailout_BadDerivedConstructorReturn);
     add(lir, ins);
     redefine(ins, retVal);
 }
 
 void
 LIRGenerator::visitCheckObjCoercible(MCheckObjCoercible* ins)
 {
     MDefinition* checkVal = ins->checkValue();
     MOZ_ASSERT(checkVal->type() == MIRType_Value);
 
-    LCheckObjCoercible* lir = new(alloc()) LCheckObjCoercible();
-    useBoxAtStart(lir, LCheckObjCoercible::CheckValue, checkVal);
+    LCheckObjCoercible* lir = new(alloc()) LCheckObjCoercible(useBoxAtStart(checkVal));
     redefine(ins, checkVal);
     add(lir, ins);
     assignSafepoint(lir, ins);
 }
 
 void
 LIRGenerator::visitDebugCheckSelfHosted(MDebugCheckSelfHosted* ins)
 {
     MDefinition* checkVal = ins->checkValue();
     MOZ_ASSERT(checkVal->type() == MIRType_Value);
 
-    LDebugCheckSelfHosted* lir = new (alloc()) LDebugCheckSelfHosted();
-    useBoxAtStart(lir, LDebugCheckSelfHosted::CheckValue, checkVal);
+    LDebugCheckSelfHosted* lir = new (alloc()) LDebugCheckSelfHosted(useBoxAtStart(checkVal));
     redefine(ins, checkVal);
     add(lir, ins);
     assignSafepoint(lir, ins);
 }
 
 static void
 SpewResumePoint(MBasicBlock* block, MInstruction* ins, MResumePoint* resumePoint)
 {
--- a/js/src/jit/Lowering.h
+++ b/js/src/jit/Lowering.h
@@ -44,20 +44,18 @@ class LIRGenerator : public LIRGenerator
     LIRGenerator(MIRGenerator* gen, MIRGraph& graph, LIRGraph& lirGraph)
       : LIRGeneratorSpecific(gen, graph, lirGraph),
         maxargslots_(0)
     { }
 
     bool generate();
 
   private:
-
-    void useBoxAtStart(LInstruction* lir, size_t n, MDefinition* mir,
-                       LUse::Policy policy = LUse::REGISTER);
-    void useBoxFixedAtStart(LInstruction* lir, size_t n, MDefinition* mir, ValueOperand op);
+    LBoxAllocation useBoxFixedAtStart(MDefinition* mir, ValueOperand op);
+    LBoxAllocation useBoxAtStart(MDefinition* mir, LUse::Policy policy = LUse::REGISTER);
 
     void lowerBitOp(JSOp op, MInstruction* ins);
     void lowerShiftOp(JSOp op, MShiftInstruction* ins);
     void lowerBinaryV(JSOp op, MBinaryInstruction* ins);
     void definePhis();
 
     void lowerCallArguments(MCall* call);
 
--- a/js/src/jit/arm/LIR-arm.h
+++ b/js/src/jit/arm/LIR-arm.h
@@ -55,19 +55,21 @@ class LUnboxFloatingPoint : public LInst
 {
     MIRType type_;
 
   public:
     LIR_HEADER(UnboxFloatingPoint);
 
     static const size_t Input = 0;
 
-    LUnboxFloatingPoint(MIRType type)
+    LUnboxFloatingPoint(const LBoxAllocation& input, MIRType type)
       : type_(type)
-    { }
+    {
+        setBoxOperand(Input, input);
+    }
 
     MUnbox* mir() const {
         return mir_->toUnbox();
     }
 
     MIRType type() const {
         return type_;
     }
@@ -296,19 +298,20 @@ class LTableSwitch : public LInstruction
 };
 
 // Takes a tableswitch with an integer to decide.
 class LTableSwitchV : public LInstructionHelper<0, BOX_PIECES, 2>
 {
   public:
     LIR_HEADER(TableSwitchV);
 
-    LTableSwitchV(const LDefinition& inputCopy, const LDefinition& floatCopy,
-                  MTableSwitch* ins)
+    LTableSwitchV(const LBoxAllocation& input, const LDefinition& inputCopy,
+                  const LDefinition& floatCopy, MTableSwitch* ins)
     {
+        setBoxOperand(InputValue, input);
         setTemp(0, inputCopy);
         setTemp(1, floatCopy);
         setMir(ins);
     }
 
     MTableSwitch* mir() const {
         return mir_->toTableSwitch();
     }
--- a/js/src/jit/arm/Lowering-arm.cpp
+++ b/js/src/jit/arm/Lowering-arm.cpp
@@ -12,26 +12,25 @@
 
 #include "jit/shared/Lowering-shared-inl.h"
 
 using namespace js;
 using namespace js::jit;
 
 using mozilla::FloorLog2;
 
-void
-LIRGeneratorARM::useBoxFixed(LInstruction* lir, size_t n, MDefinition* mir, Register reg1,
-                             Register reg2, bool useAtStart)
+LBoxAllocation
+LIRGeneratorARM::useBoxFixed(MDefinition* mir, Register reg1, Register reg2, bool useAtStart)
 {
     MOZ_ASSERT(mir->type() == MIRType_Value);
     MOZ_ASSERT(reg1 != reg2);
 
     ensureDefined(mir);
-    lir->setOperand(n, LUse(reg1, mir->virtualRegister(), useAtStart));
-    lir->setOperand(n + 1, LUse(reg2, VirtualRegisterOfPayload(mir), useAtStart));
+    return LBoxAllocation(LUse(reg1, mir->virtualRegister(), useAtStart),
+                          LUse(reg2, VirtualRegisterOfPayload(mir), useAtStart));
 }
 
 LAllocation
 LIRGeneratorARM::useByteOpRegister(MDefinition* mir)
 {
     return useRegister(mir);
 }
 
@@ -103,20 +102,19 @@ LIRGeneratorARM::visitUnbox(MUnbox* unbo
     // An unbox on arm reads in a type tag (either in memory or a register) and
     // a payload. Unlike most instructions consuming a box, we ask for the type
     // second, so that the result can re-use the first input.
     MOZ_ASSERT(inner->type() == MIRType_Value);
 
     ensureDefined(inner);
 
     if (IsFloatingPointType(unbox->type())) {
-        LUnboxFloatingPoint* lir = new(alloc()) LUnboxFloatingPoint(unbox->type());
+        LUnboxFloatingPoint* lir = new(alloc()) LUnboxFloatingPoint(useBox(inner), unbox->type());
         if (unbox->fallible())
             assignSnapshot(lir, unbox->bailoutKind());
-        useBox(lir, LUnboxFloatingPoint::Input, inner);
         define(lir, unbox);
         return;
     }
 
     // Swap the order we use the box pieces so we can re-use the payload register.
     LUnbox* lir = new(alloc()) LUnbox;
     lir->setOperand(0, usePayloadInRegisterAtStart(inner));
     lir->setOperand(1, useType(inner, LUse::REGISTER));
@@ -340,17 +338,18 @@ LIRGeneratorARM::newLTableSwitch(const L
                                        MTableSwitch* tableswitch)
 {
     return new(alloc()) LTableSwitch(in, inputCopy, tableswitch);
 }
 
 LTableSwitchV*
 LIRGeneratorARM::newLTableSwitchV(MTableSwitch* tableswitch)
 {
-    return new(alloc()) LTableSwitchV(temp(), tempDouble(), tableswitch);
+    return new(alloc()) LTableSwitchV(useBox(tableswitch->getOperand(0)),
+                                      temp(), tempDouble(), tableswitch);
 }
 
 void
 LIRGeneratorARM::visitGuardShape(MGuardShape* ins)
 {
     MOZ_ASSERT(ins->obj()->type() == MIRType_Object);
 
     LDefinition tempObj = temp(LDefinition::OBJECT);
--- a/js/src/jit/arm/Lowering-arm.h
+++ b/js/src/jit/arm/Lowering-arm.h
@@ -15,20 +15,19 @@ namespace jit {
 class LIRGeneratorARM : public LIRGeneratorShared
 {
   public:
     LIRGeneratorARM(MIRGenerator* gen, MIRGraph& graph, LIRGraph& lirGraph)
       : LIRGeneratorShared(gen, graph, lirGraph)
     { }
 
   protected:
-    // Adds a box input to an instruction, setting operand |n| to the type and
-    // |n+1| to the payload.
-    void useBoxFixed(LInstruction* lir, size_t n, MDefinition* mir, Register reg1, Register reg2,
-                     bool useAtStart = false);
+    // Returns a box allocation with type set to reg1 and payload set to reg2.
+    LBoxAllocation useBoxFixed(MDefinition* mir, Register reg1, Register reg2,
+                               bool useAtStart = false);
 
     // x86 has constraints on what registers can be formatted for 1-byte
     // stores and loads; on ARM all registers are okay.
     LAllocation useByteOpRegister(MDefinition* mir);
     LAllocation useByteOpRegisterOrNonDoubleConstant(MDefinition* mir);
     LDefinition tempByteOpRegister();
 
     inline LDefinition tempToUnbox() {
--- a/js/src/jit/arm64/LIR-arm64.h
+++ b/js/src/jit/arm64/LIR-arm64.h
@@ -277,19 +277,20 @@ class LTableSwitch : public LInstruction
 };
 
 // Takes a tableswitch with an integer to decide
 class LTableSwitchV : public LInstructionHelper<0, BOX_PIECES, 2>
 {
   public:
     LIR_HEADER(TableSwitchV);
 
-    LTableSwitchV(const LDefinition& inputCopy, const LDefinition& floatCopy,
-                  MTableSwitch* ins)
+    LTableSwitchV(const LBoxAllocation& input, const LDefinition& inputCopy,
+                  const LDefinition& floatCopy, MTableSwitch* ins)
     {
+        setBoxOperand(InputValue, input);
         setTemp(0, inputCopy);
         setTemp(1, floatCopy);
         setMir(ins);
     }
 
     MTableSwitch* mir() const {
         return mir_->toTableSwitch();
     }
--- a/js/src/jit/arm64/Lowering-arm64.cpp
+++ b/js/src/jit/arm64/Lowering-arm64.cpp
@@ -12,18 +12,18 @@
 
 #include "jit/shared/Lowering-shared-inl.h"
 
 using namespace js;
 using namespace js::jit;
 
 using mozilla::FloorLog2;
 
-void
-LIRGeneratorARM64::useBoxFixed(LInstruction* lir, size_t n, MDefinition* mir, Register reg1, Register,                               bool useAtStart)
+LBoxAllocation
+LIRGeneratorARM64::useBoxFixed(MDefinition* mir, Register reg1, Register, bool useAtStart)
 {
     MOZ_CRASH("useBoxFixed");
 }
 
 LAllocation
 LIRGeneratorARM64::useByteOpRegister(MDefinition* mir)
 {
     MOZ_CRASH("useByteOpRegister");
--- a/js/src/jit/arm64/Lowering-arm64.h
+++ b/js/src/jit/arm64/Lowering-arm64.h
@@ -15,20 +15,19 @@ namespace jit {
 class LIRGeneratorARM64 : public LIRGeneratorShared
 {
   public:
     LIRGeneratorARM64(MIRGenerator* gen, MIRGraph& graph, LIRGraph& lirGraph)
       : LIRGeneratorShared(gen, graph, lirGraph)
     { }
 
   protected:
-    // Adds a box input to an instruction, setting operand |n| to the type and
-    // |n+1| to the payload.
-    void useBoxFixed(LInstruction* lir, size_t n, MDefinition* mir, Register reg1, Register reg2,
-                     bool useAtStart = false);
+    // Returns a box allocation. reg2 is ignored on 64-bit platforms.
+    LBoxAllocation useBoxFixed(MDefinition* mir, Register reg1, Register reg2,
+                               bool useAtStart = false);
 
     LAllocation useByteOpRegister(MDefinition* mir);
     LAllocation useByteOpRegisterOrNonDoubleConstant(MDefinition* mir);
 
     inline LDefinition tempToUnbox() {
         return temp();
     }
 
--- a/js/src/jit/mips-shared/LIR-mips-shared.h
+++ b/js/src/jit/mips-shared/LIR-mips-shared.h
@@ -177,19 +177,21 @@ class LTableSwitch : public LInstruction
 };
 
 // Takes a tableswitch with an integer to decide
 class LTableSwitchV : public LInstructionHelper<0, BOX_PIECES, 3>
 {
   public:
     LIR_HEADER(TableSwitchV);
 
-    LTableSwitchV(const LDefinition& inputCopy, const LDefinition& floatCopy,
-                  const LDefinition& jumpTablePointer, MTableSwitch* ins)
+    LTableSwitchV(const LBoxAllocation& input, const LDefinition& inputCopy,
+                  const LDefinition& floatCopy, const LDefinition& jumpTablePointer,
+                  MTableSwitch* ins)
     {
+        setBoxOperand(InputValue, input);
         setTemp(0, inputCopy);
         setTemp(1, floatCopy);
         setTemp(2, jumpTablePointer);
         setMir(ins);
     }
 
     MTableSwitch* mir() const {
         return mir_->toTableSwitch();
--- a/js/src/jit/mips-shared/Lowering-mips-shared.cpp
+++ b/js/src/jit/mips-shared/Lowering-mips-shared.cpp
@@ -188,17 +188,18 @@ LIRGeneratorMIPSShared::newLTableSwitch(
                                         MTableSwitch* tableswitch)
 {
     return new(alloc()) LTableSwitch(in, inputCopy, temp(), tableswitch);
 }
 
 LTableSwitchV*
 LIRGeneratorMIPSShared::newLTableSwitchV(MTableSwitch* tableswitch)
 {
-    return new(alloc()) LTableSwitchV(temp(), tempDouble(), temp(), tableswitch);
+    return new(alloc()) LTableSwitchV(useBox(tableswitch->getOperand(0)),
+                                      temp(), tempDouble(), temp(), tableswitch);
 }
 
 void
 LIRGeneratorMIPSShared::visitGuardShape(MGuardShape* ins)
 {
     MOZ_ASSERT(ins->obj()->type() == MIRType_Object);
 
     LDefinition tempObj = temp(LDefinition::OBJECT);
--- a/js/src/jit/mips32/LIR-mips32.h
+++ b/js/src/jit/mips32/LIR-mips32.h
@@ -55,19 +55,21 @@ class LUnboxFloatingPoint : public LInst
 {
     MIRType type_;
 
   public:
     LIR_HEADER(UnboxFloatingPoint);
 
     static const size_t Input = 0;
 
-    LUnboxFloatingPoint(MIRType type)
+    LUnboxFloatingPoint(const LBoxAllocation& input, MIRType type)
       : type_(type)
-    { }
+    {
+        setBoxOperand(Input, input);
+    }
 
     MUnbox* mir() const {
         return mir_->toUnbox();
     }
 
     MIRType type() const {
         return type_;
     }
--- a/js/src/jit/mips32/Lowering-mips32.cpp
+++ b/js/src/jit/mips32/Lowering-mips32.cpp
@@ -10,26 +10,25 @@
 
 #include "jit/MIR.h"
 
 #include "jit/shared/Lowering-shared-inl.h"
 
 using namespace js;
 using namespace js::jit;
 
-void
-LIRGeneratorMIPS::useBoxFixed(LInstruction* lir, size_t n, MDefinition* mir, Register reg1,
-                              Register reg2, bool useAtStart)
+LBoxAllocation
+LIRGeneratorMIPS::useBoxFixed(MDefinition* mir, Register reg1, Register reg2, bool useAtStart)
 {
     MOZ_ASSERT(mir->type() == MIRType_Value);
     MOZ_ASSERT(reg1 != reg2);
 
     ensureDefined(mir);
-    lir->setOperand(n, LUse(reg1, mir->virtualRegister(), useAtStart));
-    lir->setOperand(n + 1, LUse(reg2, VirtualRegisterOfPayload(mir), useAtStart));
+    return LBoxAllocation(LUse(reg1, mir->virtualRegister(), useAtStart),
+                          LUse(reg2, VirtualRegisterOfPayload(mir), useAtStart));
 }
 
 void
 LIRGeneratorMIPS::visitBox(MBox* box)
 {
     MDefinition* inner = box->getOperand(0);
 
     // If the box wrapped a double, it needs a new register.
@@ -83,20 +82,19 @@ LIRGeneratorMIPS::visitUnbox(MUnbox* unb
     // An unbox on mips reads in a type tag (either in memory or a register) and
     // a payload. Unlike most instructions consuming a box, we ask for the type
     // second, so that the result can re-use the first input.
     MOZ_ASSERT(inner->type() == MIRType_Value);
 
     ensureDefined(inner);
 
     if (IsFloatingPointType(unbox->type())) {
-        LUnboxFloatingPoint* lir = new(alloc()) LUnboxFloatingPoint(unbox->type());
+        LUnboxFloatingPoint* lir = new(alloc()) LUnboxFloatingPoint(useBox(inner), unbox->type());
         if (unbox->fallible())
             assignSnapshot(lir, unbox->bailoutKind());
-        useBox(lir, LUnboxFloatingPoint::Input, inner);
         define(lir, unbox);
         return;
     }
 
     // Swap the order we use the box pieces so we can re-use the payload
     // register.
     LUnbox* lir = new(alloc()) LUnbox;
     lir->setOperand(0, usePayloadInRegisterAtStart(inner));
--- a/js/src/jit/mips32/Lowering-mips32.h
+++ b/js/src/jit/mips32/Lowering-mips32.h
@@ -15,20 +15,19 @@ namespace jit {
 class LIRGeneratorMIPS : public LIRGeneratorMIPSShared
 {
   protected:
     LIRGeneratorMIPS(MIRGenerator* gen, MIRGraph& graph, LIRGraph& lirGraph)
       : LIRGeneratorMIPSShared(gen, graph, lirGraph)
     { }
 
   protected:
-    // Adds a box input to an instruction, setting operand |n| to the type and
-    // |n+1| to the payload.
-    void useBoxFixed(LInstruction* lir, size_t n, MDefinition* mir, Register reg1, Register reg2,
-                     bool useAtStart = false);
+    // Returns a box allocation with type set to reg1 and payload set to reg2.
+    LBoxAllocation useBoxFixed(MDefinition* mir, Register reg1, Register reg2,
+                               bool useAtStart = false);
 
     inline LDefinition tempToUnbox() {
         return LDefinition::BogusTemp();
     }
 
     void lowerUntypedPhiInput(MPhi* phi, uint32_t inputPosition, LBlock* block, size_t lirIndex);
     void defineUntypedPhi(MPhi* phi, size_t lirIndex);
 
--- a/js/src/jit/mips64/Lowering-mips64.cpp
+++ b/js/src/jit/mips64/Lowering-mips64.cpp
@@ -10,24 +10,23 @@
 
 #include "jit/MIR.h"
 
 #include "jit/shared/Lowering-shared-inl.h"
 
 using namespace js;
 using namespace js::jit;
 
-void
-LIRGeneratorMIPS64::useBoxFixed(LInstruction* lir, size_t n, MDefinition* mir, Register reg1,
-                                Register reg2, bool useAtStart)
+LBoxAllocation
+LIRGeneratorMIPS64::useBoxFixed(MDefinition* mir, Register reg1, Register reg2, bool useAtStart)
 {
     MOZ_ASSERT(mir->type() == MIRType_Value);
 
     ensureDefined(mir);
-    lir->setOperand(n, LUse(reg1, mir->virtualRegister(), useAtStart));
+    return LBoxAllocation(LUse(reg1, mir->virtualRegister(), useAtStart));
 }
 
 void
 LIRGeneratorMIPS64::visitBox(MBox* box)
 {
     MDefinition* opd = box->getOperand(0);
 
     // If the operand is a constant, emit near its uses.
--- a/js/src/jit/mips64/Lowering-mips64.h
+++ b/js/src/jit/mips64/Lowering-mips64.h
@@ -15,20 +15,19 @@ namespace jit {
 class LIRGeneratorMIPS64 : public LIRGeneratorMIPSShared
 {
   protected:
     LIRGeneratorMIPS64(MIRGenerator* gen, MIRGraph& graph, LIRGraph& lirGraph)
       : LIRGeneratorMIPSShared(gen, graph, lirGraph)
     { }
 
   protected:
-    // Adds a box input to an instruction, setting operand |n| to the type and
-    // |n+1| to the payload.
-    void useBoxFixed(LInstruction* lir, size_t n, MDefinition* mir, Register reg1, Register reg2,
-                     bool useAtStart = false);
+    // Returns a box allocation. reg2 is ignored on 64-bit platforms.
+    LBoxAllocation useBoxFixed(MDefinition* mir, Register reg1, Register reg2,
+                               bool useAtStart = false);
 
     inline LDefinition tempToUnbox() {
         return temp();
     }
 
     void lowerUntypedPhiInput(MPhi* phi, uint32_t inputPosition, LBlock* block, size_t lirIndex);
     void defineUntypedPhi(MPhi* phi, size_t lirIndex);
 
--- a/js/src/jit/none/Lowering-none.h
+++ b/js/src/jit/none/Lowering-none.h
@@ -16,17 +16,17 @@ class LIRGeneratorNone : public LIRGener
 {
   public:
     LIRGeneratorNone(MIRGenerator* gen, MIRGraph& graph, LIRGraph& lirGraph)
       : LIRGeneratorShared(gen, graph, lirGraph)
     {
         MOZ_CRASH();
     }
 
-    void useBoxFixed(LInstruction*, size_t, MDefinition*, Register, Register, bool useAtStart = false) { MOZ_CRASH(); }
+    LBoxAllocation useBoxFixed(MDefinition*, Register, Register, bool useAtStart = false) { MOZ_CRASH(); }
 
     LAllocation useByteOpRegister(MDefinition*) { MOZ_CRASH(); }
     LAllocation useByteOpRegisterOrNonDoubleConstant(MDefinition*) { MOZ_CRASH(); }
     LDefinition tempByteOpRegister() { MOZ_CRASH(); }
     LDefinition tempToUnbox() { MOZ_CRASH(); }
     bool needTempForPostBarrier() { MOZ_CRASH(); }
     void lowerUntypedPhiInput(MPhi*, uint32_t, LBlock*, size_t) { MOZ_CRASH(); }
     void defineUntypedPhi(MPhi*, size_t) { MOZ_CRASH(); }
--- a/js/src/jit/shared/LIR-shared.h
+++ b/js/src/jit/shared/LIR-shared.h
@@ -1082,18 +1082,20 @@ class LNewStringObject : public LInstruc
     }
 };
 
 class LInitElem : public LCallInstructionHelper<0, 1 + 2*BOX_PIECES, 0>
 {
   public:
     LIR_HEADER(InitElem)
 
-    explicit LInitElem(const LAllocation& object) {
+    LInitElem(const LAllocation& object, const LBoxAllocation& id, const LBoxAllocation& value) {
         setOperand(0, object);
+        setBoxOperand(IdIndex, id);
+        setBoxOperand(ValueIndex, value);
     }
 
     static const size_t IdIndex = 1;
     static const size_t ValueIndex = 1 + BOX_PIECES;
 
     const LAllocation* getObject() {
         return getOperand(0);
     }
@@ -1102,19 +1104,21 @@ class LInitElem : public LCallInstructio
     }
 };
 
 class LInitElemGetterSetter : public LCallInstructionHelper<0, 2 + BOX_PIECES, 0>
 {
   public:
     LIR_HEADER(InitElemGetterSetter)
 
-    LInitElemGetterSetter(const LAllocation& object, const LAllocation& value) {
+    LInitElemGetterSetter(const LAllocation& object, const LBoxAllocation& id,
+                          const LAllocation& value) {
         setOperand(0, object);
         setOperand(1, value);
+        setBoxOperand(IdIndex, id);
     }
 
     static const size_t IdIndex = 2;
 
     const LAllocation* object() {
         return getOperand(0);
     }
     const LAllocation* value() {
@@ -1126,18 +1130,19 @@ class LInitElemGetterSetter : public LCa
 };
 
 // Takes in an Object and a Value.
 class LMutateProto : public LCallInstructionHelper<0, 1 + BOX_PIECES, 0>
 {
   public:
     LIR_HEADER(MutateProto)
 
-    explicit LMutateProto(const LAllocation& object) {
+    LMutateProto(const LAllocation& object, const LBoxAllocation& value) {
         setOperand(0, object);
+        setBoxOperand(ValueIndex, value);
     }
 
     static const size_t ValueIndex = 1;
 
     const LAllocation* getObject() {
         return getOperand(0);
     }
     const LAllocation* getValue() {
@@ -1146,18 +1151,19 @@ class LMutateProto : public LCallInstruc
 };
 
 // Takes in an Object and a Value.
 class LInitProp : public LCallInstructionHelper<0, 1 + BOX_PIECES, 0>
 {
   public:
     LIR_HEADER(InitProp)
 
-    explicit LInitProp(const LAllocation& object) {
+    LInitProp(const LAllocation& object, const LBoxAllocation& value) {
         setOperand(0, object);
+        setBoxOperand(ValueIndex, value);
     }
 
     static const size_t ValueIndex = 1;
 
     const LAllocation* getObject() {
         return getOperand(0);
     }
     const LAllocation* getValue() {
@@ -1301,17 +1307,18 @@ class LDefFun : public LCallInstructionH
     }
 };
 
 class LTypeOfV : public LInstructionHelper<1, BOX_PIECES, 1>
 {
   public:
     LIR_HEADER(TypeOfV)
 
-    explicit LTypeOfV(const LDefinition& tempToUnbox) {
+    LTypeOfV(const LBoxAllocation& input, const LDefinition& tempToUnbox) {
+        setBoxOperand(Input, input);
         setTemp(0, tempToUnbox);
     }
 
     static const size_t Input = 0;
 
     const LDefinition* tempToUnbox() {
         return getTemp(0);
     }
@@ -1321,22 +1328,23 @@ class LTypeOfV : public LInstructionHelp
     }
 };
 
 class LToIdV : public LInstructionHelper<BOX_PIECES, BOX_PIECES, 1>
 {
   public:
     LIR_HEADER(ToIdV)
 
-    explicit LToIdV(const LDefinition& temp)
+    LToIdV(const LBoxAllocation& input, const LDefinition& temp)
     {
+        setBoxOperand(Input, input);
         setTemp(0, temp);
     }
 
-    static const size_t Index = 0;
+    static const size_t Input = 0;
 
     MToId* mir() const {
         return mir_->toToId();
     }
 
     const LDefinition* tempFloat() {
         return getTemp(0);
     }
@@ -1460,19 +1468,21 @@ class LGetArgumentsObjectArg : public LI
 };
 
 // Set argument on arguments object.
 class LSetArgumentsObjectArg : public LInstructionHelper<0, 1 + BOX_PIECES, 1>
 {
   public:
     LIR_HEADER(SetArgumentsObjectArg)
 
-    LSetArgumentsObjectArg(const LAllocation& argsObj, const LDefinition& temp)
+    LSetArgumentsObjectArg(const LAllocation& argsObj, const LBoxAllocation& value,
+                           const LDefinition& temp)
     {
         setOperand(0, argsObj);
+        setBoxOperand(ValueIndex, value);
         setTemp(0, temp);
     }
 
     const LAllocation* getArgsObject() {
         return getOperand(0);
     }
 
     MSetArgumentsObjectArg* mir() const {
@@ -1484,37 +1494,41 @@ class LSetArgumentsObjectArg : public LI
 
 // If the Value is an Object, return unbox(Value).
 // Otherwise, return the other Object.
 class LReturnFromCtor : public LInstructionHelper<1, BOX_PIECES + 1, 0>
 {
   public:
     LIR_HEADER(ReturnFromCtor)
 
-    explicit LReturnFromCtor(const LAllocation& object)
+    LReturnFromCtor(const LBoxAllocation& value, const LAllocation& object)
     {
-        // Value set by useBox() during lowering.
-        setOperand(LReturnFromCtor::ObjectIndex, object);
+        setBoxOperand(ValueIndex, value);
+        setOperand(ObjectIndex, object);
     }
 
     const LAllocation* getObject() {
-        return getOperand(LReturnFromCtor::ObjectIndex);
+        return getOperand(ObjectIndex);
     }
 
     static const size_t ValueIndex = 0;
     static const size_t ObjectIndex = BOX_PIECES;
 };
 
 class LComputeThis : public LInstructionHelper<BOX_PIECES, BOX_PIECES, 0>
 {
   public:
     LIR_HEADER(ComputeThis)
 
     static const size_t ValueIndex = 0;
 
+    explicit LComputeThis(const LBoxAllocation& value) {
+        setBoxOperand(ValueIndex, value);
+    }
+
     const LDefinition* output() {
         return getDef(0);
     }
 
     MComputeThis* mir() const {
         return mir_->toComputeThis();
     }
 };
@@ -1548,19 +1562,21 @@ class LStackArgT : public LInstructionHe
 // Writes an untyped argument for a function call to the frame's argument vector.
 class LStackArgV : public LInstructionHelper<0, BOX_PIECES, 0>
 {
     uint32_t argslot_; // Index into frame-scope argument vector.
 
   public:
     LIR_HEADER(StackArgV)
 
-    explicit LStackArgV(uint32_t argslot)
+    LStackArgV(uint32_t argslot, const LBoxAllocation& value)
       : argslot_(argslot)
-    { }
+    {
+        setBoxOperand(0, value);
+    }
 
     uint32_t argslot() const {
         return argslot_;
     }
 };
 
 // Common code for LIR descended from MCall.
 template <size_t Defs, size_t Operands, size_t Temps>
@@ -1798,40 +1814,45 @@ class LGetDOMMemberT : public LInstructi
 };
 
 class LSetDOMProperty : public LDOMPropertyInstructionHelper<0, BOX_PIECES>
 {
   public:
     LIR_HEADER(SetDOMProperty)
 
     LSetDOMProperty(const LDefinition& JSContextReg, const LAllocation& ObjectReg,
-                    const LDefinition& PrivReg, const LDefinition& ValueReg)
+                    const LBoxAllocation& value, const LDefinition& PrivReg,
+                    const LDefinition& ValueReg)
       : LDOMPropertyInstructionHelper<0, BOX_PIECES>(JSContextReg, ObjectReg,
                                                      PrivReg, ValueReg)
-    { }
+    {
+        setBoxOperand(Value, value);
+    }
 
     static const size_t Value = 1;
 
     MSetDOMProperty* mir() const {
         return mir_->toSetDOMProperty();
     }
 };
 
 // Generates a polymorphic callsite, wherein the function being called is
 // unknown and anticipated to vary.
 class LApplyArgsGeneric : public LCallInstructionHelper<BOX_PIECES, BOX_PIECES + 2, 2>
 {
   public:
     LIR_HEADER(ApplyArgsGeneric)
 
     LApplyArgsGeneric(const LAllocation& func, const LAllocation& argc,
-                      const LDefinition& tmpobjreg, const LDefinition& tmpcopy)
+                      const LBoxAllocation& thisv, const LDefinition& tmpobjreg,
+                      const LDefinition& tmpcopy)
     {
         setOperand(0, func);
         setOperand(1, argc);
+        setBoxOperand(ThisIndex, thisv);
         setTemp(0, tmpobjreg);
         setTemp(1, tmpcopy);
     }
 
     MApplyArgs* mir() const {
         return mir_->toApplyArgs();
     }
 
@@ -1859,20 +1880,22 @@ class LApplyArgsGeneric : public LCallIn
 };
 
 class LApplyArrayGeneric : public LCallInstructionHelper<BOX_PIECES, BOX_PIECES + 2, 2>
 {
   public:
     LIR_HEADER(ApplyArrayGeneric)
 
     LApplyArrayGeneric(const LAllocation& func, const LAllocation& elements,
-                       const LDefinition& tmpobjreg, const LDefinition& tmpcopy)
+                       const LBoxAllocation& thisv, const LDefinition& tmpobjreg,
+                       const LDefinition& tmpcopy)
     {
         setOperand(0, func);
         setOperand(1, elements);
+        setBoxOperand(ThisIndex, thisv);
         setTemp(0, tmpobjreg);
         setTemp(1, tmpcopy);
     }
 
     MApplyArray* mir() const {
         return mir_->toApplyArray();
     }
 
@@ -1969,20 +1992,22 @@ class LGetDynamicName : public LCallInst
     }
 };
 
 class LCallDirectEval : public LCallInstructionHelper<BOX_PIECES, 2 + (2 * BOX_PIECES), 0>
 {
   public:
     LIR_HEADER(CallDirectEval)
 
-    LCallDirectEval(const LAllocation& scopeChain, const LAllocation& string)
+    LCallDirectEval(const LAllocation& scopeChain, const LAllocation& string,
+                    const LBoxAllocation& newTarget)
     {
         setOperand(0, scopeChain);
         setOperand(1, string);
+        setBoxOperand(NewTarget, newTarget);
     }
 
     static const size_t ThisValue = 2;
     static const size_t NewTarget = 2 + BOX_PIECES;
 
     MCallDirectEval* mir() const {
         return mir_->toCallDirectEval();
     }
@@ -2091,21 +2116,22 @@ class LTestOAndBranch : public LControlI
 };
 
 // Takes in a boxed value and tests it for truthiness.
 class LTestVAndBranch : public LControlInstructionHelper<2, BOX_PIECES, 3>
 {
   public:
     LIR_HEADER(TestVAndBranch)
 
-    LTestVAndBranch(MBasicBlock* ifTruthy, MBasicBlock* ifFalsy, const LDefinition& temp0,
-                    const LDefinition& temp1, const LDefinition& temp2)
+    LTestVAndBranch(MBasicBlock* ifTruthy, MBasicBlock* ifFalsy, const LBoxAllocation& input,
+                    const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2)
     {
         setSuccessor(0, ifTruthy);
         setSuccessor(1, ifFalsy);
+        setBoxOperand(Input, input);
         setTemp(0, temp0);
         setTemp(1, temp1);
         setTemp(2, temp2);
     }
 
     const char* extraName() const {
         return mir()->operandMightEmulateUndefined() ? "MightEmulateUndefined" : nullptr;
     }
@@ -2391,17 +2417,18 @@ class LCompareS : public LInstructionHel
     }
 };
 
 // strict-equality between value and string.
 class LCompareStrictS : public LInstructionHelper<1, BOX_PIECES + 1, 1>
 {
   public:
     LIR_HEADER(CompareStrictS)
-    LCompareStrictS(const LAllocation& rhs, const LDefinition& temp) {
+    LCompareStrictS(const LBoxAllocation& lhs, const LAllocation& rhs, const LDefinition& temp) {
+        setBoxOperand(Lhs, lhs);
         setOperand(BOX_PIECES, rhs);
         setTemp(0, temp);
     }
 
     static const size_t Lhs = 0;
 
     const LAllocation* right() {
         return getOperand(BOX_PIECES);
@@ -2417,17 +2444,18 @@ class LCompareStrictS : public LInstruct
 // Used for strict-equality comparisons where one side is a boolean
 // and the other is a value. Note that CompareI is used to compare
 // two booleans.
 class LCompareB : public LInstructionHelper<1, BOX_PIECES + 1, 0>
 {
   public:
     LIR_HEADER(CompareB)
 
-    explicit LCompareB(const LAllocation& rhs) {
+    LCompareB(const LBoxAllocation& lhs, const LAllocation& rhs) {
+        setBoxOperand(Lhs, lhs);
         setOperand(BOX_PIECES, rhs);
     }
 
     static const size_t Lhs = 0;
 
     const LAllocation* rhs() {
         return getOperand(BOX_PIECES);
     }
@@ -2439,20 +2467,21 @@ class LCompareB : public LInstructionHel
 
 class LCompareBAndBranch : public LControlInstructionHelper<2, BOX_PIECES + 1, 0>
 {
     MCompare* cmpMir_;
 
   public:
     LIR_HEADER(CompareBAndBranch)
 
-    LCompareBAndBranch(MCompare* cmpMir, const LAllocation& rhs,
+    LCompareBAndBranch(MCompare* cmpMir, const LBoxAllocation& lhs, const LAllocation& rhs,
                        MBasicBlock* ifTrue, MBasicBlock* ifFalse)
       : cmpMir_(cmpMir)
     {
+        setBoxOperand(Lhs, lhs);
         setOperand(BOX_PIECES, rhs);
         setSuccessor(0, ifTrue);
         setSuccessor(1, ifFalse);
     }
 
     static const size_t Lhs = 0;
 
     const LAllocation* rhs() {
@@ -2476,36 +2505,44 @@ class LCompareBAndBranch : public LContr
 class LCompareBitwise : public LInstructionHelper<1, 2 * BOX_PIECES, 0>
 {
   public:
     LIR_HEADER(CompareBitwise)
 
     static const size_t LhsInput = 0;
     static const size_t RhsInput = BOX_PIECES;
 
+    LCompareBitwise(const LBoxAllocation& lhs, const LBoxAllocation& rhs) {
+        setBoxOperand(LhsInput, lhs);
+        setBoxOperand(RhsInput, rhs);
+    }
+
     MCompare* mir() const {
         return mir_->toCompare();
     }
 };
 
 class LCompareBitwiseAndBranch : public LControlInstructionHelper<2, 2 * BOX_PIECES, 0>
 {
     MCompare* cmpMir_;
 
   public:
     LIR_HEADER(CompareBitwiseAndBranch)
 
     static const size_t LhsInput = 0;
     static const size_t RhsInput = BOX_PIECES;
 
-    LCompareBitwiseAndBranch(MCompare* cmpMir, MBasicBlock* ifTrue, MBasicBlock* ifFalse)
+    LCompareBitwiseAndBranch(MCompare* cmpMir, MBasicBlock* ifTrue, MBasicBlock* ifFalse,
+                             const LBoxAllocation& lhs, const LBoxAllocation& rhs)
       : cmpMir_(cmpMir)
     {
         setSuccessor(0, ifTrue);
         setSuccessor(1, ifFalse);
+        setBoxOperand(LhsInput, lhs);
+        setBoxOperand(RhsInput, rhs);
     }
 
     MBasicBlock* ifTrue() const {
         return getSuccessor(0);
     }
     MBasicBlock* ifFalse() const {
         return getSuccessor(1);
     }
@@ -2520,16 +2557,21 @@ class LCompareBitwiseAndBranch : public 
 class LCompareVM : public LCallInstructionHelper<1, 2 * BOX_PIECES, 0>
 {
   public:
     LIR_HEADER(CompareVM)
 
     static const size_t LhsInput = 0;
     static const size_t RhsInput = BOX_PIECES;
 
+    LCompareVM(const LBoxAllocation& lhs, const LBoxAllocation& rhs) {
+        setBoxOperand(LhsInput, lhs);
+        setBoxOperand(RhsInput, rhs);
+    }
+
     MCompare* mir() const {
         return mir_->toCompare();
     }
 };
 
 class LBitAndAndBranch : public LControlInstructionHelper<2, 2, 0>
 {
   public:
@@ -2557,18 +2599,20 @@ class LBitAndAndBranch : public LControl
 // Takes a value and tests whether it is null, undefined, or is an object that
 // emulates |undefined|, as determined by the JSCLASS_EMULATES_UNDEFINED class
 // flag on unwrapped objects.  See also js::EmulatesUndefined.
 class LIsNullOrLikeUndefinedV : public LInstructionHelper<1, BOX_PIECES, 2>
 {
   public:
     LIR_HEADER(IsNullOrLikeUndefinedV)
 
-    LIsNullOrLikeUndefinedV(const LDefinition& temp, const LDefinition& tempToUnbox)
+    LIsNullOrLikeUndefinedV(const LBoxAllocation& value, const LDefinition& temp,
+                            const LDefinition& tempToUnbox)
     {
+        setBoxOperand(Value, value);
         setTemp(0, temp);
         setTemp(1, tempToUnbox);
     }
 
     static const size_t Value = 0;
 
     MCompare* mir() {
         return mir_->toCompare();
@@ -2603,21 +2647,23 @@ class LIsNullOrLikeUndefinedT : public L
 class LIsNullOrLikeUndefinedAndBranchV : public LControlInstructionHelper<2, BOX_PIECES, 2>
 {
     MCompare* cmpMir_;
 
   public:
     LIR_HEADER(IsNullOrLikeUndefinedAndBranchV)
 
     LIsNullOrLikeUndefinedAndBranchV(MCompare* cmpMir, MBasicBlock* ifTrue, MBasicBlock* ifFalse,
-                                     const LDefinition& temp, const LDefinition& tempToUnbox)
+                                     const LBoxAllocation& value, const LDefinition& temp,
+                                     const LDefinition& tempToUnbox)
       : cmpMir_(cmpMir)
     {
         setSuccessor(0, ifTrue);
         setSuccessor(1, ifFalse);
+        setBoxOperand(Value, value);
         setTemp(0, temp);
         setTemp(1, tempToUnbox);
     }
 
     static const size_t Value = 0;
 
     MBasicBlock* ifTrue() const {
         return getSuccessor(0);
@@ -2733,18 +2779,20 @@ class LNotO : public LInstructionHelper<
 
 // Boolean complement operation on a value.
 class LNotV : public LInstructionHelper<1, BOX_PIECES, 3>
 {
   public:
     LIR_HEADER(NotV)
 
     static const size_t Input = 0;
-    LNotV(const LDefinition& temp0, const LDefinition& temp1, const LDefinition& temp2)
+    LNotV(const LBoxAllocation& input, const LDefinition& temp0, const LDefinition& temp1,
+          const LDefinition& temp2)
     {
+        setBoxOperand(Input, input);
         setTemp(0, temp0);
         setTemp(1, temp1);
         setTemp(2, temp2);
     }
 
     const LDefinition* tempFloat() {
         return getTemp(0);
     }
@@ -2772,16 +2820,20 @@ class LBitNotI : public LInstructionHelp
 
 // Call a VM function to perform a BITNOT operation.
 class LBitNotV : public LCallInstructionHelper<1, BOX_PIECES, 0>
 {
   public:
     LIR_HEADER(BitNotV)
 
     static const size_t Input = 0;
+
+    explicit LBitNotV(const LBoxAllocation& input) {
+        setBoxOperand(Input, input);
+    }
 };
 
 // Binary bitwise operation, taking two 32-bit integers as inputs and returning
 // a 32-bit integer result as an output.
 class LBitOpI : public LInstructionHelper<1, 2, 0>
 {
     JSOp op_;
 
@@ -2806,19 +2858,22 @@ class LBitOpI : public LInstructionHelpe
 // Call a VM function to perform a bitwise operation.
 class LBitOpV : public LCallInstructionHelper<1, 2 * BOX_PIECES, 0>
 {
     JSOp jsop_;
 
   public:
     LIR_HEADER(BitOpV)
 
-    explicit LBitOpV(JSOp jsop)
+    LBitOpV(JSOp jsop, const LBoxAllocation& lhs, const LBoxAllocation& rhs)
       : jsop_(jsop)
-    { }
+    {
+        setBoxOperand(LhsInput, lhs);
+        setBoxOperand(RhsInput, rhs);
+    }
 
     JSOp jsop() const {
         return jsop_;
     }
 
     const char* extraName() const {
         return CodeName[jsop_];
     }
@@ -2877,16 +2932,20 @@ class LReturn : public LInstructionHelpe
 };
 
 class LThrow : public LCallInstructionHelper<0, BOX_PIECES, 0>
 {
   public:
     LIR_HEADER(Throw)
 
     static const size_t Value = 0;
+
+    explicit LThrow(const LBoxAllocation& value) {
+        setBoxOperand(Value, value);
+    }
 };
 
 class LMinMaxBase : public LInstructionHelper<1, 2, 0>
 {
   protected:
     LMinMaxBase(const LAllocation& first, const LAllocation& second)
     {
         setOperand(0, first);
@@ -3309,19 +3368,22 @@ class LModD : public LBinaryMath<1>
 // Call a VM function to perform a binary operation.
 class LBinaryV : public LCallInstructionHelper<BOX_PIECES, 2 * BOX_PIECES, 0>
 {
     JSOp jsop_;
 
   public:
     LIR_HEADER(BinaryV)
 
-    explicit LBinaryV(JSOp jsop)
+    LBinaryV(JSOp jsop, const LBoxAllocation& lhs, const LBoxAllocation& rhs)
       : jsop_(jsop)
-    { }
+    {
+        setBoxOperand(LhsInput, lhs);
+        setBoxOperand(RhsInput, rhs);
+    }
 
     JSOp jsop() const {
         return jsop_;
     }
 
     const char* extraName() const {
         return CodeName[jsop_];
     }
@@ -3542,28 +3604,36 @@ class LInt32ToFloat32 : public LInstruct
 
 // Convert a value to a double.
 class LValueToDouble : public LInstructionHelper<1, BOX_PIECES, 0>
 {
   public:
     LIR_HEADER(ValueToDouble)
     static const size_t Input = 0;
 
+    explicit LValueToDouble(const LBoxAllocation& input) {
+        setBoxOperand(Input, input);
+    }
+
     MToDouble* mir() {
         return mir_->toToDouble();
     }
 };
 
 // Convert a value to a float32.
 class LValueToFloat32 : public LInstructionHelper<1, BOX_PIECES, 0>
 {
   public:
     LIR_HEADER(ValueToFloat32)
     static const size_t Input = 0;
 
+    explicit LValueToFloat32(const LBoxAllocation& input) {
+        setBoxOperand(Input, input);
+    }
+
     MToFloat32* mir() {
         return mir_->toToFloat32();
     }
 };
 
 // Convert a value to an int32.
 //   Input: components of a Value
 //   Output: 32-bit integer
@@ -3580,19 +3650,21 @@ class LValueToInt32 : public LInstructio
     };
 
   private:
     Mode mode_;
 
   public:
     LIR_HEADER(ValueToInt32)
 
-    LValueToInt32(const LDefinition& temp0, const LDefinition& temp1, Mode mode)
+    LValueToInt32(const LBoxAllocation& input, const LDefinition& temp0, const LDefinition& temp1,
+                  Mode mode)
       : mode_(mode)
     {
+        setBoxOperand(Input, input);
         setTemp(0, temp0);
         setTemp(1, temp1);
     }
 
     const char* extraName() const {
         return mode() == NORMAL ? "Normal" : "Truncate";
     }
 
@@ -3750,18 +3822,19 @@ class LDoubleToString : public LInstruct
 };
 
 // Convert a primitive to a string with a function call.
 class LValueToString : public LInstructionHelper<1, BOX_PIECES, 1>
 {
   public:
     LIR_HEADER(ValueToString)
 
-    explicit LValueToString(const LDefinition& tempToUnbox)
+    LValueToString(const LBoxAllocation& input, const LDefinition& tempToUnbox)
     {
+        setBoxOperand(Input, input);
         setTemp(0, tempToUnbox);
     }
 
     static const size_t Input = 0;
 
     const MToString* mir() {
         return mir_->toToString();
     }
@@ -3772,18 +3845,19 @@ class LValueToString : public LInstructi
 };
 
 // Convert a value to an object or null pointer.
 class LValueToObjectOrNull : public LInstructionHelper<1, BOX_PIECES, 0>
 {
   public:
     LIR_HEADER(ValueToObjectOrNull)
 
-    explicit LValueToObjectOrNull()
-    {}
+    explicit LValueToObjectOrNull(const LBoxAllocation& input) {
+        setBoxOperand(Input, input);
+    }
 
     static const size_t Input = 0;
 
     const MToObjectOrNull* mir() {
         return mir_->toToObjectOrNull();
     }
 };
 
@@ -4088,29 +4162,38 @@ class LStringReplace: public LStrReplace
     }
 };
 
 class LBinarySharedStub : public LCallInstructionHelper<BOX_PIECES, 2 * BOX_PIECES, 0>
 {
   public:
     LIR_HEADER(BinarySharedStub)
 
+    LBinarySharedStub(const LBoxAllocation& lhs, const LBoxAllocation& rhs) {
+        setBoxOperand(LhsInput, lhs);
+        setBoxOperand(RhsInput, rhs);
+    }
+
     const MBinarySharedStub* mir() const {
         return mir_->toBinarySharedStub();
     }
 
     static const size_t LhsInput = 0;
     static const size_t RhsInput = BOX_PIECES;
 };
 
 class LUnarySharedStub : public LCallInstructionHelper<BOX_PIECES, BOX_PIECES, 0>
 {
   public:
     LIR_HEADER(UnarySharedStub)
 
+    explicit LUnarySharedStub(const LBoxAllocation& input) {
+        setBoxOperand(Input, input);
+    }
+
     const MUnarySharedStub* mir() const {
         return mir_->toUnarySharedStub();
     }
 
     static const size_t Input = 0;
 };
 
 class LLambdaForSingleton : public LCallInstructionHelper<1, 1, 0>
@@ -4152,18 +4235,19 @@ class LLambda : public LInstructionHelpe
 
 class LLambdaArrow : public LInstructionHelper<1, 1 + BOX_PIECES, 0>
 {
   public:
     LIR_HEADER(LambdaArrow)
 
     static const size_t NewTargetValue = 1;
 
-    explicit LLambdaArrow(const LAllocation& scopeChain) {
+    LLambdaArrow(const LAllocation& scopeChain, const LBoxAllocation& newTarget) {
         setOperand(0, scopeChain);
+        setBoxOperand(NewTargetValue, newTarget);
     }
     const LAllocation* scopeChain() {
         return getOperand(0);
     }
     const MLambdaArrow* mir() const {
         return mir_->toLambdaArrow();
     }
 };
@@ -4790,19 +4874,21 @@ class LUnboxObjectOrNull : public LInstr
 };
 
 // Store a boxed value to a dense array's element vector.
 class LStoreElementV : public LInstructionHelper<0, 2 + BOX_PIECES, 0>
 {
   public:
     LIR_HEADER(StoreElementV)
 
-    LStoreElementV(const LAllocation& elements, const LAllocation& index) {
+    LStoreElementV(const LAllocation& elements, const LAllocation& index,
+                   const LBoxAllocation& value) {
         setOperand(0, elements);
         setOperand(1, index);
+        setBoxOperand(Value, value);
     }
 
     const char* extraName() const {
         return mir()->needsHoleCheck() ? "HoleCheck" : nullptr;
     }
 
     static const size_t Value = 2;
 
@@ -4852,20 +4938,22 @@ class LStoreElementT : public LInstructi
 
 // Like LStoreElementV, but supports indexes >= initialized length.
 class LStoreElementHoleV : public LInstructionHelper<0, 3 + BOX_PIECES, 1>
 {
   public:
     LIR_HEADER(StoreElementHoleV)
 
     LStoreElementHoleV(const LAllocation& object, const LAllocation& elements,
-                       const LAllocation& index, const LDefinition& temp) {
+                       const LAllocation& index, const LBoxAllocation& value,
+                       const LDefinition& temp) {
         setOperand(0, object);
         setOperand(1, elements);
         setOperand(2, index);
+        setBoxOperand(Value, value);
         setTemp(0, temp);
     }
 
     static const size_t Value = 3;
 
     const MStoreElementHole* mir() const {
         return mir_->toStoreElementHole();
     }
@@ -5014,18 +5102,19 @@ class LArrayPopShiftT : public LInstruct
     }
 };
 
 class LArrayPushV : public LInstructionHelper<1, 1 + BOX_PIECES, 1>
 {
   public:
     LIR_HEADER(ArrayPushV)
 
-    LArrayPushV(const LAllocation& object, const LDefinition& temp) {
+    LArrayPushV(const LAllocation& object, const LBoxAllocation& value, const LDefinition& temp) {
         setOperand(0, object);
+        setBoxOperand(Value, value);
         setTemp(0, temp);
     }
 
     static const size_t Value = 1;
 
     const MArrayPush* mir() const {
         return mir_->toArrayPush();
     }
@@ -5577,17 +5666,18 @@ class LClampDToUint8 : public LInstructi
     }
 };
 
 class LClampVToUint8 : public LInstructionHelper<1, BOX_PIECES, 1>
 {
   public:
     LIR_HEADER(ClampVToUint8)
 
-    explicit LClampVToUint8(const LDefinition& tempFloat) {
+    LClampVToUint8(const LBoxAllocation& input, const LDefinition& tempFloat) {
+        setBoxOperand(Input, input);
         setTemp(0, tempFloat);
     }
 
     static const size_t Input = 0;
 
     const LDefinition* tempFloat() {
         return getTemp(0);
     }
@@ -5639,18 +5729,19 @@ class LLoadFixedSlotAndUnbox : public LI
 };
 
 // Store a boxed value to an object's fixed slot.
 class LStoreFixedSlotV : public LInstructionHelper<0, 1 + BOX_PIECES, 0>
 {
   public:
     LIR_HEADER(StoreFixedSlotV)
 
-    explicit LStoreFixedSlotV(const LAllocation& obj) {
+    LStoreFixedSlotV(const LAllocation& obj, const LBoxAllocation& value) {
         setOperand(0, obj);
+        setBoxOperand(Value, value);
     }
 
     static const size_t Value = 1;
 
     const MStoreFixedSlot* mir() const {
         return mir_->toStoreFixedSlot();
     }
     const LAllocation* obj() {
@@ -5711,35 +5802,37 @@ class LCallGetIntrinsicValue : public LC
 // boxed value.
 class LGetPropertyCacheV : public LInstructionHelper<BOX_PIECES, 1 + BOX_PIECES, 0>
 {
   public:
     LIR_HEADER(GetPropertyCacheV)
 
     static const size_t Id = 1;
 
-    explicit LGetPropertyCacheV(const LAllocation& object) {
+    LGetPropertyCacheV(const LAllocation& object, const LBoxAllocation& id) {
         setOperand(0, object);
+        setBoxOperand(Id, id);
     }
     const MGetPropertyCache* mir() const {
         return mir_->toGetPropertyCache();
     }
 };
 
 // Patchable jump to stubs generated for a GetProperty cache, which loads a
 // value of a known type, possibly into an FP register.
 class LGetPropertyCacheT : public LInstructionHelper<1, 1 + BOX_PIECES, 0>
 {
   public:
     LIR_HEADER(GetPropertyCacheT)
 
     static const size_t Id = 1;
 
-    explicit LGetPropertyCacheT(const LAllocation& object) {
+    LGetPropertyCacheT(const LAllocation& object, const LBoxAllocation& id) {
         setOperand(0, object);
+        setBoxOperand(Id, id);
     }
     const MGetPropertyCache* mir() const {
         return mir_->toGetPropertyCache();
     }
 };
 
 // Emit code to load a boxed value from an object's slots if its shape matches
 // one of the shapes observed by the baseline IC, else bails out.
@@ -5783,18 +5876,20 @@ class LGetPropertyPolymorphicT : public 
 
 // Emit code to store a boxed value to an object's slots if its shape matches
 // one of the shapes observed by the baseline IC, else bails out.
 class LSetPropertyPolymorphicV : public LInstructionHelper<0, 1 + BOX_PIECES, 1>
 {
   public:
     LIR_HEADER(SetPropertyPolymorphicV)
 
-    LSetPropertyPolymorphicV(const LAllocation& obj, const LDefinition& temp) {
+    LSetPropertyPolymorphicV(const LAllocation& obj, const LBoxAllocation& value,
+                             const LDefinition& temp) {
         setOperand(0, obj);
+        setBoxOperand(Value, value);
         setTemp(0, temp);
     }
 
     static const size_t Value = 1;
 
     const LAllocation* obj() {
         return getOperand(0);
     }
@@ -5913,18 +6008,19 @@ class LLoadSlotT : public LInstructionHe
 };
 
 // Store a value to an object's dslots or a slots vector.
 class LStoreSlotV : public LInstructionHelper<0, 1 + BOX_PIECES, 0>
 {
   public:
     LIR_HEADER(StoreSlotV)
 
-    explicit LStoreSlotV(const LAllocation& slots) {
+    LStoreSlotV(const LAllocation& slots, const LBoxAllocation& value) {
         setOperand(0, slots);
+        setBoxOperand(Value, value);
     }
 
     static const size_t Value = 1;
 
     const MStoreSlot* mir() const {
         return mir_->toStoreSlot();
     }
     const LAllocation* slots() {
@@ -6071,114 +6167,148 @@ class LFunctionEnvironment : public LIns
 
 class LCallGetProperty : public LCallInstructionHelper<BOX_PIECES, BOX_PIECES, 0>
 {
   public:
     LIR_HEADER(CallGetProperty)
 
     static const size_t Value = 0;
 
+    explicit LCallGetProperty(const LBoxAllocation& val) {
+        setBoxOperand(Value, val);
+    }
+
     MCallGetProperty* mir() const {
         return mir_->toCallGetProperty();
     }
 };
 
 // Call js::GetElement.
 class LCallGetElement : public LCallInstructionHelper<BOX_PIECES, 2 * BOX_PIECES, 0>
 {
   public:
     LIR_HEADER(CallGetElement)
 
     static const size_t LhsInput = 0;
     static const size_t RhsInput = BOX_PIECES;
 
+    LCallGetElement(const LBoxAllocation& lhs, const LBoxAllocation& rhs) {
+        setBoxOperand(LhsInput, lhs);
+        setBoxOperand(RhsInput, rhs);
+    }
+
     MCallGetElement* mir() const {
         return mir_->toCallGetElement();
     }
 };
 
 // Call js::SetElement.
 class LCallSetElement : public LCallInstructionHelper<0, 1 + 2 * BOX_PIECES, 0>
 {
   public:
     LIR_HEADER(CallSetElement)
 
     static const size_t Index = 1;
     static const size_t Value = 1 + BOX_PIECES;
 
+    LCallSetElement(const LAllocation& obj, const LBoxAllocation& index,
+                    const LBoxAllocation& value) {
+        setOperand(0, obj);
+        setBoxOperand(Index, index);
+        setBoxOperand(Value, value);
+    }
+
     const MCallSetElement* mir() const {
         return mir_->toCallSetElement();
     }
 };
 
 // Call js::InitElementArray.
 class LCallInitElementArray : public LCallInstructionHelper<0, 1 + BOX_PIECES, 0>
 {
 public:
     LIR_HEADER(CallInitElementArray)
 
     static const size_t Value = 1;
 
+    LCallInitElementArray(const LAllocation& obj, const LBoxAllocation& value) {
+        setOperand(0, obj);
+        setBoxOperand(Value, value);
+    }
+
     const MCallInitElementArray* mir() const {
         return mir_->toCallInitElementArray();
     }
 };
 
 // Call a VM function to perform a property or name assignment of a generic value.
 class LCallSetProperty : public LCallInstructionHelper<0, 1 + BOX_PIECES, 0>
 {
   public:
     LIR_HEADER(CallSetProperty)
 
-    explicit LCallSetProperty(const LAllocation& obj) {
+    LCallSetProperty(const LAllocation& obj, const LBoxAllocation& value) {
         setOperand(0, obj);
+        setBoxOperand(Value, value);
     }
 
     static const size_t Value = 1;
 
     const MCallSetProperty* mir() const {
         return mir_->toCallSetProperty();
     }
 };
 
 class LCallDeleteProperty : public LCallInstructionHelper<1, BOX_PIECES, 0>
 {
   public:
     LIR_HEADER(CallDeleteProperty)
 
     static const size_t Value = 0;
 
+    explicit LCallDeleteProperty(const LBoxAllocation& value) {
+        setBoxOperand(Value, value);
+    }
+
     MDeleteProperty* mir() const {
         return mir_->toDeleteProperty();
     }
 };
 
 class LCallDeleteElement : public LCallInstructionHelper<1, 2 * BOX_PIECES, 0>
 {
   public:
     LIR_HEADER(CallDeleteElement)
 
     static const size_t Value = 0;
     static const size_t Index = BOX_PIECES;
 
+    LCallDeleteElement(const LBoxAllocation& value, const LBoxAllocation& index) {
+        setBoxOperand(Value, value);
+        setBoxOperand(Index, index);
+    }
+
     MDeleteElement* mir() const {
         return mir_->toDeleteElement();
     }
 };
 
 // Patchable jump to stubs generated for a SetProperty cache.
 class LSetPropertyCache : public LInstructionHelper<0, 1 + 2 * BOX_PIECES, 4>
 {
   public:
     LIR_HEADER(SetPropertyCache)
 
-    LSetPropertyCache(const LAllocation& object, const LDefinition& temp,
+    LSetPropertyCache(const LAllocation& object, const LBoxAllocation& id,
+                      const LBoxAllocation& value, const LDefinition& temp,
                       const LDefinition& tempToUnboxIndex, const LDefinition& tempDouble,
                       const LDefinition& tempFloat32) {
         setOperand(0, object);
+        setBoxOperand(Id, id);
+        setBoxOperand(Value, value);
         setTemp(0, temp);
         setTemp(1, tempToUnboxIndex);
         setTemp(2, tempDouble);
         setTemp(3, tempFloat32);
     }
 
     static const size_t Id = 1;
     static const size_t Value = 1 + BOX_PIECES;
@@ -6268,19 +6398,20 @@ class LIteratorMore : public LInstructio
     }
 };
 
 class LIsNoIterAndBranch : public LControlInstructionHelper<2, BOX_PIECES, 0>
 {
   public:
     LIR_HEADER(IsNoIterAndBranch)
 
-    LIsNoIterAndBranch(MBasicBlock* ifTrue, MBasicBlock* ifFalse) {
+    LIsNoIterAndBranch(MBasicBlock* ifTrue, MBasicBlock* ifFalse, const LBoxAllocation& input) {
         setSuccessor(0, ifTrue);
         setSuccessor(1, ifFalse);
+        setBoxOperand(Input, input);
     }
 
     static const size_t Input = 0;
 
     MBasicBlock* ifTrue() const {
         return getSuccessor(0);
     }
     MBasicBlock* ifFalse() const {
@@ -6375,17 +6506,19 @@ class LSetFrameArgumentC : public LInstr
 };
 
 // Load a value from the actual arguments.
 class LSetFrameArgumentV : public LInstructionHelper<0, BOX_PIECES, 0>
 {
   public:
     LIR_HEADER(SetFrameArgumentV)
 
-    LSetFrameArgumentV() {}
+    explicit LSetFrameArgumentV(const LBoxAllocation& input) {
+        setBoxOperand(Input, input);
+    }
 
     static const size_t Input = 0;
 
     MSetFrameArgument* mir() const {
         return mir_->toSetFrameArgument();
     }
 };
 
@@ -6474,17 +6607,18 @@ class LLoadUnboxedExpando : public LInst
 };
 
 // Guard that a value is in a TypeSet.
 class LTypeBarrierV : public LInstructionHelper<0, BOX_PIECES, 1>
 {
   public:
     LIR_HEADER(TypeBarrierV)
 
-    explicit LTypeBarrierV(const LDefinition& temp) {
+    LTypeBarrierV(const LBoxAllocation& input, const LDefinition& temp) {
+        setBoxOperand(Input, input);
         setTemp(0, temp);
     }
 
     static const size_t Input = 0;
 
     const MTypeBarrier* mir() const {
         return mir_->toTypeBarrier();
     }
@@ -6515,17 +6649,18 @@ class LTypeBarrierO : public LInstructio
 };
 
 // Guard that a value is in a TypeSet.
 class LMonitorTypes : public LInstructionHelper<0, BOX_PIECES, 1>
 {
   public:
     LIR_HEADER(MonitorTypes)
 
-    explicit LMonitorTypes(const LDefinition& temp) {
+    LMonitorTypes(const LBoxAllocation& input, const LDefinition& temp) {
+        setBoxOperand(Input, input);
         setTemp(0, temp);
     }
 
     static const size_t Input = 0;
 
     const MMonitorTypes* mir() const {
         return mir_->toMonitorTypes();
     }
@@ -6562,18 +6697,20 @@ class LPostWriteBarrierO : public LInstr
 };
 
 // Generational write barrier used when writing a value to another object.
 class LPostWriteBarrierV : public LInstructionHelper<0, 1 + BOX_PIECES, 1>
 {
   public:
     LIR_HEADER(PostWriteBarrierV)
 
-    LPostWriteBarrierV(const LAllocation& obj, const LDefinition& temp) {
+    LPostWriteBarrierV(const LAllocation& obj, const LBoxAllocation& value,
+                       const LDefinition& temp) {
         setOperand(0, obj);
+        setBoxOperand(Input, value);
         setTemp(0, temp);
     }
 
     static const size_t Input = 1;
 
     const MPostWriteBarrier* mir() const {
         return mir_->toPostWriteBarrier();
     }
@@ -6624,19 +6761,20 @@ class LPostWriteElementBarrierO : public
 // Generational write barrier used when writing a value to another object's
 // elements.
 class LPostWriteElementBarrierV : public LInstructionHelper<0, 2 + BOX_PIECES, 1>
 {
   public:
     LIR_HEADER(PostWriteElementBarrierV)
 
     LPostWriteElementBarrierV(const LAllocation& obj, const LAllocation& index,
-                              const LDefinition& temp) {
+                              const LBoxAllocation& value, const LDefinition& temp) {
         setOperand(0, obj);
         setOperand(1, index);
+        setBoxOperand(Input, value);
         setTemp(0, temp);
     }
 
     static const size_t Input = 2;
 
     const MPostWriteElementBarrier* mir() const {
         return mir_->toPostWriteElementBarrier();
     }
@@ -6710,17 +6848,18 @@ class LGuardSharedTypedArray : public LI
         return getTemp(0);
     }
 };
 
 class LIn : public LCallInstructionHelper<1, BOX_PIECES+1, 0>
 {
   public:
     LIR_HEADER(In)
-    explicit LIn(const LAllocation& rhs) {
+    LIn(const LBoxAllocation& lhs, const LAllocation& rhs) {
+        setBoxOperand(LHS, lhs);
         setOperand(RHS, rhs);
     }
 
     const LAllocation* lhs() {
         return getOperand(LHS);
     }
     const LAllocation* rhs() {
         return getOperand(RHS);
@@ -6746,17 +6885,18 @@ class LInstanceOfO : public LInstruction
         return getOperand(0);
     }
 };
 
 class LInstanceOfV : public LInstructionHelper<1, BOX_PIECES, 0>
 {
   public:
     LIR_HEADER(InstanceOfV)
-    LInstanceOfV() {
+    explicit LInstanceOfV(const LBoxAllocation& lhs) {
+        setBoxOperand(LHS, lhs);
     }
 
     MInstanceOf* mir() const {
         return mir_->toInstanceOf();
     }
 
     const LAllocation* lhs() {
         return getOperand(LHS);
@@ -6764,17 +6904,18 @@ class LInstanceOfV : public LInstruction
 
     static const size_t LHS = 0;
 };
 
 class LCallInstanceOf : public LCallInstructionHelper<1, BOX_PIECES+1, 0>
 {
   public:
     LIR_HEADER(CallInstanceOf)
-    explicit LCallInstanceOf(const LAllocation& rhs) {
+    LCallInstanceOf(const LBoxAllocation& lhs, const LAllocation& rhs) {
+        setBoxOperand(LHS, lhs);
         setOperand(RHS, rhs);
     }
 
     const LDefinition* output() {
         return this->getDef(0);
     }
     const LAllocation* lhs() {
         return getOperand(LHS);
@@ -6803,29 +6944,35 @@ class LIsCallable : public LInstructionH
     }
 };
 
 class LIsObject : public LInstructionHelper<1, BOX_PIECES, 0>
 {
   public:
     LIR_HEADER(IsObject);
     static const size_t Input = 0;
+
+    explicit LIsObject(const LBoxAllocation& input) {
+        setBoxOperand(Input, input);
+    }
+
     MIsObject* mir() const {
         return mir_->toIsObject();
     }
 };
 
 class LIsObjectAndBranch : public LControlInstructionHelper<2, BOX_PIECES, 0>
 {
   public:
     LIR_HEADER(IsObjectAndBranch)
 
-    LIsObjectAndBranch(MBasicBlock* ifTrue, MBasicBlock* ifFalse) {
+    LIsObjectAndBranch(MBasicBlock* ifTrue, MBasicBlock* ifFalse, const LBoxAllocation& input) {
         setSuccessor(0, ifTrue);
         setSuccessor(1, ifFalse);
+        setBoxOperand(Input, input);
     }
 
     static const size_t Input = 0;
 
     MBasicBlock* ifTrue() const {
         return getSuccessor(0);
     }
     MBasicBlock* ifFalse() const {
@@ -7334,19 +7481,20 @@ class LAssertRangeF : public LInstructio
     }
 };
 
 class LAssertRangeV : public LInstructionHelper<0, BOX_PIECES, 3>
 {
   public:
     LIR_HEADER(AssertRangeV)
 
-    LAssertRangeV(const LDefinition& temp, const LDefinition& floatTemp1,
-                  const LDefinition& floatTemp2)
+    LAssertRangeV(const LBoxAllocation& input, const LDefinition& temp,
+                  const LDefinition& floatTemp1, const LDefinition& floatTemp2)
     {
+        setBoxOperand(Input, input);
         setTemp(0, temp);
         setTemp(1, floatTemp1);
         setTemp(2, floatTemp2);
     }
 
     static const size_t Input = 0;
 
     const LDefinition* temp() {
@@ -7382,16 +7530,20 @@ class LAssertResultT : public LInstructi
 };
 
 class LAssertResultV : public LInstructionHelper<0, BOX_PIECES, 0>
 {
   public:
     LIR_HEADER(AssertResultV)
 
     static const size_t Input = 0;
+
+    explicit LAssertResultV(const LBoxAllocation& input) {
+        setBoxOperand(Input, input);
+    }
 };
 
 class LRecompileCheck : public LInstructionHelper<0, 0, 1>
 {
   public:
     LIR_HEADER(RecompileCheck)
 
     explicit LRecompileCheck(const LDefinition& scratch) {
@@ -7406,16 +7558,20 @@ class LRecompileCheck : public LInstruct
     }
 };
 
 class LLexicalCheck : public LInstructionHelper<0, BOX_PIECES, 0>
 {
   public:
     LIR_HEADER(LexicalCheck)
 
+    explicit LLexicalCheck(const LBoxAllocation& input) {
+        setBoxOperand(Input, input);
+    }
+
     MLexicalCheck* mir() {
         return mir_->toLexicalCheck();
     }
 
     static const size_t Input = 0;
 };
 
 class LThrowRuntimeLexicalError : public LCallInstructionHelper<0, 0, 0>
@@ -7540,34 +7696,47 @@ class LRandom : public LInstructionHelpe
     MRandom* mir() const {
         return mir_->toRandom();
     }
 };
 
 class LCheckReturn : public LCallInstructionHelper<BOX_PIECES, 2 * BOX_PIECES, 0>
 {
   public:
+    LIR_HEADER(CheckReturn)
+
+    LCheckReturn(const LBoxAllocation& retVal, const LBoxAllocation& thisVal) {
+        setBoxOperand(ReturnValue, retVal);
+        setBoxOperand(ThisValue, thisVal);
+    }
+
     static const size_t ReturnValue = 0;
     static const size_t ThisValue = BOX_PIECES;
-
-    LIR_HEADER(CheckReturn)
 };
 
 class LCheckObjCoercible : public LCallInstructionHelper<BOX_PIECES, BOX_PIECES, 0>
 {
   public:
+    LIR_HEADER(CheckObjCoercible)
+
     static const size_t CheckValue = 0;
 
-    LIR_HEADER(CheckObjCoercible)
+    explicit LCheckObjCoercible(const LBoxAllocation& value) {
+        setBoxOperand(CheckValue, value);
+    }
 };
 
 class LDebugCheckSelfHosted : public LCallInstructionHelper<BOX_PIECES, BOX_PIECES, 0>
 {
   public:
+    LIR_HEADER(DebugCheckSelfHosted)
+
     static const size_t CheckValue = 0;
 
-    LIR_HEADER(DebugCheckSelfHosted)
+    explicit LDebugCheckSelfHosted(const LBoxAllocation& value) {
+        setBoxOperand(CheckValue, value);
+    }
 };
 
 } // namespace jit
 } // namespace js
 
 #endif /* jit_shared_LIR_shared_h */
--- a/js/src/jit/shared/Lowering-shared-inl.h
+++ b/js/src/jit/shared/Lowering-shared-inl.h
@@ -293,18 +293,17 @@ LIRGeneratorShared::redefine(MDefinition
               case MIRType_ObjectOrNull:
               case MIRType_String:
               case MIRType_Symbol: {
                 LAssertResultT* check = new(alloc()) LAssertResultT(useRegister(def));
                 add(check, def->toInstruction());
                 break;
               }
               case MIRType_Value: {
-                LAssertResultV* check = new(alloc()) LAssertResultV();
-                useBox(check, LAssertRangeV::Input, def);
+                LAssertResultV* check = new(alloc()) LAssertResultV(useBox(def));
                 add(check, def->toInstruction());
                 break;
               }
               default:
                 break;
             }
         }
 #endif
@@ -601,44 +600,49 @@ LIRGeneratorShared::useRegisterForTypedL
     // int32/bool/double, so we just call useRegister in this case.
     if (type != MIRType_Int32 && type != MIRType_Boolean && type != MIRType_Double)
         return useRegister(mir);
 #endif
 
     return useRegisterAtStart(mir);
 }
 
-void
-LIRGeneratorShared::useBox(LInstruction* lir, size_t n, MDefinition* mir,
-                           LUse::Policy policy, bool useAtStart)
+LBoxAllocation
+LIRGeneratorShared::useBox(MDefinition* mir, LUse::Policy policy, bool useAtStart)
 {
     MOZ_ASSERT(mir->type() == MIRType_Value);
 
     ensureDefined(mir);
-    lir->setOperand(n, LUse(mir->virtualRegister(), policy, useAtStart));
+
 #if defined(JS_NUNBOX32)
-    lir->setOperand(n + 1, LUse(VirtualRegisterOfPayload(mir), policy, useAtStart));
+    return LBoxAllocation(LUse(mir->virtualRegister(), policy, useAtStart),
+                          LUse(VirtualRegisterOfPayload(mir), policy, useAtStart));
+#else
+    return LBoxAllocation(LUse(mir->virtualRegister(), policy, useAtStart));
 #endif
 }
 
-void
-LIRGeneratorShared::useBoxOrTypedOrConstant(LInstruction* lir, size_t n, MDefinition* mir,
-                                            bool useConstant)
+LBoxAllocation
+LIRGeneratorShared::useBoxOrTypedOrConstant(MDefinition* mir, bool useConstant)
 {
-    if (mir->type() == MIRType_Value) {
-        useBox(lir, n, mir);
-        return;
+    if (mir->type() == MIRType_Value)
+        return useBox(mir);
+
+
+    if (useConstant && mir->isConstant()) {
+#if defined(JS_NUNBOX32)
+        return LBoxAllocation(LAllocation(mir->toConstant()), LAllocation());
+#else
+        return LBoxAllocation(LAllocation(mir->toConstant()));
+#endif
     }
 
-    if (useConstant && mir->isConstant())
-        lir->setOperand(n, LAllocation(mir->toConstant()));
-    else
-        lir->setOperand(n, useRegister(mir));
-
 #if defined(JS_NUNBOX32)
-    lir->setOperand(n + 1, LAllocation());
+    return LBoxAllocation(useRegister(mir), LAllocation());
+#else
+    return LBoxAllocation(useRegister(mir));
 #endif
 }
 
 } // namespace jit
 } // namespace js
 
 #endif /* jit_shared_Lowering_shared_inl_h */
--- a/js/src/jit/shared/Lowering-shared.h
+++ b/js/src/jit/shared/Lowering-shared.h
@@ -154,24 +154,23 @@ class LIRGeneratorShared : public MDefin
                        LDefinition::Policy policy = LDefinition::REGISTER);
     template <size_t X>
     inline void define(details::LInstructionFixedDefsTempsHelper<1, X>* lir, MDefinition* mir,
                        const LDefinition& def);
 
     template <size_t Ops, size_t Temps>
     inline void defineReuseInput(LInstructionHelper<1, Ops, Temps>* lir, MDefinition* mir, uint32_t operand);
 
-    // Adds a use at operand |n| of a value-typed insturction.
-    inline void useBox(LInstruction* lir, size_t n, MDefinition* mir,
-                       LUse::Policy policy = LUse::REGISTER, bool useAtStart = false);
+    // Returns a box allocation for a Value-typed instruction.
+    inline LBoxAllocation useBox(MDefinition* mir, LUse::Policy policy = LUse::REGISTER,
+                                 bool useAtStart = false);
 
-    // Adds a use at operand |n|. The use is either typed, a Value, or a
-    // constant (if useConstant is true).
-    inline void useBoxOrTypedOrConstant(LInstruction* lir, size_t n, MDefinition* mir,
-                                        bool useConstant);
+    // Returns a box allocation. The use is either typed, a Value, or
+    // a constant (if useConstant is true).
+    inline LBoxAllocation useBoxOrTypedOrConstant(MDefinition* mir, bool useConstant);
 
     // Rather than defining a new virtual register, sets |ins| to have the same
     // virtual register as |as|.
     inline void redefine(MDefinition* ins, MDefinition* as);
 
     // Redefine a sin/cos call to sincos.
     inline void redefine(MDefinition* def, MDefinition* as, MMathFunction::Function func);
 
--- a/js/src/jit/x64/Lowering-x64.cpp
+++ b/js/src/jit/x64/Lowering-x64.cpp
@@ -9,23 +9,23 @@
 #include "jit/MIR.h"
 #include "jit/x64/Assembler-x64.h"
 
 #include "jit/shared/Lowering-shared-inl.h"
 
 using namespace js;
 using namespace js::jit;
 
-void
-LIRGeneratorX64::useBoxFixed(LInstruction* lir, size_t n, MDefinition* mir, Register reg1, Register, bool useAtStart)
+LBoxAllocation
+LIRGeneratorX64::useBoxFixed(MDefinition* mir, Register reg1, Register, bool useAtStart)
 {
     MOZ_ASSERT(mir->type() == MIRType_Value);
 
     ensureDefined(mir);
-    lir->setOperand(n, LUse(reg1, mir->virtualRegister(), useAtStart));
+    return LBoxAllocation(LUse(reg1, mir->virtualRegister(), useAtStart));
 }
 
 LAllocation
 LIRGeneratorX64::useByteOpRegister(MDefinition* mir)
 {
     return useRegister(mir);
 }
 
--- a/js/src/jit/x64/Lowering-x64.h
+++ b/js/src/jit/x64/Lowering-x64.h
@@ -18,18 +18,18 @@ class LIRGeneratorX64 : public LIRGenera
     LIRGeneratorX64(MIRGenerator* gen, MIRGraph& graph, LIRGraph& lirGraph)
       : LIRGeneratorX86Shared(gen, graph, lirGraph)
     { }
 
   protected:
     void lowerUntypedPhiInput(MPhi* phi, uint32_t inputPosition, LBlock* block, size_t lirIndex);
     void defineUntypedPhi(MPhi* phi, size_t lirIndex);
 
-    // Adds a use at operand |n| of a value-typed insturction.
-    void useBoxFixed(LInstruction* lir, size_t n, MDefinition* mir, Register reg1, Register, bool useAtStart = false);
+    // Returns a box allocation. reg2 is ignored on 64-bit platforms.
+    LBoxAllocation useBoxFixed(MDefinition* mir, Register reg1, Register, bool useAtStart = false);
 
     // x86 has constraints on what registers can be formatted for 1-byte
     // stores and loads; on x64 all registers are okay.
     LAllocation useByteOpRegister(MDefinition* mir);
     LAllocation useByteOpRegisterOrNonDoubleConstant(MDefinition* mir);
     LDefinition tempByteOpRegister();
 
     LDefinition tempToUnbox();
--- a/js/src/jit/x86-shared/LIR-x86-shared.h
+++ b/js/src/jit/x86-shared/LIR-x86-shared.h
@@ -249,19 +249,21 @@ class LTableSwitch : public LInstruction
 };
 
 // Takes a tableswitch with a value to decide
 class LTableSwitchV : public LInstructionHelper<0, BOX_PIECES, 3>
 {
   public:
     LIR_HEADER(TableSwitchV)
 
-    LTableSwitchV(const LDefinition& inputCopy, const LDefinition& floatCopy,
-                  const LDefinition& jumpTablePointer, MTableSwitch* ins)
+    LTableSwitchV(const LBoxAllocation& input, const LDefinition& inputCopy,
+                  const LDefinition& floatCopy, const LDefinition& jumpTablePointer,
+                  MTableSwitch* ins)
     {
+        setBoxOperand(InputValue, input);
         setTemp(0, inputCopy);
         setTemp(1, floatCopy);
         setTemp(2, jumpTablePointer);
         setMir(ins);
     }
 
     MTableSwitch* mir() const {
         return mir_->toTableSwitch();
--- a/js/src/jit/x86-shared/Lowering-x86-shared.cpp
+++ b/js/src/jit/x86-shared/Lowering-x86-shared.cpp
@@ -24,17 +24,18 @@ LIRGeneratorX86Shared::newLTableSwitch(c
                                        MTableSwitch* tableswitch)
 {
     return new(alloc()) LTableSwitch(in, inputCopy, temp(), tableswitch);
 }
 
 LTableSwitchV*
 LIRGeneratorX86Shared::newLTableSwitchV(MTableSwitch* tableswitch)
 {
-    return new(alloc()) LTableSwitchV(temp(), tempDouble(), temp(), tableswitch);
+    return new(alloc()) LTableSwitchV(useBox(tableswitch->getOperand(0)),
+                                      temp(), tempDouble(), temp(), tableswitch);
 }
 
 void
 LIRGeneratorX86Shared::visitGuardShape(MGuardShape* ins)
 {
     MOZ_ASSERT(ins->obj()->type() == MIRType_Object);
 
     LGuardShape* guard = new(alloc()) LGuardShape(useRegisterAtStart(ins->obj()));
--- a/js/src/jit/x86/LIR-x86.h
+++ b/js/src/jit/x86/LIR-x86.h
@@ -56,19 +56,21 @@ class LUnboxFloatingPoint : public LInst
 {
     MIRType type_;
 
   public:
     LIR_HEADER(UnboxFloatingPoint);
 
     static const size_t Input = 0;
 
-    LUnboxFloatingPoint(MIRType type)
+    LUnboxFloatingPoint(const LBoxAllocation& input, MIRType type)
       : type_(type)
-    { }
+    {
+        setBoxOperand(Input, input);
+    }
 
     MUnbox* mir() const {
         return mir_->toUnbox();
     }
 
     MIRType type() const {
         return type_;
     }
--- a/js/src/jit/x86/Lowering-x86.cpp
+++ b/js/src/jit/x86/Lowering-x86.cpp
@@ -9,26 +9,25 @@
 #include "jit/MIR.h"
 #include "jit/x86/Assembler-x86.h"
 
 #include "jit/shared/Lowering-shared-inl.h"
 
 using namespace js;
 using namespace js::jit;
 
-void
-LIRGeneratorX86::useBoxFixed(LInstruction* lir, size_t n, MDefinition* mir, Register reg1,
-                             Register reg2, bool useAtStart)
+LBoxAllocation
+LIRGeneratorX86::useBoxFixed(MDefinition* mir, Register reg1, Register reg2, bool useAtStart)
 {
     MOZ_ASSERT(mir->type() == MIRType_Value);
     MOZ_ASSERT(reg1 != reg2);
 
     ensureDefined(mir);
-    lir->setOperand(n, LUse(reg1, mir->virtualRegister(), useAtStart));
-    lir->setOperand(n + 1, LUse(reg2, VirtualRegisterOfPayload(mir), useAtStart));
+    return LBoxAllocation(LUse(reg1, mir->virtualRegister(), useAtStart),
+                          LUse(reg2, VirtualRegisterOfPayload(mir), useAtStart));
 }
 
 LAllocation
 LIRGeneratorX86::useByteOpRegister(MDefinition* mir)
 {
     return useFixed(mir, eax);
 }
 
@@ -100,20 +99,19 @@ LIRGeneratorX86::visitUnbox(MUnbox* unbo
     // An unbox on x86 reads in a type tag (either in memory or a register) and
     // a payload. Unlike most instructions consuming a box, we ask for the type
     // second, so that the result can re-use the first input.
     MOZ_ASSERT(inner->type() == MIRType_Value);
 
     ensureDefined(inner);
 
     if (IsFloatingPointType(unbox->type())) {
-        LUnboxFloatingPoint* lir = new(alloc()) LUnboxFloatingPoint(unbox->type());
+        LUnboxFloatingPoint* lir = new(alloc()) LUnboxFloatingPoint(useBox(inner), unbox->type());
         if (unbox->fallible())
             assignSnapshot(lir, unbox->bailoutKind());
-        useBox(lir, LUnboxFloatingPoint::Input, inner);
         define(lir, unbox);
         return;
     }
 
     // Swap the order we use the box pieces so we can re-use the payload register.
     LUnbox* lir = new(alloc()) LUnbox;
     lir->setOperand(0, usePayloadInRegisterAtStart(inner));
     lir->setOperand(1, useType(inner, LUse::ANY));
--- a/js/src/jit/x86/Lowering-x86.h
+++ b/js/src/jit/x86/Lowering-x86.h
@@ -15,20 +15,19 @@ namespace jit {
 class LIRGeneratorX86 : public LIRGeneratorX86Shared
 {
   public:
     LIRGeneratorX86(MIRGenerator* gen, MIRGraph& graph, LIRGraph& lirGraph)
       : LIRGeneratorX86Shared(gen, graph, lirGraph)
     { }
 
   protected:
-    // Adds a box input to an instruction, setting operand |n| to the type and
-    // |n+1| to the payload.
-    void useBoxFixed(LInstruction* lir, size_t n, MDefinition* mir, Register reg1, Register reg2,
-                     bool useAtStart = false);
+    // Returns a box allocation with type set to reg1 and payload set to reg2.
+    LBoxAllocation useBoxFixed(MDefinition* mir, Register reg1, Register reg2,
+                               bool useAtStart = false);
 
     // It's a trap! On x86, the 1-byte store can only use one of
     // {al,bl,cl,dl,ah,bh,ch,dh}. That means if the register allocator
     // gives us one of {edi,esi,ebp,esp}, we're out of luck. (The formatter
     // will assert on us.) Ideally, we'd just ask the register allocator to
     // give us one of {al,bl,cl,dl}. For now, just useFixed(al).
     LAllocation useByteOpRegister(MDefinition* mir);
     LAllocation useByteOpRegisterOrNonDoubleConstant(MDefinition* mir);