Bug 972817 - Enable type inference unconditionally, r=jandem.
authorBrian Hackett <bhackett1024@gmail.com>
Tue, 18 Mar 2014 09:05:16 -0600
changeset 186177 2044699c3b05d400b32f0560c0c9f22d9ace12cd
parent 186176 a3fe19cdb6182a4ddaf80d5fee4bfd556af8a3cd
child 186178 cb2cdeffc0263ad90e0b1dc204e7c05eb5341705
push idunknown
push userunknown
push dateunknown
reviewersjandem
bugs972817
milestone31.0a1
Bug 972817 - Enable type inference unconditionally, r=jandem.
dom/workers/RuntimeService.cpp
js/src/builtin/TypedObject.cpp
js/src/frontend/BytecodeEmitter.cpp
js/src/gc/Zone.cpp
js/src/gc/Zone.h
js/src/jit/BaselineCompiler.cpp
js/src/jit/BaselineIC.cpp
js/src/jit/Ion.h
js/src/jsapi.h
js/src/jsarray.cpp
js/src/jscntxt.h
js/src/jscompartment.h
js/src/jsfun.cpp
js/src/jsgc.cpp
js/src/jsinfer.cpp
js/src/jsinfer.h
js/src/jsinferinlines.h
js/src/jsobj.cpp
js/src/jsobjinlines.h
js/src/jsonparser.cpp
js/src/jsworkers.cpp
js/src/shell/js.cpp
js/src/tests/lib/tests.py
js/src/vm/Interpreter.cpp
js/src/vm/ObjectImpl.h
js/src/vm/TypedArrayObject.cpp
js/xpconnect/src/XPCJSRuntime.cpp
js/xpconnect/src/XPCShellImpl.cpp
js/xpconnect/tests/mochitest/mochitest.ini
js/xpconnect/tests/mochitest/test_bug745483.html
modules/libpref/src/init/all.js
testing/xpcshell/runxpcshelltests.py
--- a/dom/workers/RuntimeService.cpp
+++ b/dom/workers/RuntimeService.cpp
@@ -330,19 +330,16 @@ LoadRuntimeAndContextOptions(const char*
   }
 #endif
 
   // Runtime options.
   JS::RuntimeOptions runtimeOptions;
   if (GetWorkerPref<bool>(NS_LITERAL_CSTRING("asmjs"))) {
     runtimeOptions.setAsmJS(true);
   }
-  if (GetWorkerPref<bool>(NS_LITERAL_CSTRING("typeinference"))) {
-    runtimeOptions.setTypeInference(true);
-  }
   if (GetWorkerPref<bool>(NS_LITERAL_CSTRING("baselinejit"))) {
     runtimeOptions.setBaseline(true);
   }
   if (GetWorkerPref<bool>(NS_LITERAL_CSTRING("ion"))) {
     runtimeOptions.setIon(true);
   }
 
   // Common options.
