Backed out changeset 1c7e09bbee26 (bug 1000942) for dt3 orange
authorCarsten "Tomcat" Book <cbook@mozilla.com>
Tue, 29 Apr 2014 10:38:52 +0200
changeset 181087 652501df07279981c11656a97e6b7b82e20ef420
parent 181086 4cca5e45f4f9c795b8b7983df8df48538bfb3273
child 181088 336fe702ad1219be47fa9ea4fd05a32fa4b95bd6
push id272
push userpvanderbeken@mozilla.com
push dateMon, 05 May 2014 16:31:18 +0000
bugs1000942
milestone32.0a1
backs out1c7e09bbee26480ea413a01c718052f4eb63bd68
Backed out changeset 1c7e09bbee26 (bug 1000942) for dt3 orange
js/src/jit/CodeGenerator.cpp
js/src/jit/IonBuilder.cpp
js/src/jit/IonBuilder.h
js/src/jit/IonCaches.cpp
js/src/jit/IonMacroAssembler.cpp
js/src/jit/IonMacroAssembler.h
js/src/jit/IonTypes.h
js/src/jit/Lowering.cpp
js/src/jit/MCallOptimize.cpp
js/src/jit/MIR.cpp
js/src/jit/MIR.h
js/src/jsinfer.cpp
js/src/jsinfer.h
--- a/js/src/jit/CodeGenerator.cpp
+++ b/js/src/jit/CodeGenerator.cpp
@@ -1723,27 +1723,25 @@ CodeGenerator::visitGuardObjectIdentity(
 
 bool
 CodeGenerator::visitTypeBarrierV(LTypeBarrierV *lir)
 {
     ValueOperand operand = ToValue(lir, LTypeBarrierV::Input);
     Register scratch = ToTempRegisterOrInvalid(lir->temp());
 
     Label miss;
-    masm.guardTypeSet(operand, lir->mir()->resultTypeSet(), lir->mir()->barrierKind(), scratch, &miss);
+    masm.guardTypeSet(operand, lir->mir()->resultTypeSet(), scratch, &miss);
     if (!bailoutFrom(&miss, lir->snapshot()))
         return false;
     return true;
 }
 
 bool
 CodeGenerator::visitTypeBarrierO(LTypeBarrierO *lir)
 {
-    MOZ_ASSERT(lir->mir()->barrierKind() != BarrierKind::TypeTagOnly);
-
     Register obj = ToRegister(lir->object());
     Register scratch = ToTempRegisterOrInvalid(lir->temp());
 
     Label miss;
     masm.guardObjectType(obj, lir->mir()->resultTypeSet(), scratch, &miss);
     if (!bailoutFrom(&miss, lir->snapshot()))
         return false;
     return true;
@@ -1751,17 +1749,17 @@ CodeGenerator::visitTypeBarrierO(LTypeBa
 
 bool
 CodeGenerator::visitMonitorTypes(LMonitorTypes *lir)
 {
     ValueOperand operand = ToValue(lir, LMonitorTypes::Input);
     Register scratch = ToTempUnboxRegister(lir->temp());
 
     Label matched, miss;
-    masm.guardTypeSet(operand, lir->mir()->typeSet(), lir->mir()->barrierKind(), scratch, &miss);
+    masm.guardTypeSet(operand, lir->mir()->typeSet(), scratch, &miss);
     if (!bailoutFrom(&miss, lir->snapshot()))
         return false;
     return true;
 }
 
 #ifdef JSGC_GENERATIONAL
 // Out-of-line path to update the store buffer.
 class OutOfLineCallPostWriteBarrier : public OutOfLineCodeBase<CodeGenerator>
@@ -2707,17 +2705,17 @@ CodeGenerator::generateArgumentsChecks(b
         if (!types || types->unknown())
             continue;
 
         // Calculate the offset on the stack of the argument.
         // (i - info.startArgSlot())    - Compute index of arg within arg vector.
         // ... * sizeof(Value)          - Scale by value size.
         // ArgToStackOffset(...)        - Compute displacement within arg vector.
         int32_t offset = ArgToStackOffset((i - info.startArgSlot()) * sizeof(Value));
-        masm.guardTypeSet(Address(StackPointer, offset), types, BarrierKind::TypeSet, temp, &miss);
+        masm.guardTypeSet(Address(StackPointer, offset), types, temp, &miss);
     }
 
     if (miss.used()) {
         if (bailout) {
             if (!bailoutFrom(&miss, graph.entrySnapshot()))
                 return false;
         } else {
             Label success;
@@ -3183,17 +3181,17 @@ CodeGenerator::emitValueResultChecks(LIn
     // types are expected (until we reach the OsiPoint and bailout).
     Label done;
     if (!branchIfInvalidated(temp1, &done))
         return false;
 
     if (mir->resultTypeSet() && !mir->resultTypeSet()->unknown()) {
         // We have a result TypeSet, assert this value is in it.
         Label miss, ok;
-        masm.guardTypeSet(output, mir->resultTypeSet(), BarrierKind::TypeSet, temp1, &miss);
+        masm.guardTypeSet(output, mir->resultTypeSet(), temp1, &miss);
         masm.jump(&ok);
 
         masm.bind(&miss);
         masm.assumeUnreachable("MIR instruction returned value with unexpected type");
 
         masm.bind(&ok);
     }
 
--- a/js/src/jit/IonBuilder.cpp
+++ b/js/src/jit/IonBuilder.cpp
@@ -5044,17 +5044,17 @@ IonBuilder::jsop_funapplyarguments(uint3
 
         MApplyArgs *apply = MApplyArgs::New(alloc(), target, argFunc, numArgs, argThis);
         current->add(apply);
         current->push(apply);
         if (!resumeAfter(apply))
             return false;
 
         types::TemporaryTypeSet *types = bytecodeTypes(pc);
-        return pushTypeBarrier(apply, types, BarrierKind::TypeSet);
+        return pushTypeBarrier(apply, types, true);
     }
 
     // When inlining we have the arguments the function gets called with
     // and can optimize even more, by just calling the functions with the args.
     // We also try this path when doing the definite properties analysis, as we
     // can inline the apply() target and don't care about the actual arguments
     // that were passed in.
 
@@ -5373,17 +5373,17 @@ IonBuilder::makeCall(JSFunction *target,
     if (call->isEffectful() && !resumeAfter(call))
         return false;
 
     types::TemporaryTypeSet *types = bytecodeTypes(pc);
 
     if (call->isCallDOMNative())
         return pushDOMTypeBarrier(call, types, call->getSingleTarget());
 
-    return pushTypeBarrier(call, types, BarrierKind::TypeSet);
+    return pushTypeBarrier(call, types, true);
 }
 
 bool
 IonBuilder::jsop_eval(uint32_t argc)
 {
     int calleeDepth = -((int)argc + 2);
     types::TemporaryTypeSet *calleeTypes = current->peek(calleeDepth)->resultTypeSet();
 
@@ -5421,17 +5421,17 @@ IonBuilder::jsop_eval(uint32_t argc)
         MDefinition *scopeChain = current->scopeChain();
         MDefinition *string = callInfo.getArg(0);
 
         // Direct eval acts as identity on non-string types according to
         // ES5 15.1.2.1 step 1.
         if (!string->mightBeType(MIRType_String)) {
             current->push(string);
             types::TemporaryTypeSet *types = bytecodeTypes(pc);
-            return pushTypeBarrier(string, types, BarrierKind::TypeSet);
+            return pushTypeBarrier(string, types, true);
         }
 
         current->pushSlot(info().thisSlot());
         MDefinition *thisValue = current->pop();
 
         // 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.
@@ -5460,17 +5460,17 @@ IonBuilder::jsop_eval(uint32_t argc)
         MInstruction *filterArguments = MFilterArgumentsOrEval::New(alloc(), string);
         current->add(filterArguments);
 
         MInstruction *ins = MCallDirectEval::New(alloc(), scopeChain, string, thisValue, pc);
         current->add(ins);
         current->push(ins);
 
         types::TemporaryTypeSet *types = bytecodeTypes(pc);
-        return resumeAfter(ins) && pushTypeBarrier(ins, types, BarrierKind::TypeSet);
+        return resumeAfter(ins) && pushTypeBarrier(ins, types, true);
     }
 
     return jsop_call(argc, /* constructing = */ false);
 }
 
 bool
 IonBuilder::jsop_compare(JSOp op)
 {
@@ -6269,44 +6269,44 @@ IonBuilder::testSingletonPropertyTypes(M
 //     then an infallible unbox instruction replaces the value on the top of
 //     the stack.
 // (3) If a type barrier is needed, but has an unknown type set, leave the
 //     value at the top of the stack.
 // (4) If a type barrier is needed, and has a single type, an unbox
 //     instruction replaces the top of the stack.
 // (5) Lastly, a type barrier instruction replaces the top of the stack.
 bool
-IonBuilder::pushTypeBarrier(MDefinition *def, types::TemporaryTypeSet *observed, BarrierKind kind)
+IonBuilder::pushTypeBarrier(MDefinition *def, types::TemporaryTypeSet *observed, bool needsBarrier)
 {
     // Barriers are never needed for instructions whose result will not be used.
     if (BytecodeIsPopped(pc))
         return true;
 
     // If the instruction has no side effects, we'll resume the entire operation.
     // The actual type barrier will occur in the interpreter. If the
     // instruction is effectful, even if it has a singleton type, there
     // must be a resume point capturing the original def, and resuming
     // to that point will explicitly monitor the new type.
 
-    if (kind == BarrierKind::NoBarrier) {
+    if (!needsBarrier) {
         MDefinition *replace = ensureDefiniteType(def, observed->getKnownMIRType());
         if (replace != def) {
             current->pop();
             current->push(replace);
         }
         replace->setResultTypeSet(observed);
         return true;
     }
 
     if (observed->unknown())
         return true;
 
     current->pop();
 
-    MInstruction *barrier = MTypeBarrier::New(alloc(), def, observed, kind);
+    MInstruction *barrier = MTypeBarrier::New(alloc(), def, observed);
     current->add(barrier);
 
     if (barrier->type() == MIRType_Undefined)
         return pushConstant(UndefinedValue());
     if (barrier->type() == MIRType_Null)
         return pushConstant(NullValue());
 
     current->push(barrier);
@@ -6337,18 +6337,17 @@ IonBuilder::pushDOMTypeBarrier(MInstruct
         if (replace != ins) {
             current->pop();
             current->push(replace);
         }
     } else {
         JS_ASSERT(barrier);
     }
 
-    return pushTypeBarrier(replace, observed,
-                           barrier ? BarrierKind::TypeSet : BarrierKind::NoBarrier);
+    return pushTypeBarrier(replace, observed, barrier);
 }
 
 MDefinition *
 IonBuilder::ensureDefiniteType(MDefinition *def, MIRType definiteType)
 {
     MInstruction *replace;
     switch (definiteType) {
       case MIRType_Undefined:
@@ -6445,38 +6444,38 @@ IonBuilder::getStaticName(JSObject *stat
     {
         // The property has been reconfigured as non-configurable, non-enumerable
         // or non-writable.
         *psucceeded = false;
         return true;
     }
 
     types::TemporaryTypeSet *types = bytecodeTypes(pc);
-    BarrierKind barrier = PropertyReadNeedsTypeBarrier(analysisContext, constraints(), staticType,
-                                                       name, types, /* updateObserved = */ true);
+    bool barrier = PropertyReadNeedsTypeBarrier(analysisContext, constraints(), staticType,
+                                                name, types, /* updateObserved = */ true);
 
     JSObject *singleton = types->getSingleton();
 
     MIRType knownType = types->getKnownMIRType();
-    if (barrier == BarrierKind::NoBarrier) {
+    if (!barrier) {
         if (singleton) {
             // Try to inline a known constant value.
             if (testSingletonProperty(staticObject, name) == singleton)
                 return pushConstant(ObjectValue(*singleton));
         }
         if (knownType == MIRType_Undefined)
             return pushConstant(UndefinedValue());
         if (knownType == MIRType_Null)
             return pushConstant(NullValue());
     }
 
     MInstruction *obj = constant(ObjectValue(*staticObject));
 
     MIRType rvalType = types->getKnownMIRType();
-    if (barrier != BarrierKind::NoBarrier)
+    if (barrier)
         rvalType = MIRType_Value;
 
     return loadSlot(obj, property.maybeTypes()->definiteSlot(), NumFixedSlots(staticObject),
                     rvalType, barrier, types);
 }
 
 // Whether 'types' includes all possible values represented by input/inputTypes.
 bool
@@ -6608,17 +6607,17 @@ IonBuilder::jsop_getname(PropertyName *n
 
     current->add(ins);
     current->push(ins);
 
     if (!resumeAfter(ins))
         return false;
 
     types::TemporaryTypeSet *types = bytecodeTypes(pc);
-    return pushTypeBarrier(ins, types, BarrierKind::TypeSet);
+    return pushTypeBarrier(ins, types, true);
 }
 
 bool
 IonBuilder::jsop_intrinsic(PropertyName *name)
 {
     types::TemporaryTypeSet *types = bytecodeTypes(pc);
 
     // If we haven't executed this opcode yet, we need to get the intrinsic
@@ -6627,17 +6626,17 @@ IonBuilder::jsop_intrinsic(PropertyName 
         MCallGetIntrinsicValue *ins = MCallGetIntrinsicValue::New(alloc(), name);
 
         current->add(ins);
         current->push(ins);
 
         if (!resumeAfter(ins))
             return false;
 
-        return pushTypeBarrier(ins, types, BarrierKind::TypeSet);
+        return pushTypeBarrier(ins, types, true);
     }
 
     // Bake in the intrinsic. Make sure that TI agrees with us on the type.
     Value vp;
     JS_ALWAYS_TRUE(script()->global().maybeGetIntrinsicValue(name, &vp));
     JS_ASSERT(types->hasType(types::GetValueType(vp)));
 
     pushConstant(vp);
@@ -6692,17 +6691,17 @@ IonBuilder::jsop_getelem()
 
         current->add(ins);
         current->push(ins);
 
         if (!resumeAfter(ins))
             return false;
 
         types::TemporaryTypeSet *types = bytecodeTypes(pc);
-        return pushTypeBarrier(ins, types, BarrierKind::TypeSet);
+        return pushTypeBarrier(ins, types, true);
     }
 
     bool emitted = false;
 
     if (!getElemTryTypedObject(&emitted, obj, index) || emitted)
         return emitted;
 
     if (!getElemTryDense(&emitted, obj, index) || emitted)
@@ -6734,17 +6733,17 @@ IonBuilder::jsop_getelem()
 
     current->add(ins);
     current->push(ins);
 
     if (!resumeAfter(ins))
         return false;
 
     types::TemporaryTypeSet *types = bytecodeTypes(pc);
-    return pushTypeBarrier(ins, types, BarrierKind::TypeSet);
+    return pushTypeBarrier(ins, types, true);
 }
 
 bool
 IonBuilder::getElemTryTypedObject(bool *emitted, MDefinition *obj, MDefinition *index)
 {
     JS_ASSERT(*emitted == false);
 
     TypeDescrSet objDescrs;
@@ -7000,17 +6999,17 @@ IonBuilder::pushDerivedTypedObject(bool 
     //
     // Barriers are particularly expensive here because they prevent
     // us from optimizing the MNewDerivedTypedObject away.
     if (observedClass && observedProto && observedClass == expectedClass &&
         observedProto == expectedProto)
     {
         derivedTypedObj->setResultTypeSet(observedTypes);
     } else {
-        if (!pushTypeBarrier(derivedTypedObj, observedTypes, BarrierKind::TypeSet))
+        if (!pushTypeBarrier(derivedTypedObj, observedTypes, true))
             return false;
     }
 
     *emitted = true;
     return true;
 }
 
 bool
@@ -7182,17 +7181,17 @@ IonBuilder::getElemTryArguments(bool *em
     index = addBoundsCheck(index, length);
 
     // Load the argument from the actual arguments.
     MGetFrameArgument *load = MGetFrameArgument::New(alloc(), index, analysis_.hasSetArg());
     current->add(load);
     current->push(load);
 
     types::TemporaryTypeSet *types = bytecodeTypes(pc);
-    if (!pushTypeBarrier(load, types, BarrierKind::TypeSet))
+    if (!pushTypeBarrier(load, types, true))
         return false;
 
     *emitted = true;
     return true;
 }
 
 bool
 IonBuilder::getElemTryArgumentsInlined(bool *emitted, MDefinition *obj, MDefinition *index)
@@ -7251,38 +7250,37 @@ IonBuilder::getElemTryCache(bool *emitte
     // of this getelem.
     bool nonNativeGetElement = inspector->hasSeenNonNativeGetElement(pc);
     if (index->mightBeType(MIRType_Int32) && nonNativeGetElement)
         return true;
 
     // Emit GetElementCache.
 
     types::TemporaryTypeSet *types = bytecodeTypes(pc);
-    BarrierKind barrier = PropertyReadNeedsTypeBarrier(analysisContext, constraints(), obj,
-                                                       nullptr, types);
+    bool barrier = PropertyReadNeedsTypeBarrier(analysisContext, constraints(), obj, nullptr, types);
 
     // Always add a barrier if the index might be a string, so that the cache
     // can attach stubs for particular properties.
     if (index->mightBeType(MIRType_String))
-        barrier = BarrierKind::TypeSet;
+        barrier = true;
 
     // See note about always needing a barrier in jsop_getprop.
     if (needsToMonitorMissingProperties(types))
-        barrier = BarrierKind::TypeSet;
-
-    MInstruction *ins = MGetElementCache::New(alloc(), obj, index, barrier != BarrierKind::NoBarrier);
+        barrier = true;
+
+    MInstruction *ins = MGetElementCache::New(alloc(), obj, index, barrier);
 
     current->add(ins);
     current->push(ins);
 
     if (!resumeAfter(ins))
         return false;
 
     // Spice up type information.
-    if (index->type() == MIRType_Int32 && barrier == BarrierKind::NoBarrier) {
+    if (index->type() == MIRType_Int32 && !barrier) {
         bool needHoleCheck = !ElementAccessIsPacked(constraints(), obj);
         MIRType knownType = GetElemKnownType(needHoleCheck, types);
 
         if (knownType != MIRType_Value && knownType != MIRType_Double)
             ins->setResultType(knownType);
     }
 
     if (!pushTypeBarrier(ins, types, barrier))
@@ -7299,29 +7297,28 @@ IonBuilder::jsop_getelem_dense(MDefiniti
 
     if (JSOp(*pc) == JSOP_CALLELEM && !index->mightBeType(MIRType_String)) {
         // Indexed call on an element of an array. Populate the observed types
         // with any objects that could be in the array, to avoid extraneous
         // type barriers.
         AddObjectsForPropertyRead(obj, nullptr, types);
     }
 
-    BarrierKind barrier = PropertyReadNeedsTypeBarrier(analysisContext, constraints(), obj,
-                                                       nullptr, types);
+    bool barrier = PropertyReadNeedsTypeBarrier(analysisContext, constraints(), obj, nullptr, types);
     bool needsHoleCheck = !ElementAccessIsPacked(constraints(), obj);
 
     // Reads which are on holes in the object do not have to bail out if
     // undefined values have been observed at this access site and the access
     // cannot hit another indexed property on the object or its prototypes.
     bool readOutOfBounds =
         types->hasType(types::Type::UndefinedType()) &&
         !ElementAccessHasExtraIndexedProperty(constraints(), obj);
 
     MIRType knownType = MIRType_Value;
-    if (barrier == BarrierKind::NoBarrier)
+    if (!barrier)
         knownType = GetElemKnownType(needsHoleCheck, types);
 
     // Ensure index is an integer.
     MInstruction *idInt32 = MToInt32::New(alloc(), index);
     current->add(idInt32);
     index = idInt32;
 
     // Get the elements vector.
@@ -7339,17 +7336,17 @@ IonBuilder::jsop_getelem_dense(MDefiniti
     //
     // NB: We disable this optimization in parallel execution mode
     // because it is inherently not threadsafe (how do you convert the
     // array atomically when there might be concurrent readers)?
     types::TemporaryTypeSet *objTypes = obj->resultTypeSet();
     ExecutionMode executionMode = info().executionMode();
     bool loadDouble =
         executionMode == SequentialExecution &&
-        barrier == BarrierKind::NoBarrier &&
+        !barrier &&
         loopDepth_ &&
         !readOutOfBounds &&
         !needsHoleCheck &&
         knownType == MIRType_Double &&
         objTypes &&
         objTypes->convertDoubleElements(constraints()) == types::TemporaryTypeSet::AlwaysConvertToDoubles;
     if (loadDouble)
         elements = addConvertElementsToDoubles(elements);
@@ -7390,27 +7387,27 @@ IonBuilder::jsop_getelem_dense(MDefiniti
     // substitute a broader observed type set consisting of both ints
     // and doubles. There is perhaps a tradeoff here, so we limit this
     // optimization to parallel code, where it is needed to prevent
     // perpetual bailouts in some extreme cases. (Bug 977853)
     //
     // NB: we have not added a MConvertElementsToDoubles MIR, so we
     // cannot *assume* the result is a double.
     if (executionMode == ParallelExecution &&
-        barrier != BarrierKind::NoBarrier &&
+        barrier &&
         types->getKnownMIRType() == MIRType_Int32 &&
         objTypes &&
         objTypes->convertDoubleElements(constraints()) == types::TemporaryTypeSet::AlwaysConvertToDoubles)
     {
         // Note: double implies int32 as well for typesets
         types = alloc_->lifoAlloc()->new_<types::TemporaryTypeSet>(types::Type::DoubleType());
         if (!types)
             return false;
 
-        barrier = BarrierKind::NoBarrier; // Don't need a barrier anymore
+        barrier = false; // Don't need a barrier anymore
     }
 
     if (knownType != MIRType_Value)
         load->setResultType(knownType);
 
     current->push(load);
     return pushTypeBarrier(load, types, barrier);
 }
@@ -7559,46 +7556,46 @@ IonBuilder::jsop_getelem_typed(MDefiniti
         // be valid and unbarriered.
         load->setResultType(knownType);
         return true;
     } else {
         // We need a type barrier if the array's element type has never been
         // observed (we've only read out-of-bounds values). Note that for
         // Uint32Array, we only check for int32: if allowDouble is false we
         // will bailout when we read a double.
-        BarrierKind barrier = BarrierKind::TypeSet;
+        bool needsBarrier = true;
         switch (arrayType) {
           case ScalarTypeDescr::TYPE_INT8:
           case ScalarTypeDescr::TYPE_UINT8:
           case ScalarTypeDescr::TYPE_UINT8_CLAMPED:
           case ScalarTypeDescr::TYPE_INT16:
           case ScalarTypeDescr::TYPE_UINT16:
           case ScalarTypeDescr::TYPE_INT32:
           case ScalarTypeDescr::TYPE_UINT32:
             if (types->hasType(types::Type::Int32Type()))
-                barrier = BarrierKind::NoBarrier;
+                needsBarrier = false;
             break;
           case ScalarTypeDescr::TYPE_FLOAT32:
           case ScalarTypeDescr::TYPE_FLOAT64:
             if (allowDouble)
-                barrier = BarrierKind::NoBarrier;
+                needsBarrier = false;
             break;
           default:
             MOZ_ASSUME_UNREACHABLE("Unknown typed array type");
         }
 
         // Assume we will read out-of-bound values. In this case the
         // bounds check will be part of the instruction, and the instruction
         // will always return a Value.
         MLoadTypedArrayElementHole *load =
             MLoadTypedArrayElementHole::New(alloc(), obj, index, arrayType, allowDouble);
         current->add(load);
         current->push(load);
 
-        return pushTypeBarrier(load, types, barrier);
+        return pushTypeBarrier(load, types, needsBarrier);
     }
 }
 
 bool
 IonBuilder::jsop_setelem()
 {
     bool emitted = false;
 
@@ -8492,17 +8489,17 @@ IonBuilder::invalidatedIdempotentCache()
         builder = builder->callerBuilder_;
     } while (builder);
 
     return false;
 }
 
 bool
 IonBuilder::loadSlot(MDefinition *obj, size_t slot, size_t nfixed, MIRType rvalType,
-                     BarrierKind barrier, types::TemporaryTypeSet *types)
+                     bool barrier, types::TemporaryTypeSet *types)
 {
     if (slot < nfixed) {
         MLoadFixedSlot *load = MLoadFixedSlot::New(alloc(), obj, slot);
         current->add(load);
         current->push(load);
 
         load->setResultType(rvalType);
         return pushTypeBarrier(load, types, barrier);
@@ -8516,17 +8513,17 @@ IonBuilder::loadSlot(MDefinition *obj, s
     current->push(load);
 
     load->setResultType(rvalType);
     return pushTypeBarrier(load, types, barrier);
 }
 
 bool
 IonBuilder::loadSlot(MDefinition *obj, Shape *shape, MIRType rvalType,
-                     BarrierKind barrier, types::TemporaryTypeSet *types)
+                     bool barrier, types::TemporaryTypeSet *types)
 {
     return loadSlot(obj, shape->slot(), shape->numFixedSlots(), rvalType, barrier, types);
 }
 
 bool
 IonBuilder::storeSlot(MDefinition *obj, size_t slot, size_t nfixed,
                       MDefinition *value, bool needsBarrier,
                       MIRType slotType /* = MIRType_None */)
@@ -8566,18 +8563,18 @@ IonBuilder::jsop_getprop(PropertyName *n
 {
     bool emitted = false;
 
     // Try to optimize arguments.length.
     if (!getPropTryArgumentsLength(&emitted) || emitted)
         return emitted;
 
     types::TemporaryTypeSet *types = bytecodeTypes(pc);
-    BarrierKind barrier = PropertyReadNeedsTypeBarrier(analysisContext, constraints(),
-                                                       current->peek(-1), name, types);
+    bool barrier = PropertyReadNeedsTypeBarrier(analysisContext, constraints(),
+                                                current->peek(-1), name, types);
 
     // Always use a call if we are performing analysis and
     // not actually emitting code, to simplify later analysis. Also skip deeper
     // analysis if there are no known types for this operation, as it will
     // always invalidate when executing.
     if (info().executionModeIsAnalysis() || types->empty()) {
         MDefinition *obj = current->peek(-1);
         MCallGetProperty *call = MCallGetProperty::New(alloc(), obj, name, *pc == JSOP_CALLPROP);
@@ -8589,17 +8586,17 @@ IonBuilder::jsop_getprop(PropertyName *n
         // analysis knows when the |this| value has been read from.
         if (info().executionModeIsAnalysis()) {
             if (!getPropTryConstant(&emitted, name, types) || emitted)
                 return emitted;
         }
 
         current->pop();
         current->push(call);
-        return resumeAfter(call) && pushTypeBarrier(call, types, BarrierKind::TypeSet);
+        return resumeAfter(call) && pushTypeBarrier(call, types, true);
     }
 
     // Try to hardcode known constants.
     if (!getPropTryConstant(&emitted, name, types) || emitted)
         return emitted;
 
     // Try to emit loads from known binary data blocks
     if (!getPropTryTypedObject(&emitted, name, types) || emitted)
@@ -8624,17 +8621,17 @@ IonBuilder::jsop_getprop(PropertyName *n
     // Emit a call.
     MDefinition *obj = current->pop();
     MCallGetProperty *call = MCallGetProperty::New(alloc(), obj, name, *pc == JSOP_CALLPROP);
     current->add(call);
     current->push(call);
     if (!resumeAfter(call))
         return false;
 
-    return pushTypeBarrier(call, types, BarrierKind::TypeSet);
+    return pushTypeBarrier(call, types, true);
 }
 
 bool
 IonBuilder::getPropTryArgumentsLength(bool *emitted)
 {
     JS_ASSERT(*emitted == false);
     if (current->peek(-1)->type() != MIRType_MagicOptimizedArguments) {
         if (script()->argumentsHasVarBinding() &&
@@ -8763,33 +8760,33 @@ IonBuilder::getPropTryComplexPropOfTyped
     MDefinition *fieldTypeObj = typeObjectForFieldFromStructType(type, fieldIndex);
 
     return pushDerivedTypedObject(emitted, typedObj, constantInt(fieldOffset),
                                   fieldDescrs, fieldTypeObj, true);
 }
 
 bool
 IonBuilder::getPropTryDefiniteSlot(bool *emitted, PropertyName *name,
-                                   BarrierKind barrier, types::TemporaryTypeSet *types)
+                                   bool barrier, types::TemporaryTypeSet *types)
 {
     JS_ASSERT(*emitted == false);
     types::HeapTypeSetKey property;
     if (!getDefiniteSlot(current->peek(-1)->resultTypeSet(), name, &property))
         return true;
 
     MDefinition *obj = current->pop();
     MDefinition *useObj = obj;
     if (obj->type() != MIRType_Object) {
         MGuardObject *guard = MGuardObject::New(alloc(), obj);
         current->add(guard);
         useObj = guard;
     }
 
     MLoadFixedSlot *fixed = MLoadFixedSlot::New(alloc(), useObj, property.maybeTypes()->definiteSlot());
-    if (barrier == BarrierKind::NoBarrier)
+    if (!barrier)
         fixed->setResultType(types->getKnownMIRType());
 
     current->add(fixed);
     current->push(fixed);
 
     if (!pushTypeBarrier(fixed, types, barrier))
         return false;
 
@@ -8901,31 +8898,31 @@ CanInlinePropertyOpShapes(const Baseline
             return false;
     }
 
     return true;
 }
 
 bool
 IonBuilder::getPropTryInlineAccess(bool *emitted, PropertyName *name,
-                                   BarrierKind barrier, types::TemporaryTypeSet *types)
+                                   bool barrier, types::TemporaryTypeSet *types)
 {
     JS_ASSERT(*emitted == false);
     if (current->peek(-1)->type() != MIRType_Object)
         return true;
 
     BaselineInspector::ShapeVector shapes(alloc());
     if (!inspector->maybeShapesForPropertyOp(pc, shapes))
         return false;
 
     if (shapes.empty() || !CanInlinePropertyOpShapes(shapes))
         return true;
 
     MIRType rvalType = types->getKnownMIRType();
-    if (barrier != BarrierKind::NoBarrier || IsNullOrUndefined(rvalType))
+    if (barrier || IsNullOrUndefined(rvalType))
         rvalType = MIRType_Value;
 
     MDefinition *obj = current->pop();
     if (shapes.length() == 1) {
         // In the monomorphic case, use separate ShapeGuard and LoadSlot
         // instructions.
         spew("Inlining monomorphic GETPROP");
 
@@ -8962,46 +8959,45 @@ IonBuilder::getPropTryInlineAccess(bool 
     }
 
     *emitted = true;
     return true;
 }
 
 bool
 IonBuilder::getPropTryCache(bool *emitted, PropertyName *name,
-                            BarrierKind barrier, types::TemporaryTypeSet *types)
+                            bool barrier, types::TemporaryTypeSet *types)
 {
     JS_ASSERT(*emitted == false);
 
     MDefinition *obj = current->peek(-1);
 
     // The input value must either be an object, or we should have strong suspicions
     // that it can be safely unboxed to an object.
     if (obj->type() != MIRType_Object) {
         types::TemporaryTypeSet *types = obj->resultTypeSet();
         if (!types || !types->objectOrSentinel())
             return true;
     }
 
     // Since getters have no guaranteed return values, we must barrier in order to be
     // able to attach stubs for them.
     if (inspector->hasSeenAccessedGetter(pc))
-        barrier = BarrierKind::TypeSet;
+        barrier = true;
 
     if (needsToMonitorMissingProperties(types))
-        barrier = BarrierKind::TypeSet;
+        barrier = true;
 
     // Caches can read values from prototypes, so update the barrier to
     // reflect such possible values.
-    if (barrier == BarrierKind::NoBarrier)
+    if (!barrier)
         barrier = PropertyReadOnPrototypeNeedsTypeBarrier(constraints(), obj, name, types);
 
     current->pop();
-    MGetPropertyCache *load = MGetPropertyCache::New(alloc(), obj, name,
-                                                     barrier != BarrierKind::NoBarrier);
+    MGetPropertyCache *load = MGetPropertyCache::New(alloc(), obj, name, barrier);
 
     // Try to mark the cache as idempotent.
     //
     // In parallel execution, idempotency of caches is ignored, since we
     // repeat the entire ForkJoin workload if we bail out. Note that it's
     // overly restrictive to mark everything as idempotent, because we can
     // treat non-idempotent caches in parallel as repeatable.
     if (obj->type() == MIRType_Object && !invalidatedIdempotentCache() &&
@@ -9018,17 +9014,17 @@ IonBuilder::getPropTryCache(bool *emitte
 
     current->add(load);
     current->push(load);
 
     if (load->isEffectful() && !resumeAfter(load))
         return false;
 
     MIRType rvalType = types->getKnownMIRType();
-    if (barrier != BarrierKind::NoBarrier || IsNullOrUndefined(rvalType))
+    if (barrier || IsNullOrUndefined(rvalType))
         rvalType = MIRType_Value;
     load->setResultType(rvalType);
 
     if (!pushTypeBarrier(load, types, barrier))
         return false;
 
     *emitted = true;
     return true;
@@ -9862,17 +9858,17 @@ IonBuilder::jsop_getaliasedvar(ScopeCoor
     } else {
         load = MLoadFixedSlot::New(alloc(), obj, sc.slot());
     }
 
     current->add(load);
     current->push(load);
 
     types::TemporaryTypeSet *types = bytecodeTypes(pc);
-    return pushTypeBarrier(load, types, BarrierKind::TypeSet);
+    return pushTypeBarrier(load, types, true);
 }
 
 bool
 IonBuilder::jsop_setaliasedvar(ScopeCoordinate sc)
 {
     JSObject *call = nullptr;
     if (hasStaticScopeObject(sc, &call)) {
         uint32_t depth = current->stackDepth() + 1;
--- a/js/src/jit/IonBuilder.h
+++ b/js/src/jit/IonBuilder.h
@@ -338,17 +338,17 @@ class IonBuilder : public MIRGenerator
     MConstant *constant(const Value &v);
     MConstant *constantInt(int32_t i);
 
     // Filter the type information at tests
     bool filterTypesAtTest(MTest *test);
 
     // Add a guard which ensure that the set of type which goes through this
     // generated code correspond to the observed types for the bytecode.
-    bool pushTypeBarrier(MDefinition *def, types::TemporaryTypeSet *observed, BarrierKind kind);
+    bool pushTypeBarrier(MDefinition *def, types::TemporaryTypeSet *observed, bool needBarrier);
 
     // As pushTypeBarrier, but will compute the needBarrier boolean itself based
     // on observed and the JSFunction that we're planning to call. The
     // JSFunction must be a DOM method or getter.
     bool pushDOMTypeBarrier(MInstruction *ins, types::TemporaryTypeSet *observed, JSFunction* func);
 
     // If definiteType is not known or def already has the right type, just
     // returns def.  Otherwise, returns an MInstruction that has that definite
@@ -375,48 +375,48 @@ class IonBuilder : public MIRGenerator
 
     MDefinition *convertShiftToMaskForStaticTypedArray(MDefinition *id,
                                                        ArrayBufferView::ViewType viewType);
 
     bool invalidatedIdempotentCache();
 
     bool hasStaticScopeObject(ScopeCoordinate sc, JSObject **pcall);
     bool loadSlot(MDefinition *obj, size_t slot, size_t nfixed, MIRType rvalType,
-                  BarrierKind barrier, types::TemporaryTypeSet *types);
+                  bool barrier, types::TemporaryTypeSet *types);
     bool loadSlot(MDefinition *obj, Shape *shape, MIRType rvalType,
-                  BarrierKind barrier, types::TemporaryTypeSet *types);
+                  bool barrier, types::TemporaryTypeSet *types);
     bool storeSlot(MDefinition *obj, size_t slot, size_t nfixed,
                    MDefinition *value, bool needsBarrier,
                    MIRType slotType = MIRType_None);
     bool storeSlot(MDefinition *obj, Shape *shape, MDefinition *value, bool needsBarrier,
                    MIRType slotType = MIRType_None);
 
     // jsop_getprop() helpers.
     bool getPropTryArgumentsLength(bool *emitted);
     bool getPropTryConstant(bool *emitted, PropertyName *name,
                             types::TemporaryTypeSet *types);
     bool getPropTryDefiniteSlot(bool *emitted, PropertyName *name,
-                                BarrierKind barrier, types::TemporaryTypeSet *types);
+                                bool barrier, types::TemporaryTypeSet *types);
     bool getPropTryCommonGetter(bool *emitted, PropertyName *name,
                                 types::TemporaryTypeSet *types);
     bool getPropTryInlineAccess(bool *emitted, PropertyName *name,
-                                BarrierKind barrier, types::TemporaryTypeSet *types);
+                                bool barrier, types::TemporaryTypeSet *types);
     bool getPropTryTypedObject(bool *emitted, PropertyName *name,
                                types::TemporaryTypeSet *resultTypes);
     bool getPropTryScalarPropOfTypedObject(bool *emitted,
                                            int32_t fieldOffset,
                                            TypeDescrSet fieldTypeReprs,
                                            types::TemporaryTypeSet *resultTypes);
     bool getPropTryComplexPropOfTypedObject(bool *emitted,
                                             int32_t fieldOffset,
                                             TypeDescrSet fieldTypeReprs,
                                             size_t fieldIndex,
                                             types::TemporaryTypeSet *resultTypes);
     bool getPropTryCache(bool *emitted, PropertyName *name,
-                         BarrierKind barrier, types::TemporaryTypeSet *types);
+                         bool barrier, types::TemporaryTypeSet *types);
     bool needsToMonitorMissingProperties(types::TemporaryTypeSet *types);
 
     // jsop_setprop() helpers.
     bool setPropTryCommonSetter(bool *emitted, MDefinition *obj,
                                 PropertyName *name, MDefinition *value);
     bool setPropTryCommonDOMSetter(bool *emitted, MDefinition *obj,
                                    MDefinition *value, JSFunction *setter,
                                    bool isDOM);
--- a/js/src/jit/IonCaches.cpp
+++ b/js/src/jit/IonCaches.cpp
@@ -1964,17 +1964,17 @@ GenerateSetSlot(JSContext *cx, MacroAsse
             TypedOrValueRegister valReg = value.reg();
             types::HeapTypeSet *propTypes = type->maybeGetProperty(shape->propid());
             JS_ASSERT(propTypes);
             JS_ASSERT(!propTypes->unknown());
 
             Register scratchReg = object;
             masm.push(scratchReg);
 
-            masm.guardTypeSet(valReg, propTypes, BarrierKind::TypeSet, scratchReg, &barrierFailure);
+            masm.guardTypeSet(valReg, propTypes, scratchReg, &barrierFailure);
             masm.pop(object);
         }
     }
 
     if (obj->isFixedSlot(shape->slot())) {
         Address addr(object, JSObject::getFixedSlotOffset(shape->slot()));
 
         if (cx->zone()->needsBarrier())
@@ -2516,17 +2516,17 @@ GenerateAddSlot(JSContext *cx, MacroAsse
     if (checkTypeset) {
         TypedOrValueRegister valReg = value.reg();
         types::TypeObject *type = obj->type();
         types::HeapTypeSet *propTypes = type->maybeGetProperty(obj->lastProperty()->propid());
         JS_ASSERT(propTypes);
         JS_ASSERT(!propTypes->unknown());
 
         Register scratchReg = object;
-        masm.guardTypeSet(valReg, propTypes, BarrierKind::TypeSet, scratchReg, &failuresPopObject);
+        masm.guardTypeSet(valReg, propTypes, scratchReg, &failuresPopObject);
         masm.loadPtr(Address(StackPointer, 0), object);
     }
 
     JSObject *proto = obj->getProto();
     Register protoReg = object;
     while (proto) {
         Shape *protoShape = proto->lastProperty();
 
--- a/js/src/jit/IonMacroAssembler.cpp
+++ b/js/src/jit/IonMacroAssembler.cpp
@@ -64,20 +64,19 @@ class TypeWrapper {
             return t_.typeObject();
         return nullptr;
     }
 };
 
 } /* anonymous namespace */
 
 template <typename Source, typename TypeSet> void
-MacroAssembler::guardTypeSet(const Source &address, const TypeSet *types, BarrierKind kind,
+MacroAssembler::guardTypeSet(const Source &address, const TypeSet *types,
                              Register scratch, Label *miss)
 {
-    JS_ASSERT(kind == BarrierKind::TypeTagOnly || kind == BarrierKind::TypeSet);
     JS_ASSERT(!types->unknown());
 
     Label matched;
     types::Type tests[7] = {
         types::Type::Int32Type(),
         types::Type::UndefinedType(),
         types::Type::BooleanType(),
         types::Type::StringType(),
@@ -122,20 +121,18 @@ MacroAssembler::guardTypeSet(const Sourc
     }
 
     if (lastBranch.isInitialized())
         lastBranch.emit(*this);
 
     // Test specific objects.
     JS_ASSERT(scratch != InvalidReg);
     branchTestObject(NotEqual, tag, miss);
-    if (kind != BarrierKind::TypeTagOnly) {
-        Register obj = extractObject(address, scratch);
-        guardObjectType(obj, types, scratch, miss);
-    }
+    Register obj = extractObject(address, scratch);
+    guardObjectType(obj, types, scratch, miss);
 
     bind(&matched);
 }
 
 template <typename TypeSet> void
 MacroAssembler::guardObjectType(Register obj, const TypeSet *types,
                                 Register scratch, Label *miss)
 {
@@ -201,40 +198,40 @@ MacroAssembler::guardObjectType(Register
     return;
 }
 
 template <typename Source> void
 MacroAssembler::guardType(const Source &address, types::Type type,
                           Register scratch, Label *miss)
 {
     TypeWrapper wrapper(type);
-    guardTypeSet(address, &wrapper, BarrierKind::TypeSet, scratch, miss);
+    guardTypeSet(address, &wrapper, scratch, miss);
 }
 
 template void MacroAssembler::guardTypeSet(const Address &address, const types::TemporaryTypeSet *types,
-                                           BarrierKind kind, Register scratch, Label *miss);
+                                           Register scratch, Label *miss);
 template void MacroAssembler::guardTypeSet(const ValueOperand &value, const types::TemporaryTypeSet *types,
-                                           BarrierKind kind, Register scratch, Label *miss);
+                                           Register scratch, Label *miss);
 
 template void MacroAssembler::guardTypeSet(const Address &address, const types::HeapTypeSet *types,
-                                           BarrierKind kind, Register scratch, Label *miss);
+                                           Register scratch, Label *miss);
 template void MacroAssembler::guardTypeSet(const ValueOperand &value, const types::HeapTypeSet *types,
-                                           BarrierKind kind, Register scratch, Label *miss);
+                                           Register scratch, Label *miss);
 template void MacroAssembler::guardTypeSet(const TypedOrValueRegister &reg, const types::HeapTypeSet *types,
-                                           BarrierKind kind, Register scratch, Label *miss);
+                                           Register scratch, Label *miss);
 
 template void MacroAssembler::guardTypeSet(const Address &address, const types::TypeSet *types,
-                                           BarrierKind kind, Register scratch, Label *miss);
+                                           Register scratch, Label *miss);
 template void MacroAssembler::guardTypeSet(const ValueOperand &value, const types::TypeSet *types,
-                                           BarrierKind kind, Register scratch, Label *miss);
+                                           Register scratch, Label *miss);
 
 template void MacroAssembler::guardTypeSet(const Address &address, const TypeWrapper *types,
-                                           BarrierKind kind, Register scratch, Label *miss);
+                                           Register scratch, Label *miss);
 template void MacroAssembler::guardTypeSet(const ValueOperand &value, const TypeWrapper *types,
-                                           BarrierKind kind, Register scratch, Label *miss);
+                                           Register scratch, Label *miss);
 
 template void MacroAssembler::guardObjectType(Register obj, const types::TemporaryTypeSet *types,
                                               Register scratch, Label *miss);
 template void MacroAssembler::guardObjectType(Register obj, const types::TypeSet *types,
                                               Register scratch, Label *miss);
 template void MacroAssembler::guardObjectType(Register obj, const TypeWrapper *types,
                                               Register scratch, Label *miss);
 
--- a/js/src/jit/IonMacroAssembler.h
+++ b/js/src/jit/IonMacroAssembler.h
@@ -295,17 +295,17 @@ class MacroAssembler : public MacroAssem
 
     bool embedsNurseryPointers() const {
         return embedsNurseryPointers_;
     }
 
     // Emits a test of a value against all types in a TypeSet. A scratch
     // register is required.
     template <typename Source, typename TypeSet>
-    void guardTypeSet(const Source &address, const TypeSet *types, BarrierKind kind, Register scratch, Label *miss);
+    void guardTypeSet(const Source &address, const TypeSet *types, Register scratch, Label *miss);
     template <typename TypeSet>
     void guardObjectType(Register obj, const TypeSet *types, Register scratch, Label *miss);
     template <typename Source>
     void guardType(const Source &address, types::Type type, Register scratch, Label *miss);
 
     void loadObjShape(Register objReg, Register dest) {
         loadPtr(Address(objReg, JSObject::offsetOfShape()), dest);
     }
--- a/js/src/jit/IonTypes.h
+++ b/js/src/jit/IonTypes.h
@@ -2,18 +2,16 @@
  * vim: set ts=8 sts=4 et sw=4 tw=99:
  * This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef jit_IonTypes_h
 #define jit_IonTypes_h
 
-#include "mozilla/TypedEnum.h"
-
 #include "jstypes.h"
 
 #include "js/Value.h"
 
 namespace js {
 namespace jit {
 
 typedef uint32_t RecoverOffset;
@@ -321,25 +319,12 @@ enum ABIFunctionType
         (ArgType_General << (ArgType_Shift * 2)),
 
     // int f(int, double)
     Args_Int_IntDouble = Args_General0 |
         (ArgType_Double << (ArgType_Shift * 1)) |
         (ArgType_General << (ArgType_Shift * 2))
 };
 
-MOZ_BEGIN_ENUM_CLASS(BarrierKind, uint32_t)
-    // No barrier is needed.
-    NoBarrier,
-
-    // The barrier only has to check the value's type tag is in the TypeSet.
-    // Specific object types don't have to be checked.
-    TypeTagOnly,
-
-    // Check if the value is in the TypeSet, including the object type if it's
-    // an object.
-    TypeSet
-MOZ_END_ENUM_CLASS(BarrierKind)
-
 } // namespace jit
 } // namespace js
 
 #endif /* jit_IonTypes_h */
--- a/js/src/jit/Lowering.cpp
+++ b/js/src/jit/Lowering.cpp
@@ -2298,18 +2298,17 @@ LIRGenerator::visitTypeBarrier(MTypeBarr
         if (!useBox(barrier, LTypeBarrierV::Input, ins->input()))
             return false;
         if (!assignSnapshot(barrier))
             return false;
         return redefine(ins, ins->input()) && add(barrier, ins);
     }
 
     // Handle typebarrier with specific TypeObject/SingleObjects.
-    if (inputType == MIRType_Object && !types->hasType(types::Type::AnyObjectType()) &&
-        ins->barrierKind() != BarrierKind::TypeTagOnly)
+    if (inputType == MIRType_Object && !types->hasType(types::Type::AnyObjectType()))
     {
         LDefinition tmp = needTemp ? temp() : LDefinition::BogusTemp();
         LTypeBarrierO *barrier = new(alloc()) LTypeBarrierO(useRegister(ins->getOperand(0)), tmp);
         if (!assignSnapshot(barrier))
             return false;
         return redefine(ins, ins->getOperand(0)) && add(barrier, ins);
     }
 
--- a/js/src/jit/MCallOptimize.cpp
+++ b/js/src/jit/MCallOptimize.cpp
@@ -380,19 +380,19 @@ IonBuilder::inlineArrayPopShift(CallInfo
         return InliningStatus_NotInlined;
 
     callInfo.setImplicitlyUsedUnchecked();
 
     types::TemporaryTypeSet *returnTypes = getInlineReturnTypeSet();
     bool needsHoleCheck = thisTypes->hasObjectFlags(constraints(), types::OBJECT_FLAG_NON_PACKED);
     bool maybeUndefined = returnTypes->hasType(types::Type::UndefinedType());
 
-    BarrierKind barrier = PropertyReadNeedsTypeBarrier(analysisContext, constraints(),
-                                                       callInfo.thisArg(), nullptr, returnTypes);
-    if (barrier != BarrierKind::NoBarrier)
+    bool barrier = PropertyReadNeedsTypeBarrier(analysisContext, constraints(),
+                                                callInfo.thisArg(), nullptr, returnTypes);
+    if (barrier)
         returnType = MIRType_Value;
 
     MArrayPopShift *ins = MArrayPopShift::New(alloc(), callInfo.thisArg(), mode,
                                               needsHoleCheck, maybeUndefined);
     current->add(ins);
     current->push(ins);
     ins->setResultType(returnType);
 
@@ -1226,17 +1226,17 @@ IonBuilder::inlineRegExpExec(CallInfo &c
 
     MInstruction *exec = MRegExpExec::New(alloc(), callInfo.thisArg(), callInfo.getArg(0));
     current->add(exec);
     current->push(exec);
 
     if (!resumeAfter(exec))
         return InliningStatus_Error;
 
-    if (!pushTypeBarrier(exec, getInlineReturnTypeSet(), BarrierKind::TypeSet))
+    if (!pushTypeBarrier(exec, getInlineReturnTypeSet(), true))
         return InliningStatus_Error;
 
     return InliningStatus_Inlined;
 }
 
 IonBuilder::InliningStatus
 IonBuilder::inlineRegExpTest(CallInfo &callInfo)
 {
@@ -1777,17 +1777,17 @@ IonBuilder::inlineUnsafeGetReservedSlot(
 
     callInfo.setImplicitlyUsedUnchecked();
 
     MLoadFixedSlot *load = MLoadFixedSlot::New(alloc(), callInfo.getArg(0), slot);
     current->add(load);
     current->push(load);
 
     // We don't track reserved slot types, so always emit a barrier.
-    if (!pushTypeBarrier(load, getInlineReturnTypeSet(), BarrierKind::TypeSet))
+    if (!pushTypeBarrier(load, getInlineReturnTypeSet(), true))
         return InliningStatus_Error;
 
     return InliningStatus_Inlined;
 }
 
 IonBuilder::InliningStatus
 IonBuilder::inlineHaveSameClass(CallInfo &callInfo)
 {
--- a/js/src/jit/MIR.cpp
+++ b/js/src/jit/MIR.cpp
@@ -3084,64 +3084,57 @@ jit::DenseNativeElementType(types::Compi
             elementType = type;
         else if (elementType != type)
             return MIRType_None;
     }
 
     return elementType;
 }
 
-static BarrierKind
+static bool
 PropertyReadNeedsTypeBarrier(types::CompilerConstraintList *constraints,
                              types::TypeObjectKey *object, PropertyName *name,
                              types::TypeSet *observed)
 {
     // If the object being read from has types for the property which haven't
     // been observed at this access site, the read could produce a new type and
     // a barrier is needed. Note that this only covers reads from properties
     // which are accounted for by type information, i.e. native data properties
     // and elements.
     //
     // We also need a barrier if the object is a proxy, because then all bets
     // are off, just as if it has unknown properties.
     if (object->unknownProperties() || observed->empty() ||
         object->clasp()->isProxy())
     {
-        return BarrierKind::TypeSet;
+        return true;
     }
 
     jsid id = name ? NameToId(name) : JSID_VOID;
     types::HeapTypeSetKey property = object->property(id);
-    if (property.maybeTypes()) {
-        if (!TypeSetIncludes(observed, MIRType_Value, property.maybeTypes())) {
-            // If all possible objects have been observed, we don't have to
-            // guard on the specific object types.
-            if (property.maybeTypes()->objectsAreSubset(observed))
-                return BarrierKind::TypeTagOnly;
-            return BarrierKind::TypeSet;
-        }
-    }
+    if (property.maybeTypes() && !TypeSetIncludes(observed, MIRType_Value, property.maybeTypes()))
+        return true;
 
     // Type information for global objects is not required to reflect the
     // initial 'undefined' value for properties, in particular global
     // variables declared with 'var'. Until the property is assigned a value
     // other than undefined, a barrier is required.
     if (JSObject *obj = object->singleton()) {
         if (name && types::CanHaveEmptyPropertyTypesForOwnProperty(obj) &&
             (!property.maybeTypes() || property.maybeTypes()->empty()))
         {
-            return BarrierKind::TypeSet;
+            return true;
         }
     }
 
     property.freeze(constraints);
-    return BarrierKind::NoBarrier;
+    return false;
 }
 
-BarrierKind
+bool
 jit::PropertyReadNeedsTypeBarrier(JSContext *propertycx,
                                   types::CompilerConstraintList *constraints,
                                   types::TypeObjectKey *object, PropertyName *name,
                                   types::TemporaryTypeSet *observed, bool updateObserved)
 {
     // If this access has never executed, try to add types to the observed set
     // according to any property which exists on the object or its prototype.
     if (updateObserved && observed->empty() && name) {
@@ -3179,90 +3172,72 @@ jit::PropertyReadNeedsTypeBarrier(JSCont
                 break;
             obj = obj->getProto();
         }
     }
 
     return PropertyReadNeedsTypeBarrier(constraints, object, name, observed);
 }
 
-BarrierKind
+bool
 jit::PropertyReadNeedsTypeBarrier(JSContext *propertycx,
                                   types::CompilerConstraintList *constraints,
                                   MDefinition *obj, PropertyName *name,
                                   types::TemporaryTypeSet *observed)
 {
     if (observed->unknown())
-        return BarrierKind::NoBarrier;
+        return false;
 
     types::TypeSet *types = obj->resultTypeSet();
     if (!types || types->unknownObject())
-        return BarrierKind::TypeSet;
-
-    BarrierKind res = BarrierKind::NoBarrier;
+        return true;
 
     bool updateObserved = types->getObjectCount() == 1;
     for (size_t i = 0; i < types->getObjectCount(); i++) {
         types::TypeObjectKey *object = types->getObject(i);
         if (object) {
-            BarrierKind kind = PropertyReadNeedsTypeBarrier(propertycx, constraints, object, name,
-                                                            observed, updateObserved);
-            if (kind == BarrierKind::TypeSet)
-                return BarrierKind::TypeSet;
-
-            if (kind == BarrierKind::TypeTagOnly) {
-                MOZ_ASSERT(res == BarrierKind::NoBarrier || res == BarrierKind::TypeTagOnly);
-                res = BarrierKind::TypeTagOnly;
-            } else {
-                MOZ_ASSERT(kind == BarrierKind::NoBarrier);
+            if (PropertyReadNeedsTypeBarrier(propertycx, constraints, object, name,
+                                             observed, updateObserved))
+            {
+                return true;
             }
         }
     }
 
-    return res;
+    return false;
 }
 
-BarrierKind
+bool
 jit::PropertyReadOnPrototypeNeedsTypeBarrier(types::CompilerConstraintList *constraints,
                                              MDefinition *obj, PropertyName *name,
                                              types::TemporaryTypeSet *observed)
 {
     if (observed->unknown())
-        return BarrierKind::NoBarrier;
+        return false;
 
     types::TypeSet *types = obj->resultTypeSet();
     if (!types || types->unknownObject())
-        return BarrierKind::TypeSet;
-
-    BarrierKind res = BarrierKind::NoBarrier;
+        return true;
 
     for (size_t i = 0; i < types->getObjectCount(); i++) {
         types::TypeObjectKey *object = types->getObject(i);
         if (!object)
             continue;
         while (true) {
             if (!object->hasTenuredProto())
-                return BarrierKind::TypeSet;
+                return true;
             if (!object->proto().isObject())
                 break;
             object = types::TypeObjectKey::get(object->proto().toObject());
-            BarrierKind kind = PropertyReadNeedsTypeBarrier(constraints, object, name, observed);
-            if (kind == BarrierKind::TypeSet)
-                return BarrierKind::TypeSet;
-
-            if (kind == BarrierKind::TypeTagOnly) {
-                MOZ_ASSERT(res == BarrierKind::NoBarrier || res == BarrierKind::TypeTagOnly);
-                res = BarrierKind::TypeTagOnly;
-            } else {
-                MOZ_ASSERT(kind == BarrierKind::NoBarrier);
-            }
+            if (PropertyReadNeedsTypeBarrier(constraints, object, name, observed))
+                return true;
         }
     }
 
-    return res;
+    return false;
 }
 
 bool
 jit::PropertyReadIsIdempotent(types::CompilerConstraintList *constraints,
                               MDefinition *obj, PropertyName *name)
 {
     // Determine if reading a property from obj is likely to be idempotent.
 
@@ -3402,23 +3377,17 @@ TryAddTypeBarrierForWrite(TempAllocator 
 
     if ((*pvalue)->type() != MIRType_Value)
         return false;
 
     types::TemporaryTypeSet *types = aggregateProperty.ref().maybeTypes()->clone(alloc.lifoAlloc());
     if (!types)
         return false;
 
-    // If all possible objects can be stored without a barrier, we don't have to
-    // guard on the specific object types.
-    BarrierKind kind = BarrierKind::TypeSet;
-    if ((*pvalue)->resultTypeSet() && (*pvalue)->resultTypeSet()->objectsAreSubset(types))
-        kind = BarrierKind::TypeTagOnly;
-
-    MInstruction *ins = MMonitorTypes::New(alloc, *pvalue, types, kind);
+    MInstruction *ins = MMonitorTypes::New(alloc, *pvalue, types);
     current->add(ins);
     return true;
 }
 
 static MInstruction *
 AddTypeGuard(TempAllocator &alloc, MBasicBlock *current, MDefinition *obj,
              types::TypeObjectKey *type, bool bailOnEquality)
 {
--- a/js/src/jit/MIR.h
+++ b/js/src/jit/MIR.h
@@ -9065,38 +9065,32 @@ class MFilterTypeSet
 };
 
 // Given a value, guard that the value is in a particular TypeSet, then returns
 // that value.
 class MTypeBarrier
   : public MUnaryInstruction,
     public TypeBarrierPolicy
 {
-    BarrierKind barrierKind_;
-
-    MTypeBarrier(MDefinition *def, types::TemporaryTypeSet *types, BarrierKind kind)
-      : MUnaryInstruction(def),
-        barrierKind_(kind)
-    {
-        MOZ_ASSERT(kind == BarrierKind::TypeTagOnly || kind == BarrierKind::TypeSet);
-
-        MOZ_ASSERT(!types->unknown());
+    MTypeBarrier(MDefinition *def, types::TemporaryTypeSet *types)
+      : MUnaryInstruction(def)
+    {
+        JS_ASSERT(!types->unknown());
         setResultType(types->getKnownMIRType());
         setResultTypeSet(types);
 
         setGuard();
         setMovable();
     }
 
   public:
     INSTRUCTION_HEADER(TypeBarrier)
 
-    static MTypeBarrier *New(TempAllocator &alloc, MDefinition *def, types::TemporaryTypeSet *types,
-                             BarrierKind kind = BarrierKind::TypeSet) {
-        return new(alloc) MTypeBarrier(def, types, kind);
+    static MTypeBarrier *New(TempAllocator &alloc, MDefinition *def, types::TemporaryTypeSet *types) {
+        return new(alloc) MTypeBarrier(def, types);
     }
 
     void printOpcode(FILE *fp) const;
 
     TypePolicy *typePolicy() {
         return this;
     }
 
@@ -9104,19 +9098,16 @@ class MTypeBarrier
         return false;
     }
     AliasSet getAliasSet() const {
         return AliasSet::None();
     }
     virtual bool neverHoist() const {
         return resultTypeSet()->empty();
     }
-    BarrierKind barrierKind() const {
-        return barrierKind_;
-    }
 
     bool alwaysBails() const {
         // If mirtype of input doesn't agree with mirtype of barrier,
         // we will definitely bail.
         MIRType type = resultTypeSet()->getKnownMIRType();
         if (type == MIRType_Value)
             return false;
         if (input()->type() == MIRType_Value)
@@ -9126,48 +9117,39 @@ class MTypeBarrier
 };
 
 // Like MTypeBarrier, guard that the value is in the given type set. This is
 // used before property writes to ensure the value being written is represented
 // in the property types for the object.
 class MMonitorTypes : public MUnaryInstruction, public BoxInputsPolicy
 {
     const types::TemporaryTypeSet *typeSet_;
-    BarrierKind barrierKind_;
-
-    MMonitorTypes(MDefinition *def, const types::TemporaryTypeSet *types, BarrierKind kind)
+
+    MMonitorTypes(MDefinition *def, const types::TemporaryTypeSet *types)
       : MUnaryInstruction(def),
-        typeSet_(types),
-        barrierKind_(kind)
-    {
-        MOZ_ASSERT(kind == BarrierKind::TypeTagOnly || kind == BarrierKind::TypeSet);
-
+        typeSet_(types)
+    {
         setGuard();
-        MOZ_ASSERT(!types->unknown());
+        JS_ASSERT(!types->unknown());
     }
 
   public:
     INSTRUCTION_HEADER(MonitorTypes)
 
-    static MMonitorTypes *New(TempAllocator &alloc, MDefinition *def, const types::TemporaryTypeSet *types,
-                              BarrierKind kind) {
-        return new(alloc) MMonitorTypes(def, types, kind);
+    static MMonitorTypes *New(TempAllocator &alloc, MDefinition *def, const types::TemporaryTypeSet *types) {
+        return new(alloc) MMonitorTypes(def, types);
     }
 
     TypePolicy *typePolicy() {
         return this;
     }
 
     const types::TemporaryTypeSet *typeSet() const {
         return typeSet_;
     }
-    BarrierKind barrierKind() const {
-        return barrierKind_;
-    }
-
     AliasSet getAliasSet() const {
         return AliasSet::None();
     }
 };
 
 // Given a value being written to another object, update the generational store
 // buffer if the value is in the nursery and object is in the tenured heap.
 class MPostWriteBarrier : public MBinaryInstruction, public ObjectPolicy<0>
@@ -10107,27 +10089,27 @@ typedef Vector<MDefinition *, 8, IonAllo
 
 bool ElementAccessIsDenseNative(MDefinition *obj, MDefinition *id);
 bool ElementAccessIsTypedArray(MDefinition *obj, MDefinition *id,
                                ScalarTypeDescr::Type *arrayType);
 bool ElementAccessIsPacked(types::CompilerConstraintList *constraints, MDefinition *obj);
 bool ElementAccessHasExtraIndexedProperty(types::CompilerConstraintList *constraints,
                                           MDefinition *obj);
 MIRType DenseNativeElementType(types::CompilerConstraintList *constraints, MDefinition *obj);
-BarrierKind PropertyReadNeedsTypeBarrier(JSContext *propertycx,
-                                         types::CompilerConstraintList *constraints,
-                                         types::TypeObjectKey *object, PropertyName *name,
-                                         types::TemporaryTypeSet *observed, bool updateObserved);
-BarrierKind PropertyReadNeedsTypeBarrier(JSContext *propertycx,
-                                         types::CompilerConstraintList *constraints,
-                                         MDefinition *obj, PropertyName *name,
-                                         types::TemporaryTypeSet *observed);
-BarrierKind PropertyReadOnPrototypeNeedsTypeBarrier(types::CompilerConstraintList *constraints,
-                                                    MDefinition *obj, PropertyName *name,
-                                                    types::TemporaryTypeSet *observed);
+bool PropertyReadNeedsTypeBarrier(JSContext *propertycx,
+                                  types::CompilerConstraintList *constraints,
+                                  types::TypeObjectKey *object, PropertyName *name,
+                                  types::TemporaryTypeSet *observed, bool updateObserved);
+bool PropertyReadNeedsTypeBarrier(JSContext *propertycx,
+                                  types::CompilerConstraintList *constraints,
+                                  MDefinition *obj, PropertyName *name,
+                                  types::TemporaryTypeSet *observed);
+bool PropertyReadOnPrototypeNeedsTypeBarrier(types::CompilerConstraintList *constraints,
+                                             MDefinition *obj, PropertyName *name,
+                                             types::TemporaryTypeSet *observed);
 bool PropertyReadIsIdempotent(types::CompilerConstraintList *constraints,
                               MDefinition *obj, PropertyName *name);
 void AddObjectsForPropertyRead(MDefinition *obj, PropertyName *name,
                                types::TemporaryTypeSet *observed);
 bool PropertyWriteNeedsTypeBarrier(TempAllocator &alloc, types::CompilerConstraintList *constraints,
                                    MBasicBlock *current, MDefinition **pobj,
                                    PropertyName *name, MDefinition **pvalue,
                                    bool canModify);
--- a/js/src/jsinfer.cpp
+++ b/js/src/jsinfer.cpp
@@ -347,36 +347,16 @@ TypeSet::mightBeMIRType(jit::MIRType typ
         // same join point in GuessPhiType.
         return false;
       default:
         MOZ_ASSUME_UNREACHABLE("Bad MIR type");
     }
 }
 
 bool
-TypeSet::objectsAreSubset(TypeSet *other)
-{
-    if (other->unknownObject())
-        return true;
-
-    if (unknownObject())
-        return false;
-
-    for (unsigned i = 0; i < getObjectCount(); i++) {
-        TypeObjectKey *obj = getObject(i);
-        if (!obj)
-            continue;
-        if (!other->hasType(Type::ObjectType(obj)))
-            return false;
-    }
-
-    return true;
-}
-
-bool
 TypeSet::isSubset(TypeSet *other)
 {
     if ((baseFlags() & other->baseFlags()) != baseFlags())
         return false;
 
     if (unknownObject()) {
         JS_ASSERT(other->unknownObject());
     } else {
--- a/js/src/jsinfer.h
+++ b/js/src/jsinfer.h
@@ -579,22 +579,16 @@ class TypeSet
     bool mightBeMIRType(jit::MIRType type);
 
     /*
      * Get whether this type set is known to be a subset of other.
      * This variant doesn't freeze constraints. That variant is called knownSubset
      */
     bool isSubset(TypeSet *other);
 
-    /*
-     * Get whether the objects in this TypeSet are a subset of the objects
-     * in other.
-     */
-    bool objectsAreSubset(TypeSet *other);
-
     /* Forward all types in this set to the specified constraint. */
     bool addTypesToConstraint(JSContext *cx, TypeConstraint *constraint);
 
     // Clone a type set into an arbitrary allocator.
     TemporaryTypeSet *clone(LifoAlloc *alloc) const;
     bool clone(LifoAlloc *alloc, TemporaryTypeSet *result) const;
 
     // Create a new TemporaryTypeSet where undefined and/or null has been filtered out.