Bug 1246658 part 3 - Rewrite MConstant's public interface to not expose js::Value directly. r=luke
authorJan de Mooij <jdemooij@mozilla.com>
Fri, 12 Feb 2016 08:58:31 +0100
changeset 320466 98bc20ce84527365ab0398e32183127d5f7786fc
parent 320465 dae4acefe53bd29077ec624c3621dbd79693abd1
child 320467 d8781a4c7092db380f52de8467515fd317e24201
push id5913
push userjlund@mozilla.com
push dateMon, 25 Apr 2016 16:57:49 +0000
treeherdermozilla-beta@dcaf0a6fa115 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersluke
bugs1246658
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 1246658 part 3 - Rewrite MConstant's public interface to not expose js::Value directly. r=luke
js/src/asmjs/WasmIonCompile.cpp
js/src/jit/AlignmentMaskAnalysis.cpp
js/src/jit/CodeGenerator.cpp
js/src/jit/EffectiveAddressAnalysis.cpp
js/src/jit/IonAnalysis.cpp
js/src/jit/IonBuilder.cpp
js/src/jit/LIR.h
js/src/jit/LoopUnroller.cpp
js/src/jit/Lowering.cpp
js/src/jit/MCallOptimize.cpp
js/src/jit/MIR.cpp
js/src/jit/MIR.h
js/src/jit/MIRGraph.cpp
js/src/jit/RangeAnalysis.cpp
js/src/jit/ScalarReplacement.cpp
js/src/jit/arm/Lowering-arm.cpp
js/src/jit/shared/CodeGenerator-shared.cpp
js/src/jit/shared/Lowering-shared-inl.h
js/src/jit/shared/Lowering-shared.cpp
js/src/jit/x64/CodeGenerator-x64.cpp
js/src/jit/x64/Lowering-x64.cpp
js/src/jit/x86-shared/Lowering-x86-shared.cpp
js/src/jit/x86/Lowering-x86.cpp
js/src/jsapi-tests/testJitDCEinGVN.cpp
js/src/jsapi-tests/testJitFoldsTo.cpp
--- a/js/src/asmjs/WasmIonCompile.cpp
+++ b/js/src/asmjs/WasmIonCompile.cpp
@@ -1797,17 +1797,17 @@ EmitExtractLane(FunctionCompiler& f, Exp
         return false;
 
     if (!laneDef) {
         *def = nullptr;
         return true;
     }
 
     MOZ_ASSERT(laneDef->isConstant());
-    int32_t laneLit = laneDef->toConstant()->value().toInt32();
+    int32_t laneLit = laneDef->toConstant()->toInt32();
     MOZ_ASSERT(laneLit < 4);
     SimdLane lane = SimdLane(laneLit);
 
     *def = f.extractSimdElement(lane, vec, ToMIRType(SimdToLaneType(type)));
     return true;
 }
 
 // Emit an I32 expression and then convert it to a boolean SIMD lane value, i.e. -1 or 0.