--- a/js/src/builtin/TypedObject.cpp
+++ b/js/src/builtin/TypedObject.cpp
@@ -1406,18 +1406,17 @@ TypedObject::createUnattachedWithClass(J
     obj->initReservedSlot(JS_TYPEDOBJ_SLOT_BYTELENGTH, Int32Value(0));
     obj->initReservedSlot(JS_TYPEDOBJ_SLOT_OWNER, NullValue());
     obj->initReservedSlot(JS_TYPEDOBJ_SLOT_NEXT_VIEW, PrivateValue(nullptr));
     obj->initReservedSlot(JS_TYPEDOBJ_SLOT_LENGTH, Int32Value(length));
     obj->initReservedSlot(JS_TYPEDOBJ_SLOT_TYPE_DESCR, ObjectValue(*type));
 
     // Tag the type object for this instance with the type
     // representation, if that has not been done already.
-    if (cx->typeInferenceEnabled() && !type->is<SimpleTypeDescr>()) {
-        // FIXME Bug 929651           ^~~~~~~~~~~~~~~~~~~~~~~~~~~
+    if (!type->is<SimpleTypeDescr>()) { // FIXME Bug 929651
         RootedTypeObject typeObj(cx, obj->getType(cx));
         if (typeObj) {
             if (!typeObj->addTypedObjectAddendum(cx, type))
                 return nullptr;
         }
     }
 
     return static_cast<TypedObject*>(&*obj);
--- a/js/src/frontend/BytecodeEmitter.cpp
+++ b/js/src/frontend/BytecodeEmitter.cpp
@@ -4865,17 +4865,16 @@ EmitFunc(ExclusiveContext *cx, BytecodeE
     /*
      * Mark as singletons any function which will only be executed once, or
      * which is inner to a lambda we only expect to run once. In the latter
      * case, if the lambda runs multiple times then CloneFunctionObject will
      * make a deep clone of its contents.
      */
     if (fun->isInterpreted()) {
         bool singleton =
-            cx->typeInferenceEnabled() &&
             bce->script->compileAndGo() &&
             fun->isInterpreted() &&
             (bce->checkSingletonContext() ||
              (!bce->isInLoop() && bce->isRunOnceLambda()));
         if (!JSFunction::setTypeForScriptedFunction(cx, fun, singleton))
             return false;
 
         if (fun->isInterpretedLazy()) {
--- a/js/src/gc/Zone.cpp
+++ b/js/src/gc/Zone.cpp
@@ -58,23 +58,16 @@ Zone::~Zone()
     if (this == runtimeFromMainThread()->systemZone)
         runtimeFromMainThread()->systemZone = nullptr;
 
 #ifdef JS_ION
     js_delete(jitZone_);
 #endif
 }
 
-bool
-Zone::init(JSContext *cx)
-{
-    types.init(cx);
-    return true;
-}
-
 void
 Zone::setNeedsBarrier(bool needs, ShouldUpdateIon updateIon)
 {
 #ifdef JS_ION
     if (updateIon == UpdateIon && needs != ionUsingBarriers_) {
         jit::ToggleBarriers(this, needs);
         ionUsingBarriers_ = needs;
     }
--- a/js/src/gc/Zone.h
+++ b/js/src/gc/Zone.h
@@ -273,17 +273,16 @@ struct Zone : public JS::shadow::Zone,
     /* This compartment's gray roots. */
     js::Vector<js::GrayRoot, 0, js::SystemAllocPolicy> gcGrayRoots;
 
     /* Per-zone data for use by an embedder. */
     void *data;
 
     Zone(JSRuntime *rt);
     ~Zone();
-    bool init(JSContext *cx);
 
     void findOutgoingEdges(js::gc::ComponentFinder<JS::Zone> &finder);
 
     void discardJitCode(js::FreeOp *fop);
 
     void addSizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf,
                                 size_t *typePool,
                                 size_t *baselineStubsOptimized);
--- a/js/src/jit/BaselineCompiler.cpp
+++ b/js/src/jit/BaselineCompiler.cpp
@@ -69,17 +69,17 @@ MethodStatus
 BaselineCompiler::compile()
 {
     IonSpew(IonSpew_BaselineScripts, "Baseline compiling script %s:%d (%p)",
             script->filename(), script->lineno(), script.get());
 
     IonSpew(IonSpew_Codegen, "# Emitting baseline code for script %s:%d",
             script->filename(), script->lineno());
 
-    if (cx->typeInferenceEnabled() && !script->ensureHasTypes(cx))
+    if (!script->ensureHasTypes(cx))
         return Method_Error;
 
     // Only need to analyze scripts which are marked |argumensHasVarBinding|, to
     // compute |needsArgsObj| flag.
     if (script->argumentsHasVarBinding()) {
         if (!script->ensureRanAnalysis(cx))
             return Method_Error;
     }
@@ -167,17 +167,17 @@ BaselineCompiler::compile()
 
     if (pcEntries.oom())
         return Method_Error;
 
     prologueOffset_.fixup(&masm);
     spsPushToggleOffset_.fixup(&masm);
 
     // Note: There is an extra entry in the bytecode type map for the search hint, see below.
-    size_t bytecodeTypeMapEntries = cx->typeInferenceEnabled() ? script->nTypeSets() + 1 : 0;
+    size_t bytecodeTypeMapEntries = script->nTypeSets() + 1;
 
     BaselineScript *baselineScript = BaselineScript::New(cx, prologueOffset_.offset(),
                                                          spsPushToggleOffset_.offset(),
                                                          icEntries_.length(),
                                                          pcMappingIndexEntries.length(),
                                                          pcEntries.length(),
                                                          bytecodeTypeMapEntries);
     if (!baselineScript)
@@ -224,36 +224,34 @@ BaselineCompiler::compile()
     // All barriers are emitted off-by-default, toggle them on if needed.
     if (cx->zone()->needsBarrier())
         baselineScript->toggleBarriers(true);
 
     // All SPS instrumentation is emitted toggled off.  Toggle them on if needed.
     if (cx->runtime()->spsProfiler.enabled())
         baselineScript->toggleSPS(true);
 
-    if (cx->typeInferenceEnabled()) {
-        uint32_t *bytecodeMap = baselineScript->bytecodeTypeMap();
-
-        uint32_t added = 0;
-        for (jsbytecode *pc = script->code(); pc < script->codeEnd(); pc += GetBytecodeLength(pc)) {
-            JSOp op = JSOp(*pc);
-            if (js_CodeSpec[op].format & JOF_TYPESET) {
-                bytecodeMap[added++] = script->pcToOffset(pc);
-                if (added == script->nTypeSets())
-                    break;
-            }
+    uint32_t *bytecodeMap = baselineScript->bytecodeTypeMap();
+
+    uint32_t added = 0;
+    for (jsbytecode *pc = script->code(); pc < script->codeEnd(); pc += GetBytecodeLength(pc)) {
+        JSOp op = JSOp(*pc);
+        if (js_CodeSpec[op].format & JOF_TYPESET) {
+            bytecodeMap[added++] = script->pcToOffset(pc);
+            if (added == script->nTypeSets())
+                break;
         }
-
-        JS_ASSERT(added == script->nTypeSets());
-
-        // The last entry in the last index found, and is used to avoid binary
-        // searches for the sought entry when queries are in linear order.
-        bytecodeMap[script->nTypeSets()] = 0;
     }
 
+    JS_ASSERT(added == script->nTypeSets());
+
+    // The last entry in the last index found, and is used to avoid binary
+    // searches for the sought entry when queries are in linear order.
+    bytecodeMap[script->nTypeSets()] = 0;
+
     if (script->compartment()->debugMode())
         baselineScript->setDebugMode();
 
     script->setBaselineScript(cx, baselineScript);
 
     return Method_Compiled;
 }
 
--- a/js/src/jit/BaselineIC.cpp
+++ b/js/src/jit/BaselineIC.cpp
@@ -8065,19 +8065,16 @@ MaybeCloneFunctionAtCallsite(JSContext *
 {
     RootedFunction fun(cx);
     if (!IsFunctionObject(callee, fun.address()))
         return true;
 
     if (!fun->hasScript() || !fun->nonLazyScript()->shouldCloneAtCallsite())
         return true;
 
-    if (!cx->typeInferenceEnabled())
-        return true;
-
     fun = CloneFunctionAtCallsite(cx, fun, script, pc);
     if (!fun)
         return false;
 
     callee.setObject(*fun);
     return true;
 }
 
@@ -8103,19 +8100,17 @@ DoCallFallback(JSContext *cx, BaselineFr
     // Handle funapply with JSOP_ARGUMENTS
     if (op == JSOP_FUNAPPLY && argc == 2 && args[1].isMagic(JS_OPTIMIZED_ARGUMENTS)) {
         if (!GuardFunApplyArgumentsOptimization(cx, frame, callee, args, argc))
             return false;
     }
 
     // Compute construcing and useNewType flags.
     bool constructing = (op == JSOP_NEW);
-    bool newType = false;
-    if (cx->typeInferenceEnabled())
-        newType = types::UseNewType(cx, script, pc);
+    bool newType = types::UseNewType(cx, script, pc);
 
     // Try attaching a call stub.
     if (!TryAttachCallStub(cx, stub, script, pc, op, argc, vp, constructing, newType))
         return false;
 
     // Maybe update PC in profiler entry before leaving this script by call.
     if (cx->runtime()->spsProfiler.enabled() && frame->hasPushedSPSFrame())
         cx->runtime()->spsProfiler.updatePC(script, pc);
--- a/js/src/jit/Ion.h
+++ b/js/src/jit/Ion.h
@@ -155,18 +155,18 @@ CodeGenerator *CompileBackEnd(MIRGenerat
 void AttachFinishedCompilations(JSContext *cx);
 void FinishOffThreadBuilder(IonBuilder *builder);
 void StopAllOffThreadCompilations(JSCompartment *comp);
 
 static inline bool
 IsIonEnabled(JSContext *cx)
 {
     return cx->runtime()->options().ion() &&
-        cx->runtime()->options().baseline() &&
-        cx->typeInferenceEnabled();
+           cx->runtime()->options().baseline() &&
+           cx->runtime()->jitSupportsFloatingPoint;
 }
 
 inline bool
 IsIonInlinablePC(jsbytecode *pc) {
     // CALL, FUNCALL, FUNAPPLY, EVAL, NEW (Normal Callsites)
     // GETPROP, CALLPROP, and LENGTH. (Inlined Getters)
     // SETPROP, SETNAME, SETGNAME (Inlined Setters)
     return IsCallPC(pc) || IsGetPropPC(pc) || IsSetPropPC(pc);
--- a/js/src/jsapi.h
+++ b/js/src/jsapi.h
@@ -1424,42 +1424,31 @@ extern JS_PUBLIC_API(JSVersion)
 JS_StringToVersion(const char *string);
 
 namespace JS {
 
 class JS_PUBLIC_API(RuntimeOptions) {
   public:
     RuntimeOptions()
       : baseline_(false),
-        typeInference_(false),
         ion_(false),
         asmJS_(false)
     {
     }
 
     bool baseline() const { return baseline_; }
     RuntimeOptions &setBaseline(bool flag) {
         baseline_ = flag;
         return *this;
     }
     RuntimeOptions &toggleBaseline() {
         baseline_ = !baseline_;
         return *this;
     }
 
-    bool typeInference() const { return typeInference_; }
-    RuntimeOptions &setTypeInference(bool flag) {
-        typeInference_ = flag;
-        return *this;
-    }
-    RuntimeOptions &toggleTypeInference() {
-        typeInference_ = !typeInference_;
-        return *this;
-    }
-
     bool ion() const { return ion_; }
     RuntimeOptions &setIon(bool flag) {
         ion_ = flag;
         return *this;
     }
     RuntimeOptions &toggleIon() {
         ion_ = !ion_;
         return *this;
@@ -1472,17 +1461,16 @@ class JS_PUBLIC_API(RuntimeOptions) {
     }
     RuntimeOptions &toggleAsmJS() {
         asmJS_ = !asmJS_;
         return *this;
     }
 
   private:
     bool baseline_ : 1;
-    bool typeInference_ : 1;
     bool ion_ : 1;
     bool asmJS_ : 1;
 };
 
 JS_PUBLIC_API(RuntimeOptions &)
 RuntimeOptionsRef(JSRuntime *rt);
 
 JS_PUBLIC_API(RuntimeOptions &)
--- a/js/src/jsarray.cpp
+++ b/js/src/jsarray.cpp
@@ -1196,17 +1196,17 @@ array_join(JSContext *cx, unsigned argc,
 
     CallArgs args = CallArgsFromVp(argc, vp);
     return ArrayJoin<false>(cx, args);
 }
 
 static inline bool
 InitArrayTypes(JSContext *cx, TypeObject *type, const Value *vector, unsigned count)
 {
-    if (cx->typeInferenceEnabled() && !type->unknownProperties()) {
+    if (!type->unknownProperties()) {
         AutoEnterAnalysis enter(cx);
 
         HeapTypeSet *types = type->getProperty(cx, JSID_VOID);
         if (!types)
             return false;
 
         for (unsigned i = 0; i < count; i++) {
             if (vector[i].isMagic(JS_ELEMENTS_HOLE))
@@ -2435,18 +2435,17 @@ array_splice(JSContext *cx, unsigned arg
         if (CanOptimizeForDenseStorage(obj, 0, len, cx)) {
             /* Steps 12(a)-(b). */
             obj->moveDenseElements(targetIndex, sourceIndex, len - sourceIndex);
 
             /*
              * Update the initialized length. Do so before shrinking so that we
              * can apply the write barrier to the old slots.
              */
-            if (cx->typeInferenceEnabled())
-                obj->setDenseInitializedLength(finalLength);
+            obj->setDenseInitializedLength(finalLength);
 
             /* Steps 12(c)-(d). */
             obj->shrinkElements(cx, finalLength);
 
             /* Fix running enumerators for the deleted items. */
             if (!js_SuppressDeletedElements(cx, obj, finalLength, len))
                 return false;
         } else {
@@ -2517,19 +2516,17 @@ array_splice(JSContext *cx, unsigned arg
                     return false;
             }
         }
 
         if (CanOptimizeForDenseStorage(obj, len, itemCount - actualDeleteCount, cx)) {
             obj->moveDenseElements(actualStart + itemCount,
                                    actualStart + actualDeleteCount,
                                    len - (actualStart + actualDeleteCount));
-
-            if (cx->typeInferenceEnabled())
-                obj->setDenseInitializedLength(len + itemCount - actualDeleteCount);
+            obj->setDenseInitializedLength(len + itemCount - actualDeleteCount);
         } else {
             RootedValue fromValue(cx);
             for (double k = len - actualDeleteCount; k > actualStart; k--) {
                 if (!CheckForInterrupt(cx))
                     return false;
 
                 double from = k + actualDeleteCount - 1;
                 double to = k + itemCount - 1;
--- a/js/src/jscntxt.h
+++ b/js/src/jscntxt.h
@@ -361,17 +361,16 @@ class ExclusiveContext : public ThreadSa
     }
     JS::Zone *zone() const {
         JS_ASSERT_IF(!compartment(), !zone_);
         JS_ASSERT_IF(compartment(), js::GetCompartmentZone(compartment()) == zone_);
         return zone_;
     }
 
     // Zone local methods that can be used freely from an ExclusiveContext.
-    inline bool typeInferenceEnabled() const;
     types::TypeObject *getNewType(const Class *clasp, TaggedProto proto, JSFunction *fun = nullptr);
     types::TypeObject *getLazyType(const Class *clasp, TaggedProto proto);
     inline js::LifoAlloc &typeLifoAlloc();
 
     // Current global. This is only safe to use within the scope of the
     // AutoCompartment from which it's called.
     inline js::Handle<js::GlobalObject*> global() const;
 
--- a/js/src/jscompartment.h
+++ b/js/src/jscompartment.h
@@ -512,22 +512,16 @@ class js::AutoDebugModeInvalidation
         MOZ_ASSERT_IF(needInvalidation_ != NoNeed,
                       needInvalidation_ == (debugMode ? ToggledOn : ToggledOff));
         needInvalidation_ = debugMode ? ToggledOn : ToggledOff;
     }
 };
 
 namespace js {
 
-inline bool
-ExclusiveContext::typeInferenceEnabled() const
-{
-    return zone()->types.inferenceEnabled;
-}
-
 inline js::Handle<js::GlobalObject*>
 ExclusiveContext::global() const
 {
     /*
      * It's safe to use |unsafeGet()| here because any compartment that is
      * on-stack will be marked automatically, so there's no need for a read
      * barrier on it. Once the compartment is popped, the handle is no longer
      * safe to use.
--- a/js/src/jsfun.cpp
+++ b/js/src/jsfun.cpp
@@ -1664,17 +1664,17 @@ js::NewFunctionWithProto(ExclusiveContex
     JS_ASSERT(allocKind == JSFunction::FinalizeKind || allocKind == JSFunction::ExtendedFinalizeKind);
     JS_ASSERT(sizeof(JSFunction) <= gc::Arena::thingSize(JSFunction::FinalizeKind));
     JS_ASSERT(sizeof(FunctionExtended) <= gc::Arena::thingSize(JSFunction::ExtendedFinalizeKind));
 
     RootedObject funobj(cx, funobjArg);
     if (funobj) {
         JS_ASSERT(funobj->is<JSFunction>());
         JS_ASSERT(funobj->getParent() == parent);
-        JS_ASSERT_IF(native && cx->typeInferenceEnabled(), funobj->hasSingletonType());
+        JS_ASSERT_IF(native, funobj->hasSingletonType());
     } else {
         // Don't give asm.js module functions a singleton type since they
         // are cloned (via CloneFunctionObjectIfNotSingleton) which assumes
         // that hasSingletonType implies isInterpreted.
         if (native && !IsAsmJSModuleNative(native))
             newKind = SingletonObject;
         funobj = NewObjectWithClassProto(cx, &JSFunction::class_, proto,
                                          SkipScopeParent(parent), allocKind, newKind);
--- a/js/src/jsgc.cpp
+++ b/js/src/jsgc.cpp
@@ -2852,17 +2852,17 @@ PurgeRuntime(JSRuntime *rt)
     if (!rt->hasActiveCompilations())
         rt->parseMapPool().purgeAll();
 }
 
 static bool
 ShouldPreserveJITCode(JSCompartment *comp, int64_t currentTime)
 {
     JSRuntime *rt = comp->runtimeFromMainThread();
-    if (rt->gcShouldCleanUpEverything || !comp->zone()->types.inferenceEnabled)
+    if (rt->gcShouldCleanUpEverything)
         return false;
 
     if (rt->alwaysPreserveCode)
         return true;
     if (comp->lastAnimationTime + PRMJ_USEC_PER_SEC >= currentTime)
         return true;
 
     return false;
@@ -5108,19 +5108,16 @@ js::NewCompartment(JSContext *cx, Zone *
     ScopedJSDeletePtr<Zone> zoneHolder;
     if (!zone) {
         zone = cx->new_<Zone>(rt);
         if (!zone)
             return nullptr;
 
         zoneHolder.reset(zone);
 
-        if (!zone->init(cx))
-            return nullptr;
-
         zone->setGCLastBytes(8192, GC_NORMAL);
 
         const JSPrincipals *trusted = rt->trustedPrincipals();
         zone->isSystem = principals && principals == trusted;
     }
 
     ScopedJSDeletePtr<JSCompartment> compartment(cx->new_<JSCompartment>(zone, options));
     if (!compartment || !compartment->init(cx))
--- a/js/src/jsinfer.cpp
+++ b/js/src/jsinfer.cpp
@@ -231,17 +231,17 @@ types::InferSpew(SpewChannel channel, co
 
 bool
 types::TypeHasProperty(JSContext *cx, TypeObject *obj, jsid id, const Value &value)
 {
     /*
      * Check the correctness of the type information in the object's property
      * against an actual value.
      */
-    if (cx->typeInferenceEnabled() && !obj->unknownProperties() && !value.isUndefined()) {
+    if (!obj->unknownProperties() && !value.isUndefined()) {
         id = IdToTypeId(id);
 
         /* Watch for properties which inference does not monitor. */
         if (id == id___proto__(cx) || id == id_constructor(cx) || id == id_caller(cx))
             return true;
 
         Type type = GetValueType(value);
 
@@ -1866,38 +1866,22 @@ TemporaryTypeSet::propertyNeedsBarrier(C
 // TypeCompartment
 /////////////////////////////////////////////////////////////////////
 
 TypeCompartment::TypeCompartment()
 {
     PodZero(this);
 }
 
-void
-TypeZone::init(JSContext *cx)
-{
-    if (!cx ||
-        !cx->runtime()->options().typeInference() ||
-        !cx->runtime()->jitSupportsFloatingPoint)
-    {
-        return;
-    }
-
-    inferenceEnabled = true;
-}
-
 TypeObject *
 TypeCompartment::newTypeObject(ExclusiveContext *cx, const Class *clasp, Handle<TaggedProto> proto,
                                TypeObjectFlags initialFlags)
 {
     JS_ASSERT_IF(proto.isObject(), cx->isInsideCurrentCompartment(proto.toObject()));
 
-    if (!cx->typeInferenceEnabled())
-        initialFlags |= OBJECT_FLAG_UNKNOWN_MASK;
-
     if (cx->isJSContext()) {
         if (proto.isObject() && IsInsideNursery(cx->asJSContext()->runtime(), proto.toObject()))
             initialFlags |= OBJECT_FLAG_NURSERY_PROTO;
     }
 
     TypeObject *object = js::NewTypeObject(cx);
     if (!object)
         return nullptr;
@@ -2053,18 +2037,16 @@ GetAtomId(JSContext *cx, JSScript *scrip
 {
     PropertyName *name = script->getName(GET_UINT32_INDEX(pc + offset));
     return IdToTypeId(NameToId(name));
 }
 
 bool
 types::UseNewType(JSContext *cx, JSScript *script, jsbytecode *pc)
 {
-    JS_ASSERT(cx->typeInferenceEnabled());
-
     /*
      * Make a heuristic guess at a use of JSOP_NEW that the constructed object
      * should have a fresh type object. We do this when the NEW is immediately
      * followed by a simple assignment to an object's .prototype field.
      * This is designed to catch common patterns for subclassing in JS:
      *
      * function Super() { ... }
      * function Sub1() { ... }
@@ -2452,18 +2434,17 @@ TypeCompartment::fixArrayType(ExclusiveC
     }
 
     setTypeToHomogenousArray(cx, obj, type);
 }
 
 void
 types::FixRestArgumentsType(ExclusiveContext *cx, JSObject *obj)
 {
-    if (cx->typeInferenceEnabled())
-        cx->compartment()->types.fixRestArgumentsType(cx, obj);
+    cx->compartment()->types.fixRestArgumentsType(cx, obj);
 }
 
 void
 TypeCompartment::fixRestArgumentsType(ExclusiveContext *cx, JSObject *obj)
 {
     AutoEnterAnalysis enter(cx);
 
     /*
@@ -3550,26 +3531,16 @@ types::UseNewTypeForClone(JSFunction *fu
 // TypeScript
 /////////////////////////////////////////////////////////////////////
 
 bool
 JSScript::makeTypes(JSContext *cx)
 {
     JS_ASSERT(!types);
 
-    if (!cx->typeInferenceEnabled()) {
-        types = cx->pod_calloc<TypeScript>();
-        if (!types) {
-            js_ReportOutOfMemory(cx);
-            return false;
-        }
-        new(types) TypeScript();
-        return analyzedArgsUsage() || ensureRanAnalysis(cx);
-    }
-
     AutoEnterAnalysis enter(cx);
 
     unsigned count = TypeScript::NumTypeSets(this);
 
     TypeScript *typeScript = (TypeScript *) cx->calloc_(sizeof(TypeScript) + (sizeof(StackTypeSet) * count));
     if (!typeScript)
         return false;
 
@@ -3625,19 +3596,16 @@ JSScript::makeAnalysis(JSContext *cx)
 
     return true;
 }
 
 /* static */ bool
 JSFunction::setTypeForScriptedFunction(ExclusiveContext *cx, HandleFunction fun,
                                        bool singleton /* = false */)
 {
-    if (!cx->typeInferenceEnabled())
-        return true;
-
     if (singleton) {
         if (!setSingletonType(cx, fun))
             return false;
     } else {
         RootedObject funProto(cx, fun->getProto());
         TypeObject *type =
             cx->compartment()->types.newTypeObject(cx, &JSFunction::class_, funProto);
         if (!type)
@@ -3657,38 +3625,35 @@ JSFunction::setTypeForScriptedFunction(E
 bool
 JSObject::shouldSplicePrototype(JSContext *cx)
 {
     /*
      * During bootstrapping, if inference is enabled we need to make sure not
      * to splice a new prototype in for Function.prototype or the global
      * object if their __proto__ had previously been set to null, as this
      * will change the prototype for all other objects with the same type.
-     * If inference is disabled we cannot determine from the object whether it
-     * has had its __proto__ set after creation.
      */
     if (getProto() != nullptr)
         return false;
-    return !cx->typeInferenceEnabled() || hasSingletonType();
+    return hasSingletonType();
 }
 
 bool
 JSObject::splicePrototype(JSContext *cx, const Class *clasp, Handle<TaggedProto> proto)
 {
     JS_ASSERT(cx->compartment() == compartment());
 
     RootedObject self(cx, this);
 
     /*
      * For singleton types representing only a single JSObject, the proto
      * can be rearranged as needed without destroying type information for
-     * the old or new types. Note that type constraints propagating properties
-     * from the old prototype are not removed.
+     * the old or new types.
      */
-    JS_ASSERT_IF(cx->typeInferenceEnabled(), self->hasSingletonType());
+    JS_ASSERT(self->hasSingletonType());
 
     /* Inner objects may not appear on prototype chains. */
     JS_ASSERT_IF(proto.isObject(), !proto.toObject()->getClass()->ext.outerObject);
 
     /*
      * Force type instantiation when splicing lazy types. This may fail,
      * in which case inference will be disabled for the compartment.
      */
@@ -3697,35 +3662,26 @@ JSObject::splicePrototype(JSContext *cx,
         return false;
     Rooted<TypeObject*> protoType(cx, nullptr);
     if (proto.isObject()) {
         protoType = proto.toObject()->getType(cx);
         if (!protoType)
             return false;
     }
 
-    if (!cx->typeInferenceEnabled()) {
-        TypeObject *type = cx->getNewType(clasp, proto);
-        if (!type)
-            return false;
-        self->type_ = type;
-        return true;
-    }
-
     type->setClasp(clasp);
     type->setProto(cx, proto);
     return true;
 }
 
 /* static */ TypeObject *
 JSObject::makeLazyType(JSContext *cx, HandleObject obj)
 {
     JS_ASSERT(obj->hasLazyType());
     JS_ASSERT(cx->compartment() == obj->compartment());
-    JS_ASSERT(cx->typeInferenceEnabled());
 
     /* De-lazification of functions can GC, so we need to do it up here. */
     if (obj->is<JSFunction>() && obj->as<JSFunction>().isInterpretedLazy()) {
         RootedFunction fun(cx, &obj->as<JSFunction>());
         if (!fun->getOrCreateScript(cx))
             return nullptr;
     }
 
@@ -3902,19 +3858,16 @@ ExclusiveContext::getNewType(const Class
 
 #ifdef JSGC_GENERATIONAL
     if (proto.isObject() && hasNursery() && nursery().isInside(proto.toObject())) {
         asJSContext()->runtime()->gcStoreBuffer.putGeneric(
             NewTypeObjectsSetRef(&newTypeObjects, clasp, proto.toObject(), fun));
     }
 #endif
 
-    if (!typeInferenceEnabled())
-        return type;
-
     if (proto.isObject()) {
         RootedObject obj(this, proto.toObject());
 
         if (fun)
             CheckNewScriptProperties(asJSContext(), type, fun);
 
         /*
          * Some builtin objects have slotful native properties baked in at
@@ -4259,17 +4212,16 @@ TypeCompartment::~TypeCompartment()
     js_delete(allocationSiteTable);
 }
 
 /* static */ void
 TypeScript::Sweep(FreeOp *fop, JSScript *script)
 {
     JSCompartment *compartment = script->compartment();
     JS_ASSERT(compartment->zone()->isGCSweeping());
-    JS_ASSERT(compartment->zone()->types.inferenceEnabled);
 
     unsigned num = NumTypeSets(script);
     StackTypeSet *typeArray = script->types->typeArray();
 
     /* Remove constraints and references to dead objects from the persistent type sets. */
     for (unsigned i = 0; i < num; i++)
         typeArray[i].sweep(compartment->zone());
 }
@@ -4327,18 +4279,17 @@ TypeObject::sizeOfExcludingThis(mozilla:
 {
     return mallocSizeOf(addendum);
 }
 
 TypeZone::TypeZone(Zone *zone)
   : zone_(zone),
     typeLifoAlloc(TYPE_LIFO_ALLOC_PRIMARY_CHUNK_SIZE),
     compilerOutputs(nullptr),
-    pendingRecompiles(nullptr),
-    inferenceEnabled(false)
+    pendingRecompiles(nullptr)
 {
 }
 
 TypeZone::~TypeZone()
 {
     js_delete(compilerOutputs);
     js_delete(pendingRecompiles);
 }
@@ -4367,17 +4318,17 @@ TypeZone::sweep(FreeOp *fop, bool releas
                 if (IsScriptAboutToBeFinalized(&script))
                     output.invalidate();
                 else
                     output.setSweepIndex(newCompilerOutputCount++);
             }
         }
     }
 
-    if (inferenceEnabled) {
+    {
         gcstats::AutoPhase ap2(rt->gcStats, gcstats::PHASE_DISCARD_TI);
 
         for (CellIterUnderGC i(zone(), FINALIZE_SCRIPT); !i.done(); i.next()) {
             JSScript *script = i.get<JSScript>();
             if (script->types) {
                 types::TypeScript::Sweep(fop, script);
 
                 if (releaseTypes) {
@@ -4506,19 +4457,16 @@ void
 TypeObject::setAddendum(TypeObjectAddendum *addendum)
 {
     this->addendum = addendum;
 }
 
 bool
 TypeObject::addTypedObjectAddendum(JSContext *cx, Handle<TypeDescr*> descr)
 {
-    if (!cx->typeInferenceEnabled())
-        return true;
-
     // Type descriptors are always pre-tenured. This is both because
     // we expect them to live a long time and so that they can be
     // safely accessed during ion compilation.
     JS_ASSERT(!IsInsideNursery(cx->runtime(), descr));
     JS_ASSERT(descr);
 
     if (flags() & OBJECT_FLAG_ADDENDUM_CLEARED)
         return true;
--- a/js/src/jsinfer.h
+++ b/js/src/jsinfer.h
@@ -1558,22 +1558,18 @@ struct TypeZone
      * RecompileInfo. This includes both valid and invalid compilations, though
      * invalidated compilations are swept on GC.
      */
     Vector<CompilerOutput> *compilerOutputs;
 
     /* Pending recompilations to perform before execution of JIT code can resume. */
     Vector<RecompileInfo> *pendingRecompiles;
 
-    /* Whether type inference is enabled in this compartment. */
-    bool                         inferenceEnabled;
-
     TypeZone(JS::Zone *zone);
     ~TypeZone();
-    void init(JSContext *cx);
 
     JS::Zone *zone() const { return zone_; }
 
     void sweep(FreeOp *fop, bool releaseTypes);
 
     /* Mark a script as needing recompilation once inference has finished. */
     void addPendingRecompile(JSContext *cx, const RecompileInfo &info);
     void addPendingRecompile(JSContext *cx, JSScript *script);
--- a/js/src/jsinferinlines.h
+++ b/js/src/jsinferinlines.h
@@ -260,23 +260,16 @@ struct AutoEnterAnalysis
         compartment->activeAnalysis = true;
     }
 };
 
 /////////////////////////////////////////////////////////////////////
 // Interface functions
 /////////////////////////////////////////////////////////////////////
 
-/*
- * These functions check whether inference is enabled before performing some
- * action on the type state. To avoid checking cx->typeInferenceEnabled()
- * everywhere, it is generally preferred to use one of these functions or
- * a type function on JSScript to perform inference operations.
- */
-
 inline const Class *
 GetClassForProtoKey(JSProtoKey key)
 {
     switch (key) {
       case JSProto_Object:
         return &JSObject::class_;
       case JSProto_Array:
         return &ArrayObject::class_;
@@ -327,22 +320,20 @@ GetTypeNewObject(JSContext *cx, JSProtoK
         return nullptr;
     return cx->getNewType(GetClassForProtoKey(key), proto.get());
 }
 
 /* Get a type object for the immediate allocation site within a native. */
 inline TypeObject *
 GetTypeCallerInitObject(JSContext *cx, JSProtoKey key)
 {
-    if (cx->typeInferenceEnabled()) {
-        jsbytecode *pc;
-        RootedScript script(cx, cx->currentScript(&pc));
-        if (script)
-            return TypeScript::InitObject(cx, script, pc, key);
-    }
+    jsbytecode *pc;
+    RootedScript script(cx, cx->currentScript(&pc));
+    if (script)
+        return TypeScript::InitObject(cx, script, pc, key);
     return GetTypeNewObject(cx, key);
 }
 
 void MarkIteratorUnknownSlow(JSContext *cx);
 
 void TypeMonitorCallSlow(JSContext *cx, JSObject *callee, const CallArgs &args,
                          bool constructing);
 
@@ -350,39 +341,36 @@ void TypeMonitorCallSlow(JSContext *cx, 
  * Monitor a javascript call, either on entry to the interpreter or made
  * from within the interpreter.
  */
 inline void
 TypeMonitorCall(JSContext *cx, const js::CallArgs &args, bool constructing)
 {
     if (args.callee().is<JSFunction>()) {
         JSFunction *fun = &args.callee().as<JSFunction>();
-        if (fun->isInterpreted() && fun->nonLazyScript()->types && cx->typeInferenceEnabled())
+        if (fun->isInterpreted() && fun->nonLazyScript()->types)
             TypeMonitorCallSlow(cx, &args.callee(), args, constructing);
     }
 }
 
 inline bool
 TrackPropertyTypes(ExclusiveContext *cx, JSObject *obj, jsid id)
 {
-    if (!cx->typeInferenceEnabled() || obj->hasLazyType() || obj->type()->unknownProperties())
+    if (obj->hasLazyType() || obj->type()->unknownProperties())
         return false;
 
     if (obj->hasSingletonType() && !obj->type()->maybeGetProperty(id))
         return false;
 
     return true;
 }
 
 inline void
 EnsureTrackPropertyTypes(JSContext *cx, JSObject *obj, jsid id)
 {
-    if (!cx->typeInferenceEnabled())
-        return;
-
     id = IdToTypeId(id);
 
     if (obj->hasSingletonType()) {
         AutoEnterAnalysis enter(cx);
         if (obj->hasLazyType() && !obj->getType(cx)) {
             CrashAtUnhandlableOOM("Could not allocate TypeObject in EnsureTrackPropertyTypes");
             return;
         }
@@ -424,91 +412,81 @@ HasTypePropertyId(JSObject *obj, jsid id
 {
     return HasTypePropertyId(obj, id, GetValueType(value));
 }
 
 /* Add a possible type for a property of obj. */
 inline void
 AddTypePropertyId(ExclusiveContext *cx, JSObject *obj, jsid id, Type type)
 {
-    if (cx->typeInferenceEnabled()) {
-        id = IdToTypeId(id);
-        if (TrackPropertyTypes(cx, obj, id))
-            obj->type()->addPropertyType(cx, id, type);
-    }
+    id = IdToTypeId(id);
+    if (TrackPropertyTypes(cx, obj, id))
+        obj->type()->addPropertyType(cx, id, type);
 }
 
 inline void
 AddTypePropertyId(ExclusiveContext *cx, JSObject *obj, jsid id, const Value &value)
 {
-    if (cx->typeInferenceEnabled()) {
-        id = IdToTypeId(id);
-        if (TrackPropertyTypes(cx, obj, id))
-            obj->type()->addPropertyType(cx, id, value);
-    }
+    id = IdToTypeId(id);
+    if (TrackPropertyTypes(cx, obj, id))
+        obj->type()->addPropertyType(cx, id, value);
 }
 
 inline void
 AddTypePropertyId(ExclusiveContext *cx, TypeObject *obj, jsid id, Type type)
 {
-    if (cx->typeInferenceEnabled() && !obj->unknownProperties())
+    if (!obj->unknownProperties())
         obj->addPropertyType(cx, id, type);
 }
 
 inline void
 AddTypePropertyId(ExclusiveContext *cx, TypeObject *obj, jsid id, const Value &value)
 {
-    if (cx->typeInferenceEnabled() && !obj->unknownProperties())
+    if (!obj->unknownProperties())
         obj->addPropertyType(cx, id, value);
 }
 
 /* Set one or more dynamic flags on a type object. */
 inline void
 MarkTypeObjectFlags(ExclusiveContext *cx, JSObject *obj, TypeObjectFlags flags)
 {
-    if (cx->typeInferenceEnabled() && !obj->hasLazyType() && !obj->type()->hasAllFlags(flags))
+    if (!obj->hasLazyType() && !obj->type()->hasAllFlags(flags))
         obj->type()->setFlags(cx, flags);
 }
 
 /*
  * Mark all properties of a type object as unknown. If markSetsUnknown is set,
  * scan the entire compartment and mark all type sets containing it as having
  * an unknown object. This is needed for correctness in dealing with mutable
  * __proto__, which can change the type of an object dynamically.
  */
 inline void
 MarkTypeObjectUnknownProperties(JSContext *cx, TypeObject *obj,
                                 bool markSetsUnknown = false)
 {
-    if (cx->typeInferenceEnabled()) {
-        if (!obj->unknownProperties())
-            obj->markUnknown(cx);
-        if (markSetsUnknown && !(obj->flags() & OBJECT_FLAG_SETS_MARKED_UNKNOWN))
-            cx->compartment()->types.markSetsUnknown(cx, obj);
-    }
+    if (!obj->unknownProperties())
+        obj->markUnknown(cx);
+    if (markSetsUnknown && !(obj->flags() & OBJECT_FLAG_SETS_MARKED_UNKNOWN))
+        cx->compartment()->types.markSetsUnknown(cx, obj);
 }
 
 inline void
 MarkTypePropertyNonData(ExclusiveContext *cx, JSObject *obj, jsid id)
 {
-    if (cx->typeInferenceEnabled()) {
-        id = IdToTypeId(id);
-        if (TrackPropertyTypes(cx, obj, id))
-            obj->type()->markPropertyNonData(cx, id);
-    }
+    id = IdToTypeId(id);
+    if (TrackPropertyTypes(cx, obj, id))
+        obj->type()->markPropertyNonData(cx, id);
 }
 
 inline void
 MarkTypePropertyNonWritable(ExclusiveContext *cx, JSObject *obj, jsid id)
 {
-    if (cx->typeInferenceEnabled()) {
-        id = IdToTypeId(id);
-        if (TrackPropertyTypes(cx, obj, id))
-            obj->type()->markPropertyNonWritable(cx, id);
-    }
+    id = IdToTypeId(id);
+    if (TrackPropertyTypes(cx, obj, id))
+        obj->type()->markPropertyNonWritable(cx, id);
 }
 
 inline bool
 IsTypePropertyIdMarkedNonData(JSObject *obj, jsid id)
 {
     return obj->type()->isPropertyNonData(id);
 }
 
@@ -517,37 +495,35 @@ IsTypePropertyIdMarkedNonWritable(JSObje
 {
     return obj->type()->isPropertyNonWritable(id);
 }
 
 /* Mark a state change on a particular object. */
 inline void
 MarkObjectStateChange(ExclusiveContext *cx, JSObject *obj)
 {
-    if (cx->typeInferenceEnabled() && !obj->hasLazyType() && !obj->type()->unknownProperties())
+    if (!obj->hasLazyType() && !obj->type()->unknownProperties())
         obj->type()->markStateChange(cx);
 }
 
 /*
  * For an array or object which has not yet escaped and been referenced elsewhere,
  * pick a new type based on the object's current contents.
  */
 
 inline void
 FixArrayType(ExclusiveContext *cx, HandleObject obj)
 {
-    if (cx->typeInferenceEnabled())
-        cx->compartment()->types.fixArrayType(cx, obj);
+    cx->compartment()->types.fixArrayType(cx, obj);
 }
 
 inline void
 FixObjectType(ExclusiveContext *cx, HandleObject obj)
 {
-    if (cx->typeInferenceEnabled())
-        cx->compartment()->types.fixObjectType(cx, obj);
+    cx->compartment()->types.fixObjectType(cx, obj);
 }
 
 /* Interface helpers for JSScript*. */
 extern void TypeMonitorResult(JSContext *cx, JSScript *script, jsbytecode *pc,
                               const js::Value &rval);
 extern void TypeDynamicResult(JSContext *cx, JSScript *script, jsbytecode *pc,
                               js::types::Type type);
 
@@ -668,17 +644,17 @@ UseNewTypeForInitializer(JSScript *scrip
 /* static */ inline TypeObject *
 TypeScript::InitObject(JSContext *cx, JSScript *script, jsbytecode *pc, JSProtoKey kind)
 {
     JS_ASSERT(!UseNewTypeForInitializer(script, pc, kind));
 
     /* :XXX: Limit script->length so we don't need to check the offset up front? */
     uint32_t offset = script->pcToOffset(pc);
 
-    if (!cx->typeInferenceEnabled() || !script->compileAndGo() || offset >= AllocationSiteKey::OFFSET_LIMIT)
+    if (!script->compileAndGo() || offset >= AllocationSiteKey::OFFSET_LIMIT)
         return GetTypeNewObject(cx, kind);
 
     AllocationSiteKey key;
     key.script = script;
     key.offset = offset;
     key.kind = kind;
 
     if (!cx->compartment()->types.allocationSiteTable)
@@ -690,19 +666,16 @@ TypeScript::InitObject(JSContext *cx, JS
         return p->value();
     return cx->compartment()->types.addAllocationSiteTypeObject(cx, key);
 }
 
 /* Set the type to use for obj according to the site it was allocated at. */
 static inline bool
 SetInitializerObjectType(JSContext *cx, HandleScript script, jsbytecode *pc, HandleObject obj, NewObjectKind kind)
 {
-    if (!cx->typeInferenceEnabled())
-        return true;
-
     JSProtoKey key = JSCLASS_CACHED_PROTO_KEY(obj->getClass());
     JS_ASSERT(key != JSProto_Null);
     JS_ASSERT(kind == UseNewTypeForInitializer(script, pc, key));
 
     if (kind == SingletonObject) {
         JS_ASSERT(obj->hasSingletonType());
 
         /*
@@ -719,32 +692,31 @@ SetInitializerObjectType(JSContext *cx, 
     }
 
     return true;
 }
 
 /* static */ inline void
 TypeScript::Monitor(JSContext *cx, JSScript *script, jsbytecode *pc, const js::Value &rval)
 {
-    if (cx->typeInferenceEnabled())
-        TypeMonitorResult(cx, script, pc, rval);
+    TypeMonitorResult(cx, script, pc, rval);
 }
 
 /* static */ inline void
 TypeScript::Monitor(JSContext *cx, const js::Value &rval)
 {
     jsbytecode *pc;
     RootedScript script(cx, cx->currentScript(&pc));
     Monitor(cx, script, pc, rval);
 }
 
 /* static */ inline void
 TypeScript::MonitorAssign(JSContext *cx, HandleObject obj, jsid id)
 {
-    if (cx->typeInferenceEnabled() && !obj->hasSingletonType()) {
+    if (!obj->hasSingletonType()) {
         /*
          * Mark as unknown any object which has had dynamic assignments to
          * non-integer properties at SETELEM opcodes. This avoids making large
          * numbers of type properties for hashmap-style objects. We don't need
          * to do this for objects with singleton type, because type properties
          * are only constructed for them when analyzed scripts depend on those
          * specific properties.
          */
@@ -760,57 +732,54 @@ TypeScript::MonitorAssign(JSContext *cx,
             return;
         MarkTypeObjectUnknownProperties(cx, type);
     }
 }
 
 /* static */ inline void
 TypeScript::SetThis(JSContext *cx, JSScript *script, Type type)
 {
-    if (!cx->typeInferenceEnabled() || !script->types)
+    if (!script->types)
         return;
 
     if (!ThisTypes(script)->hasType(type)) {
         AutoEnterAnalysis enter(cx);
 
         InferSpew(ISpewOps, "externalType: setThis #%u: %s",
                   script->id(), TypeString(type));
         ThisTypes(script)->addType(cx, type);
     }
 }
 
 /* static */ inline void
 TypeScript::SetThis(JSContext *cx, JSScript *script, const js::Value &value)
 {
-    if (cx->typeInferenceEnabled())
-        SetThis(cx, script, GetValueType(value));
+    SetThis(cx, script, GetValueType(value));
 }
 
 /* static */ inline void
 TypeScript::SetArgument(JSContext *cx, JSScript *script, unsigned arg, Type type)
 {
-    if (!cx->typeInferenceEnabled() || !script->types)
+    if (!script->types)
         return;
 
     if (!ArgTypes(script, arg)->hasType(type)) {
         AutoEnterAnalysis enter(cx);
 
         InferSpew(ISpewOps, "externalType: setArg #%u %u: %s",
                   script->id(), arg, TypeString(type));
         ArgTypes(script, arg)->addType(cx, type);
     }
 }
 
 /* static */ inline void
 TypeScript::SetArgument(JSContext *cx, JSScript *script, unsigned arg, const js::Value &value)
 {
-    if (cx->typeInferenceEnabled()) {
-        Type type = GetValueType(value);
-        SetArgument(cx, script, arg, type);
-    }
+    Type type = GetValueType(value);
+    SetArgument(cx, script, arg, type);
 }
 
 /////////////////////////////////////////////////////////////////////
 // TypeCompartment
 /////////////////////////////////////////////////////////////////////
 
 inline JSCompartment *
 TypeCompartment::compartment()
--- a/js/src/jsobj.cpp
+++ b/js/src/jsobj.cpp
@@ -1555,17 +1555,17 @@ js::CreateThisForFunctionWithProto(JSCon
         if (!type)
             return nullptr;
         res = CreateThisForFunctionWithType(cx, type, callee->getParent(), newKind);
     } else {
         gc::AllocKind allocKind = NewObjectGCKind(&JSObject::class_);
         res = NewObjectWithClassProto(cx, &JSObject::class_, proto, callee->getParent(), allocKind, newKind);
     }
 
-    if (res && cx->typeInferenceEnabled()) {
+    if (res) {
         JSScript *script = callee->as<JSFunction>().getOrCreateScript(cx);
         if (!script)
             return nullptr;
         TypeScript::SetThis(cx, script, types::Type::ObjectType(res));
     }
 
     return res;
 }
--- a/js/src/jsobjinlines.h
+++ b/js/src/jsobjinlines.h
@@ -368,19 +368,16 @@ JSObject::setDenseOrTypedArrayElementWit
         return as<js::TypedArrayObject>().setElement(cx, index, val);
     setDenseElementWithType(cx, index, val);
     return true;
 }
 
 /* static */ inline bool
 JSObject::setSingletonType(js::ExclusiveContext *cx, js::HandleObject obj)
 {
-    if (!cx->typeInferenceEnabled())
-        return true;
-
     JS_ASSERT_IF(cx->isJSContext(),
                  !IsInsideNursery(cx->asJSContext()->runtime(), obj.get()));
 
     js::types::TypeObject *type = cx->getLazyType(obj->getClass(), obj->getTaggedProto());
     if (!type)
         return false;
 
     obj->type_ = type;
--- a/js/src/jsonparser.cpp
+++ b/js/src/jsonparser.cpp
@@ -567,19 +567,19 @@ JSONParser::advanceAfterProperty()
 
 JSObject *
 JSONParser::createFinishedObject(PropertyVector &properties)
 {
     /*
      * Look for an existing cached type and shape for objects with this set of
      * properties.
      */
-    if (cx->typeInferenceEnabled()) {
+    {
         JSObject *obj = cx->compartment()->types.newTypedObject(cx, properties.begin(),
-                                                              properties.length());
+                                                                properties.length());
         if (obj)
             return obj;
     }
 
     /*
      * Make a new object sized for the given number of properties and fill its
      * shape in manually.
      */
@@ -600,18 +600,17 @@ JSONParser::createFinishedObject(Propert
         }
     }
 
     /*
      * Try to assign a new type to the object with type information for its
      * properties, and update the initializer type object cache with this
      * object's final shape.
      */
-    if (cx->typeInferenceEnabled())
-        cx->compartment()->types.fixObjectType(cx, obj);
+    cx->compartment()->types.fixObjectType(cx, obj);
 
     return obj;
 }
 
 inline bool
 JSONParser::finishObject(MutableHandleValue vp, PropertyVector &properties)
 {
     JS_ASSERT(&properties == &stack.back().properties());
@@ -632,18 +631,17 @@ JSONParser::finishArray(MutableHandleVal
 {
     JS_ASSERT(&elements == &stack.back().elements());
 
     JSObject *obj = NewDenseCopiedArray(cx, elements.length(), elements.begin());
     if (!obj)
         return false;
 
     /* Try to assign a new type to the array according to its elements. */
-    if (cx->typeInferenceEnabled())
-        cx->compartment()->types.fixArrayType(cx, obj);
+    cx->compartment()->types.fixArrayType(cx, obj);
 
     vp.setObject(*obj);
     if (!freeElements.append(&elements))
         return false;
     stack.popBack();
     return true;
 }
 
--- a/js/src/jsworkers.cpp
+++ b/js/src/jsworkers.cpp
@@ -307,17 +307,16 @@ js::StartOffThreadParseScript(JSContext 
     compartmentOptions.setInvisibleToDebugger(true);
     compartmentOptions.setMergeable(true);
 
     JSObject *global = JS_NewGlobalObject(cx, &workerGlobalClass, nullptr,
                                           JS::FireOnNewGlobalHook, compartmentOptions);
     if (!global)
         return false;
 
-    global->zone()->types.inferenceEnabled = cx->typeInferenceEnabled();
     JS_SetCompartmentPrincipals(global->compartment(), cx->compartment()->principals);
 
     RootedObject obj(cx);
 
     // Initialize all classes needed for parsing while we are still on the main
     // thread. Do this for both the target and the new global so that prototype
     // pointers can be changed infallibly after parsing finishes.
     if (!GetBuiltinConstructor(cx, JSProto_Function, &obj) ||
--- a/js/src/shell/js.cpp
+++ b/js/src/shell/js.cpp
@@ -708,27 +708,25 @@ Options(JSContext *cx, unsigned argc, js
         args[i].setString(str);
 
         JSAutoByteString opt(cx, str);
         if (!opt)
             return false;
 
         if (strcmp(opt.ptr(), "strict") == 0)
             JS::ContextOptionsRef(cx).toggleExtraWarnings();
-        else if (strcmp(opt.ptr(), "typeinfer") == 0)
-            JS::RuntimeOptionsRef(cx).toggleTypeInference();
         else if (strcmp(opt.ptr(), "werror") == 0)
             JS::ContextOptionsRef(cx).toggleWerror();
         else if (strcmp(opt.ptr(), "strict_mode") == 0)
             JS::ContextOptionsRef(cx).toggleStrictMode();
         else {
             char* msg = JS_sprintf_append(nullptr,
                                           "unknown option name '%s'."
                                           " The valid names are strict,"
-                                          " typeinfer, werror, and strict_mode.",
+                                          " werror, and strict_mode.",
                                           opt.ptr());
             if (!msg) {
                 JS_ReportOutOfMemory(cx);
                 return false;
             }
 
             JS_ReportError(cx, msg);
             free(msg);
@@ -737,20 +735,16 @@ Options(JSContext *cx, unsigned argc, js
     }
 
     char *names = strdup("");
     bool found = false;
     if (!names && oldContextOptions.extraWarnings()) {
         names = JS_sprintf_append(names, "%s%s", found ? "," : "", "strict");
         found = true;
     }
-    if (!names && oldRuntimeOptions.typeInference()) {
-        names = JS_sprintf_append(names, "%s%s", found ? "," : "", "typeinfer");
-        found = true;
-    }
     if (!names && oldContextOptions.werror()) {
         names = JS_sprintf_append(names, "%s%s", found ? "," : "", "werror");
         found = true;
     }
     if (!names && oldContextOptions.strictMode()) {
         names = JS_sprintf_append(names, "%s%s", found ? "," : "", "strict_mode");
         found = true;
     }
@@ -5746,22 +5740,20 @@ ProcessArgs(JSContext *cx, JSObject *obj
 }
 
 static bool
 SetRuntimeOptions(JSRuntime *rt, const OptionParser &op)
 {
 #if defined(JS_ION)
     bool enableBaseline = !op.getBoolOption("no-baseline");
     bool enableIon = !op.getBoolOption("no-ion");
-    bool enableTypeInference = !op.getBoolOption("no-ti");
     bool enableAsmJS = !op.getBoolOption("no-asmjs");
 
     JS::RuntimeOptionsRef(rt).setBaseline(enableBaseline)
                              .setIon(enableIon)
-                             .setTypeInference(enableTypeInference)
                              .setAsmJS(enableAsmJS);
 
     if (const char *str = op.getStringOption("ion-gvn")) {
         if (strcmp(str, "off") == 0) {
             jit::js_JitOptions.disableGvn = true;
         } else if (strcmp(str, "pessimistic") == 0) {
             jit::js_JitOptions.forceGvnKind = true;
             jit::js_JitOptions.forcedGvnKind = jit::GVN_Pessimistic;
@@ -6004,18 +5996,16 @@ main(int argc, char **argv, char **envp)
     op.setHelpWidth(80);
     op.setVersion(JS_GetImplementationVersion());
 
     if (!op.addMultiStringOption('f', "file", "PATH", "File path to run")
         || !op.addMultiStringOption('e', "execute", "CODE", "Inline code to run")
         || !op.addBoolOption('i', "shell", "Enter prompt after running code")
         || !op.addBoolOption('m', "jm", "No-op (still used by fuzzers)")
         || !op.addBoolOption('\0', "no-jm", "No-op (still used by fuzzers)")
-        || !op.addBoolOption('n', "ti", "Enable type inference (default)")
-        || !op.addBoolOption('\0', "no-ti", "Disable type inference")
         || !op.addBoolOption('c', "compileonly", "Only compile, don't run (syntax checking mode)")
         || !op.addBoolOption('w', "warnings", "Emit warnings")
         || !op.addBoolOption('W', "nowarnings", "Don't emit warnings")
         || !op.addBoolOption('s', "strict", "Check strictness")
         || !op.addBoolOption('d', "debugjit", "Enable runtime debug mode for method JIT code")
         || !op.addBoolOption('a', "always-mjit", "No-op (still used by fuzzers)")
         || !op.addBoolOption('D', "dump-bytecode", "Dump bytecode with exec count for all scripts")
         || !op.addBoolOption('b', "print-timing", "Print sub-ms runtime for each file that's run")
--- a/js/src/tests/lib/tests.py
+++ b/js/src/tests/lib/tests.py
@@ -10,19 +10,18 @@ from threading import Thread
 from results import TestOutput
 
 # When run on tbpl, we run each test multiple times with the following arguments.
 TBPL_FLAGS = [
     [], # no flags, normal baseline and ion
     ['--ion-eager', '--ion-parallel-compile=off'], # implies --baseline-eager
     ['--ion-eager', '--ion-parallel-compile=off', '--ion-check-range-analysis', '--no-sse3'],
     ['--baseline-eager'],
-    ['--baseline-eager', '--no-ti', '--no-fpu'],
+    ['--baseline-eager', '--no-fpu'],
     ['--no-baseline', '--no-ion'],
-    ['--no-baseline', '--no-ion', '--no-ti'],
 ]
 
 def do_run_cmd(cmd):
     l = [ None, None ]
     th_run_cmd(cmd, l)
     return l[1]
 
 def set_limits():
--- a/js/src/vm/Interpreter.cpp
+++ b/js/src/vm/Interpreter.cpp
@@ -477,17 +477,17 @@ js::Invoke(JSContext *cx, CallArgs args,
 
     if (!fun->getOrCreateScript(cx))
         return false;
 
     /* Run function until JSOP_RETRVAL, JSOP_RETURN or error. */
     InvokeState state(cx, args, initial);
 
     // Check to see if useNewType flag should be set for this frame.
-    if (construct && cx->typeInferenceEnabled()) {
+    if (construct) {
         FrameIter iter(cx);
         if (!iter.done() && iter.hasScript()) {
             JSScript *script = iter.script();
             jsbytecode *pc = iter.pc();
             if (UseNewType(cx, script, pc))
                 state.setUseNewType();
         }
     }
@@ -2592,17 +2592,17 @@ CASE(JSOP_FUNCALL)
     /*
      * Some builtins are marked as clone-at-callsite to increase precision of
      * TI and JITs.
      */
     if (isFunction && fun->isInterpreted()) {
         funScript = fun->getOrCreateScript(cx);
         if (!funScript)
             goto error;
-        if (cx->typeInferenceEnabled() && funScript->shouldCloneAtCallsite()) {
+        if (funScript->shouldCloneAtCallsite()) {
             fun = CloneFunctionAtCallsite(cx, fun, script, REGS.pc);
             if (!fun)
                 goto error;
             args.setCallee(ObjectValue(*fun));
         }
     }
 
     /* Don't bother trying to fast-path calls to scripted non-constructors. */
@@ -2616,17 +2616,17 @@ CASE(JSOP_FUNCALL)
         }
         Value *newsp = args.spAfterCall();
         TypeScript::Monitor(cx, script, REGS.pc, newsp[-1]);
         REGS.sp = newsp;
         ADVANCE_AND_DISPATCH(JSOP_CALL_LENGTH);
     }
 
     InitialFrameFlags initial = construct ? INITIAL_CONSTRUCT : INITIAL_NONE;
-    bool newType = cx->typeInferenceEnabled() && UseNewType(cx, script, REGS.pc);
+    bool newType = UseNewType(cx, script, REGS.pc);
 
     TypeMonitorCall(cx, args, construct);
 
 #ifdef JS_ION
     {
         InvokeState state(cx, args, initial);
         if (newType)
             state.setUseNewType();
--- a/js/src/vm/ObjectImpl.h
+++ b/js/src/vm/ObjectImpl.h
@@ -140,20 +140,19 @@ ArraySetLength(typename ExecutionModeTra
  * case the capacity is always less than or equal to the length.  This permits
  * JIT code to optimize away the check for non-writable length when assigning
  * to possibly out-of-range elements: such code already has to check for
  * |index < capacity|, and fallback code checks for non-writable length.
  *
  * The initialized length of an object specifies the number of elements that
  * have been initialized. All elements above the initialized length are
  * holes in the object, and the memory for all elements between the initialized
- * length and capacity is left uninitialized. When type inference is disabled,
- * the initialized length always equals the capacity. When inference is
- * enabled, the initialized length is some value less than or equal to both the
- * object's length and the object's capacity.
+ * length and capacity is left uninitialized. The initialized length is some
+ * value less than or equal to both the object's length and the object's
+ * capacity.
  *
  * With inference enabled, there is flexibility in exactly the value the
  * initialized length must hold, e.g. if an array has length 5, capacity 10,
  * completely empty, it is valid for the initialized length to be any value
  * between zero and 5, as long as the in memory values below the initialized
  * length have been initialized with a hole value. However, in such cases we
  * want to keep the initialized length as small as possible: if the object is
  * known to have no hole values below its initialized length, then it is
--- a/js/src/vm/TypedArrayObject.cpp
+++ b/js/src/vm/TypedArrayObject.cpp
@@ -325,20 +325,18 @@ class TypedArrayObjectTemplate : public 
 
     static JSObject *
     makeInstance(JSContext *cx, HandleObject bufobj, uint32_t byteOffset, uint32_t len,
                  HandleObject proto)
     {
         Rooted<TypedArrayObject*> obj(cx);
         if (proto)
             obj = makeProtoInstance(cx, proto);
-        else if (cx->typeInferenceEnabled())
+        else
             obj = makeTypedInstance(cx, len);
-        else
-            obj = &NewBuiltinClassInstance(cx, fastClass())->as<TypedArrayObject>();
         if (!obj)
             return nullptr;
         JS_ASSERT_IF(obj->isTenured(),
                      obj->tenuredGetAllocKind() == gc::FINALIZE_OBJECT8_BACKGROUND);
 
         obj->setSlot(TYPE_SLOT, Int32Value(ArrayTypeID()));
         obj->setSlot(BUFFER_SLOT, ObjectValue(*bufobj));
 
@@ -1320,26 +1318,24 @@ DataViewObject::create(JSContext *cx, ui
     if (!obj)
         return nullptr;
 
     if (proto) {
         types::TypeObject *type = cx->getNewType(&class_, TaggedProto(proto));
         if (!type)
             return nullptr;
         obj->setType(type);
-    } else if (cx->typeInferenceEnabled()) {
-        if (byteLength >= TypedArrayObject::SINGLETON_TYPE_BYTE_LENGTH) {
-            JS_ASSERT(obj->hasSingletonType());
-        } else {
-            jsbytecode *pc;
-            RootedScript script(cx, cx->currentScript(&pc));
-            if (script) {
-                if (!types::SetInitializerObjectType(cx, script, pc, obj, newKind))
-                    return nullptr;
-            }
+    } else if (byteLength >= TypedArrayObject::SINGLETON_TYPE_BYTE_LENGTH) {
+        JS_ASSERT(obj->hasSingletonType());
+    } else {
+        jsbytecode *pc;
+        RootedScript script(cx, cx->currentScript(&pc));
+        if (script) {
+            if (!types::SetInitializerObjectType(cx, script, pc, obj, newKind))
+                return nullptr;
         }
     }
 
     DataViewObject &dvobj = obj->as<DataViewObject>();
     dvobj.setFixedSlot(BYTEOFFSET_SLOT, Int32Value(byteOffset));
     dvobj.setFixedSlot(BYTELENGTH_SLOT, Int32Value(byteLength));
     dvobj.setFixedSlot(BUFFER_SLOT, ObjectValue(*arrayBuffer));
     dvobj.setFixedSlot(NEXT_VIEW_SLOT, PrivateValue(nullptr));
--- a/js/xpconnect/src/XPCJSRuntime.cpp
+++ b/js/xpconnect/src/XPCJSRuntime.cpp
@@ -1518,29 +1518,27 @@ ReloadPrefsCallback(const char *pref, vo
 
     bool safeMode = false;
     nsCOMPtr<nsIXULRuntime> xr = do_GetService("@mozilla.org/xre/runtime;1");
     if (xr) {
         xr->GetInSafeMode(&safeMode);
     }
 
     bool useBaseline = Preferences::GetBool(JS_OPTIONS_DOT_STR "baselinejit") && !safeMode;
-    bool useTypeInference = Preferences::GetBool(JS_OPTIONS_DOT_STR "typeinference") && !safeMode;
     bool useIon = Preferences::GetBool(JS_OPTIONS_DOT_STR "ion") && !safeMode;
     bool useAsmJS = Preferences::GetBool(JS_OPTIONS_DOT_STR "asmjs") && !safeMode;
 
     bool parallelParsing = Preferences::GetBool(JS_OPTIONS_DOT_STR "parallel_parsing");
     bool parallelIonCompilation = Preferences::GetBool(JS_OPTIONS_DOT_STR
                                                        "ion.parallel_compilation");
     bool useBaselineEager = Preferences::GetBool(JS_OPTIONS_DOT_STR
                                                  "baselinejit.unsafe_eager_compilation");
     bool useIonEager = Preferences::GetBool(JS_OPTIONS_DOT_STR "ion.unsafe_eager_compilation");
 
     JS::RuntimeOptionsRef(rt).setBaseline(useBaseline)
-                             .setTypeInference(useTypeInference)
                              .setIon(useIon)
                            .  setAsmJS(useAsmJS);
 
     JS_SetParallelParsingEnabled(rt, parallelParsing);
     JS_SetParallelIonCompilationEnabled(rt, parallelIonCompilation);
     JS_SetGlobalJitCompilerOption(rt, JSJITCOMPILER_BASELINE_USECOUNT_TRIGGER,
                                   useBaselineEager ? 0 : -1);
     JS_SetGlobalJitCompilerOption(rt, JSJITCOMPILER_ION_USECOUNT_TRIGGER,
--- a/js/xpconnect/src/XPCShellImpl.cpp
+++ b/js/xpconnect/src/XPCShellImpl.cpp
@@ -1033,19 +1033,16 @@ ProcessArgsForCompartment(JSContext *cx,
             ContextOptionsRef(cx).toggleWerror();
         case 's':
             ContextOptionsRef(cx).toggleExtraWarnings();
             break;
         case 'I':
             RuntimeOptionsRef(cx).toggleIon()
                                  .toggleAsmJS();
             break;
-        case 'n':
-            RuntimeOptionsRef(cx).toggleTypeInference();
-            break;
         }
     }
 }
 
 static int
 ProcessArgs(JSContext *cx, JS::Handle<JSObject*> obj, char **argv, int argc, XPCShellDirProvider* aDirProvider)
 {
     const char rcfilename[] = "xpcshell.js";
@@ -1163,17 +1160,16 @@ ProcessArgs(JSContext *cx, JS::Handle<JS
         case 'C':
             compileOnly = true;
             isInteractive = false;
             break;
         case 'S':
         case 's':
         case 'm':
         case 'I':
-        case 'n':
             // These options are processed in ProcessArgsForCompartment.
             break;
         case 'p':
         {
           // plugins path
           char *pluginPath = argv[++i];
           nsCOMPtr<nsIFile> pluginsDir;
           if (NS_FAILED(XRE_GetFileFromPath(pluginPath, getter_AddRefs(pluginsDir)))) {
--- a/js/xpconnect/tests/mochitest/mochitest.ini
+++ b/js/xpconnect/tests/mochitest/mochitest.ini
@@ -62,17 +62,16 @@ support-files =
 [test_bug636097.html]
 [test_bug650273.html]
 [test_bug655297-1.html]
 [test_bug655297-2.html]
 [test_bug661980.html]
 [test_bug691059.html]
 [test_bug720619.html]
 [test_bug731471.html]
-[test_bug745483.html]
 [test_bug764389.html]
 [test_bug772288.html]
 [test_bug781476.html]
 [test_bug789713.html]
 [test_bug790732.html]
 [test_bug793969.html]
 [test_bug800864.html]
 [test_bug802557.html]
deleted file mode 100644
--- a/js/xpconnect/tests/mochitest/test_bug745483.html
+++ /dev/null
@@ -1,37 +0,0 @@
-<!DOCTYPE HTML>
-<html>
-<!--
-https://bugzilla.mozilla.org/show_bug.cgi?id=745483
--->
-<head>
-  <meta charset="utf-8">
-  <title>Test for Bug 745483</title>
-  <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
-  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
-</head>
-<body>
-<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=745483">Mozilla Bug 745483</a>
-<p id="display"></p>
-<div id="content" style="display: none">
-  
-</div>
-<pre id="test">
-<script type="application/javascript">
-
-/** Test for Bug 745483 **/
-SimpleTest.waitForExplicitFinish();
-
-// Make sure we can make iframes with TI disabled.
-SpecialPowers.pushPrefEnv({ set: [['javascript.options.typeinference', false]] }, doTest);
-
-function doTest() {
-    var ifr = document.createElement('iframe');
-    document.body.appendChild(ifr);
-    ok(true, "didn't assert");
-    SimpleTest.finish();
-}
-
-</script>
-</pre>
-</body>
-</html>
--- a/modules/libpref/src/init/all.js
+++ b/modules/libpref/src/init/all.js
@@ -766,17 +766,16 @@ pref("javascript.options.strict",       
 #ifdef DEBUG
 pref("javascript.options.strict.debug",     true);
 #endif
 pref("javascript.options.baselinejit",      true);
 pref("javascript.options.ion",              true);
 pref("javascript.options.asmjs",            true);
 pref("javascript.options.parallel_parsing", true);
 pref("javascript.options.ion.parallel_compilation", true);
-pref("javascript.options.typeinference",    true);
 // This preference limits the memory usage of javascript.
 // If you want to change these values for your device,
 // please find Bug 417052 comment 17 and Bug 456721
 // Comment 32 and Bug 613551.
 pref("javascript.options.mem.high_water_mark", 128);
 pref("javascript.options.mem.max", -1);
 pref("javascript.options.mem.gc_per_compartment", true);
 pref("javascript.options.mem.gc_incremental", true);
--- a/testing/xpcshell/runxpcshelltests.py
+++ b/testing/xpcshell/runxpcshelltests.py
@@ -372,17 +372,16 @@ class XPCShellTestThread(Thread):
             self.appPath = self.xrePath
 
         self.xpcsCmd = [
             self.xpcshell,
             '-g', self.xrePath,
             '-a', self.appPath,
             '-r', self.httpdManifest,
             '-m',
-            '-n',
             '-s',
             '-e', 'const _HTTPD_JS_PATH = "%s";' % self.httpdJSPath,
             '-e', 'const _HEAD_JS_PATH = "%s";' % self.headJSPath
         ]
 
         if self.testingModulesDir:
             # Escape backslashes in string literal.
             sanitized = self.testingModulesDir.replace('\\', '\\\\')