Bug 1175535 - Don't require objects embedded in MIR nodes to always be tenured, r=jandem.
authorBrian Hackett <bhackett1024@gmail.com>
Wed, 24 Jun 2015 16:08:39 -0700
changeset 268270 59c94503731aabbec19ea8ea345f13bd7693f621
parent 268269 a195a8127e8d62a7abd646d167cfee61b0be8834
child 268271 b47603f369df25a25550612cca2baf97c2ba50d0
push id4932
push userjlund@mozilla.com
push dateMon, 10 Aug 2015 18:23:06 +0000
treeherdermozilla-esr52@6dd5a4f5f745 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjandem
bugs1175535
milestone41.0a1
Bug 1175535 - Don't require objects embedded in MIR nodes to always be tenured, r=jandem.
js/src/jit/IonBuilder.cpp
js/src/jit/MCallOptimize.cpp
js/src/jit/MIR.cpp
js/src/jit/MIR.h
--- a/js/src/jit/IonBuilder.cpp
+++ b/js/src/jit/IonBuilder.cpp
@@ -5469,17 +5469,17 @@ IonBuilder::inlineCalls(CallInfo& callIn
         if (!inlineBlock)
             return false;
 
         // Create a function MConstant to use in the entry ResumePoint. If we
         // can't use a constant, add a no-op MPolyInlineGuard, to prevent
         // hoisting scope chain gets above the dispatch instruction.
         MInstruction* funcDef;
         if (target->isSingleton())
-            funcDef = MConstant::New(alloc(), ObjectValue(*target), constraints(), this);
+            funcDef = MConstant::New(alloc(), ObjectValue(*target), constraints());
         else
             funcDef = MPolyInlineGuard::New(alloc(), callInfo.fun());
 
         funcDef->setImplicitlyUsedUnchecked();
         dispatchBlock->add(funcDef);
 
         // Use the inlined callee in the inline resume point and on stack.
         int funIndex = inlineBlock->entryResumePoint()->stackDepth() - callInfo.numFormals();
@@ -5784,17 +5784,17 @@ IonBuilder::createThisScriptedSingleton(
         return nullptr;
 
     StackTypeSet* thisTypes = TypeScript::ThisTypes(target->nonLazyScript());
     if (!thisTypes || !thisTypes->hasType(TypeSet::ObjectType(templateObject)))
         return nullptr;
 
     // Generate an inline path to create a new |this| object with
     // the given singleton prototype.
-    MConstant* templateConst = MConstant::NewConstraintlessObject(alloc(), templateObject, this);
+    MConstant* templateConst = MConstant::NewConstraintlessObject(alloc(), templateObject);
     MCreateThisWithTemplate* createThis =
         MCreateThisWithTemplate::New(alloc(), constraints(), templateConst,
                                      templateObject->group()->initialHeap(constraints()));
     current->add(templateConst);
     current->add(createThis);
 
     return createThis;
 }
@@ -5843,17 +5843,17 @@ IonBuilder::createThisScriptedBaseline(M
     current->add(prototype);
     MDefinition* protoConst = constant(ObjectValue(*proto));
     MGuardObjectIdentity* guard = MGuardObjectIdentity::New(alloc(), prototype, protoConst,
                                                             /* bailOnEquality = */ false);
     current->add(guard);
 
     // Generate an inline path to create a new |this| object with
     // the given prototype.
-    MConstant* templateConst = MConstant::NewConstraintlessObject(alloc(), templateObject, this);
+    MConstant* templateConst = MConstant::NewConstraintlessObject(alloc(), templateObject);
     MCreateThisWithTemplate* createThis =
         MCreateThisWithTemplate::New(alloc(), constraints(), templateConst,
                                      templateObject->group()->initialHeap(constraints()));
     current->add(templateConst);
     current->add(createThis);
 
     return createThis;
 }
@@ -6145,19 +6145,16 @@ IonBuilder::jsop_call(uint32_t argc, boo
     }
 
     return makeCall(target, callInfo);
 }
 
 bool
 IonBuilder::testShouldDOMCall(TypeSet* inTypes, JSFunction* func, JSJitInfo::OpType opType)
 {
-    if (IsInsideNursery(func))
-        return false;
-
     if (!func->isNative() || !func->jitInfo())
         return false;
 
     // If all the DOM objects flowing through are legal with this
     // property, we can bake in a call to the bottom half of the DOM
     // accessor
     DOMInstanceClassHasProtoAtDepth instanceChecker =
         compartment->runtime()->DOMcallbacks()->instanceClassMatchesProto;
@@ -6463,17 +6460,17 @@ bool
 IonBuilder::jsop_newarray(uint32_t count)
 {
     JSObject* templateObject = inspector->getTemplateObject(pc);
     gc::InitialHeap heap;
     MConstant* templateConst;
 
     if (templateObject) {
         heap = templateObject->group()->initialHeap(constraints());
-        templateConst = MConstant::NewConstraintlessObject(alloc(), templateObject, this);
+        templateConst = MConstant::NewConstraintlessObject(alloc(), templateObject);
     } else {
         heap = gc::DefaultHeap;
         templateConst = MConstant::New(alloc(), NullValue());
     }
     current->add(templateConst);
 
     MNewArray* ins = MNewArray::New(alloc(), constraints(), count, templateConst, heap, pc);
     current->add(ins);
@@ -6514,17 +6511,17 @@ bool
 IonBuilder::jsop_newobject()
 {
     JSObject* templateObject = inspector->getTemplateObject(pc);
     gc::InitialHeap heap;
     MConstant* templateConst;
 
     if (templateObject) {
         heap = templateObject->group()->initialHeap(constraints());
-        templateConst = MConstant::NewConstraintlessObject(alloc(), templateObject, this);
+        templateConst = MConstant::NewConstraintlessObject(alloc(), templateObject);
     } else {
         heap = gc::DefaultHeap;
         templateConst = MConstant::New(alloc(), NullValue());
     }
 
     current->add(templateConst);
     MNewObject* ins = MNewObject::New(alloc(), constraints(), templateConst, heap,
                                       MNewObject::ObjectLiteral);
@@ -9009,17 +9006,17 @@ IonBuilder::setElemTryDense(bool* emitte
     JSValueType unboxedType = UnboxedArrayElementType(constraints(), object, index);
     if (unboxedType == JSVAL_TYPE_MAGIC) {
         if (!ElementAccessIsDenseNative(constraints(), object, index)) {
             trackOptimizationOutcome(TrackedOutcome::AccessNotDense);
             return true;
         }
     }
 
-    if (PropertyWriteNeedsTypeBarrier(this, constraints(), current,
+    if (PropertyWriteNeedsTypeBarrier(alloc(), constraints(), current,
                                       &object, nullptr, &value, /* canModify = */ true))
     {
         trackOptimizationOutcome(TrackedOutcome::NeedsTypeBarrier);
         return true;
     }
 
     if (!object->resultTypeSet()) {
         trackOptimizationOutcome(TrackedOutcome::NoTypeInfo);
@@ -9089,17 +9086,17 @@ IonBuilder::setElemTryCache(bool* emitte
     // Temporary disable the cache if non dense native,
     // until the cache supports more ics
     SetElemICInspector icInspect(inspector->setElemICInspector(pc));
     if (!icInspect.sawDenseWrite() && !icInspect.sawTypedArrayWrite()) {
         trackOptimizationOutcome(TrackedOutcome::SetElemNonDenseNonTANotCached);
         return true;
     }
 
-    if (PropertyWriteNeedsTypeBarrier(this, constraints(), current,
+    if (PropertyWriteNeedsTypeBarrier(alloc(), constraints(), current,
                                       &object, nullptr, &value, /* canModify = */ true))
     {
         trackOptimizationOutcome(TrackedOutcome::NeedsTypeBarrier);
         return true;
     }
 
     // We can avoid worrying about holes in the IC if we know a priori we are safe
     // from them. If TI can guard that there are no indexed properties on the prototype
@@ -9427,17 +9424,17 @@ IonBuilder::jsop_rest()
         return true;
     }
 
     // We know the exact number of arguments the callee pushed.
     unsigned numActuals = inlineCallInfo_->argc();
     unsigned numFormals = info().nargs() - 1;
     unsigned numRest = numActuals > numFormals ? numActuals - numFormals : 0;
 
-    MConstant* templateConst = MConstant::NewConstraintlessObject(alloc(), templateObject, this);
+    MConstant* templateConst = MConstant::NewConstraintlessObject(alloc(), templateObject);
     current->add(templateConst);
 
     MNewArray* array = MNewArray::New(alloc(), constraints(), numRest, templateConst,
                                       templateObject->group()->initialHeap(constraints()), pc);
     current->add(array);
 
     if (numRest == 0) {
         // No more updating to do. (Note that in this one case the length from
@@ -10807,18 +10804,17 @@ IonBuilder::getPropTryCommonGetter(bool*
           case InliningDecision_Inline:
             if (!inlineScriptedCall(callInfo, commonGetter))
                 return false;
             *emitted = true;
             return true;
         }
     }
 
-    JSFunction* tenuredCommonGetter = IsInsideNursery(commonGetter) ? nullptr : commonGetter;
-    if (!makeCall(tenuredCommonGetter, callInfo))
+    if (!makeCall(commonGetter, callInfo))
         return false;
 
     // If the getter could have been inlined, don't track success. The call to
     // makeInliningDecision above would have tracked a specific reason why we
     // couldn't inline.
     if (!commonGetter->isInterpreted())
         trackOptimizationSuccess();
 
@@ -11178,17 +11174,17 @@ IonBuilder::jsop_setprop(PropertyName* n
 
         // Try to emit stores to known binary data blocks
         trackOptimizationAttempt(TrackedStrategy::SetProp_TypedObject);
         if (!setPropTryTypedObject(&emitted, obj, name, value) || emitted)
             return emitted;
     }
 
     TemporaryTypeSet* objTypes = obj->resultTypeSet();
-    bool barrier = PropertyWriteNeedsTypeBarrier(this, constraints(), current, &obj, name, &value,
+    bool barrier = PropertyWriteNeedsTypeBarrier(alloc(), constraints(), current, &obj, name, &value,
                                                  /* canModify = */ true);
 
     if (!forceInlineCaches()) {
         // Try to emit stores to unboxed objects.
         trackOptimizationAttempt(TrackedStrategy::SetProp_Unboxed);
         if (!setPropTryUnboxed(&emitted, obj, name, value, barrier, objTypes) || emitted)
             return emitted;
     }
@@ -11302,18 +11298,17 @@ IonBuilder::setPropTryCommonSetter(bool*
           case InliningDecision_Inline:
             if (!inlineScriptedCall(callInfo, commonSetter))
                 return false;
             *emitted = true;
             return true;
         }
     }
 
-    JSFunction* tenuredCommonSetter = IsInsideNursery(commonSetter) ? nullptr : commonSetter;
-    MCall* call = makeCallHelper(tenuredCommonSetter, callInfo);
+    MCall* call = makeCallHelper(commonSetter, callInfo);
     if (!call)
         return false;
 
     current->push(value);
     if (!resumeAfter(call))
         return false;
 
     // If the setter could have been inlined, don't track success. The call to
@@ -11820,17 +11815,17 @@ bool
 IonBuilder::jsop_lambda(JSFunction* fun)
 {
     MOZ_ASSERT(analysis().usesScopeChain());
     MOZ_ASSERT(!fun->isArrow());
 
     if (fun->isNative() && IsAsmJSModuleNative(fun->native()))
         return abort("asm.js module function");
 
-    MConstant* cst = MConstant::NewConstraintlessObject(alloc(), fun, this);
+    MConstant* cst = MConstant::NewConstraintlessObject(alloc(), fun);
     current->add(cst);
     MLambda* ins = MLambda::New(alloc(), constraints(), current->scopeChain(), cst);
     current->add(ins);
     current->push(ins);
 
     return resumeAfter(ins);
 }
 
@@ -12505,17 +12500,17 @@ IonBuilder::jsop_instanceof()
         rhs = addShapeGuard(rhs, shape, Bailout_ShapeGuard);
 
         // Guard .prototype == protoObject.
         MOZ_ASSERT(shape->numFixedSlots() == 0, "Must be a dynamic slot");
         MSlots* slots = MSlots::New(alloc(), rhs);
         current->add(slots);
         MLoadSlot* prototype = MLoadSlot::New(alloc(), slots, slot);
         current->add(prototype);
-        MConstant* protoConst = MConstant::NewConstraintlessObject(alloc(), protoObject, this);
+        MConstant* protoConst = MConstant::NewConstraintlessObject(alloc(), protoObject);
         current->add(protoConst);
         MGuardObjectIdentity* guard = MGuardObjectIdentity::New(alloc(), prototype, protoConst,
                                                                 /* bailOnEquality = */ false);
         current->add(guard);
 
         if (tryFoldInstanceOf(obj, protoObject))
             return true;
 
@@ -12916,17 +12911,17 @@ IonBuilder::storeReferenceTypedObjectVal
     // Make sure we aren't adding new type information for writes of object and value
     // references.
     if (type != ReferenceTypeDescr::TYPE_STRING) {
         MOZ_ASSERT(type == ReferenceTypeDescr::TYPE_ANY ||
                    type == ReferenceTypeDescr::TYPE_OBJECT);
         MIRType implicitType =
             (type == ReferenceTypeDescr::TYPE_ANY) ? MIRType_Undefined : MIRType_Null;
 
-        if (PropertyWriteNeedsTypeBarrier(this, constraints(), current, &typedObj, name, &value,
+        if (PropertyWriteNeedsTypeBarrier(alloc(), constraints(), current, &typedObj, name, &value,
                                           /* canModify = */ true, implicitType))
         {
             trackOptimizationOutcome(TrackedOutcome::NeedsTypeBarrier);
             return false;
         }
     }
 
     // Find location within the owner object.
@@ -12985,17 +12980,17 @@ MConstant*
 IonBuilder::constant(const Value& v)
 {
     MOZ_ASSERT(!v.isString() || v.toString()->isAtom(),
                "Handle non-atomized strings outside IonBuilder.");
 
     if (v.isObject())
         checkNurseryObject(&v.toObject());
 
-    MConstant* c = MConstant::New(alloc(), v, constraints(), this);
+    MConstant* c = MConstant::New(alloc(), v, constraints());
     current->add(c);
     return c;
 }
 
 MConstant*
 IonBuilder::constantInt(int32_t i)
 {
     return constant(Int32Value(i));
--- a/js/src/jit/MCallOptimize.cpp
+++ b/js/src/jit/MCallOptimize.cpp
@@ -586,17 +586,17 @@ IonBuilder::inlineArray(CallInfo& callIn
 
         // Don't inline large allocations.
         if (initLength > ArrayObject::EagerAllocationMaxLength)
             return InliningStatus_NotInlined;
     }
 
     callInfo.setImplicitlyUsedUnchecked();
 
-    MConstant* templateConst = MConstant::NewConstraintlessObject(alloc(), templateObject, this);
+    MConstant* templateConst = MConstant::NewConstraintlessObject(alloc(), templateObject);
     current->add(templateConst);
 
     MNewArray* ins = MNewArray::New(alloc(), constraints(), initLength, templateConst,
                                     templateObject->group()->initialHeap(constraints()), pc);
     current->add(ins);
     current->push(ins);
 
     if (callInfo.argc() >= 2) {
@@ -760,17 +760,17 @@ IonBuilder::inlineArrayPush(CallInfo& ca
 {
     if (callInfo.argc() != 1 || callInfo.constructing()) {
         trackOptimizationOutcome(TrackedOutcome::CantInlineNativeBadForm);
         return InliningStatus_NotInlined;
     }
 
     MDefinition* obj = callInfo.thisArg();
     MDefinition* value = callInfo.getArg(0);
-    if (PropertyWriteNeedsTypeBarrier(this, constraints(), current,
+    if (PropertyWriteNeedsTypeBarrier(alloc(), constraints(), current,
                                       &obj, nullptr, &value, /* canModify = */ false))
     {
         trackOptimizationOutcome(TrackedOutcome::NeedsTypeBarrier);
         return InliningStatus_NotInlined;
     }
     MOZ_ASSERT(obj == callInfo.thisArg() && value == callInfo.getArg(0));
 
     if (getInlineReturnType() != MIRType_Int32)
@@ -1696,17 +1696,17 @@ IonBuilder::inlineConstantStringSplit(Ca
     }
     callInfo.setImplicitlyUsedUnchecked();
 
     TemporaryTypeSet::DoubleConversion conversion =
             getInlineReturnTypeSet()->convertDoubleElements(constraints());
     if (conversion == TemporaryTypeSet::AlwaysConvertToDoubles)
         return InliningStatus_NotInlined;
 
-    MConstant* templateConst = MConstant::NewConstraintlessObject(alloc(), templateObject, this);
+    MConstant* templateConst = MConstant::NewConstraintlessObject(alloc(), templateObject);
     current->add(templateConst);
 
     MNewArray* ins = MNewArray::New(alloc(), constraints(), initLength, templateConst,
                                     templateObject->group()->initialHeap(constraints()), pc);
 
     current->add(ins);
     current->push(ins);
 
@@ -1767,17 +1767,17 @@ IonBuilder::inlineStringSplit(CallInfo& 
 
     if (!key.maybeTypes()->hasType(TypeSet::StringType())) {
         key.freeze(constraints());
         return InliningStatus_NotInlined;
     }
 
     callInfo.setImplicitlyUsedUnchecked();
     MConstant* templateObjectDef = MConstant::New(alloc(), ObjectValue(*templateObject),
-                                                  constraints(), this);
+                                                  constraints());
     current->add(templateObjectDef);
 
     MStringSplit* ins = MStringSplit::New(alloc(), constraints(), callInfo.thisArg(),
                                           callInfo.getArg(0), templateObjectDef);
     current->add(ins);
     current->push(ins);
 
     return InliningStatus_Inlined;
@@ -2092,17 +2092,17 @@ IonBuilder::inlineObjectCreate(CallInfo&
         MOZ_ASSERT(types->getKnownMIRType() == MIRType_Object);
     } else {
         if (arg->type() != MIRType_Null)
             return InliningStatus_NotInlined;
     }
 
     callInfo.setImplicitlyUsedUnchecked();
 
-    MConstant* templateConst = MConstant::NewConstraintlessObject(alloc(), templateObject, this);
+    MConstant* templateConst = MConstant::NewConstraintlessObject(alloc(), templateObject);
     current->add(templateConst);
     MNewObject* ins = MNewObject::New(alloc(), constraints(), templateConst,
                                       templateObject->group()->initialHeap(constraints()),
                                       MNewObject::ObjectCreate);
     current->add(ins);
     current->push(ins);
     if (!resumeAfter(ins))
         return InliningStatus_Error;
--- a/js/src/jit/MIR.cpp
+++ b/js/src/jit/MIR.cpp
@@ -636,46 +636,45 @@ MDefinition::replaceAllLiveUsesWith(MDef
 
 bool
 MDefinition::emptyResultTypeSet() const
 {
     return resultTypeSet() && resultTypeSet()->empty();
 }
 
 MConstant*
-MConstant::New(TempAllocator& alloc, const Value& v,
-               CompilerConstraintList* constraints, MIRGenerator* gen)
-{
-    return new(alloc) MConstant(v, constraints, gen);
+MConstant::New(TempAllocator& alloc, const Value& v, CompilerConstraintList* constraints)
+{
+    return new(alloc) MConstant(v, constraints);
 }
 
 MConstant*
 MConstant::NewTypedValue(TempAllocator& alloc, const Value& v, MIRType type,
-                         CompilerConstraintList* constraints, MIRGenerator* gen)
+                         CompilerConstraintList* constraints)
 {
     MOZ_ASSERT(!IsSimdType(type));
     MOZ_ASSERT_IF(type == MIRType_Float32,
                   IsNaN(v.toDouble()) || v.toDouble() == double(float(v.toDouble())));
-    MConstant* constant = new(alloc) MConstant(v, constraints, gen);
+    MConstant* constant = new(alloc) MConstant(v, constraints);
     constant->setResultType(type);
     return constant;
 }
 
 MConstant*
 MConstant::NewAsmJS(TempAllocator& alloc, const Value& v, MIRType type)
 {
     if (type == MIRType_Float32)
         return NewTypedValue(alloc, Float32Value(v.toNumber()), type);
     return NewTypedValue(alloc, v, type);
 }
 
 MConstant*
-MConstant::NewConstraintlessObject(TempAllocator& alloc, JSObject* v, MIRGenerator* gen)
-{
-    return new(alloc) MConstant(v, gen);
+MConstant::NewConstraintlessObject(TempAllocator& alloc, JSObject* v)
+{
+    return new(alloc) MConstant(v);
 }
 
 static TemporaryTypeSet*
 MakeSingletonTypeSetFromKey(CompilerConstraintList* constraints, TypeSet::ObjectKey* key)
 {
     // Invalidate when this object's ObjectGroup gets unknown properties. This
     // happens for instance when we mutate an object's __proto__, in this case
     // we want to invalidate and mark this TypeSet as containing AnyObject
@@ -701,25 +700,44 @@ jit::MakeSingletonTypeSet(CompilerConstr
 
 static TemporaryTypeSet*
 MakeUnknownTypeSet()
 {
     LifoAlloc* alloc = GetJitContext()->temp->lifoAlloc();
     return alloc->new_<TemporaryTypeSet>(alloc, TypeSet::UnknownType());
 }
 
-MConstant::MConstant(const js::Value& vp, CompilerConstraintList* constraints, MIRGenerator* gen)
+#ifdef DEBUG
+
+bool
+jit::IonCompilationCanUseNurseryPointers()
+{
+    // If we are doing backend compilation, which could occur on a helper
+    // thread but might actually be on the main thread, check the flag set on
+    // the PerThreadData by AutoEnterIonCompilation.
+    if (CurrentThreadIsIonCompiling())
+        return !CurrentThreadIsIonCompilingSafeForMinorGC();
+
+    // Otherwise, we must be on the main thread during MIR construction. The
+    // store buffer must have been notified that minor GCs must cancel pending
+    // or in progress Ion compilations.
+    JSRuntime* rt = TlsPerThreadData.get()->runtimeFromMainThread();
+    return rt->gc.storeBuffer.cancelIonCompilations();
+}
+
+#endif // DEBUG
+
+MConstant::MConstant(const js::Value& vp, CompilerConstraintList* constraints)
   : value_(vp)
 {
     setResultType(MIRTypeFromValue(vp));
     if (vp.isObject()) {
         // Create a singleton type set for the object. This isn't necessary for
         // other types as the result type encodes all needed information.
-        MOZ_ASSERT(gen);
-        MOZ_ASSERT_IF(IsInsideNursery(&vp.toObject()), !gen->safeForMinorGC());
+        MOZ_ASSERT_IF(IsInsideNursery(&vp.toObject()), IonCompilationCanUseNurseryPointers());
         setResultTypeSet(MakeSingletonTypeSet(constraints, &vp.toObject()));
     }
     if (vp.isMagic() && vp.whyMagic() == JS_UNINITIALIZED_LEXICAL) {
         // JS_UNINITIALIZED_LEXICAL does not escape to script and is not
         // observed in type sets. However, it may flow around freely during
         // Ion compilation. Give it an unknown typeset to poison any type sets
         // it merges with.
         //
@@ -728,21 +746,20 @@ MConstant::MConstant(const js::Value& vp
         setResultTypeSet(MakeUnknownTypeSet());
     }
 
     MOZ_ASSERT_IF(vp.isString(), vp.toString()->isAtom());
 
     setMovable();
 }
 
-MConstant::MConstant(JSObject* obj, MIRGenerator* gen)
+MConstant::MConstant(JSObject* obj)
   : value_(ObjectValue(*obj))
 {
-    MOZ_ASSERT(gen);
-    MOZ_ASSERT_IF(IsInsideNursery(obj), !gen->safeForMinorGC());
+    MOZ_ASSERT_IF(IsInsideNursery(obj), IonCompilationCanUseNurseryPointers());
     setResultType(MIRType_Object);
     setMovable();
 }
 
 HashNumber
 MConstant::valueHash() const
 {
     // Fold all 64 bits into the 32-bit result. It's tempting to just discard
@@ -5203,28 +5220,28 @@ TryAddTypeBarrierForWrite(TempAllocator&
         kind = BarrierKind::TypeTagOnly;
 
     MInstruction* ins = MMonitorTypes::New(alloc, *pvalue, types, kind);
     current->add(ins);
     return true;
 }
 
 static MInstruction*
-AddGroupGuard(MIRGenerator* gen, MBasicBlock* current, MDefinition* obj,
+AddGroupGuard(TempAllocator& alloc, MBasicBlock* current, MDefinition* obj,
               TypeSet::ObjectKey* key, bool bailOnEquality)
 {
     MInstruction* guard;
 
     if (key->isGroup()) {
-        guard = MGuardObjectGroup::New(gen->alloc(), obj, key->group(), bailOnEquality,
+        guard = MGuardObjectGroup::New(alloc, obj, key->group(), bailOnEquality,
                                        Bailout_ObjectIdentityOrTypeGuard);
     } else {
-        MConstant* singletonConst = MConstant::NewConstraintlessObject(gen->alloc(), key->singleton(), gen);
+        MConstant* singletonConst = MConstant::NewConstraintlessObject(alloc, key->singleton());
         current->add(singletonConst);
-        guard = MGuardObjectIdentity::New(gen->alloc(), obj, singletonConst, bailOnEquality);
+        guard = MGuardObjectIdentity::New(alloc, obj, singletonConst, bailOnEquality);
     }
 
     current->add(guard);
 
     // For now, never move object group / identity guards.
     guard->setNotMovable();
 
     return guard;
@@ -5237,17 +5254,17 @@ jit::CanWriteProperty(TempAllocator& all
                       MIRType implicitType /* = MIRType_None */)
 {
     if (property.couldBeConstant(constraints))
         return false;
     return PropertyTypeIncludes(alloc, property, value, implicitType);
 }
 
 bool
-jit::PropertyWriteNeedsTypeBarrier(MIRGenerator* gen, CompilerConstraintList* constraints,
+jit::PropertyWriteNeedsTypeBarrier(TempAllocator& alloc, CompilerConstraintList* constraints,
                                    MBasicBlock* current, MDefinition** pobj,
                                    PropertyName* name, MDefinition** pvalue,
                                    bool canModify, MIRType implicitType)
 {
     // If any value being written is not reflected in the type information for
     // objects which obj could represent, a type barrier is needed when writing
     // the value. As for propertyReadNeedsTypeBarrier, this only applies for
     // properties that are accounted for by type information, i.e. normal data
@@ -5270,24 +5287,24 @@ jit::PropertyWriteNeedsTypeBarrier(MIRGe
 
         // TI doesn't track TypedArray indexes and should never insert a type
         // barrier for them.
         if (!name && IsAnyTypedArrayClass(key->clasp()))
             continue;
 
         jsid id = name ? NameToId(name) : JSID_VOID;
         HeapTypeSetKey property = key->property(id);
-        if (!CanWriteProperty(gen->alloc(), constraints, property, *pvalue, implicitType)) {
+        if (!CanWriteProperty(alloc, constraints, property, *pvalue, implicitType)) {
             // Either pobj or pvalue needs to be modified to filter out the
             // types which the value could have but are not in the property,
             // or a VM call is required. A VM call is always required if pobj
             // and pvalue cannot be modified.
             if (!canModify)
                 return true;
-            success = TryAddTypeBarrierForWrite(gen->alloc(), constraints, current, types, name, pvalue,
+            success = TryAddTypeBarrierForWrite(alloc, constraints, current, types, name, pvalue,
                                                 implicitType);
             break;
         }
     }
 
     if (success)
         return false;
 
@@ -5303,17 +5320,17 @@ jit::PropertyWriteNeedsTypeBarrier(MIRGe
         TypeSet::ObjectKey* key = types->getObject(i);
         if (!key || key->unknownProperties())
             continue;
         if (!name && IsAnyTypedArrayClass(key->clasp()))
             continue;
 
         jsid id = name ? NameToId(name) : JSID_VOID;
         HeapTypeSetKey property = key->property(id);
-        if (CanWriteProperty(gen->alloc(), constraints, property, *pvalue, implicitType))
+        if (CanWriteProperty(alloc, constraints, property, *pvalue, implicitType))
             continue;
 
         if ((property.maybeTypes() && !property.maybeTypes()->empty()) || excluded)
             return true;
         excluded = key;
     }
 
     MOZ_ASSERT(excluded);
@@ -5324,11 +5341,11 @@ jit::PropertyWriteNeedsTypeBarrier(MIRGe
     if (excluded->isGroup()) {
         if (UnboxedLayout* layout = excluded->group()->maybeUnboxedLayout()) {
             if (layout->nativeGroup())
                 return true;
             excluded->watchStateChangeForUnboxedConvertedToNative(constraints);
         }
     }
 
-    *pobj = AddGroupGuard(gen, current, *pobj, excluded, /* bailOnEquality = */ true);
+    *pobj = AddGroupGuard(alloc, current, *pobj, excluded, /* bailOnEquality = */ true);
     return false;
 }
--- a/js/src/jit/MIR.h
+++ b/js/src/jit/MIR.h
@@ -1304,30 +1304,27 @@ class MLimitedTruncate
 };
 
 // A constant js::Value.
 class MConstant : public MNullaryInstruction
 {
     Value value_;
 
   protected:
-    MConstant(const Value& v, CompilerConstraintList* constraints, MIRGenerator* gen);
-    explicit MConstant(JSObject* obj, MIRGenerator* gen);
+    MConstant(const Value& v, CompilerConstraintList* constraints);
+    explicit MConstant(JSObject* obj);
 
   public:
     INSTRUCTION_HEADER(Constant)
     static MConstant* New(TempAllocator& alloc, const Value& v,
-                          CompilerConstraintList* constraints = nullptr,
-                          MIRGenerator* gen = nullptr);
+                          CompilerConstraintList* constraints = nullptr);
     static MConstant* NewTypedValue(TempAllocator& alloc, const Value& v, MIRType type,
-                                    CompilerConstraintList* constraints = nullptr,
-                                    MIRGenerator* gen = nullptr);
+                                    CompilerConstraintList* constraints = nullptr);
     static MConstant* NewAsmJS(TempAllocator& alloc, const Value& v, MIRType type);
-    static MConstant* NewConstraintlessObject(TempAllocator& alloc, JSObject* v,
-                                              MIRGenerator* gen);
+    static MConstant* NewConstraintlessObject(TempAllocator& alloc, JSObject* v);
 
     const js::Value& value() const {
         return value_;
     }
     const js::Value* vp() const {
         return &value_;
     }
     bool valueToBoolean() const {
@@ -2839,52 +2836,59 @@ MergeTypes(MIRType* ptype, TemporaryType
 
 bool
 TypeSetIncludes(TypeSet* types, MIRType input, TypeSet* inputTypes);
 
 bool
 EqualTypes(MIRType type1, TemporaryTypeSet* typeset1,
            MIRType type2, TemporaryTypeSet* typeset2);
 
-// Helper class to assert all GC pointers embedded in MIR instructions are
-// tenured. Off-thread Ion compilation and nursery GCs can happen in parallel,
-// so it's invalid to store pointers to nursery things. There's no need to root
-// these pointers, as GC is suppressed during compilation and off-thread
-// compilations are canceled on every major GC.
+#ifdef DEBUG
+bool
+IonCompilationCanUseNurseryPointers();
+#endif
+
+// Helper class to check that GC pointers embedded in MIR instructions are in
+// in the nursery only when the store buffer has been marked as needing to
+// cancel all ion compilations. Otherwise, off-thread Ion compilation and
+// nursery GCs can happen in parallel, so it's invalid to store pointers to
+// nursery things. There's no need to root these pointers, as GC is suppressed
+// during compilation and off-thread compilations are canceled on major GCs.
 template <typename T>
-class AlwaysTenured
+class CompilerGCPointer
 {
     js::gc::Cell* ptr_;
 
   public:
-    explicit AlwaysTenured(T ptr)
+    explicit CompilerGCPointer(T ptr)
       : ptr_(ptr)
     {
+        MOZ_ASSERT_IF(IsInsideNursery(ptr), IonCompilationCanUseNurseryPointers());
 #ifdef DEBUG
-        MOZ_ASSERT(!IsInsideNursery(ptr_));
         PerThreadData* pt = TlsPerThreadData.get();
         MOZ_ASSERT_IF(pt->runtimeIfOnOwnerThread(), pt->suppressGC);
 #endif
     }
 
     operator T() const { return static_cast<T>(ptr_); }
     T operator->() const { return static_cast<T>(ptr_); }
 
   private:
-    AlwaysTenured() = delete;
-    AlwaysTenured(const AlwaysTenured<T>&) = delete;
-    AlwaysTenured<T>& operator=(const AlwaysTenured<T>&) = delete;
-};
-
-typedef AlwaysTenured<JSObject*> AlwaysTenuredObject;
-typedef AlwaysTenured<NativeObject*> AlwaysTenuredNativeObject;
-typedef AlwaysTenured<JSFunction*> AlwaysTenuredFunction;
-typedef AlwaysTenured<JSScript*> AlwaysTenuredScript;
-typedef AlwaysTenured<PropertyName*> AlwaysTenuredPropertyName;
-typedef AlwaysTenured<Shape*> AlwaysTenuredShape;
+    CompilerGCPointer() = delete;
+    CompilerGCPointer(const CompilerGCPointer<T>&) = delete;
+    CompilerGCPointer<T>& operator=(const CompilerGCPointer<T>&) = delete;
+};
+
+typedef CompilerGCPointer<JSObject*> CompilerObject;
+typedef CompilerGCPointer<NativeObject*> CompilerNativeObject;
+typedef CompilerGCPointer<JSFunction*> CompilerFunction;
+typedef CompilerGCPointer<JSScript*> CompilerScript;
+typedef CompilerGCPointer<PropertyName*> CompilerPropertyName;
+typedef CompilerGCPointer<Shape*> CompilerShape;
+typedef CompilerGCPointer<ObjectGroup*> CompilerObjectGroup;
 
 class MNewArray
   : public MUnaryInstruction,
     public NoTypePolicy::Data
 {
   private:
     // Number of space to allocate for the array.
     uint32_t count_;
@@ -2949,17 +2953,17 @@ class MNewArray
         // The template object can safely be used in the recover instruction
         // because it can never be mutated by any other function execution.
         return templateObject() != nullptr;
     }
 };
 
 class MNewArrayCopyOnWrite : public MNullaryInstruction
 {
-    AlwaysTenured<ArrayObject*> templateObject_;
+    CompilerGCPointer<ArrayObject*> templateObject_;
     gc::InitialHeap initialHeap_;
 
     MNewArrayCopyOnWrite(CompilerConstraintList* constraints, ArrayObject* templateObject,
               gc::InitialHeap initialHeap)
       : templateObject_(templateObject),
         initialHeap_(initialHeap)
     {
         MOZ_ASSERT(!templateObject->isSingleton());
@@ -2990,17 +2994,17 @@ class MNewArrayCopyOnWrite : public MNul
         return AliasSet::None();
     }
 };
 
 class MNewArrayDynamicLength
   : public MUnaryInstruction,
     public IntPolicy<0>::Data
 {
-    AlwaysTenuredObject templateObject_;
+    CompilerObject templateObject_;
     gc::InitialHeap initialHeap_;
 
     MNewArrayDynamicLength(CompilerConstraintList* constraints, JSObject* templateObject,
                            gc::InitialHeap initialHeap, MDefinition* length)
       : MUnaryInstruction(length),
         templateObject_(templateObject),
         initialHeap_(initialHeap)
     {
@@ -3098,17 +3102,17 @@ class MNewObject
         // The template object can safely be used in the recover instruction
         // because it can never be mutated by any other function execution.
         return templateObject() != nullptr;
     }
 };
 
 class MNewTypedObject : public MNullaryInstruction
 {
-    AlwaysTenured<InlineTypedObject*> templateObject_;
+    CompilerGCPointer<InlineTypedObject*> templateObject_;
     gc::InitialHeap initialHeap_;
 
     MNewTypedObject(CompilerConstraintList* constraints,
                     InlineTypedObject* templateObject,
                     gc::InitialHeap initialHeap)
       : templateObject_(templateObject),
         initialHeap_(initialHeap)
     {
@@ -3173,17 +3177,17 @@ class MTypedObjectDescr
 // Generic way for constructing a SIMD object in IonMonkey, this instruction
 // takes as argument a SIMD instruction and returns a new SIMD object which
 // corresponds to the MIRType of its operand.
 class MSimdBox
   : public MUnaryInstruction,
     public NoTypePolicy::Data
 {
   protected:
-    AlwaysTenured<InlineTypedObject*> templateObject_;
+    CompilerGCPointer<InlineTypedObject*> templateObject_;
     gc::InitialHeap initialHeap_;
 
     MSimdBox(CompilerConstraintList* constraints,
              MDefinition* op,
              InlineTypedObject* templateObject,
              gc::InitialHeap initialHeap)
       : MUnaryInstruction(op),
         templateObject_(templateObject),
@@ -3526,17 +3530,17 @@ class MMutateProto
     }
 };
 
 // Slow path for adding a property to an object without a known base.
 class MInitProp
   : public MAryInstruction<2>,
     public MixPolicy<ObjectPolicy<0>, BoxPolicy<1> >::Data
 {
-    AlwaysTenuredPropertyName name_;
+    CompilerPropertyName name_;
 
   protected:
     MInitProp(MDefinition* obj, PropertyName* name, MDefinition* value)
       : name_(name)
     {
         initOperand(0, obj);
         initOperand(1, value);
         setResultType(MIRType_None);
@@ -3566,17 +3570,17 @@ class MInitProp
         return true;
     }
 };
 
 class MInitPropGetterSetter
   : public MBinaryInstruction,
     public MixPolicy<ObjectPolicy<0>, ObjectPolicy<1> >::Data
 {
-    AlwaysTenuredPropertyName name_;
+    CompilerPropertyName name_;
 
     MInitPropGetterSetter(MDefinition* obj, PropertyName* name, MDefinition* value)
       : MBinaryInstruction(obj, value),
         name_(name)
     { }
 
   public:
     INSTRUCTION_HEADER(InitPropGetterSetter)
@@ -3668,17 +3672,17 @@ class MCall
   private:
     // An MCall uses the MPrepareCall, MDefinition for the function, and
     // MPassArg instructions. They are stored in the same list.
     static const size_t FunctionOperandIndex   = 0;
     static const size_t NumNonArgumentOperands = 1;
 
   protected:
     // Monomorphic cache of single target from TI, or nullptr.
-    AlwaysTenuredFunction target_;
+    CompilerFunction target_;
 
     // Original value of argc from the bytecode.
     uint32_t numActualArgs_;
 
     // True if the call is for JSOP_NEW.
     bool construct_;
 
     bool needsArgCheck_;
@@ -3843,17 +3847,17 @@ class MArraySplice
 
 // fun.apply(self, arguments)
 class MApplyArgs
   : public MAryInstruction<3>,
     public Mix3Policy<ObjectPolicy<0>, IntPolicy<1>, BoxPolicy<2> >::Data
 {
   protected:
     // Monomorphic cache of single target from TI, or nullptr.
-    AlwaysTenuredFunction target_;
+    CompilerFunction target_;
 
     MApplyArgs(JSFunction* target, MDefinition* fun, MDefinition* argc, MDefinition* self)
       : target_(target)
     {
         initOperand(0, fun);
         initOperand(1, argc);
         initOperand(2, self);
         setResultType(MIRType_Value);
@@ -7186,17 +7190,17 @@ class MThrowUninitializedLexical : publi
     }
 };
 
 // If not defined, set a global variable to |undefined|.
 class MDefVar
   : public MUnaryInstruction,
     public NoTypePolicy::Data
 {
-    AlwaysTenuredPropertyName name_; // Target name to be defined.
+    CompilerPropertyName name_; // Target name to be defined.
     unsigned attrs_; // Attributes to be set.
 
   private:
     MDefVar(PropertyName* name, unsigned attrs, MDefinition* scopeChain)
       : MUnaryInstruction(scopeChain),
         name_(name),
         attrs_(attrs)
     {
@@ -7224,17 +7228,17 @@ class MDefVar
         return true;
     }
 };
 
 class MDefFun
   : public MUnaryInstruction,
     public NoTypePolicy::Data
 {
-    AlwaysTenuredFunction fun_;
+    CompilerFunction fun_;
 
   private:
     MDefFun(JSFunction* fun, MDefinition* scopeChain)
       : MUnaryInstruction(scopeChain),
         fun_(fun)
     {}
 
   public:
@@ -7252,17 +7256,17 @@ class MDefFun
     }
     bool possiblyCalls() const override {
         return true;
     }
 };
 
 class MRegExp : public MNullaryInstruction
 {
-    AlwaysTenured<RegExpObject*> source_;
+    CompilerGCPointer<RegExpObject*> source_;
     bool mustClone_;
 
     MRegExp(CompilerConstraintList* constraints, RegExpObject* source, bool mustClone)
       : source_(source),
         mustClone_(mustClone)
     {
         setResultType(MIRType_Object);
         setResultTypeSet(MakeSingletonTypeSet(constraints, source));
@@ -7508,17 +7512,17 @@ class MSubstr
     }
 };
 
 struct LambdaFunctionInfo
 {
     // The functions used in lambdas are the canonical original function in
     // the script, and are immutable except for delazification. Record this
     // information while still on the main thread to avoid races.
-    AlwaysTenuredFunction fun;
+    CompilerFunction fun;
     uint16_t flags;
     uint16_t nargs;
     gc::Cell* scriptOrLazyScript;
     bool singletonType;
     bool useSingletonForClone;
 
     explicit LambdaFunctionInfo(JSFunction* fun)
       : fun(fun), flags(fun->flags()), nargs(fun->nargs()),
@@ -9025,17 +9029,17 @@ class MStoreUnboxedString
 };
 
 // Passes through an object, after ensuring it is converted from an unboxed
 // object to a native representation.
 class MConvertUnboxedObjectToNative
   : public MUnaryInstruction,
     public SingleObjectPolicy::Data
 {
-    AlwaysTenured<ObjectGroup*> group_;
+    CompilerObjectGroup group_;
 
     explicit MConvertUnboxedObjectToNative(MDefinition* obj, ObjectGroup* group)
       : MUnaryInstruction(obj),
         group_(group)
     {
         setGuard();
         setMovable();
         setResultType(MIRType_Object);
@@ -9172,17 +9176,17 @@ class MArrayPush
     ALLOW_CLONE(MArrayPush)
 };
 
 // Array.prototype.concat on two dense arrays.
 class MArrayConcat
   : public MBinaryInstruction,
     public MixPolicy<ObjectPolicy<0>, ObjectPolicy<1> >::Data
 {
-    AlwaysTenuredObject templateObj_;
+    CompilerObject templateObj_;
     gc::InitialHeap initialHeap_;
     JSValueType unboxedType_;
 
     MArrayConcat(CompilerConstraintList* constraints, MDefinition* lhs, MDefinition* rhs,
                  JSObject* templateObj, gc::InitialHeap initialHeap, JSValueType unboxedType)
       : MBinaryInstruction(lhs, rhs),
         templateObj_(templateObj),
         initialHeap_(initialHeap),
@@ -9225,17 +9229,17 @@ class MArrayConcat
     }
 };
 
 // Array.prototype.slice on a dense array.
 class MArraySlice
   : public MTernaryInstruction,
     public Mix3Policy<ObjectPolicy<0>, IntPolicy<1>, IntPolicy<2>>::Data
 {
-    AlwaysTenuredObject templateObj_;
+    CompilerObject templateObj_;
     gc::InitialHeap initialHeap_;
     JSValueType unboxedType_;
 
     MArraySlice(CompilerConstraintList* constraints, MDefinition* obj,
                 MDefinition* begin, MDefinition* end,
                 JSObject* templateObj, gc::InitialHeap initialHeap, JSValueType unboxedType)
       : MTernaryInstruction(obj, begin, end),
         templateObj_(templateObj),
@@ -9519,17 +9523,18 @@ class MLoadTypedArrayElementStatic
         if (type == Scalar::Float32)
             setResultType(MIRType_Float32);
         else if (type == Scalar::Float64)
             setResultType(MIRType_Double);
         else
             setResultType(MIRType_Int32);
     }
 
-    AlwaysTenured<JSObject*> someTypedArray_;
+    CompilerObject someTypedArray_;
+
     // An offset to be encoded in the load instruction - taking advantage of the
     // addressing modes. This is only non-zero when the access is proven to be
     // within bounds.
     int32_t offset_;
     bool needsBoundsCheck_;
     bool fallible_;
 
   public:
@@ -9765,17 +9770,17 @@ class MStoreTypedArrayElementStatic :
     MStoreTypedArrayElementStatic(JSObject* someTypedArray, MDefinition* ptr, MDefinition* v,
                                   int32_t offset, bool needsBoundsCheck)
         : MBinaryInstruction(ptr, v),
           StoreUnboxedScalarBase(AnyTypedArrayType(someTypedArray)),
           someTypedArray_(someTypedArray),
           offset_(offset), needsBoundsCheck_(needsBoundsCheck)
     {}
 
-    AlwaysTenured<JSObject*> someTypedArray_;
+    CompilerObject someTypedArray_;
 
     // An offset to be encoded in the store instruction - taking advantage of the
     // addressing modes. This is only non-zero when the access is proven to be
     // within bounds.
     int32_t offset_;
     bool needsBoundsCheck_;
 
   public:
@@ -9985,18 +9990,18 @@ class MStoreFixedSlot
 };
 
 typedef Vector<JSObject*, 4, JitAllocPolicy> ObjectVector;
 typedef Vector<bool, 4, JitAllocPolicy> BoolVector;
 
 class InlinePropertyTable : public TempObject
 {
     struct Entry : public TempObject {
-        AlwaysTenured<ObjectGroup*> group;
-        AlwaysTenuredFunction func;
+        CompilerObjectGroup group;
+        CompilerFunction func;
 
         Entry(ObjectGroup* group, JSFunction* func)
           : group(group), func(func)
         { }
     };
 
     jsbytecode* pc_;
     MResumePoint* priorResumePoint_;
@@ -10062,17 +10067,17 @@ class CacheLocationList : public InlineC
     jsbytecode* pc;
     JSScript* script;
 };
 
 class MGetPropertyCache
   : public MUnaryInstruction,
     public SingleObjectPolicy::Data
 {
-    AlwaysTenuredPropertyName name_;
+    CompilerPropertyName name_;
     bool idempotent_;
     bool monitoredResult_;
 
     CacheLocationList location_;
 
     InlinePropertyTable* inlinePropertyTable_;
 
     MGetPropertyCache(MDefinition* obj, PropertyName* name, bool monitoredResult)
@@ -10166,17 +10171,17 @@ class MGetPropertyPolymorphic
         // The group and/or shape to guard against.
         ReceiverGuard receiver;
 
         // The property to load, null for loads from unboxed properties.
         Shape* shape;
     };
 
     Vector<Entry, 4, JitAllocPolicy> receivers_;
-    AlwaysTenuredPropertyName name_;
+    CompilerPropertyName name_;
 
     MGetPropertyPolymorphic(TempAllocator& alloc, MDefinition* obj, PropertyName* name)
       : MUnaryInstruction(obj),
         receivers_(alloc),
         name_(name)
     {
         setGuard();
         setMovable();
@@ -10246,17 +10251,17 @@ class MSetPropertyPolymorphic
         // The group and/or shape to guard against.
         ReceiverGuard receiver;
 
         // The property to store, null for stores to unboxed properties.
         Shape* shape;
     };
 
     Vector<Entry, 4, JitAllocPolicy> receivers_;
-    AlwaysTenuredPropertyName name_;
+    CompilerPropertyName name_;
     bool needsBarrier_;
 
     MSetPropertyPolymorphic(TempAllocator& alloc, MDefinition* obj, MDefinition* value,
                             PropertyName* name)
       : MBinaryInstruction(obj, value),
         receivers_(alloc),
         name_(name),
         needsBarrier_(false)
@@ -10509,18 +10514,18 @@ class MGetElementCache
 
     bool allowDoubleResult() const;
 };
 
 class MBindNameCache
   : public MUnaryInstruction,
     public SingleObjectPolicy::Data
 {
-    AlwaysTenuredPropertyName name_;
-    AlwaysTenuredScript script_;
+    CompilerPropertyName name_;
+    CompilerScript script_;
     jsbytecode* pc_;
 
     MBindNameCache(MDefinition* scopeChain, PropertyName* name, JSScript* script, jsbytecode* pc)
       : MUnaryInstruction(scopeChain), name_(name), script_(script), pc_(pc)
     {
         setResultType(MIRType_Object);
     }
 
@@ -10547,17 +10552,17 @@ class MBindNameCache
     }
 };
 
 // Guard on an object's shape.
 class MGuardShape
   : public MUnaryInstruction,
     public SingleObjectPolicy::Data
 {
-    AlwaysTenuredShape shape_;
+    CompilerShape shape_;
     BailoutKind bailoutKind_;
 
     MGuardShape(MDefinition* obj, Shape* shape, BailoutKind bailoutKind)
       : MUnaryInstruction(obj),
         shape_(shape),
         bailoutKind_(bailoutKind)
     {
         setGuard();
@@ -10648,17 +10653,17 @@ class MGuardReceiverPolymorphic
     }
 };
 
 // Guard on an object's group, inclusively or exclusively.
 class MGuardObjectGroup
   : public MUnaryInstruction,
     public SingleObjectPolicy::Data
 {
-    AlwaysTenured<ObjectGroup*> group_;
+    CompilerObjectGroup group_;
     bool bailOnEquality_;
     BailoutKind bailoutKind_;
 
     MGuardObjectGroup(MDefinition* obj, ObjectGroup* group, bool bailOnEquality,
                       BailoutKind bailoutKind)
       : MUnaryInstruction(obj),
         group_(group),
         bailOnEquality_(bailOnEquality),
@@ -11023,17 +11028,17 @@ class MGetNameCache
 {
   public:
     enum AccessKind {
         NAMETYPEOF,
         NAME
     };
 
   private:
-    AlwaysTenuredPropertyName name_;
+    CompilerPropertyName name_;
     AccessKind kind_;
 
     MGetNameCache(MDefinition* obj, PropertyName* name, AccessKind kind)
       : MUnaryInstruction(obj),
         name_(name),
         kind_(kind)
     {
         setResultType(MIRType_Value);
@@ -11055,17 +11060,17 @@ class MGetNameCache
     }
     AccessKind accessKind() const {
         return kind_;
     }
 };
 
 class MCallGetIntrinsicValue : public MNullaryInstruction
 {
-    AlwaysTenuredPropertyName name_;
+    CompilerPropertyName name_;
 
     explicit MCallGetIntrinsicValue(PropertyName* name)
       : name_(name)
     {
         setResultType(MIRType_Value);
     }
 
   public:
@@ -11082,17 +11087,17 @@ class MCallGetIntrinsicValue : public MN
     }
     bool possiblyCalls() const override {
         return true;
     }
 };
 
 class MSetPropertyInstruction : public MBinaryInstruction
 {
-    AlwaysTenuredPropertyName name_;
+    CompilerPropertyName name_;
     bool strict_;
     bool needsBarrier_;
 
   protected:
     MSetPropertyInstruction(MDefinition* obj, MDefinition* value, PropertyName* name,
                             bool strict)
       : MBinaryInstruction(obj, value),
         name_(name), strict_(strict), needsBarrier_(true)
@@ -11144,17 +11149,17 @@ class MSetElementInstruction
         return strict_;
     }
 };
 
 class MDeleteProperty
   : public MUnaryInstruction,
     public BoxInputsPolicy::Data
 {
-    AlwaysTenuredPropertyName name_;
+    CompilerPropertyName name_;
     bool strict_;
 
   protected:
     MDeleteProperty(MDefinition* val, PropertyName* name, bool strict)
       : MUnaryInstruction(val),
         name_(name),
         strict_(strict)
     {
@@ -11292,17 +11297,17 @@ class MSetElementCache
 
     bool canConsumeFloat32(MUse* use) const override { return use == getUseFor(2); }
 };
 
 class MCallGetProperty
   : public MUnaryInstruction,
     public BoxInputsPolicy::Data
 {
-    AlwaysTenuredPropertyName name_;
+    CompilerPropertyName name_;
     bool idempotent_;
     bool callprop_;
 
     MCallGetProperty(MDefinition* value, PropertyName* name, bool callprop)
       : MUnaryInstruction(value), name_(name),
         idempotent_(false),
         callprop_(callprop)
     {
@@ -11991,17 +11996,17 @@ class MInArray
     }
 };
 
 // Implementation for instanceof operator with specific rhs.
 class MInstanceOf
   : public MUnaryInstruction,
     public InstanceOfPolicy::Data
 {
-    AlwaysTenuredObject protoObj_;
+    CompilerObject protoObj_;
 
     MInstanceOf(MDefinition* obj, JSObject* proto)
       : MUnaryInstruction(obj),
         protoObj_(proto)
     {
         setResultType(MIRType_Boolean);
     }
 
@@ -12164,17 +12169,17 @@ class MSetFrameArgument
     AliasSet getAliasSet() const override {
         return AliasSet::Store(AliasSet::FrameArgument);
     }
 };
 
 class MRestCommon
 {
     unsigned numFormals_;
-    AlwaysTenured<ArrayObject*> templateObject_;
+    CompilerGCPointer<ArrayObject*> templateObject_;
 
   protected:
     MRestCommon(unsigned numFormals, ArrayObject* templateObject)
       : numFormals_(numFormals),
         templateObject_(templateObject)
    { }
 
   public:
@@ -12388,17 +12393,17 @@ class MPostWriteBarrier : public MBinary
     }
 #endif
 
     ALLOW_CLONE(MPostWriteBarrier)
 };
 
 class MNewDeclEnvObject : public MNullaryInstruction
 {
-    AlwaysTenured<DeclEnvObject*> templateObj_;
+    CompilerGCPointer<DeclEnvObject*> templateObj_;
 
     explicit MNewDeclEnvObject(DeclEnvObject* templateObj)
       : MNullaryInstruction(),
         templateObj_(templateObj)
     {
         setResultType(MIRType_Object);
     }
 
@@ -12414,17 +12419,17 @@ class MNewDeclEnvObject : public MNullar
     }
     AliasSet getAliasSet() const override {
         return AliasSet::None();
     }
 };
 
 class MNewCallObjectBase : public MNullaryInstruction
 {
-    AlwaysTenured<CallObject*> templateObj_;
+    CompilerGCPointer<CallObject*> templateObj_;
 
   protected:
     explicit MNewCallObjectBase(CallObject* templateObj)
       : MNullaryInstruction(),
         templateObj_(templateObj)
     {
         setResultType(MIRType_Object);
     }
@@ -12469,17 +12474,17 @@ class MNewRunOnceCallObject : public MNe
         return new(alloc) MNewRunOnceCallObject(templateObj);
     }
 };
 
 class MNewStringObject :
   public MUnaryInstruction,
   public ConvertToStringPolicy<0>::Data
 {
-    AlwaysTenuredObject templateObj_;
+    CompilerObject templateObj_;
 
     MNewStringObject(MDefinition* input, JSObject* templateObj)
       : MUnaryInstruction(input),
         templateObj_(templateObj)
     {
         setResultType(MIRType_Object);
     }
 
@@ -13605,17 +13610,17 @@ BarrierKind PropertyReadOnPrototypeNeeds
                                                     TemporaryTypeSet* observed);
 bool PropertyReadIsIdempotent(CompilerConstraintList* constraints,
                               MDefinition* obj, PropertyName* name);
 void AddObjectsForPropertyRead(MDefinition* obj, PropertyName* name,
                                TemporaryTypeSet* observed);
 bool CanWriteProperty(TempAllocator& alloc, CompilerConstraintList* constraints,
                       HeapTypeSetKey property, MDefinition* value,
                       MIRType implicitType = MIRType_None);
-bool PropertyWriteNeedsTypeBarrier(MIRGenerator* gen, CompilerConstraintList* constraints,
+bool PropertyWriteNeedsTypeBarrier(TempAllocator& alloc, CompilerConstraintList* constraints,
                                    MBasicBlock* current, MDefinition** pobj,
                                    PropertyName* name, MDefinition** pvalue,
                                    bool canModify, MIRType implicitType = MIRType_None);
 
 } // namespace jit
 } // namespace js
 
 #endif /* jit_MIR_h */