@@ -1832,17 +1832,17 @@ EmitSimdReplaceLane(FunctionCompiler& f,
 
     MDefinition* laneDef;
     if (!EmitExpr(f, ExprType::I32, &laneDef))
         return false;
 
     SimdLane lane;
     if (laneDef) {
         MOZ_ASSERT(laneDef->isConstant());
-        int32_t laneLit = laneDef->toConstant()->value().toInt32();
+        int32_t laneLit = laneDef->toConstant()->toInt32();
         MOZ_ASSERT(laneLit < 4);
         lane = SimdLane(laneLit);
     } else {
         lane = SimdLane(-1);
     }
 
     MDefinition* scalar;
     if (IsSimdBoolType(simdType)) {
--- a/js/src/jit/AlignmentMaskAnalysis.cpp
+++ b/js/src/jit/AlignmentMaskAnalysis.cpp
@@ -54,18 +54,18 @@ AnalyzeAsmHeapAddress(MDefinition* ptr, 
 
     MDefinition* op0 = lhs->toAdd()->getOperand(0);
     MDefinition* op1 = lhs->toAdd()->getOperand(1);
     if (op0->isConstant())
         mozilla::Swap(op0, op1);
     if (!op1->isConstant())
         return;
 
-    uint32_t i = op1->toConstant()->value().toInt32();
-    uint32_t m = rhs->toConstant()->value().toInt32();
+    uint32_t i = op1->toConstant()->toInt32();
+    uint32_t m = rhs->toConstant()->toInt32();
     if (!IsAlignmentMask(m) || (i & m) != i)
         return;
 
     // The pattern was matched! Produce the replacement expression.
     MInstruction* and_ = MBitAnd::NewAsmJS(graph.alloc(), op0, rhs);
     ptr->block()->insertBefore(ptr->toBitAnd(), and_);
     MInstruction* add = MAdd::NewAsmJS(graph.alloc(), and_, op1, MIRType_Int32);
     ptr->block()->insertBefore(ptr->toBitAnd(), add);
--- a/js/src/jit/CodeGenerator.cpp
+++ b/js/src/jit/CodeGenerator.cpp
@@ -2545,17 +2545,17 @@ CodeGenerator::visitStackArgT(LStackArgT
     int32_t stack_offset = StackOffsetOfPassedArg(argslot);
     Address dest(masm.getStackPointer(), stack_offset);
 
     if (arg->isFloatReg())
         masm.storeDouble(ToFloatRegister(arg), dest);
     else if (arg->isRegister())
         masm.storeValue(ValueTypeFromMIRType(argType), ToRegister(arg), dest);
     else
-        masm.storeValue(*(arg->toConstant()), dest);
+        masm.storeValue(arg->toConstant()->toJSValue(), dest);
 }
 
 void
 CodeGenerator::visitStackArgV(LStackArgV* lir)
 {
     ValueOperand val = ToValue(lir, 0);
     uint32_t argslot = lir->argslot();
     MOZ_ASSERT(argslot - 1u < graph.argumentSlotCount());
@@ -2682,17 +2682,17 @@ CodeGenerator::visitStoreSlotT(LStoreSlo
 
     MIRType valueType = lir->mir()->value()->type();
 
     if (valueType == MIRType_ObjectOrNull) {
         masm.storeObjectOrNull(ToRegister(lir->value()), dest);
     } else {
         ConstantOrRegister value;
         if (lir->value()->isConstant())
-            value = ConstantOrRegister(*lir->value()->toConstant());
+            value = ConstantOrRegister(lir->value()->toConstant()->toJSValue());
         else
             value = TypedOrValueRegister(valueType, ToAnyRegister(lir->value()));
         masm.storeUnboxedValue(value, valueType, dest, lir->mir()->slotType());
     }
 }
 
 void
 CodeGenerator::visitStoreSlotV(LStoreSlotV* lir)
@@ -2873,17 +2873,17 @@ CodeGenerator::visitSetPropertyPolymorph
 void
 CodeGenerator::visitSetPropertyPolymorphicT(LSetPropertyPolymorphicT* ins)
 {
     Register obj = ToRegister(ins->obj());
     Register temp = ToRegister(ins->temp());
 
     ConstantOrRegister value;
     if (ins->mir()->value()->isConstant())
-        value = ConstantOrRegister(ins->mir()->value()->toConstant()->value());
+        value = ConstantOrRegister(ins->mir()->value()->toConstant()->toJSValue());
     else
         value = TypedOrValueRegister(ins->mir()->value()->type(), ToAnyRegister(ins->value()));
 
     emitSetPropertyPolymorphic(ins, obj, temp, value);
 }
 
 void
 CodeGenerator::visitElements(LElements* lir)
@@ -7232,17 +7232,17 @@ CodeGenerator::emitStoreHoleCheck(Regist
     }
     bailoutFrom(&bail, snapshot);
 }
 
 static ConstantOrRegister
 ToConstantOrRegister(const LAllocation* value, MIRType valueType)
 {
     if (value->isConstant())
-        return ConstantOrRegister(*value->toConstant());
+        return ConstantOrRegister(value->toConstant()->toJSValue());
     return TypedOrValueRegister(valueType, ToAnyRegister(value));
 }
 
 void
 CodeGenerator::emitStoreElementTyped(const LAllocation* value,
                                      MIRType valueType, MIRType elementType,
                                      Register elements, const LAllocation* index,
                                      int32_t offsetAdjustment)
@@ -7424,17 +7424,17 @@ CodeGenerator::visitOutOfLineStoreElemen
         temp = store->getTemp(0);
     } else {
         LStoreElementHoleT* store = ins->toStoreElementHoleT();
         object = ToRegister(store->object());
         elements = ToRegister(store->elements());
         index = store->index();
         valueType = store->mir()->value()->type();
         if (store->value()->isConstant())
-            value = ConstantOrRegister(*store->value()->toConstant());
+            value = ConstantOrRegister(store->value()->toConstant()->toJSValue());
         else
             value = TypedOrValueRegister(valueType, ToAnyRegister(store->value()));
         unboxedType = store->mir()->unboxedType();
         temp = store->getTemp(0);
     }
 
     // If index == initializedLength, try to bump the initialized length inline.
     // If index > initializedLength, call a stub. Note that this relies on the
@@ -7521,17 +7521,17 @@ CodeGenerator::visitOutOfLineStoreElemen
 template <typename T>
 static void
 StoreUnboxedPointer(MacroAssembler& masm, T address, MIRType type, const LAllocation* value,
                     bool preBarrier)
 {
     if (preBarrier)
         masm.patchableCallPreBarrier(address, type);
     if (value->isConstant()) {
-        Value v = *value->toConstant();
+        Value v = value->toConstant()->toJSValue();
         if (v.isMarkable()) {
             masm.storePtr(ImmGCPtr(v.toGCThing()), address);
         } else {
             MOZ_ASSERT(v.isNull());
             masm.storePtr(ImmWord(0), address);
         }
     } else {
         masm.storePtr(ToRegister(value), address);
@@ -7789,17 +7789,17 @@ CodeGenerator::visitArrayPushV(LArrayPus
 void
 CodeGenerator::visitArrayPushT(LArrayPushT* lir)
 {
     Register obj = ToRegister(lir->object());
     Register elementsTemp = ToRegister(lir->temp());
     Register length = ToRegister(lir->output());
     ConstantOrRegister value;
     if (lir->value()->isConstant())
-        value = ConstantOrRegister(*lir->value()->toConstant());
+        value = ConstantOrRegister(lir->value()->toConstant()->toJSValue());
     else
         value = TypedOrValueRegister(lir->mir()->value()->type(), ToAnyRegister(lir->value()));
     emitArrayPush(lir, lir->mir(), obj, value, elementsTemp, length);
 }
 
 typedef JSObject* (*ArrayConcatDenseFn)(JSContext*, HandleObject, HandleObject, HandleObject);
 static const VMFunction ArrayConcatDenseInfo = FunctionInfo<ArrayConcatDenseFn>(ArrayConcatDense);
 
@@ -8957,17 +8957,17 @@ CodeGenerator::visitStoreFixedSlotT(LSto
     if (ins->mir()->needsBarrier())
         emitPreBarrier(address);
 
     if (valueType == MIRType_ObjectOrNull) {
         Register nvalue = ToRegister(value);
         masm.storeObjectOrNull(nvalue, address);
     } else {
         ConstantOrRegister nvalue = value->isConstant()
-                                    ? ConstantOrRegister(*value->toConstant())
+                                    ? ConstantOrRegister(value->toConstant()->toJSValue())
                                     : TypedOrValueRegister(valueType, ToAnyRegister(value));
         masm.storeConstantOrRegister(nvalue, address);
     }
 }
 
 void
 CodeGenerator::visitGetNameCache(LGetNameCache* ins)
 {
@@ -9027,17 +9027,17 @@ CodeGenerator::addSetPropertyCache(LInst
 ConstantOrRegister
 CodeGenerator::toConstantOrRegister(LInstruction* lir, size_t n, MIRType type)
 {
     if (type == MIRType_Value)
         return TypedOrValueRegister(ToValue(lir, n));
 
     const LAllocation* value = lir->getOperand(n);
     if (value->isConstant())
-        return ConstantOrRegister(*value->toConstant());
+        return ConstantOrRegister(value->toConstant()->toJSValue());
 
     return TypedOrValueRegister(type, ToAnyRegister(value));
 }
 
 void
 CodeGenerator::visitGetPropertyCacheV(LGetPropertyCacheV* ins)
 {
     LiveRegisterSet liveRegs = ins->safepoint()->liveRegs();
--- a/js/src/jit/EffectiveAddressAnalysis.cpp
+++ b/js/src/jit/EffectiveAddressAnalysis.cpp
@@ -22,21 +22,20 @@ AnalyzeLsh(TempAllocator& alloc, MLsh* l
 
     MDefinition* index = lsh->lhs();
     MOZ_ASSERT(index->type() == MIRType_Int32);
 
     MConstant* shiftValue = lsh->rhs()->maybeConstantValue();
     if (!shiftValue)
         return;
 
-    Value shiftv = shiftValue->value();
-    if (!shiftv.isInt32() || !IsShiftInScaleRange(shiftv.toInt32()))
+    if (shiftValue->type() != MIRType_Int32 || !IsShiftInScaleRange(shiftValue->toInt32()))
         return;
 
-    Scale scale = ShiftToScale(shiftv.toInt32());
+    Scale scale = ShiftToScale(shiftValue->toInt32());
 
     int32_t displacement = 0;
     MInstruction* last = lsh;
     MDefinition* base = nullptr;
     while (true) {
         if (!last->hasOneUse())
             break;
 
@@ -46,17 +45,17 @@ AnalyzeLsh(TempAllocator& alloc, MLsh* l
 
         MAdd* add = use->consumer()->toDefinition()->toAdd();
         if (add->specialization() != MIRType_Int32 || !add->isTruncated())
             break;
 
         MDefinition* other = add->getOperand(1 - add->indexOf(*use));
 
         if (MConstant* otherConst = other->maybeConstantValue()) {
-            displacement += otherConst->value().toInt32();
+            displacement += otherConst->toInt32();
         } else {
             if (base)
                 break;
             base = other;
         }
 
         last = add;
         if (last->isRecoveredOnBailout())
@@ -80,17 +79,17 @@ AnalyzeLsh(TempAllocator& alloc, MLsh* l
             return;
 
         MDefinition* other = bitAnd->getOperand(1 - bitAnd->indexOf(*use));
         MConstant* otherConst = other->maybeConstantValue();
         if (!otherConst || otherConst->type() != MIRType_Int32)
             return;
 
         uint32_t bitsClearedByShift = elemSize - 1;
-        uint32_t bitsClearedByMask = ~uint32_t(otherConst->value().toInt32());
+        uint32_t bitsClearedByMask = ~uint32_t(otherConst->toInt32());
         if ((bitsClearedByShift & bitsClearedByMask) != bitsClearedByMask)
             return;
 
         bitAnd->replaceAllUsesWith(last);
         return;
     }
 
     if (base->isRecoveredOnBailout())
@@ -138,32 +137,32 @@ EffectiveAddressAnalysis::analyzeAsmHeap
     MDefinition* ptr = ins->ptr();
 
     if (ptr->isConstant()) {
         // Look for heap[i] where i is a constant offset, and fold the offset.
         // By doing the folding now, we simplify the task of codegen; the offset
         // is always the address mode immediate. This also allows it to avoid
         // a situation where the sum of a constant pointer value and a non-zero
         // offset doesn't actually fit into the address mode immediate.
-        int32_t imm = ptr->toConstant()->value().toInt32();
+        int32_t imm = ptr->toConstant()->toInt32();
         if (imm != 0 && tryAddDisplacement(ins, imm)) {
             MInstruction* zero = MConstant::New(graph_.alloc(), Int32Value(0));
             ins->block()->insertBefore(ins, zero);
             ins->replacePtr(zero);
         }
     } else if (ptr->isAdd()) {
         // Look for heap[a+i] where i is a constant offset, and fold the offset.
         // Alignment masks have already been moved out of the way by the
         // Alignment Mask Analysis pass.
         MDefinition* op0 = ptr->toAdd()->getOperand(0);
         MDefinition* op1 = ptr->toAdd()->getOperand(1);
         if (op0->isConstant())
             mozilla::Swap(op0, op1);
         if (op1->isConstant()) {
-            int32_t imm = op1->toConstant()->value().toInt32();
+            int32_t imm = op1->toConstant()->toInt32();
             if (tryAddDisplacement(ins, imm))
                 ins->replacePtr(op0);
         }
     }
 }
 
 // This analysis converts patterns of the form:
 //   truncate(x + (y << {0,1,2,3}))
--- a/js/src/jit/IonAnalysis.cpp
+++ b/js/src/jit/IonAnalysis.cpp
@@ -2697,21 +2697,18 @@ SimpleLinearSum
 jit::ExtractLinearSum(MDefinition* ins)
 {
     if (ins->isBeta())
         ins = ins->getOperand(0);
 
     if (ins->type() != MIRType_Int32)
         return SimpleLinearSum(ins, 0);
 
-    if (ins->isConstant()) {
-        const Value& v = ins->toConstant()->value();
-        MOZ_ASSERT(v.isInt32());
-        return SimpleLinearSum(nullptr, v.toInt32());
-    }
+    if (ins->isConstant())
+        return SimpleLinearSum(nullptr, ins->toConstant()->toInt32());
 
     if (ins->isAdd() || ins->isSub()) {
         MDefinition* lhs = ins->getOperand(0);
         MDefinition* rhs = ins->getOperand(1);
         if (lhs->type() == MIRType_Int32 && rhs->type() == MIRType_Int32) {
             SimpleLinearSum lsum = ExtractLinearSum(lhs);
             SimpleLinearSum rsum = ExtractLinearSum(rhs);
 
@@ -3318,17 +3315,17 @@ bool
 LinearSum::add(MDefinition* term, int32_t scale)
 {
     MOZ_ASSERT(term);
 
     if (scale == 0)
         return true;
 
     if (MConstant* termConst = term->maybeConstantValue()) {
-        int32_t constant = termConst->value().toInt32();
+        int32_t constant = termConst->toInt32();
         if (!SafeMul(constant, scale, &constant))
             return false;
         return add(constant);
     }
 
     for (size_t i = 0; i < terms_.length(); i++) {
         if (term == terms_[i].term) {
             if (!SafeAdd(scale, terms_[i].scale, &terms_[i].scale))
--- a/js/src/jit/IonBuilder.cpp
+++ b/js/src/jit/IonBuilder.cpp
@@ -3679,20 +3679,19 @@ IonBuilder::improveTypesAtCompare(MCompa
 
     return true;
 }
 
 bool
 IonBuilder::improveTypesAtTypeOfCompare(MCompare* ins, bool trueBranch, MTest* test)
 {
     MTypeOf* typeOf = ins->lhs()->isTypeOf() ? ins->lhs()->toTypeOf() : ins->rhs()->toTypeOf();
-    MConstant* constantDef = ins->lhs()->isConstant() ? ins->lhs()->toConstant() : ins->rhs()->toConstant();
-    const Value* constant = constantDef->vp();
-
-    if (!constant->isString())
+    MConstant* constant = ins->lhs()->isConstant() ? ins->lhs()->toConstant() : ins->rhs()->toConstant();
+
+    if (constant->type() != MIRType_String)
         return true;
 
     bool equal = ins->jsop() == JSOP_EQ || ins->jsop() == JSOP_STRICTEQ;
     bool notEqual = ins->jsop() == JSOP_NE || ins->jsop() == JSOP_STRICTNE;
 
     if (notEqual)
         trueBranch = !trueBranch;
 
@@ -4863,17 +4862,17 @@ IonBuilder::arithTrySharedStub(bool* emi
     if (actualOp == JSOP_POS)
         return true;
 
     MInstruction* stub = nullptr;
     switch (actualOp) {
       case JSOP_NEG:
       case JSOP_BITNOT:
         MOZ_ASSERT_IF(op == JSOP_MUL,
-                      left->maybeConstantValue() && left->maybeConstantValue()->value().toInt32() == -1);
+                      left->maybeConstantValue() && left->maybeConstantValue()->toInt32() == -1);
         MOZ_ASSERT_IF(op != JSOP_MUL, !left);
 
         stub = MUnarySharedStub::New(alloc(), right);
         break;
       case JSOP_ADD:
       case JSOP_SUB:
       case JSOP_MUL:
       case JSOP_DIV:
@@ -6877,17 +6876,17 @@ IonBuilder::jsop_eval(uint32_t argc)
 
         // Try to pattern match 'eval(v + "()")'. In this case v is likely a
         // name on the scope chain and the eval is performing a call on that
         // value. Use a dynamic scope chain lookup rather than a full eval.
         if (string->isConcat() &&
             string->getOperand(1)->type() == MIRType_String &&
             string->getOperand(1)->maybeConstantValue())
         {
-            JSAtom* atom = &string->getOperand(1)->maybeConstantValue()->value().toString()->asAtom();
+            JSAtom* atom = &string->getOperand(1)->maybeConstantValue()->toString()->asAtom();
 
             if (StringEqualsAscii(atom, "()")) {
                 MDefinition* name = string->getOperand(0);
                 MInstruction* dynamicName = MGetDynamicName::New(alloc(), scopeChain, name);
                 current->add(dynamicName);
 
                 current->push(dynamicName);
                 current->push(constant(UndefinedValue())); // thisv
@@ -8298,17 +8297,17 @@ IonBuilder::setStaticName(JSObject* stat
     // compile time.
     if (isGlobalLexical && IsUninitializedGlobalLexicalSlot(staticObject, name))
         return jsop_setprop(name);
 
     current->pop();
 
     // Pop the bound object on the stack.
     MDefinition* obj = current->pop();
-    MOZ_ASSERT(&obj->toConstant()->value().toObject() == staticObject);
+    MOZ_ASSERT(&obj->toConstant()->toObject() == staticObject);
 
     if (NeedsPostBarrier(value))
         current->add(MPostWriteBarrier::New(alloc(), obj, value));
 
     // If the property has a known type, we may be able to optimize typed stores by not
     // storing the type tag.
     MIRType slotType = MIRType_None;
     MIRType knownType = property.knownMIRType(constraints());
@@ -8977,17 +8976,17 @@ IonBuilder::getElemTryGetProp(bool* emit
 {
     // If index is a constant string or symbol, try to optimize this GETELEM
     // as a GETPROP.
 
     MOZ_ASSERT(*emitted == false);
 
     MConstant* indexConst = index->maybeConstantValue();
     jsid id;
-    if (!indexConst || !ValueToIdPure(indexConst->value(), &id))
+    if (!indexConst || !ValueToIdPure(indexConst->toJSValue(), &id))
         return true;
 
     if (id != IdToTypeId(id))
         return true;
 
     TemporaryTypeSet* types = bytecodeTypes(pc);
 
     trackOptimizationAttempt(TrackedStrategy::GetProp_Constant);
@@ -9247,17 +9246,17 @@ IonBuilder::getElemTryArgumentsInlined(b
 
     MOZ_ASSERT(!info().argsObjAliasesFormals());
 
     // When the id is constant, we can just return the corresponding inlined argument
     MConstant* indexConst = index->maybeConstantValue();
     if (indexConst && indexConst->type() == MIRType_Int32) {
         MOZ_ASSERT(inliningDepth_ > 0);
 
-        int32_t id = indexConst->value().toInt32();
+        int32_t id = indexConst->toInt32();
         index->setImplicitlyUsedUnchecked();
 
         if (id < (int32_t)inlineCallInfo_->argc() && id >= 0)
             current->push(inlineCallInfo_->getArg(id));
         else
             pushConstant(UndefinedValue());
 
         trackOptimizationSuccess();
@@ -9489,17 +9488,17 @@ IonBuilder::addTypedArrayLengthAndData(M
                                        MInstruction** length, MInstruction** elements)
 {
     MOZ_ASSERT((index != nullptr) == (elements != nullptr));
 
     JSObject* tarr = nullptr;
 
     if (MConstant* objConst = obj->maybeConstantValue()) {
         if (objConst->type() == MIRType_Object)
-            tarr = &objConst->value().toObject();
+            tarr = &objConst->toObject();
     } else if (TemporaryTypeSet* types = obj->resultTypeSet()) {
         tarr = types->maybeSingleton();
     }
 
     if (tarr) {
         SharedMem<void*> data = tarr->as<TypedArrayObject>().viewDataEither();
         // Bug 979449 - Optimistically embed the elements and use TI to
         //              invalidate if we move them.
@@ -9551,34 +9550,35 @@ IonBuilder::convertShiftToMaskForStaticT
     // No shifting is necessary if the typed array has single byte elements.
     if (TypedArrayShift(viewType) == 0)
         return id;
 
     // If the index is an already shifted constant, undo the shift to get the
     // absolute offset being accessed.
     if (MConstant* idConst = id->maybeConstantValue()) {
         if (idConst->type() == MIRType_Int32) {
-            int32_t index = idConst->value().toInt32();
+            int32_t index = idConst->toInt32();
             MConstant* offset = MConstant::New(alloc(), Int32Value(index << TypedArrayShift(viewType)));
             current->add(offset);
             return offset;
         }
     }
 
     if (!id->isRsh() || id->isEffectful())
         return nullptr;
-    if (!id->getOperand(1)->maybeConstantValue())
+
+    MConstant* shiftAmount = id->toRsh()->rhs()->maybeConstantValue();
+    if (!shiftAmount || shiftAmount->type() != MIRType_Int32)
         return nullptr;
-    const Value& value = id->getOperand(1)->maybeConstantValue()->value();
-    if (!value.isInt32() || uint32_t(value.toInt32()) != TypedArrayShift(viewType))
+    if (uint32_t(shiftAmount->toInt32()) != TypedArrayShift(viewType))
         return nullptr;
 
     // Instead of shifting, mask off the low bits of the index so that
     // a non-scaled access on the typed array can be performed.
-    MConstant* mask = MConstant::New(alloc(), Int32Value(~((1 << value.toInt32()) - 1)));
+    MConstant* mask = MConstant::New(alloc(), Int32Value(~((1 << shiftAmount->toInt32()) - 1)));
     MBitAnd* ptr = MBitAnd::New(alloc(), id->getOperand(0), mask);
 
     ptr->infer(nullptr, nullptr);
     MOZ_ASSERT(!ptr->isEffectful());
 
     current->add(mask);
     current->add(ptr);
 
@@ -13397,18 +13397,19 @@ IonBuilder::inTryDense(bool* emitted, MD
 bool
 IonBuilder::inTryFold(bool* emitted, MDefinition* obj, MDefinition* id)
 {
     // Fold |id in obj| to |false|, if we know the object (or an object on its
     // prototype chain) does not have this property.
 
     MOZ_ASSERT(!*emitted);
 
+    MConstant* idConst = id->maybeConstantValue();
     jsid propId;
-    if (!id->maybeConstantValue() || !ValueToIdPure(id->maybeConstantValue()->value(), &propId))
+    if (!idConst || !ValueToIdPure(idConst->toJSValue(), &propId))
         return true;
 
     if (propId != IdToTypeId(propId))
         return true;
 
     TemporaryTypeSet* types = obj->resultTypeSet();
     if (!types || types->unknownObject())
         return true;
--- a/js/src/jit/LIR.h
+++ b/js/src/jit/LIR.h
@@ -64,17 +64,17 @@ class LAllocation : public TempObject
     static const uintptr_t KIND_MASK = (1 << KIND_BITS) - 1;
 
   protected:
     static const uintptr_t DATA_BITS = (sizeof(uint32_t) * 8) - KIND_BITS;
     static const uintptr_t DATA_SHIFT = KIND_SHIFT + KIND_BITS;
 
   public:
     enum Kind {
-        CONSTANT_VALUE, // Constant js::Value.
+        CONSTANT_VALUE, // MConstant*.
         CONSTANT_INDEX, // Constant arbitrary index.
         USE,            // Use of a virtual register, with physical allocation policy.
         GPR,            // General purpose register.
         FPU,            // Floating-point register.
         STACK_SLOT,     // Stack slot.
         ARGUMENT_SLOT   // Argument slot.
     };
 
@@ -102,20 +102,20 @@ class LAllocation : public TempObject
     }
 
   public:
     LAllocation() : bits_(0)
     {
         MOZ_ASSERT(isBogus());
     }
 
-    // The value pointer must be rooted in MIR and have its low bits cleared.
-    explicit LAllocation(const Value* vp) {
-        MOZ_ASSERT(vp);
-        bits_ = uintptr_t(vp);
+    // The MConstant pointer must have its low bits cleared.
+    explicit LAllocation(const MConstant* c) {
+        MOZ_ASSERT(c);
+        bits_ = uintptr_t(c);
         MOZ_ASSERT((bits_ & (KIND_MASK << KIND_SHIFT)) == 0);
         bits_ |= CONSTANT_VALUE << KIND_SHIFT;
     }
     inline explicit LAllocation(AnyRegister reg);
 
     Kind kind() const {
         return (Kind)((bits_ >> KIND_SHIFT) & KIND_MASK);
     }
@@ -161,19 +161,19 @@ class LAllocation : public TempObject
     inline const LUse* toUse() const;
     inline const LGeneralReg* toGeneralReg() const;
     inline const LFloatReg* toFloatReg() const;
     inline const LStackSlot* toStackSlot() const;
     inline const LArgument* toArgument() const;
     inline const LConstantIndex* toConstantIndex() const;
     inline AnyRegister toRegister() const;
 
-    const Value* toConstant() const {
+    const MConstant* toConstant() const {
         MOZ_ASSERT(isConstantValue());
-        return reinterpret_cast<const Value*>(bits_ & ~(KIND_MASK << KIND_SHIFT));
+        return reinterpret_cast<const MConstant*>(bits_ & ~(KIND_MASK << KIND_SHIFT));
     }
 
     bool operator ==(const LAllocation& other) const {
         return bits_ == other.bits_;
     }
 
     bool operator !=(const LAllocation& other) const {
         return bits_ != other.bits_;
--- a/js/src/jit/LoopUnroller.cpp
+++ b/js/src/jit/LoopUnroller.cpp
@@ -63,17 +63,17 @@ LoopUnroller::getReplacementDefinition(M
 
     DefinitionMap::Ptr p = unrolledDefinitions.lookup(def);
     if (!p) {
         // After phi analysis (TypeAnalyzer::replaceRedundantPhi) the resume
         // point at the start of a block can contain definitions from within
         // the block itself.
         MOZ_ASSERT(def->isConstant());
 
-        MConstant* constant = MConstant::New(alloc, def->toConstant()->value());
+        MConstant* constant = new(alloc) MConstant(*def->toConstant());
         oldPreheader->insertBefore(*oldPreheader->begin(), constant);
         return constant;
     }
 
     return p->value();
 }
 
 bool
--- a/js/src/jit/Lowering.cpp
+++ b/js/src/jit/Lowering.cpp
@@ -1591,35 +1591,35 @@ LIRGenerator::visitMul(MMul* ins)
     MOZ_ASSERT(lhs->type() == rhs->type());
 
     if (ins->specialization() == MIRType_Int32) {
         MOZ_ASSERT(lhs->type() == MIRType_Int32);
         ReorderCommutative(&lhs, &rhs, ins);
 
         // If our RHS is a constant -1 and we don't have to worry about
         // overflow, we can optimize to an LNegI.
-        if (!ins->fallible() && rhs->isConstant() && rhs->toConstant()->value().toInt32() == -1)
+        if (!ins->fallible() && rhs->isConstant() && rhs->toConstant()->toInt32() == -1)
             defineReuseInput(new(alloc()) LNegI(useRegisterAtStart(lhs)), ins, 0);
         else
             lowerMulI(ins, lhs, rhs);
     } else if (ins->specialization() == MIRType_Double) {
         MOZ_ASSERT(lhs->type() == MIRType_Double);
         ReorderCommutative(&lhs, &rhs, ins);
 
         // If our RHS is a constant -1.0, we can optimize to an LNegD.
-        if (rhs->isConstant() && rhs->toConstant()->value().toDouble() == -1.0)
+        if (rhs->isConstant() && rhs->toConstant()->toDouble() == -1.0)
             defineReuseInput(new(alloc()) LNegD(useRegisterAtStart(lhs)), ins, 0);
         else
             lowerForFPU(new(alloc()) LMathD(JSOP_MUL), ins, lhs, rhs);
     } else if (ins->specialization() == MIRType_Float32) {
         MOZ_ASSERT(lhs->type() == MIRType_Float32);
         ReorderCommutative(&lhs, &rhs, ins);
 
         // We apply the same optimizations as for doubles
-        if (rhs->isConstant() && rhs->toConstant()->value().toDouble() == -1.0)
+        if (rhs->isConstant() && rhs->toConstant()->toFloat32() == -1.0f)
             defineReuseInput(new(alloc()) LNegF(useRegisterAtStart(lhs)), ins, 0);
         else
             lowerForFPU(new(alloc()) LMathF(JSOP_MUL), ins, lhs, rhs);
     } else {
         lowerBinaryV(JSOP_MUL, ins);
     }
 }
 
@@ -2479,17 +2479,17 @@ LIRGenerator::visitMonitorTypes(MMonitor
 
 // 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)
 {
     if (!def->isConstant())
         return false;
-    Value v = def->toConstant()->value();
+    Value v = def->toConstant()->toJSValue();
     return !v.isMarkable() || !IsInsideNursery(v.toGCThing());
 }
 
 void
 LIRGenerator::visitPostWriteBarrier(MPostWriteBarrier* ins)
 {
     MOZ_ASSERT(ins->object()->type() == MIRType_Object);
 
@@ -2538,17 +2538,17 @@ LIRGenerator::visitPostWriteElementBarri
     MOZ_ASSERT(ins->index()->type() == MIRType_Int32);
 
     // LPostWriteElementBarrier assumes that if it has a constant object then that
     // object is tenured, and does not need to be tested for being in the
     // nursery. Ensure that assumption holds by lowering constant nursery
     // objects to a register.
     bool useConstantObject =
         ins->object()->isConstant() &&
-        !IsInsideNursery(&ins->object()->toConstant()->value().toObject());
+        !IsInsideNursery(&ins->object()->toConstant()->toObject());
 
     switch (ins->value()->type()) {
       case MIRType_Object:
       case MIRType_ObjectOrNull: {
         LDefinition tmp = needTempForPostBarrier() ? temp() : LDefinition::BogusTemp();
         LPostWriteElementBarrierO* lir =
             new(alloc()) LPostWriteElementBarrierO(useConstantObject
                                                    ? useOrConstant(ins->object())
--- a/js/src/jit/MCallOptimize.cpp
+++ b/js/src/jit/MCallOptimize.cpp
@@ -432,17 +432,17 @@ IonBuilder::inlineArray(CallInfo& callIn
             current->push(ins);
             return InliningStatus_Inlined;
         }
 
         // The next several checks all may fail due to range conditions.
         trackOptimizationOutcome(TrackedOutcome::ArrayRange);
 
         // Negative lengths generate a RangeError, unhandled by the inline path.
-        initLength = arg->toConstant()->value().toInt32();
+        initLength = arg->toConstant()->toInt32();
         if (initLength > NativeObject::MAX_DENSE_ELEMENTS_COUNT)
             return InliningStatus_NotInlined;
         MOZ_ASSERT(initLength <= INT32_MAX);
 
         // Make sure initLength matches the template object's length. This is
         // not guaranteed to be the case, for instance if we're inlining the
         // MConstant may come from an outer script.
         if (initLength != GetAnyBoxedOrUnboxedArrayLength(templateObject))
@@ -1260,17 +1260,17 @@ IonBuilder::inlineMathPowHelper(MDefinit
         return InliningStatus_NotInlined;
 
     MDefinition* base = lhs;
     MDefinition* power = rhs;
     MDefinition* output = nullptr;
 
     // Optimize some constant powers.
     if (rhs->isConstant()) {
-        double pow = rhs->toConstant()->value().toNumber();
+        double pow = rhs->toConstant()->toNumber();
 
         // Math.pow(x, 0.5) is a sqrt with edge-case detection.
         if (pow == 0.5) {
             MPowHalf* half = MPowHalf::New(alloc(), base);
             current->add(half);
             output = half;
         }
 
@@ -1466,17 +1466,17 @@ IonBuilder::inlineMathMinMax(CallInfo& c
             if (!int32_cases.append(arg))
                 return InliningStatus_Error;
             break;
           case MIRType_Double:
           case MIRType_Float32:
             // Don't force a double MMinMax for arguments that would be a NOP
             // when doing an integer MMinMax.
             if (arg->isConstant()) {
-                double cte = arg->toConstant()->value().toDouble();
+                double cte = arg->toConstant()->toNumber();
                 // min(int32, cte >= INT32_MAX) = int32
                 if (cte >= INT32_MAX && !max)
                     break;
                 // max(int32, cte <= INT32_MIN) = int32
                 if (cte <= INT32_MIN && max)
                     break;
             }
 
@@ -1549,27 +1549,24 @@ IonBuilder::InliningStatus
 IonBuilder::inlineConstantStringSplit(CallInfo& callInfo)
 {
     if (!callInfo.thisArg()->isConstant())
         return InliningStatus_NotInlined;
 
     if (!callInfo.getArg(0)->isConstant())
         return InliningStatus_NotInlined;
 
-    const js::Value* argval = callInfo.getArg(0)->toConstant()->vp();
-    if (!argval->isString())
+    MConstant* argval = callInfo.getArg(0)->toConstant();
+    if (argval->type() != MIRType_String)
         return InliningStatus_NotInlined;
 
-    const js::Value* strval = callInfo.thisArg()->toConstant()->vp();
-    if (!strval->isString())
+    MConstant* strval = callInfo.thisArg()->toConstant();
+    if (strval->type() != MIRType_String)
         return InliningStatus_NotInlined;
 
-    MOZ_ASSERT(callInfo.getArg(0)->type() == MIRType_String);
-    MOZ_ASSERT(callInfo.thisArg()->type() == MIRType_String);
-
     // Check if exist a template object in stub.
     JSString* stringThis = nullptr;
     JSString* stringArg = nullptr;
     JSObject* templateObject = nullptr;
     if (!inspector->isOptimizableCallStringSplit(pc, &stringThis, &stringArg, &templateObject))
         return InliningStatus_NotInlined;
 
     MOZ_ASSERT(stringThis);
@@ -1739,20 +1736,20 @@ IonBuilder::inlineStrCharCodeAt(CallInfo
 IonBuilder::InliningStatus
 IonBuilder::inlineConstantCharCodeAt(CallInfo& callInfo)
 {
     if (!callInfo.thisArg()->maybeConstantValue() || !callInfo.getArg(0)->maybeConstantValue()) {
         trackOptimizationOutcome(TrackedOutcome::CantInlineGeneric);
         return InliningStatus_NotInlined;
     }
 
-    const js::Value* strval = callInfo.thisArg()->maybeConstantValue()->vp();
-    const js::Value* idxval = callInfo.getArg(0)->maybeConstantValue()->vp();
-
-    if (!strval->isString() || !idxval->isInt32())
+    MConstant* strval = callInfo.thisArg()->maybeConstantValue();
+    MConstant* idxval = callInfo.getArg(0)->maybeConstantValue();
+
+    if (strval->type() != MIRType_String || idxval->type() != MIRType_Int32)
         return InliningStatus_NotInlined;
 
     JSString* str = strval->toString();
     if (!str->isLinear()) {
         trackOptimizationOutcome(TrackedOutcome::CantInlineGeneric);
         return InliningStatus_NotInlined;
     }
 
@@ -2411,17 +2408,17 @@ IonBuilder::inlineUnsafeSetReservedSlot(
         return InliningStatus_NotInlined;
     if (callInfo.getArg(1)->type() != MIRType_Int32)
         return InliningStatus_NotInlined;
 
     // Don't inline if we don't have a constant slot.
     MDefinition* arg = callInfo.getArg(1);
     if (!arg->isConstant())
         return InliningStatus_NotInlined;
-    uint32_t slot = arg->toConstant()->value().toPrivateUint32();
+    uint32_t slot = uint32_t(arg->toConstant()->toInt32());
 
     callInfo.setImplicitlyUsedUnchecked();
 
     MStoreFixedSlot* store = MStoreFixedSlot::New(alloc(), callInfo.getArg(0), slot, callInfo.getArg(2));
     current->add(store);
     current->push(store);
 
     if (NeedsPostBarrier(callInfo.getArg(2)))
@@ -2441,17 +2438,17 @@ IonBuilder::inlineUnsafeGetReservedSlot(
         return InliningStatus_NotInlined;
     if (callInfo.getArg(1)->type() != MIRType_Int32)
         return InliningStatus_NotInlined;
 
     // Don't inline if we don't have a constant slot.
     MDefinition* arg = callInfo.getArg(1);
     if (!arg->isConstant())
         return InliningStatus_NotInlined;
-    uint32_t slot = arg->toConstant()->value().toPrivateUint32();
+    uint32_t slot = uint32_t(arg->toConstant()->toInt32());
 
     callInfo.setImplicitlyUsedUnchecked();
 
     MLoadFixedSlot* load = MLoadFixedSlot::New(alloc(), callInfo.getArg(0), slot);
     current->add(load);
     current->push(load);
     if (knownValueType != MIRType_Value) {
         // We know what type we have in this slot.  Assert that this is in fact
@@ -2629,17 +2626,17 @@ IonBuilder::inlineAssertFloat32(CallInfo
     if (callInfo.argc() != 2)
         return InliningStatus_NotInlined;
 
     MDefinition* secondArg = callInfo.getArg(1);
 
     MOZ_ASSERT(secondArg->type() == MIRType_Boolean);
     MOZ_ASSERT(secondArg->isConstant());
 
-    bool mustBeFloat32 = secondArg->toConstant()->value().toBoolean();
+    bool mustBeFloat32 = secondArg->toConstant()->toBoolean();
     current->add(MAssertFloat32::New(alloc(), callInfo.getArg(0), mustBeFloat32));
 
     MConstant* undefined = MConstant::New(alloc(), UndefinedValue());
     current->add(undefined);
     current->push(undefined);
     callInfo.setImplicitlyUsedUnchecked();
     return InliningStatus_Inlined;
 }
@@ -2659,17 +2656,17 @@ IonBuilder::inlineAssertRecoveredOnBailo
         return InliningStatus_Inlined;
     }
 
     MDefinition* secondArg = callInfo.getArg(1);
 
     MOZ_ASSERT(secondArg->type() == MIRType_Boolean);
     MOZ_ASSERT(secondArg->isConstant());
 
-    bool mustBeRecovered = secondArg->toConstant()->value().toBoolean();
+    bool mustBeRecovered = secondArg->toConstant()->toBoolean();
     MAssertRecoveredOnBailout* assert =
         MAssertRecoveredOnBailout::New(alloc(), callInfo.getArg(0), mustBeRecovered);
     current->add(assert);
     current->push(assert);
 
     // Create an instruction sequence which implies that the argument of the
     // assertRecoveredOnBailout function would be encoded at least in one
     // Snapshot.
@@ -3492,17 +3489,17 @@ IonBuilder::inlineSimdExtractLane(CallIn
         trackOptimizationOutcome(TrackedOutcome::CantInlineNativeBadForm);
         return InliningStatus_NotInlined;
     }
 
     // Lane index.
     MDefinition* arg = callInfo.getArg(1);
     if (!arg->isConstant() || arg->type() != MIRType_Int32)
         return InliningStatus_NotInlined;
-    int32_t lane = arg->toConstant()->value().toInt32();
+    int32_t lane = arg->toConstant()->toInt32();
     if (lane < 0 || lane >= 4)
         return InliningStatus_NotInlined;
 
     // Original vector.
     MDefinition* orig = unboxSimd(callInfo.getArg(0), type);
     MIRType vecType = orig->type();
     MIRType laneType = SimdTypeToLaneType(vecType);
     SimdSign sign = GetSimdSign(type);
@@ -3526,17 +3523,17 @@ IonBuilder::inlineSimdReplaceLane(CallIn
     if (!canInlineSimd(callInfo, native, 3, &templateObj))
         return InliningStatus_NotInlined;
 
     // Lane index.
     MDefinition* arg = callInfo.getArg(1);
     if (!arg->isConstant() || arg->type() != MIRType_Int32)
         return InliningStatus_NotInlined;
 
-    int32_t lane = arg->toConstant()->value().toInt32();
+    int32_t lane = arg->toConstant()->toInt32();
     if (lane < 0 || lane >= 4)
         return InliningStatus_NotInlined;
 
     // Original vector.
     MDefinition* orig = unboxSimd(callInfo.getArg(0), type);
     MIRType vecType = orig->type();
 
     // Convert to 0 / -1 before inserting a boolean lane.
--- a/js/src/jit/MIR.cpp
+++ b/js/src/jit/MIR.cpp
@@ -85,59 +85,59 @@ EvaluateConstantOperands(TempAllocator& 
     MDefinition* left = ins->getOperand(0);
     MDefinition* right = ins->getOperand(1);
 
     MOZ_ASSERT(IsNumberType(left->type()) && IsNumberType(right->type()));
 
     if (!left->isConstant() || !right->isConstant())
         return nullptr;
 
-    Value lhs = left->toConstant()->value();
-    Value rhs = right->toConstant()->value();
+    MConstant* lhs = left->toConstant();
+    MConstant* rhs = right->toConstant();
     Value ret = UndefinedValue();
 
     switch (ins->op()) {
       case MDefinition::Op_BitAnd:
-        ret = Int32Value(lhs.toInt32() & rhs.toInt32());
+        ret = Int32Value(lhs->toInt32() & rhs->toInt32());
         break;
       case MDefinition::Op_BitOr:
-        ret = Int32Value(lhs.toInt32() | rhs.toInt32());
+        ret = Int32Value(lhs->toInt32() | rhs->toInt32());
         break;
       case MDefinition::Op_BitXor:
-        ret = Int32Value(lhs.toInt32() ^ rhs.toInt32());
+        ret = Int32Value(lhs->toInt32() ^ rhs->toInt32());
         break;
       case MDefinition::Op_Lsh:
-        ret = Int32Value(uint32_t(lhs.toInt32()) << (rhs.toInt32() & 0x1F));
+        ret = Int32Value(uint32_t(lhs->toInt32()) << (rhs->toInt32() & 0x1F));
         break;
       case MDefinition::Op_Rsh:
-        ret = Int32Value(lhs.toInt32() >> (rhs.toInt32() & 0x1F));
+        ret = Int32Value(lhs->toInt32() >> (rhs->toInt32() & 0x1F));
         break;
       case MDefinition::Op_Ursh:
-        ret.setNumber(uint32_t(lhs.toInt32()) >> (rhs.toInt32() & 0x1F));
+        ret.setNumber(uint32_t(lhs->toInt32()) >> (rhs->toInt32() & 0x1F));
         break;
       case MDefinition::Op_Add:
-        ret.setNumber(lhs.toNumber() + rhs.toNumber());
+        ret.setNumber(lhs->toNumber() + rhs->toNumber());
         break;
       case MDefinition::Op_Sub:
-        ret.setNumber(lhs.toNumber() - rhs.toNumber());
+        ret.setNumber(lhs->toNumber() - rhs->toNumber());
         break;
       case MDefinition::Op_Mul:
-        ret.setNumber(lhs.toNumber() * rhs.toNumber());
+        ret.setNumber(lhs->toNumber() * rhs->toNumber());
         break;
       case MDefinition::Op_Div:
         if (ins->toDiv()->isUnsigned())
-            ret.setInt32(rhs.isInt32(0) ? 0 : uint32_t(lhs.toInt32()) / uint32_t(rhs.toInt32()));
+            ret.setInt32(rhs->isInt32(0) ? 0 : uint32_t(lhs->toInt32()) / uint32_t(rhs->toInt32()));
         else
-            ret.setNumber(NumberDiv(lhs.toNumber(), rhs.toNumber()));
+            ret.setNumber(NumberDiv(lhs->toNumber(), rhs->toNumber()));
         break;
       case MDefinition::Op_Mod:
         if (ins->toMod()->isUnsigned())
-            ret.setInt32(rhs.isInt32(0) ? 0 : uint32_t(lhs.toInt32()) % uint32_t(rhs.toInt32()));
+            ret.setInt32(rhs->isInt32(0) ? 0 : uint32_t(lhs->toInt32()) % uint32_t(rhs->toInt32()));
         else
-            ret.setNumber(NumberMod(lhs.toNumber(), rhs.toNumber()));
+            ret.setNumber(NumberMod(lhs->toNumber(), rhs->toNumber()));
         break;
       default:
         MOZ_CRASH("NYI");
     }
 
     // setNumber eagerly transforms a number to int32.
     // Transform back to double, if the output type is double.
     if (ins->type() == MIRType_Double && ret.isInt32())
@@ -160,20 +160,18 @@ EvaluateExactReciprocal(TempAllocator& a
         return nullptr;
 
     MDefinition* left = ins->getOperand(0);
     MDefinition* right = ins->getOperand(1);
 
     if (!right->isConstant())
         return nullptr;
 
-    Value rhs = right->toConstant()->value();
-
     int32_t num;
-    if (!mozilla::NumberIsInt32(rhs.toNumber(), &num))
+    if (!mozilla::NumberIsInt32(right->toConstant()->toNumber(), &num))
         return nullptr;
 
     // check if rhs is a power of two
     if (mozilla::Abs(num) & (mozilla::Abs(num) - 1))
         return nullptr;
 
     Value ret;
     ret.setDouble(1.0 / (double) num);
@@ -785,71 +783,70 @@ MConstant::valueHash() const
     return (HashNumber)bits ^ (HashNumber)(bits >> 32);
 }
 
 bool
 MConstant::congruentTo(const MDefinition* ins) const
 {
     if (!ins->isConstant())
         return false;
-    return ins->toConstant()->value() == value();
+    return ins->toConstant()->value_ == value_;
 }
 
 void
 MConstant::printOpcode(GenericPrinter& out) const
 {
     PrintOpcodeName(out, op());
     out.printf(" ");
     switch (type()) {
       case MIRType_Undefined:
         out.printf("undefined");
         break;
       case MIRType_Null:
         out.printf("null");
         break;
       case MIRType_Boolean:
-        out.printf(value().toBoolean() ? "true" : "false");
+        out.printf(toBoolean() ? "true" : "false");
         break;
       case MIRType_Int32:
-        out.printf("0x%x", value().toInt32());
+        out.printf("0x%x", toInt32());
         break;
       case MIRType_Double:
-        out.printf("%.16g", value().toDouble());
+        out.printf("%.16g", toDouble());
         break;
       case MIRType_Float32:
       {
-        float val = value().toDouble();
+        float val = toFloat32();
         out.printf("%.16g", val);
         break;
       }
       case MIRType_Object:
-        if (value().toObject().is<JSFunction>()) {
-            JSFunction* fun = &value().toObject().as<JSFunction>();
+        if (toObject().is<JSFunction>()) {
+            JSFunction* fun = &toObject().as<JSFunction>();
             if (fun->displayAtom()) {
                 out.put("function ");
                 EscapedStringPrinter(out, fun->displayAtom(), 0);
             } else {
                 out.put("unnamed function");
             }
             if (fun->hasScript()) {
                 JSScript* script = fun->nonLazyScript();
                 out.printf(" (%s:%" PRIuSIZE ")",
                         script->filename() ? script->filename() : "", script->lineno());
             }
             out.printf(" at %p", (void*) fun);
             break;
         }
-        out.printf("object %p (%s)", (void*)&value().toObject(),
-                value().toObject().getClass()->name);
+        out.printf("object %p (%s)", (void*)&toObject(), toObject().getClass()->name);
         break;
       case MIRType_Symbol:
-        out.printf("symbol at %p", (void*)value().toSymbol());
+        out.printf("symbol at %p", (void*)toSymbol());
         break;
       case MIRType_String:
-        out.printf("string %p", (void*)value().toString());
+        out.printf("string %p", (void*)toString());
         break;
       case MIRType_MagicOptimizedArguments:
         out.printf("magic lazyargs");
         break;
       case MIRType_MagicHole:
         out.printf("magic hole");
         break;
       case MIRType_MagicIsConstructing:
@@ -868,22 +865,29 @@ MConstant::printOpcode(GenericPrinter& o
 
 bool
 MConstant::canProduceFloat32() const
 {
     if (!IsNumberType(type()))
         return false;
 
     if (type() == MIRType_Int32)
-        return IsFloat32Representable(static_cast<double>(value_.toInt32()));
+        return IsFloat32Representable(static_cast<double>(toInt32()));
     if (type() == MIRType_Double)
-        return IsFloat32Representable(value_.toDouble());
+        return IsFloat32Representable(toDouble());
+    MOZ_ASSERT(type() == MIRType_Float32);
     return true;
 }
 
+Value
+MConstant::toJSValue() const
+{
+    return value_;
+}
+
 bool
 MConstant::valueToBoolean(bool* res) const
 {
     switch (type()) {
       case MIRType_Boolean:
         *res = value_.toBoolean();
         return true;
       case MIRType_Int32:
@@ -939,24 +943,24 @@ MSimdValueX4::foldsTo(TempAllocator& all
             for (size_t i = 0; i < 4; ++i)
                 a[i] = getOperand(i)->toConstant()->valueToBooleanInfallible() ? -1 : 0;
             cst = SimdConstant::CreateX4(a);
             break;
           }
           case MIRType_Int32x4: {
             int32_t a[4];
             for (size_t i = 0; i < 4; ++i)
-                a[i] = getOperand(i)->toConstant()->value().toInt32();
+                a[i] = getOperand(i)->toConstant()->toInt32();
             cst = SimdConstant::CreateX4(a);
             break;
           }
           case MIRType_Float32x4: {
             float a[4];
             for (size_t i = 0; i < 4; ++i)
-                a[i] = getOperand(i)->toConstant()->value().toNumber();
+                a[i] = getOperand(i)->toConstant()->toNumber();
             cst = SimdConstant::CreateX4(a);
             break;
           }
           default: MOZ_CRASH("unexpected type in MSimdValueX4::foldsTo");
         }
 
         return MSimdConstant::New(alloc, cst, type());
     }
@@ -977,22 +981,22 @@ MSimdSplatX4::foldsTo(TempAllocator& all
     SimdConstant cst;
     switch (type()) {
       case MIRType_Bool32x4: {
         int32_t v = op->toConstant()->valueToBooleanInfallible() ? -1 : 0;
         cst = SimdConstant::SplatX4(v);
         break;
       }
       case MIRType_Int32x4: {
-        int32_t v = op->toConstant()->value().toInt32();
+        int32_t v = op->toConstant()->toInt32();
         cst = SimdConstant::SplatX4(v);
         break;
       }
       case MIRType_Float32x4: {
-        float v = op->toConstant()->value().toNumber();
+        float v = op->toConstant()->toNumber();
         cst = SimdConstant::SplatX4(v);
         break;
       }
       default: MOZ_CRASH("unexpected type in MSimdSplatX4::foldsTo");
     }
 
     return MSimdConstant::New(alloc, cst, type());
 }
@@ -1030,17 +1034,17 @@ MSimdGeneralShuffle::foldsTo(TempAllocat
 {
     FixedList<uint32_t> lanes;
     if (!lanes.init(alloc, numLanes()))
         return this;
 
     for (size_t i = 0; i < numLanes(); i++) {
         if (!lane(i)->isConstant() || lane(i)->type() != MIRType_Int32)
             return this;
-        int32_t temp = lane(i)->toConstant()->value().toInt32();
+        int32_t temp = lane(i)->toConstant()->toInt32();
         if (temp < 0 || uint32_t(temp) >= numLanes() * numVectors())
             return this;
         lanes[i] = uint32_t(temp);
     }
 
     if (numVectors() == 1)
         return MSimdSwizzle::New(alloc, vector(0), lanes[0], lanes[1], lanes[2], lanes[3]);
 
@@ -1310,24 +1314,20 @@ MMathFunction::printOpcode(GenericPrinte
     MDefinition::printOpcode(out);
     out.printf(" %s", FunctionName(function()));
 }
 
 MDefinition*
 MMathFunction::foldsTo(TempAllocator& alloc)
 {
     MDefinition* input = getOperand(0);
-    if (!input->isConstant())
+    if (!input->isConstant() || !input->toConstant()->isNumber())
         return this;
 
-    Value val = input->toConstant()->value();
-    if (!val.isNumber())
-        return this;
-
-    double in = val.toNumber();
+    double in = input->toConstant()->toNumber();
     double out;
     switch (function_) {
       case Log:
         out = js::math_log_uncached(in);
         break;
       case Sin:
         out = js::math_sin_uncached(in);
         break;
@@ -1405,24 +1405,21 @@ MMathFunction::foldsTo(TempAllocator& al
         return MConstant::NewTypedValue(alloc, DoubleValue(out), MIRType_Float32);
     return MConstant::New(alloc, DoubleValue(out));
 }
 
 MDefinition*
 MAtomicIsLockFree::foldsTo(TempAllocator& alloc)
 {
     MDefinition* input = getOperand(0);
-    if (!input->isConstant())
+    if (!input->isConstant() || input->type() != MIRType_Int32)
         return this;
 
-    Value val = input->toConstant()->value();
-    if (!val.isInt32())
-        return this;
-
-    return MConstant::New(alloc, BooleanValue(AtomicOperations::isLockfree(val.toInt32())));
+    int32_t i = input->toConstant()->toInt32();
+    return MConstant::New(alloc, BooleanValue(AtomicOperations::isLockfree(i)));
 }
 
 MParameter*
 MParameter::New(TempAllocator& alloc, int32_t index, TemporaryTypeSet* types)
 {
     return new(alloc) MParameter(index, types);
 }
 
@@ -1598,31 +1595,30 @@ MApplyArray::New(TempAllocator& alloc, J
 {
     return new(alloc) MApplyArray(target, fun, elements, self);
 }
 
 MDefinition*
 MStringLength::foldsTo(TempAllocator& alloc)
 {
     if (type() == MIRType_Int32 && string()->isConstant()) {
-        Value value = string()->toConstant()->value();
-        JSAtom* atom = &value.toString()->asAtom();
+        JSAtom* atom = &string()->toConstant()->toString()->asAtom();
         return MConstant::New(alloc, Int32Value(atom->length()));
     }
 
     return this;
 }
 
 MDefinition*
 MConcat::foldsTo(TempAllocator& alloc)
 {
-    if (lhs()->isConstant() && lhs()->toConstant()->value().toString()->empty())
+    if (lhs()->isConstant() && lhs()->toConstant()->toString()->empty())
         return rhs();
 
-    if (rhs()->isConstant() && rhs()->toConstant()->value().toString()->empty())
+    if (rhs()->isConstant() && rhs()->toConstant()->toString()->empty())
         return lhs();
 
     return this;
 }
 
 static bool
 EnsureFloatInputOrConvert(MUnaryInstruction* owner, TempAllocator& alloc)
 {
@@ -1889,28 +1885,28 @@ MPhi::foldsTernary()
         !falseDef->block()->dominates(falsePred))
     {
         return nullptr;
     }
 
     // If testArg is an int32 type we can:
     // - fold testArg ? testArg : 0 to testArg
     // - fold testArg ? 0 : testArg to 0
-    if (testArg->type() == MIRType_Int32 && c->vp()->toNumber() == 0) {
+    if (testArg->type() == MIRType_Int32 && c->toNumber() == 0) {
         // When folding to the constant we need to hoist it.
         if (trueDef == c && !c->block()->dominates(block()))
             c->block()->moveBefore(pred->lastIns(), c);
         return trueDef;
     }
 
     // If testArg is a string type we can:
     // - fold testArg ? testArg : "" to testArg
     // - fold testArg ? "" : testArg to ""
     if (testArg->type() == MIRType_String &&
-        c->vp()->toString() == GetJitContext()->runtime->emptyString())
+        c->toString() == GetJitContext()->runtime->emptyString())
     {
         // When folding to the constant we need to hoist it.
         if (trueDef == c && !c->block()->dominates(block()))
             c->block()->moveBefore(pred->lastIns(), c);
         return trueDef;
     }
 
     return nullptr;
@@ -2265,17 +2261,17 @@ MCall::addArg(size_t argnum, MDefinition
 }
 
 static inline bool
 IsConstant(MDefinition* def, double v)
 {
     if (!def->isConstant())
         return false;
 
-    return NumbersAreIdentical(def->toConstant()->value().toNumber(), v);
+    return NumbersAreIdentical(def->toConstant()->toNumber(), v);
 }
 
 MDefinition*
 MBinaryBitwiseInstruction::foldsTo(TempAllocator& alloc)
 {
     if (specialization_ != MIRType_Int32)
         return this;
 
@@ -2382,17 +2378,17 @@ MUrsh::infer(BaselineInspector* inspecto
 
 static inline bool
 CanProduceNegativeZero(MDefinition* def)
 {
     // Test if this instruction can produce negative zero even when bailing out
     // and changing types.
     switch (def->op()) {
         case MDefinition::Op_Constant:
-            if (def->type() == MIRType_Double && def->toConstant()->value().toDouble() == -0.0)
+            if (def->type() == MIRType_Double && def->toConstant()->toDouble() == -0.0)
                 return true;
             MOZ_FALLTHROUGH;
         case MDefinition::Op_BitAnd:
         case MDefinition::Op_BitOr:
         case MDefinition::Op_BitXor:
         case MDefinition::Op_BitNot:
         case MDefinition::Op_Lsh:
         case MDefinition::Op_Rsh:
@@ -2679,23 +2675,21 @@ MDefinition*
 MMinMax::foldsTo(TempAllocator& alloc)
 {
     if (!lhs()->isConstant() && !rhs()->isConstant())
         return this;
 
     // Directly apply math utility to compare the rhs() and lhs() when
     // they are both constants.
     if (lhs()->isConstant() && rhs()->isConstant()) {
-        Value lval = lhs()->toConstant()->value();
-        Value rval = rhs()->toConstant()->value();
-        if (!lval.isNumber() || !rval.isNumber())
+        if (!lhs()->toConstant()->isNumber() || !rhs()->toConstant()->isNumber())
             return this;
 
-        double lnum = lval.toNumber();
-        double rnum = rval.toNumber();
+        double lnum = lhs()->toConstant()->toNumber();
+        double rnum = rhs()->toConstant()->toNumber();
         double result;
         if (isMax())
             result = js::math_max_impl(lnum, rnum);
         else
             result = js::math_min_impl(lnum, rnum);
 
         // The folded MConstant should maintain the same MIRType with
         // the original MMinMax.
@@ -2708,31 +2702,30 @@ MMinMax::foldsTo(TempAllocator& alloc)
             MConstant* constant = MConstant::New(alloc, DoubleValue(result));
             if (type() == MIRType_Float32)
                 constant->setResultType(MIRType_Float32);
             return constant;
         }
     }
 
     MDefinition* operand = lhs()->isConstant() ? rhs() : lhs();
-    const js::Value& val =
-        lhs()->isConstant() ? lhs()->toConstant()->value() : rhs()->toConstant()->value();
+    MConstant* constant = lhs()->isConstant() ? lhs()->toConstant() : rhs()->toConstant();
 
     if (operand->isToDouble() && operand->getOperand(0)->type() == MIRType_Int32) {
         // min(int32, cte >= INT32_MAX) = int32
-        if (val.isDouble() && val.toDouble() >= INT32_MAX && !isMax()) {
+        if (constant->isNumber() && constant->toNumber() >= INT32_MAX && !isMax()) {
             MLimitedTruncate* limit =
                 MLimitedTruncate::New(alloc, operand->getOperand(0), MDefinition::NoTruncate);
             block()->insertBefore(this, limit);
             MToDouble* toDouble = MToDouble::New(alloc, limit);
             return toDouble;
         }
 
         // max(int32, cte <= INT32_MIN) = int32
-        if (val.isDouble() && val.toDouble() <= INT32_MIN && isMax()) {
+        if (constant->isNumber() && constant->toNumber() <= INT32_MIN && isMax()) {
             MLimitedTruncate* limit =
                 MLimitedTruncate::New(alloc, operand->getOperand(0), MDefinition::NoTruncate);
             block()->insertBefore(this, limit);
             MToDouble* toDouble = MToDouble::New(alloc, limit);
             return toDouble;
         }
     }
     return this;
@@ -2782,36 +2775,35 @@ MDiv::analyzeEdgeCasesForward()
     // This is only meaningful when doing integer division.
     if (specialization_ != MIRType_Int32)
         return;
 
     MOZ_ASSERT(lhs()->type() == MIRType_Int32);
     MOZ_ASSERT(rhs()->type() == MIRType_Int32);
 
     // Try removing divide by zero check
-    if (rhs()->isConstant() && !rhs()->toConstant()->value().isInt32(0))
+    if (rhs()->isConstant() && !rhs()->toConstant()->isInt32(0))
         canBeDivideByZero_ = false;
 
     // If lhs is a constant int != INT32_MIN, then
     // negative overflow check can be skipped.
-    if (lhs()->isConstant() && !lhs()->toConstant()->value().isInt32(INT32_MIN))
+    if (lhs()->isConstant() && !lhs()->toConstant()->isInt32(INT32_MIN))
         canBeNegativeOverflow_ = false;
 
     // If rhs is a constant int != -1, likewise.
-    if (rhs()->isConstant() && !rhs()->toConstant()->value().isInt32(-1))
+    if (rhs()->isConstant() && !rhs()->toConstant()->isInt32(-1))
         canBeNegativeOverflow_ = false;
 
     // If lhs is != 0, then negative zero check can be skipped.
-    if (lhs()->isConstant() && !lhs()->toConstant()->value().isInt32(0))
+    if (lhs()->isConstant() && !lhs()->toConstant()->isInt32(0))
         setCanBeNegativeZero(false);
 
     // If rhs is >= 0, likewise.
-    if (rhs()->isConstant()) {
-        const js::Value& val = rhs()->toConstant()->value();
-        if (val.isInt32() && val.toInt32() >= 0)
+    if (rhs()->isConstant() && rhs()->type() == MIRType_Int32) {
+        if (rhs()->toConstant()->toInt32() >= 0)
             setCanBeNegativeZero(false);
     }
 }
 
 void
 MDiv::analyzeEdgeCasesBackward()
 {
     if (canBeNegativeZero() && !NeedNegativeZeroCheck(this))
@@ -2838,21 +2830,21 @@ MMod::foldsTo(TempAllocator& alloc)
 
 void
 MMod::analyzeEdgeCasesForward()
 {
     // These optimizations make sense only for integer division
     if (specialization_ != MIRType_Int32)
         return;
 
-    if (rhs()->isConstant() && !rhs()->toConstant()->value().isInt32(0))
+    if (rhs()->isConstant() && !rhs()->toConstant()->isInt32(0))
         canBeDivideByZero_ = false;
 
     if (rhs()->isConstant()) {
-        int32_t n = rhs()->toConstant()->value().toInt32();
+        int32_t n = rhs()->toConstant()->toInt32();
         if (n > 0 && !IsPowerOfTwo(n))
             canBePowerOfTwoDivisor_ = false;
     }
 }
 
 bool
 MMod::fallible() const
 {
@@ -2928,26 +2920,24 @@ void
 MMul::analyzeEdgeCasesForward()
 {
     // Try to remove the check for negative zero
     // This only makes sense when using the integer multiplication
     if (specialization() != MIRType_Int32)
         return;
 
     // If lhs is > 0, no need for negative zero check.
-    if (lhs()->isConstant()) {
-        const js::Value& val = lhs()->toConstant()->value();
-        if (val.isInt32() && val.toInt32() > 0)
+    if (lhs()->isConstant() && lhs()->type() == MIRType_Int32) {
+        if (lhs()->toConstant()->toInt32() > 0)
             setCanBeNegativeZero(false);
     }
 
     // If rhs is > 0, likewise.
-    if (rhs()->isConstant()) {
-        const js::Value& val = rhs()->toConstant()->value();
-        if (val.isInt32() && val.toInt32() > 0)
+    if (rhs()->isConstant() && rhs()->type() == MIRType_Int32) {
+        if (rhs()->toConstant()->toInt32() > 0)
             setCanBeNegativeZero(false);
     }
 }
 
 void
 MMul::analyzeEdgeCasesBackward()
 {
     if (canBeNegativeZero() && !NeedNegativeZeroCheck(this))
@@ -3039,22 +3029,22 @@ MCompare::inputType()
 static inline bool
 MustBeUInt32(MDefinition* def, MDefinition** pwrapped)
 {
     if (def->isUrsh()) {
         *pwrapped = def->toUrsh()->lhs();
         MDefinition* rhs = def->toUrsh()->rhs();
         return !def->toUrsh()->bailoutsDisabled() &&
                rhs->maybeConstantValue() &&
-               rhs->maybeConstantValue()->value().isInt32(0);
+               rhs->maybeConstantValue()->isInt32(0);
     }
 
     if (MConstant* defConst = def->maybeConstantValue()) {
         *pwrapped = defConst;
-        return defConst->value().isInt32(0);
+        return defConst->isInt32(0);
     }
 
     return false;
 }
 
 /* static */ bool
 MBinaryInstruction::unsignedOperands(MDefinition* left, MDefinition* right)
 {
@@ -3193,17 +3183,17 @@ MDefinition*
 MBitNot::foldsTo(TempAllocator& alloc)
 {
     if (specialization_ != MIRType_Int32)
         return this;
 
     MDefinition* input = getOperand(0);
 
     if (input->isConstant()) {
-        js::Value v = Int32Value(~(input->toConstant()->value().toInt32()));
+        js::Value v = Int32Value(~(input->toConstant()->toInt32()));
         return MConstant::New(alloc, v);
     }
 
     if (input->isBitNot() && input->toBitNot()->specialization_ == MIRType_Int32) {
         MOZ_ASSERT(input->toBitNot()->getOperand(0)->type() == MIRType_Int32);
         return MTruncateToInt32::New(alloc, input->toBitNot()->input()); // ~~x => x | 0
     }
 
@@ -3512,33 +3502,32 @@ MResumePoint::isRecoverableOperand(MUse*
 
 MDefinition*
 MToInt32::foldsTo(TempAllocator& alloc)
 {
     MDefinition* input = getOperand(0);
 
     // Fold this operation if the input operand is constant.
     if (input->isConstant()) {
-        Value val = input->toConstant()->value();
         DebugOnly<MacroAssembler::IntConversionInputKind> convert = conversion();
         switch (input->type()) {
           case MIRType_Null:
             MOZ_ASSERT(convert == MacroAssembler::IntConversion_Any);
             return MConstant::New(alloc, Int32Value(0));
           case MIRType_Boolean:
             MOZ_ASSERT(convert == MacroAssembler::IntConversion_Any ||
                        convert == MacroAssembler::IntConversion_NumbersOrBoolsOnly);
-            return MConstant::New(alloc, Int32Value(val.toBoolean()));
+            return MConstant::New(alloc, Int32Value(input->toConstant()->toBoolean()));
           case MIRType_Int32:
-            return MConstant::New(alloc, Int32Value(val.toInt32()));
+            return MConstant::New(alloc, Int32Value(input->toConstant()->toInt32()));
           case MIRType_Float32:
           case MIRType_Double:
             int32_t ival;
             // Only the value within the range of Int32 can be substituted as constant.
-            if (mozilla::NumberEqualsInt32(val.toNumber(), &ival))
+            if (mozilla::NumberEqualsInt32(input->toConstant()->toNumber(), &ival))
                 return MConstant::New(alloc, Int32Value(ival));
             break;
           default:
             break;
         }
     }
 
     if (input->type() == MIRType_Int32)
@@ -3559,40 +3548,36 @@ MTruncateToInt32::foldsTo(TempAllocator&
     MDefinition* input = getOperand(0);
     if (input->isBox())
         input = input->getOperand(0);
 
     if (input->type() == MIRType_Int32)
         return input;
 
     if (input->type() == MIRType_Double && input->isConstant()) {
-        const Value& v = input->toConstant()->value();
-        int32_t ret = ToInt32(v.toDouble());
+        int32_t ret = ToInt32(input->toConstant()->toDouble());
         return MConstant::New(alloc, Int32Value(ret));
     }
 
     return this;
 }
 
 MDefinition*
 MToDouble::foldsTo(TempAllocator& alloc)
 {
     MDefinition* input = getOperand(0);
     if (input->isBox())
         input = input->getOperand(0);
 
     if (input->type() == MIRType_Double)
         return input;
 
-    if (input->isConstant()) {
-        const Value& v = input->toConstant()->value();
-        if (v.isNumber()) {
-            double out = v.toNumber();
-            return MConstant::New(alloc, DoubleValue(out));
-        }
+    if (input->isConstant() && input->toConstant()->isNumber()) {
+        double out = input->toConstant()->toNumber();
+        return MConstant::New(alloc, DoubleValue(out));
     }
 
     return this;
 }
 
 MDefinition*
 MToFloat32::foldsTo(TempAllocator& alloc)
 {
@@ -3602,24 +3587,21 @@ MToFloat32::foldsTo(TempAllocator& alloc
 
     if (input->type() == MIRType_Float32)
         return input;
 
     // If x is a Float32, Float32(Double(x)) == x
     if (input->isToDouble() && input->toToDouble()->input()->type() == MIRType_Float32)
         return input->toToDouble()->input();
 
-    if (input->isConstant()) {
-        const Value& v = input->toConstant()->value();
-        if (v.isNumber()) {
-            float out = v.toNumber();
-            MConstant* c = MConstant::New(alloc, DoubleValue(out));
-            c->setResultType(MIRType_Float32);
-            return c;
-        }
+    if (input->isConstant() && input->toConstant()->isNumber()) {
+        float out = float(input->toConstant()->toNumber());
+        MConstant* c = MConstant::New(alloc, DoubleValue(out));
+        c->setResultType(MIRType_Float32);
+        return c;
     }
     return this;
 }
 
 MDefinition*
 MToString::foldsTo(TempAllocator& alloc)
 {
     MDefinition* in = input();
@@ -3630,23 +3612,18 @@ MToString::foldsTo(TempAllocator& alloc)
         return in;
     return this;
 }
 
 MDefinition*
 MClampToUint8::foldsTo(TempAllocator& alloc)
 {
     if (MConstant* inputConst = input()->maybeConstantValue()) {
-        const Value& v = inputConst->value();
-        if (v.isDouble()) {
-            int32_t clamped = ClampDoubleToUint8(v.toDouble());
-            return MConstant::New(alloc, Int32Value(clamped));
-        }
-        if (v.isInt32()) {
-            int32_t clamped = ClampIntForUint8Array(v.toInt32());
+        if (inputConst->isNumber()) {
+            int32_t clamped = ClampDoubleToUint8(inputConst->toNumber());
             return MConstant::New(alloc, Int32Value(clamped));
         }
     }
     return this;
 }
 
 bool
 MCompare::tryFoldEqualOperands(bool* result)
@@ -3691,19 +3668,19 @@ bool
 MCompare::tryFoldTypeOf(bool* result)
 {
     if (!lhs()->isTypeOf() && !rhs()->isTypeOf())
         return false;
     if (!lhs()->isConstant() && !rhs()->isConstant())
         return false;
 
     MTypeOf* typeOf = lhs()->isTypeOf() ? lhs()->toTypeOf() : rhs()->toTypeOf();
-    const Value* constant = lhs()->isConstant() ? lhs()->toConstant()->vp() : rhs()->toConstant()->vp();
-
-    if (!constant->isString())
+    MConstant* constant = lhs()->isConstant() ? lhs()->toConstant() : rhs()->toConstant();
+
+    if (constant->type() != MIRType_String)
         return false;
 
     if (jsop() != JSOP_STRICTEQ && jsop() != JSOP_STRICTNE &&
         jsop() != JSOP_EQ && jsop() != JSOP_NE)
     {
         return false;
     }
 
@@ -3835,18 +3812,18 @@ MCompare::evaluateConstantOperands(TempA
         // In most cases the MToDouble was added, because the constant is
         // a double.
         // e.g. v < 9007199254740991, where v is an int32 is always true.
         if (!lhs()->isConstant() && !rhs()->isConstant())
             return false;
 
         MDefinition* operand = left->isConstant() ? right : left;
         MConstant* constant = left->isConstant() ? left->toConstant() : right->toConstant();
-        MOZ_ASSERT(constant->value().isDouble());
-        double cte = constant->value().toDouble();
+        MOZ_ASSERT(constant->type() == MIRType_Double);
+        double cte = constant->toDouble();
 
         if (operand->isToDouble() && operand->getOperand(0)->type() == MIRType_Int32) {
             bool replaced = false;
             switch (jsop_) {
               case JSOP_LT:
                 if (cte > INT32_MAX || cte < INT32_MIN) {
                     *result = !((constant == lhs()) ^ (cte < INT32_MIN));
                     replaced = true;
@@ -3909,24 +3886,24 @@ MCompare::evaluateConstantOperands(TempA
                 return true;
             }
         }
     }
 
     if (!left->isConstant() || !right->isConstant())
         return false;
 
-    Value lhs = left->toConstant()->value();
-    Value rhs = right->toConstant()->value();
+    MConstant* lhs = left->toConstant();
+    MConstant* rhs = right->toConstant();
 
     // Fold away some String equality comparisons.
-    if (lhs.isString() && rhs.isString()) {
+    if (lhs->type() == MIRType_String && rhs->type() == MIRType_String) {
         int32_t comp = 0; // Default to equal.
         if (left != right)
-            comp = CompareAtoms(&lhs.toString()->asAtom(), &rhs.toString()->asAtom());
+            comp = CompareAtoms(&lhs->toString()->asAtom(), &rhs->toString()->asAtom());
 
         switch (jsop_) {
           case JSOP_LT:
             *result = (comp < 0);
             break;
           case JSOP_LE:
             *result = (comp <= 0);
             break;
@@ -3947,18 +3924,18 @@ MCompare::evaluateConstantOperands(TempA
           default:
             MOZ_CRASH("Unexpected op.");
         }
 
         return true;
     }
 
     if (compareType_ == Compare_UInt32) {
-        uint32_t lhsUint = uint32_t(lhs.toInt32());
-        uint32_t rhsUint = uint32_t(rhs.toInt32());
+        uint32_t lhsUint = uint32_t(lhs->toInt32());
+        uint32_t rhsUint = uint32_t(rhs->toInt32());
 
         switch (jsop_) {
           case JSOP_LT:
             *result = (lhsUint < rhsUint);
             break;
           case JSOP_LE:
             *result = (lhsUint <= rhsUint);
             break;
@@ -3978,39 +3955,39 @@ MCompare::evaluateConstantOperands(TempA
             break;
           default:
             MOZ_CRASH("Unexpected op.");
         }
 
         return true;
     }
 
-    if (!lhs.isNumber() || !rhs.isNumber())
+    if (!lhs->isNumber() || !rhs->isNumber())
         return false;
 
     switch (jsop_) {
       case JSOP_LT:
-        *result = (lhs.toNumber() < rhs.toNumber());
+        *result = (lhs->toNumber() < rhs->toNumber());
         break;
       case JSOP_LE:
-        *result = (lhs.toNumber() <= rhs.toNumber());
+        *result = (lhs->toNumber() <= rhs->toNumber());
         break;
       case JSOP_GT:
-        *result = (lhs.toNumber() > rhs.toNumber());
+        *result = (lhs->toNumber() > rhs->toNumber());
         break;
       case JSOP_GE:
-        *result = (lhs.toNumber() >= rhs.toNumber());
+        *result = (lhs->toNumber() >= rhs->toNumber());
         break;
       case JSOP_STRICTEQ: // Fall through.
       case JSOP_EQ:
-        *result = (lhs.toNumber() == rhs.toNumber());
+        *result = (lhs->toNumber() == rhs->toNumber());
         break;
       case JSOP_STRICTNE: // Fall through.
       case JSOP_NE:
-        *result = (lhs.toNumber() != rhs.toNumber());
+        *result = (lhs->toNumber() != rhs->toNumber());
         break;
       default:
         return false;
     }
 
     return true;
 }
 
@@ -4436,17 +4413,17 @@ MAsmJSLoadHeap::mightAlias(const MDefini
 {
     if (def->isAsmJSStoreHeap()) {
         const MAsmJSStoreHeap* store = def->toAsmJSStoreHeap();
         if (store->accessType() != accessType())
             return true;
         if (!ptr()->isConstant() || !store->ptr()->isConstant())
             return true;
         const MConstant* otherPtr = store->ptr()->toConstant();
-        return ptr()->toConstant()->value() == otherPtr->value();
+        return ptr()->toConstant()->equals(otherPtr);
     }
     return true;
 }
 
 bool
 MAsmJSLoadHeap::congruentTo(const MDefinition* ins) const
 {
     if (!ins->isAsmJSLoadHeap())
@@ -4936,35 +4913,29 @@ MGetPropertyCache::updateForReplacement(
     MGetPropertyCache* other = ins->toGetPropertyCache();
     location_.append(&other->location_);
     return true;
 }
 
 MDefinition*
 MAsmJSUnsignedToDouble::foldsTo(TempAllocator& alloc)
 {
-    if (input()->isConstant()) {
-        const Value& v = input()->toConstant()->value();
-        if (v.isInt32())
-            return MConstant::New(alloc, DoubleValue(uint32_t(v.toInt32())));
-    }
+    if (input()->isConstant() && input()->type() == MIRType_Int32)
+        return MConstant::New(alloc, DoubleValue(uint32_t(input()->toConstant()->toInt32())));
 
     return this;
 }
 
 MDefinition*
 MAsmJSUnsignedToFloat32::foldsTo(TempAllocator& alloc)
 {
-    if (input()->isConstant()) {
-        const Value& v = input()->toConstant()->value();
-        if (v.isInt32()) {
-            double dval = double(uint32_t(v.toInt32()));
-            if (IsFloat32Representable(dval))
-                return MConstant::NewAsmJS(alloc, JS::Float32Value(float(dval)), MIRType_Float32);
-        }
+    if (input()->isConstant() && input()->type() == MIRType_Int32) {
+        double dval = double(uint32_t(input()->toConstant()->toInt32()));
+        if (IsFloat32Representable(dval))
+            return MConstant::NewAsmJS(alloc, JS::Float32Value(float(dval)), MIRType_Float32);
     }
 
     return this;
 }
 
 MAsmJSCall*
 MAsmJSCall::New(TempAllocator& alloc, const wasm::CallSiteDesc& desc, Callee callee,
                 const Args& args, MIRType resultType, size_t spIncrement)
@@ -4999,31 +4970,31 @@ MSqrt::trySpecializeFloat32(TempAllocato
     setResultType(MIRType_Float32);
     specialization_ = MIRType_Float32;
 }
 
 MDefinition*
 MClz::foldsTo(TempAllocator& alloc)
 {
     if (num()->isConstant()) {
-        int32_t n = num()->toConstant()->value().toInt32();
+        int32_t n = num()->toConstant()->toInt32();
         if (n == 0)
             return MConstant::New(alloc, Int32Value(32));
         return MConstant::New(alloc, Int32Value(mozilla::CountLeadingZeroes32(n)));
     }
 
     return this;
 }
 
 MDefinition*
 MBoundsCheck::foldsTo(TempAllocator& alloc)
 {
     if (index()->isConstant() && length()->isConstant()) {
-        uint32_t len = length()->toConstant()->value().toInt32();
-        uint32_t idx = index()->toConstant()->value().toInt32();
+        uint32_t len = length()->toConstant()->toInt32();
+        uint32_t idx = index()->toConstant()->toInt32();
         if (idx + uint32_t(minimum()) < len && idx + uint32_t(maximum()) < len)
             return index();
     }
 
     return this;
 }
 
 MDefinition*
@@ -5033,19 +5004,18 @@ MTableSwitch::foldsTo(TempAllocator& all
 
     // If we only have one successor, convert to a plain goto to the only
     // successor. TableSwitch indices are numeric; other types will always go to
     // the only successor.
     if (numSuccessors() == 1 || (op->type() != MIRType_Value && !IsNumberType(op->type())))
         return MGoto::New(alloc, getDefault());
 
     if (MConstant* opConst = op->maybeConstantValue()) {
-        Value v = opConst->value();
-        if (v.isInt32()) {
-            int32_t i = v.toInt32() - low_;
+        if (op->type() == MIRType_Int32) {
+            int32_t i = opConst->toInt32() - low_;
             MBasicBlock* target;
             if (size_t(i) < numCases())
                 target = getCase(size_t(i));
             else
                 target = getDefault();
             MOZ_ASSERT(target);
             return MGoto::New(alloc, target);
         }
--- a/js/src/jit/MIR.h
+++ b/js/src/jit/MIR.h
@@ -1377,23 +1377,16 @@ class MConstant : public MNullaryInstruc
     INSTRUCTION_HEADER(Constant)
     static MConstant* New(TempAllocator& alloc, const Value& v,
                           CompilerConstraintList* constraints = nullptr);
     static MConstant* NewTypedValue(TempAllocator& alloc, const Value& v, MIRType type,
                                     CompilerConstraintList* constraints = nullptr);
     static MConstant* NewAsmJS(TempAllocator& alloc, const Value& v, MIRType type);
     static MConstant* NewConstraintlessObject(TempAllocator& alloc, JSObject* v);
 
-    const js::Value& value() const {
-        return value_;
-    }
-    const js::Value* vp() const {
-        return &value_;
-    }
-
     // Try to convert this constant to boolean, similar to js::ToBoolean.
     // Returns false if the type is MIRType_Magic*.
     bool valueToBoolean(bool* res) const;
 
     // Like valueToBoolean, but returns the result directly instead of using
     // an outparam. Should not be used if this constant might be a magic value.
     bool valueToBooleanInfallible() const {
         bool res;
@@ -1423,16 +1416,75 @@ class MConstant : public MNullaryInstruc
 
     void computeRange(TempAllocator& alloc) override;
     bool needTruncation(TruncateKind kind) override;
     void truncate() override;
 
     bool canProduceFloat32() const override;
 
     ALLOW_CLONE(MConstant)
+
+    bool equals(const MConstant* other) {
+        return value_ == other->value_;
+    }
+
+    bool toBoolean() const {
+        MOZ_ASSERT(type() == MIRType_Boolean);
+        return value_.toBoolean();
+    }
+    int32_t toInt32() const {
+        MOZ_ASSERT(type() == MIRType_Int32);
+        return value_.toInt32();
+    }
+    bool isInt32(int32_t i) const {
+        return type() == MIRType_Int32 && value_.toInt32() == i;
+    }
+    double toDouble() const {
+        MOZ_ASSERT(type() == MIRType_Double);
+        return value_.toDouble();
+    }
+    float toFloat32() const {
+        MOZ_ASSERT(type() == MIRType_Float32);
+        return value_.toDouble();
+    }
+    JSString* toString() const {
+        MOZ_ASSERT(type() == MIRType_String);
+        return value_.toString();
+    }
+    JS::Symbol* toSymbol() const {
+        MOZ_ASSERT(type() == MIRType_Symbol);
+        return value_.toSymbol();
+    }
+    JSObject& toObject() const {
+        MOZ_ASSERT(type() == MIRType_Object);
+        return value_.toObject();
+    }
+    JSObject* toObjectOrNull() const {
+        if (type() == MIRType_Object)
+            return &value_.toObject();
+        MOZ_ASSERT(type() == MIRType_Null);
+        return nullptr;
+    }
+
+    bool isNumber() const {
+        return IsNumberType(type());
+    }
+    double toNumber() const {
+        if (type() == MIRType_Int32)
+            return toInt32();
+        if (type() == MIRType_Double)
+            return toDouble();
+        MOZ_ASSERT(type() == MIRType_Float32);
+        return toFloat32();
+    }
+
+    // Convert this constant to a js::Value. Float32 constants will be stored
+    // as DoubleValue and NaNs are canonicalized. Callers must be careful: not
+    // all constants can be represented by js::Value (wasm supports int64).
+    Value toJSValue() const;
 };
 
 // Generic constructor of SIMD valuesX4.
 class MSimdValueX4
   : public MQuaternaryInstruction,
     public Mix4Policy<SimdScalarPolicy<0>, SimdScalarPolicy<1>,
                       SimdScalarPolicy<2>, SimdScalarPolicy<3> >::Data
 {
@@ -3085,17 +3137,17 @@ class MNewArray
         return new(alloc) MNewArray(constraints, length, templateConst, initialHeap, pc);
     }
 
     uint32_t length() const {
         return length_;
     }
 
     JSObject* templateObject() const {
-        return getOperand(0)->toConstant()->value().toObjectOrNull();
+        return getOperand(0)->toConstant()->toObjectOrNull();
     }
 
     gc::InitialHeap initialHeap() const {
         return initialHeap_;
     }
 
     jsbytecode* pc() const {
         return pc_;
@@ -3233,17 +3285,17 @@ class MNewObject
         if (JSObject* obj = templateObject())
             setResultTypeSet(MakeSingletonTypeSet(constraints, obj));
 
         // The constant is kept separated in a MConstant, this way we can safely
         // mark it during GC if we recover the object allocation.  Otherwise, by
         // making it emittedAtUses, we do not produce register allocations for
         // it and inline its content inside the code produced by the
         // CodeGenerator.
-        if (templateConst->toConstant()->value().isObject())
+        if (templateConst->toConstant()->type() == MIRType_Object)
             templateConst->setEmittedAtUses();
     }
 
   public:
     INSTRUCTION_HEADER(NewObject)
 
     static MNewObject* New(TempAllocator& alloc, CompilerConstraintList* constraints,
                            MConstant* templateConst, gc::InitialHeap initialHeap,
@@ -3256,17 +3308,17 @@ class MNewObject
     // VM rather than the fast path.
     bool shouldUseVM() const;
 
     Mode mode() const {
         return mode_;
     }
 
     JSObject* templateObject() const {
-        return getOperand(0)->toConstant()->value().toObjectOrNull();
+        return getOperand(0)->toConstant()->toObjectOrNull();
     }
 
     gc::InitialHeap initialHeap() const {
         return initialHeap_;
     }
 
     bool writeRecoverData(CompactBufferWriter& writer) const override;
     bool canRecoverOnBailout() const override {
@@ -4806,17 +4858,17 @@ class MCreateThisWithTemplate
     static MCreateThisWithTemplate* New(TempAllocator& alloc, CompilerConstraintList* constraints,
                                         MConstant* templateConst, gc::InitialHeap initialHeap)
     {
         return new(alloc) MCreateThisWithTemplate(constraints, templateConst, initialHeap);
     }
 
     // Template for |this|, provided by TI.
     JSObject* templateObject() const {
-        return &getOperand(0)->toConstant()->value().toObject();
+        return &getOperand(0)->toConstant()->toObject();
     }
 
     gc::InitialHeap initialHeap() const {
         return initialHeap_;
     }
 
     // Although creation of |this| modifies global state, it is safely repeatable.
     AliasSet getAliasSet() const override {
@@ -6928,17 +6980,17 @@ class MStringSplit
     }
     MDefinition* string() const {
         return getOperand(0);
     }
     MDefinition* separator() const {
         return getOperand(1);
     }
     JSObject* templateObject() const {
-        return &getOperand(2)->toConstant()->value().toObject();
+        return &getOperand(2)->toConstant()->toObject();
     }
     ObjectGroup* group() const {
         return templateObject()->group();
     }
     bool possiblyCalls() const override {
         return true;
     }
     virtual AliasSet getAliasSet() const override {
@@ -7926,17 +7978,17 @@ struct LambdaFunctionInfo
 
 class MLambda
   : public MBinaryInstruction,
     public SingleObjectPolicy::Data
 {
     const LambdaFunctionInfo info_;
 
     MLambda(CompilerConstraintList* constraints, MDefinition* scopeChain, MConstant* cst)
-      : MBinaryInstruction(scopeChain, cst), info_(&cst->value().toObject().as<JSFunction>())
+      : MBinaryInstruction(scopeChain, cst), info_(&cst->toObject().as<JSFunction>())
     {
         setResultType(MIRType_Object);
         if (!info().fun->isSingleton() && !ObjectGroup::useSingletonForClone(info().fun))
             setResultTypeSet(MakeSingletonTypeSet(constraints, info().fun));
     }
 
   public:
     INSTRUCTION_HEADER(Lambda)
--- a/js/src/jit/MIRGraph.cpp
+++ b/js/src/jit/MIRGraph.cpp
@@ -613,27 +613,27 @@ MBasicBlock::linkOsrValues(MStart* start
         if (i == info().scopeChainSlot()) {
             if (def->isOsrScopeChain())
                 cloneRp = def->toOsrScopeChain();
         } else if (i == info().returnValueSlot()) {
             if (def->isOsrReturnValue())
                 cloneRp = def->toOsrReturnValue();
         } else if (info().hasArguments() && i == info().argsObjSlot()) {
             MOZ_ASSERT(def->isConstant() || def->isOsrArgumentsObject());
-            MOZ_ASSERT_IF(def->isConstant(), def->toConstant()->value() == UndefinedValue());
+            MOZ_ASSERT_IF(def->isConstant(), def->toConstant()->type() == MIRType_Undefined);
             if (def->isOsrArgumentsObject())
                 cloneRp = def->toOsrArgumentsObject();
         } else {
             MOZ_ASSERT(def->isOsrValue() || def->isGetArgumentsObjectArg() || def->isConstant() ||
                        def->isParameter());
 
             // A constant Undefined can show up here for an argument slot when
             // the function has an arguments object, but the argument in
             // question is stored on the scope chain.
-            MOZ_ASSERT_IF(def->isConstant(), def->toConstant()->value() == UndefinedValue());
+            MOZ_ASSERT_IF(def->isConstant(), def->toConstant()->type() == MIRType_Undefined);
 
             if (def->isOsrValue())
                 cloneRp = def->toOsrValue();
             else if (def->isGetArgumentsObjectArg())
                 cloneRp = def->toGetArgumentsObjectArg();
             else if (def->isParameter())
                 cloneRp = def->toParameter();
         }
--- a/js/src/jit/RangeAnalysis.cpp
+++ b/js/src/jit/RangeAnalysis.cpp
@@ -193,22 +193,22 @@ RangeAnalysis::addBetaNodes()
         if (branch_dir == FALSE_BRANCH) {
             jsop = NegateCompareOp(jsop);
             conservativeLower = GenericNaN();
             conservativeUpper = GenericNaN();
         }
 
         MConstant* leftConst = left->maybeConstantValue();
         MConstant* rightConst = right->maybeConstantValue();
-        if (leftConst && leftConst->value().isNumber()) {
-            bound = leftConst->value().toNumber();
+        if (leftConst && leftConst->isNumber()) {
+            bound = leftConst->toNumber();
             val = right;
             jsop = ReverseCompareOp(jsop);
-        } else if (rightConst && rightConst->value().isNumber()) {
-            bound = rightConst->value().toNumber();
+        } else if (rightConst && rightConst->isNumber()) {
+            bound = rightConst->toNumber();
             val = left;
         } else if (left->type() == MIRType_Int32 && right->type() == MIRType_Int32) {
             MDefinition* smaller = nullptr;
             MDefinition* greater = nullptr;
             if (jsop == JSOP_LT) {
                 smaller = left;
                 greater = right;
             } else if (jsop == JSOP_GT) {
@@ -1286,21 +1286,21 @@ MBeta::computeRange(TempAllocator& alloc
     } else {
         setRange(range);
     }
 }
 
 void
 MConstant::computeRange(TempAllocator& alloc)
 {
-    if (value().isNumber()) {
-        double d = value().toNumber();
+    if (isNumber()) {
+        double d = toNumber();
         setRange(Range::NewDoubleSingletonRange(alloc, d));
-    } else if (value().isBoolean()) {
-        bool b = value().toBoolean();
+    } else if (type() == MIRType_Boolean) {
+        bool b = toBoolean();
         setRange(Range::NewInt32Range(alloc, b, b));
     }
 }
 
 void
 MCharCodeAt::computeRange(TempAllocator& alloc)
 {
     // ECMA 262 says that the integer will be non-negative and at most 65535.
@@ -1359,17 +1359,17 @@ void
 MLsh::computeRange(TempAllocator& alloc)
 {
     Range left(getOperand(0));
     Range right(getOperand(1));
     left.wrapAroundToInt32();
 
     MConstant* rhsConst = getOperand(1)->maybeConstantValue();
     if (rhsConst && rhsConst->type() == MIRType_Int32) {
-        int32_t c = rhsConst->value().toInt32();
+        int32_t c = rhsConst->toInt32();
         setRange(Range::lsh(alloc, &left, c));
         return;
     }
 
     right.wrapAroundToShiftCount();
     setRange(Range::lsh(alloc, &left, &right));
 }
 
@@ -1377,17 +1377,17 @@ void
 MRsh::computeRange(TempAllocator& alloc)
 {
     Range left(getOperand(0));
     Range right(getOperand(1));
     left.wrapAroundToInt32();
 
     MConstant* rhsConst = getOperand(1)->maybeConstantValue();
     if (rhsConst && rhsConst->type() == MIRType_Int32) {
-        int32_t c = rhsConst->value().toInt32();
+        int32_t c = rhsConst->toInt32();
         setRange(Range::rsh(alloc, &left, c));
         return;
     }
 
     right.wrapAroundToShiftCount();
     setRange(Range::rsh(alloc, &left, &right));
 }
 
@@ -1402,17 +1402,17 @@ MUrsh::computeRange(TempAllocator& alloc
     // reinterpreting the int32 bits as a uint32 value. Both approaches yield
     // the same result. Since we lack support for full uint32 ranges, we use
     // the second interpretation, though it does cause us to be conservative.
     left.wrapAroundToInt32();
     right.wrapAroundToShiftCount();
 
     MConstant* rhsConst = getOperand(1)->maybeConstantValue();
     if (rhsConst && rhsConst->type() == MIRType_Int32) {
-        int32_t c = rhsConst->value().toInt32();
+        int32_t c = rhsConst->toInt32();
         setRange(Range::ursh(alloc, &left, c));
     } else {
         setRange(Range::ursh(alloc, &left, &right));
     }
 
     MOZ_ASSERT(range()->lower() >= 0);
 }
 
@@ -3353,23 +3353,23 @@ DoesMaskMatchRange(int32_t mask, Range& 
 
 void
 MBinaryBitwiseInstruction::collectRangeInfoPreTrunc()
 {
     Range lhsRange(lhs());
     Range rhsRange(rhs());
 
     if (lhs()->isConstant() && lhs()->type() == MIRType_Int32 &&
-        DoesMaskMatchRange(lhs()->toConstant()->value().toInt32(), rhsRange))
+        DoesMaskMatchRange(lhs()->toConstant()->toInt32(), rhsRange))
     {
         maskMatchesRightRange = true;
     }
 
     if (rhs()->isConstant() && rhs()->type() == MIRType_Int32 &&
-        DoesMaskMatchRange(rhs()->toConstant()->value().toInt32(), lhsRange))
+        DoesMaskMatchRange(rhs()->toConstant()->toInt32(), lhsRange))
     {
         maskMatchesLeftRange = true;
     }
 }
 
 bool
 RangeAnalysis::prepareForUCE(bool* shouldRemoveDeadCode)
 {
--- a/js/src/jit/ScalarReplacement.cpp
+++ b/js/src/jit/ScalarReplacement.cpp
@@ -654,17 +654,17 @@ ObjectMemoryView::visitLambda(MLambda* i
     // In order to recover the lambda we need to recover the scope chain, as the
     // lambda is holding it.
     ins->setIncompleteObject();
 }
 
 static size_t
 GetOffsetOf(MDefinition* index, size_t width, int32_t baseOffset)
 {
-    int32_t idx = index->toConstant()->value().toInt32();
+    int32_t idx = index->toConstant()->toInt32();
     MOZ_ASSERT(idx >= 0);
     MOZ_ASSERT(baseOffset >= 0 && size_t(baseOffset) >= UnboxedPlainObject::offsetOfData());
     return idx * width + baseOffset - UnboxedPlainObject::offsetOfData();
 }
 
 static size_t
 GetOffsetOf(MDefinition* index, Scalar::Type type, int32_t baseOffset)
 {
@@ -776,23 +776,19 @@ IndexOf(MDefinition* ins, int32_t* res)
 {
     MOZ_ASSERT(ins->isLoadElement() || ins->isStoreElement());
     MDefinition* indexDef = ins->getOperand(1); // ins->index();
     if (indexDef->isBoundsCheck())
         indexDef = indexDef->toBoundsCheck()->index();
     if (indexDef->isToInt32())
         indexDef = indexDef->toToInt32()->getOperand(0);
     MConstant* indexDefConst = indexDef->maybeConstantValue();
-    if (!indexDefConst)
+    if (!indexDefConst || indexDefConst->type() != MIRType_Int32)
         return false;
-
-    Value index = indexDefConst->value();
-    if (!index.isInt32())
-        return false;
-    *res = index.toInt32();
+    *res = indexDefConst->toInt32();
     return true;
 }
 
 // Returns False if the elements is not escaped and if it is optimizable by
 // ScalarReplacementOfArray.
 static bool
 IsElementEscaped(MElements* def, uint32_t arraySize)
 {
@@ -1254,17 +1250,17 @@ ArrayMemoryView::visitSetInitializedLeng
     // To obtain the length, we need to add 1 to it, and thus we need to create
     // a new constant that we register in the ArrayState.
     state_ = BlockState::Copy(alloc_, state_);
     if (!state_) {
         oom_ = true;
         return;
     }
 
-    int32_t initLengthValue = ins->index()->maybeConstantValue()->value().toInt32() + 1;
+    int32_t initLengthValue = ins->index()->maybeConstantValue()->toInt32() + 1;
     MConstant* initLength = MConstant::New(alloc_, Int32Value(initLengthValue));
     ins->block()->insertBefore(ins, initLength);
     ins->block()->insertBefore(ins, state_);
     state_->setInitializedLength(initLength);
 
     // Remove original instruction.
     discardInstruction(ins, elements);
 }
--- a/js/src/jit/arm/Lowering-arm.cpp
+++ b/js/src/jit/arm/Lowering-arm.cpp
@@ -60,17 +60,17 @@ LIRGeneratorARM::visitBox(MBox* box)
     }
 
     if (box->canEmitAtUses()) {
         emitAtUses(box);
         return;
     }
 
     if (inner->isConstant()) {
-        defineBox(new(alloc()) LValue(inner->toConstant()->value()), box);
+        defineBox(new(alloc()) LValue(inner->toConstant()->toJSValue()), box);
         return;
     }
 
     LBox* lir = new(alloc()) LBox(use(inner), inner->type());
 
     // Otherwise, we should not define a new register for the payload portion
     // of the output, so bypass defineBox().
     uint32_t vreg = getVirtualRegister();
@@ -238,17 +238,17 @@ LIRGeneratorARM::lowerDivI(MDiv* div)
     if (div->isUnsigned()) {
         lowerUDiv(div);
         return;
     }
 
     // Division instructions are slow. Division by constant denominators can be
     // rewritten to use other instructions.
     if (div->rhs()->isConstant()) {
-        int32_t rhs = div->rhs()->toConstant()->value().toInt32();
+        int32_t rhs = div->rhs()->toConstant()->toInt32();
         // Check for division by a positive power of two, which is an easy and
         // important case to optimize. Note that other optimizations are also
         // possible; division by negative powers of two can be optimized in a
         // similar manner as positive powers of two, and division by other
         // constants can be optimized by a reciprocal multiplication technique.
         int32_t shift = FloorLog2(rhs);
         if (rhs > 0 && 1 << shift == rhs) {
             LDivPowTwoI* lir = new(alloc()) LDivPowTwoI(useRegisterAtStart(div->lhs()), shift);
@@ -287,17 +287,17 @@ void
 LIRGeneratorARM::lowerModI(MMod* mod)
 {
     if (mod->isUnsigned()) {
         lowerUMod(mod);
         return;
     }
 
     if (mod->rhs()->isConstant()) {
-        int32_t rhs = mod->rhs()->toConstant()->value().toInt32();
+        int32_t rhs = mod->rhs()->toConstant()->toInt32();
         int32_t shift = FloorLog2(rhs);
         if (rhs > 0 && 1 << shift == rhs) {
             LModPowTwoI* lir = new(alloc()) LModPowTwoI(useRegister(mod->lhs()), shift);
             if (mod->fallible())
                 assignSnapshot(lir, Bailout_DoubleOutput);
             define(lir, mod);
             return;
         }
@@ -463,35 +463,35 @@ LIRGeneratorARM::visitAsmJSLoadHeap(MAsm
 {
     MDefinition* ptr = ins->ptr();
     MOZ_ASSERT(ptr->type() == MIRType_Int32);
     LAllocation ptrAlloc;
 
     // For the ARM it is best to keep the 'ptr' in a register if a bounds check is needed.
     if (ptr->isConstant() && !ins->needsBoundsCheck()) {
         // A bounds check is only skipped for a positive index.
-        MOZ_ASSERT(ptr->toConstant()->value().toInt32() >= 0);
-        ptrAlloc = LAllocation(ptr->toConstant()->vp());
+        MOZ_ASSERT(ptr->toConstant()->toInt32() >= 0);
+        ptrAlloc = LAllocation(ptr->toConstant());
     } else {
         ptrAlloc = useRegisterAtStart(ptr);
     }
 
     define(new(alloc()) LAsmJSLoadHeap(ptrAlloc), ins);
 }
 
 void
 LIRGeneratorARM::visitAsmJSStoreHeap(MAsmJSStoreHeap* ins)
 {
     MDefinition* ptr = ins->ptr();
     MOZ_ASSERT(ptr->type() == MIRType_Int32);
     LAllocation ptrAlloc;
 
     if (ptr->isConstant() && !ins->needsBoundsCheck()) {
-        MOZ_ASSERT(ptr->toConstant()->value().toInt32() >= 0);
-        ptrAlloc = LAllocation(ptr->toConstant()->vp());
+        MOZ_ASSERT(ptr->toConstant()->toInt32() >= 0);
+        ptrAlloc = LAllocation(ptr->toConstant());
     } else {
         ptrAlloc = useRegisterAtStart(ptr);
     }
 
     add(new(alloc()) LAsmJSStoreHeap(ptrAlloc, useRegisterAtStart(ins->value())), ins);
 }
 
 void
--- a/js/src/jit/shared/CodeGenerator-shared.cpp
+++ b/js/src/jit/shared/CodeGenerator-shared.cpp
@@ -409,17 +409,17 @@ CodeGeneratorShared::encodeAllocation(LS
         // LRecoverInfo.
         MOZ_ASSERT(it != end && mir == *it);
 
         // Lambda should have a default value readable for iterating over the
         // inner frames.
         if (mir->isLambda()) {
             MConstant* constant = mir->toLambda()->functionOperand();
             uint32_t cstIndex;
-            masm.propagateOOM(graph.addConstantToPool(constant->value(), &cstIndex));
+            masm.propagateOOM(graph.addConstantToPool(constant->toJSValue(), &cstIndex));
             alloc = RValueAllocation::RecoverInstruction(index, cstIndex);
             break;
         }
 
         alloc = RValueAllocation::RecoverInstruction(index);
         break;
       }
       case MIRType_Undefined:
@@ -435,17 +435,17 @@ CodeGeneratorShared::encodeAllocation(LS
       case MIRType_ObjectOrNull:
       case MIRType_Boolean:
       case MIRType_Double:
       {
         LAllocation* payload = snapshot->payloadOfSlot(*allocIndex);
         if (payload->isConstant()) {
             MConstant* constant = mir->toConstant();
             uint32_t index;
-            masm.propagateOOM(graph.addConstantToPool(constant->value(), &index));
+            masm.propagateOOM(graph.addConstantToPool(constant->toJSValue(), &index));
             alloc = RValueAllocation::ConstantPool(index);
             break;
         }
 
         JSValueType valueType =
             (type == MIRType_ObjectOrNull) ? JSVAL_TYPE_OBJECT : ValueTypeFromMIRType(type);
 
         MOZ_ASSERT(payload->isMemory() || payload->isRegister());
@@ -461,17 +461,17 @@ CodeGeneratorShared::encodeAllocation(LS
       case MIRType_Bool32x4:
       case MIRType_Int32x4:
       case MIRType_Float32x4:
       {
         LAllocation* payload = snapshot->payloadOfSlot(*allocIndex);
         if (payload->isConstant()) {
             MConstant* constant = mir->toConstant();
             uint32_t index;
-            masm.propagateOOM(graph.addConstantToPool(constant->value(), &index));
+            masm.propagateOOM(graph.addConstantToPool(constant->toJSValue(), &index));
             alloc = RValueAllocation::ConstantPool(index);
             break;
         }
 
         MOZ_ASSERT(payload->isMemory() || payload->isFloatReg());
         if (payload->isFloatReg())
             alloc = RValueAllocation::AnyFloat(ToFloatRegister(payload));
         else
--- a/js/src/jit/shared/Lowering-shared-inl.h
+++ b/js/src/jit/shared/Lowering-shared-inl.h
@@ -264,21 +264,20 @@ LIRGeneratorShared::redefine(MDefinition
     if (as->isEmittedAtUses() &&
         (def->type() == as->type() ||
          (as->isConstant() &&
           (def->type() == MIRType_Int32 || def->type() == MIRType_Boolean) &&
           (as->type() == MIRType_Int32 || as->type() == MIRType_Boolean))))
     {
         MInstruction* replacement;
         if (def->type() != as->type()) {
-            Value v = as->toConstant()->value();
             if (as->type() == MIRType_Int32)
-                replacement = MConstant::New(alloc(), BooleanValue(v.toInt32()));
+                replacement = MConstant::New(alloc(), BooleanValue(as->toConstant()->toInt32()));
             else
-                replacement = MConstant::New(alloc(), Int32Value(v.toBoolean()));
+                replacement = MConstant::New(alloc(), Int32Value(as->toConstant()->toBoolean()));
             def->block()->insertBefore(def->toInstruction(), replacement);
             emitAtUses(replacement->toInstruction());
         } else {
             replacement = as->toInstruction();
         }
         def->replaceAllUsesWith(replacement);
     } else {
         ensureDefined(as);
@@ -344,57 +343,57 @@ LIRGeneratorShared::useAtStart(MDefiniti
 {
     return use(mir, LUse(LUse::ANY, true));
 }
 
 LAllocation
 LIRGeneratorShared::useOrConstant(MDefinition* mir)
 {
     if (mir->isConstant())
-        return LAllocation(mir->toConstant()->vp());
+        return LAllocation(mir->toConstant());
     return use(mir);
 }
 
 LAllocation
 LIRGeneratorShared::useOrConstantAtStart(MDefinition* mir)
 {
     if (mir->isConstant())
-        return LAllocation(mir->toConstant()->vp());
+        return LAllocation(mir->toConstant());
     return useAtStart(mir);
 }
 
 LAllocation
 LIRGeneratorShared::useRegisterOrConstant(MDefinition* mir)
 {
     if (mir->isConstant())
-        return LAllocation(mir->toConstant()->vp());
+        return LAllocation(mir->toConstant());
     return useRegister(mir);
 }
 
 LAllocation
 LIRGeneratorShared::useRegisterOrConstantAtStart(MDefinition* mir)
 {
     if (mir->isConstant())
-        return LAllocation(mir->toConstant()->vp());
+        return LAllocation(mir->toConstant());
     return useRegisterAtStart(mir);
 }
 
 LAllocation
 LIRGeneratorShared::useRegisterOrZeroAtStart(MDefinition* mir)
 {
-    if (mir->isConstant() && mir->toConstant()->value().isInt32(0))
+    if (mir->isConstant() && mir->toConstant()->isInt32(0))
         return LAllocation();
     return useRegisterAtStart(mir);
 }
 
 LAllocation
 LIRGeneratorShared::useRegisterOrNonDoubleConstant(MDefinition* mir)
 {
     if (mir->isConstant() && mir->type() != MIRType_Double && mir->type() != MIRType_Float32)
-        return LAllocation(mir->toConstant()->vp());
+        return LAllocation(mir->toConstant());
     return useRegister(mir);
 }
 
 #if defined(JS_CODEGEN_ARM) || defined(JS_CODEGEN_ARM64)
 LAllocation
 LIRGeneratorShared::useAnyOrConstant(MDefinition* mir)
 {
     return useRegisterOrConstant(mir);
@@ -445,17 +444,17 @@ LIRGeneratorShared::useKeepalive(MDefini
 {
     return use(mir, LUse(LUse::KEEPALIVE));
 }
 
 LAllocation
 LIRGeneratorShared::useKeepaliveOrConstant(MDefinition* mir)
 {
     if (mir->isConstant())
-        return LAllocation(mir->toConstant()->vp());
+        return LAllocation(mir->toConstant());
     return useKeepalive(mir);
 }
 
 LUse
 LIRGeneratorShared::useFixed(MDefinition* mir, Register reg)
 {
     return use(mir, LUse(reg));
 }
@@ -625,17 +624,17 @@ LIRGeneratorShared::useBoxOrTypedOrConst
                                             bool useConstant)
 {
     if (mir->type() == MIRType_Value) {
         useBox(lir, n, mir);
         return;
     }
 
     if (useConstant && mir->isConstant())
-        lir->setOperand(n, LAllocation(mir->toConstant()->vp()));
+        lir->setOperand(n, LAllocation(mir->toConstant()));
     else
         lir->setOperand(n, useRegister(mir));
 
 #if defined(JS_NUNBOX32)
     lir->setOperand(n + 1, LAllocation());
 #endif
 }
 
--- a/js/src/jit/shared/Lowering-shared.cpp
+++ b/js/src/jit/shared/Lowering-shared.cpp
@@ -74,38 +74,37 @@ LIRGeneratorShared::ReorderCommutative(M
 void
 LIRGeneratorShared::visitConstant(MConstant* ins)
 {
     if (!IsFloatingPointType(ins->type()) && ins->canEmitAtUses()) {
         emitAtUses(ins);
         return;
     }
 
-    const Value& v = ins->value();
     switch (ins->type()) {
       case MIRType_Double:
-        define(new(alloc()) LDouble(v.toDouble()), ins);
+        define(new(alloc()) LDouble(ins->toDouble()), ins);
         break;
       case MIRType_Float32:
-        define(new(alloc()) LFloat32(v.toDouble()), ins);
+        define(new(alloc()) LFloat32(ins->toFloat32()), ins);
         break;
       case MIRType_Boolean:
-        define(new(alloc()) LInteger(v.toBoolean()), ins);
+        define(new(alloc()) LInteger(ins->toBoolean()), ins);
         break;
       case MIRType_Int32:
-        define(new(alloc()) LInteger(v.toInt32()), ins);
+        define(new(alloc()) LInteger(ins->toInt32()), ins);
         break;
       case MIRType_String:
-        define(new(alloc()) LPointer(v.toString()), ins);
+        define(new(alloc()) LPointer(ins->toString()), ins);
         break;
       case MIRType_Symbol:
-        define(new(alloc()) LPointer(v.toSymbol()), ins);
+        define(new(alloc()) LPointer(ins->toSymbol()), ins);
         break;
       case MIRType_Object:
-        define(new(alloc()) LPointer(&v.toObject()), ins);
+        define(new(alloc()) LPointer(&ins->toObject()), ins);
         break;
       default:
         // Constants of special types (undefined, null) should never flow into
         // here directly. Operations blindly consuming them require a Box.
         MOZ_CRASH("unexpected constant type");
     }
 }
 
--- a/js/src/jit/x64/CodeGenerator-x64.cpp
+++ b/js/src/jit/x64/CodeGenerator-x64.cpp
@@ -146,17 +146,17 @@ CodeGeneratorX64::visitCompareB(LCompare
     const LAllocation* rhs = lir->rhs();
     const Register output = ToRegister(lir->output());
 
     MOZ_ASSERT(mir->jsop() == JSOP_STRICTEQ || mir->jsop() == JSOP_STRICTNE);
 
     // Load boxed boolean in ScratchReg.
     ScratchRegisterScope scratch(masm);
     if (rhs->isConstant())
-        masm.moveValue(*rhs->toConstant(), scratch);
+        masm.moveValue(rhs->toConstant()->toJSValue(), scratch);
     else
         masm.boxValue(JSVAL_TYPE_BOOLEAN, ToRegister(rhs), scratch);
 
     // Perform the comparison.
     masm.cmpPtr(lhs.valueReg(), scratch);
     masm.emitSet(JSOpToCondition(mir->compareType(), mir->jsop()), output);
 }
 
@@ -168,17 +168,17 @@ CodeGeneratorX64::visitCompareBAndBranch
     const ValueOperand lhs = ToValue(lir, LCompareBAndBranch::Lhs);
     const LAllocation* rhs = lir->rhs();
 
     MOZ_ASSERT(mir->jsop() == JSOP_STRICTEQ || mir->jsop() == JSOP_STRICTNE);
 
     // Load boxed boolean in ScratchReg.
     ScratchRegisterScope scratch(masm);
     if (rhs->isConstant())
-        masm.moveValue(*rhs->toConstant(), scratch);
+        masm.moveValue(rhs->toConstant()->toJSValue(), scratch);
     else
         masm.boxValue(JSVAL_TYPE_BOOLEAN, ToRegister(rhs), scratch);
 
     // Perform the comparison.
     masm.cmpPtr(lhs.valueReg(), scratch);
     emitBranch(JSOpToCondition(mir->compareType(), mir->jsop()), lir->ifTrue(), lir->ifFalse());
 }
 
--- a/js/src/jit/x64/Lowering-x64.cpp
+++ b/js/src/jit/x64/Lowering-x64.cpp
@@ -54,17 +54,17 @@ LIRGeneratorX64::visitBox(MBox* box)
 
     // If the operand is a constant, emit near its uses.
     if (opd->isConstant() && box->canEmitAtUses()) {
         emitAtUses(box);
         return;
     }
 
     if (opd->isConstant()) {
-        define(new(alloc()) LValue(opd->toConstant()->value()), box, LDefinition(LDefinition::BOX));
+        define(new(alloc()) LValue(opd->toConstant()->toJSValue()), box, LDefinition(LDefinition::BOX));
     } else {
         LBox* ins = new(alloc()) LBox(useRegister(opd), opd->type());
         define(ins, box, LDefinition(LDefinition::BOX));
     }
 }
 
 void
 LIRGeneratorX64::visitUnbox(MUnbox* unbox)
--- a/js/src/jit/x86-shared/Lowering-x86-shared.cpp
+++ b/js/src/jit/x86-shared/Lowering-x86-shared.cpp
@@ -174,17 +174,17 @@ LIRGeneratorX86Shared::lowerDivI(MDiv* d
     if (div->isUnsigned()) {
         lowerUDiv(div);
         return;
     }
 
     // Division instructions are slow. Division by constant denominators can be
     // rewritten to use other instructions.
     if (div->rhs()->isConstant()) {
-        int32_t rhs = div->rhs()->toConstant()->value().toInt32();
+        int32_t rhs = div->rhs()->toConstant()->toInt32();
 
         // Division by powers of two can be done by shifting, and division by
         // other numbers can be done by a reciprocal multiplication technique.
         int32_t shift = FloorLog2(Abs(rhs));
         if (rhs != 0 && uint32_t(1) << shift == Abs(rhs)) {
             LAllocation lhs = useRegisterAtStart(div->lhs());
             LDivPowTwoI* lir;
             if (!div->canBeNegativeDividend()) {
@@ -221,17 +221,17 @@ void
 LIRGeneratorX86Shared::lowerModI(MMod* mod)
 {
     if (mod->isUnsigned()) {
         lowerUMod(mod);
         return;
     }
 
     if (mod->rhs()->isConstant()) {
-        int32_t rhs = mod->rhs()->toConstant()->value().toInt32();
+        int32_t rhs = mod->rhs()->toConstant()->toInt32();
         int32_t shift = FloorLog2(Abs(rhs));
         if (rhs != 0 && uint32_t(1) << shift == Abs(rhs)) {
             LModPowTwoI* lir = new(alloc()) LModPowTwoI(useRegisterAtStart(mod->lhs()), shift);
             if (mod->fallible())
                 assignSnapshot(lir, Bailout_DoubleOutput);
             defineReuseInput(lir, mod, 0);
             return;
         }
@@ -270,17 +270,17 @@ LIRGeneratorX86Shared::visitAsmJSNeg(MAs
         MOZ_CRASH();
     }
 }
 
 void
 LIRGeneratorX86Shared::lowerUDiv(MDiv* div)
 {
     if (div->rhs()->isConstant()) {
-        uint32_t rhs = div->rhs()->toConstant()->value().toInt32();
+        uint32_t rhs = div->rhs()->toConstant()->toInt32();
         int32_t shift = FloorLog2(rhs);
 
         LAllocation lhs = useRegisterAtStart(div->lhs());
         if (rhs != 0 && uint32_t(1) << shift == rhs) {
             LDivPowTwoI* lir = new(alloc()) LDivPowTwoI(lhs, lhs, shift, false);
             if (div->fallible())
                 assignSnapshot(lir, Bailout_DoubleOutput);
             defineReuseInput(lir, div, 0);
@@ -301,17 +301,17 @@ LIRGeneratorX86Shared::lowerUDiv(MDiv* d
         assignSnapshot(lir, Bailout_DoubleOutput);
     defineFixed(lir, div, LAllocation(AnyRegister(eax)));
 }
 
 void
 LIRGeneratorX86Shared::lowerUMod(MMod* mod)
 {
     if (mod->rhs()->isConstant()) {
-        uint32_t rhs = mod->rhs()->toConstant()->value().toInt32();
+        uint32_t rhs = mod->rhs()->toConstant()->toInt32();
         int32_t shift = FloorLog2(rhs);
 
         if (rhs != 0 && uint32_t(1) << shift == rhs) {
             LModPowTwoI* lir = new(alloc()) LModPowTwoI(useRegisterAtStart(mod->lhs()), shift);
             if (mod->fallible())
                 assignSnapshot(lir, Bailout_DoubleOutput);
             defineReuseInput(lir, mod, 0);
         } else {
--- a/js/src/jit/x86/Lowering-x86.cpp
+++ b/js/src/jit/x86/Lowering-x86.cpp
@@ -57,17 +57,17 @@ LIRGeneratorX86::visitBox(MBox* box)
     }
 
     if (box->canEmitAtUses()) {
         emitAtUses(box);
         return;
     }
 
     if (inner->isConstant()) {
-        defineBox(new(alloc()) LValue(inner->toConstant()->value()), box);
+        defineBox(new(alloc()) LValue(inner->toConstant()->toJSValue()), box);
         return;
     }
 
     LBox* lir = new(alloc()) LBox(use(inner), inner->type());
 
     // Otherwise, we should not define a new register for the payload portion
     // of the output, so bypass defineBox().
     uint32_t vreg = getVirtualRegister();
--- a/js/src/jsapi-tests/testJitDCEinGVN.cpp
+++ b/js/src/jsapi-tests/testJitDCEinGVN.cpp
@@ -131,13 +131,13 @@ BEGIN_TEST(testJitDCEinGVN_phi)
     MReturn* ret = MReturn::New(func.alloc, y);
     joinBlock->end(ret);
 
     if (!func.runGVN())
         return false;
 
     // c1 should be deleted.
     for (MInstructionIterator ins = block->begin(); ins != block->end(); ins++) {
-        CHECK(!ins->isConstant() || (ins->toConstant()->value().toNumber() != 1.0));
+        CHECK(!ins->isConstant() || (ins->toConstant()->toNumber() != 1.0));
     }
     return true;
 }
 END_TEST(testJitDCEinGVN_phi)
--- a/js/src/jsapi-tests/testJitFoldsTo.cpp
+++ b/js/src/jsapi-tests/testJitFoldsTo.cpp
@@ -37,17 +37,17 @@ BEGIN_TEST(testJitFoldsTo_DivReciprocal)
     if (!func.runGVN())
         return false;
 
     // Test that the div got folded to p * 0.25.
     MDefinition* op = ret->getOperand(0);
     CHECK(op->isMul());
     CHECK(op->getOperand(0) == left);
     CHECK(op->getOperand(1)->isConstant());
-    CHECK(op->getOperand(1)->toConstant()->value().toNumber() == 0.25);
+    CHECK(op->getOperand(1)->toConstant()->toNumber() == 0.25);
     return true;
 }
 END_TEST(testJitFoldsTo_DivReciprocal)
 
 BEGIN_TEST(testJitFoldsTo_NoDivReciprocal)
 {
     MinimalFunc func;
     MBasicBlock* block = func.createEntryBlock();
@@ -224,17 +224,17 @@ BEGIN_TEST(testJitFoldsTo_UnsignedDiv)
     MReturn* ret = MReturn::New(func.alloc, div);
     block->end(ret);
 
     if (!func.runGVN())
         return false;
 
     // Test that the div got folded to 0.
     MConstant* op = ret->getOperand(0)->toConstant();
-    CHECK(mozilla::NumbersAreIdentical(op->value().toNumber(), 0.0));
+    CHECK(mozilla::NumbersAreIdentical(op->toNumber(), 0.0));
     return true;
 }
 END_TEST(testJitFoldsTo_UnsignedDiv)
 
 BEGIN_TEST(testJitFoldsTo_UnsignedMod)
 {
     MinimalFunc func;
     MBasicBlock* block = func.createEntryBlock();
@@ -249,12 +249,12 @@ BEGIN_TEST(testJitFoldsTo_UnsignedMod)
     MReturn* ret = MReturn::New(func.alloc, mod);
     block->end(ret);
 
     if (!func.runGVN())
         return false;
 
     // Test that the mod got folded to 1.
     MConstant* op = ret->getOperand(0)->toConstant();
-    CHECK(mozilla::NumbersAreIdentical(op->value().toNumber(), 1.0));
+    CHECK(mozilla::NumbersAreIdentical(op->toNumber(), 1.0));
     return true;
 }
 END_TEST(testJitFoldsTo_UnsignedMod)