Backed out 6 changesets (bug 939614) for Hf timeouts on a CLOSED TREE.
authorRyan VanderMeulen <ryanvm@gmail.com>
Thu, 12 Dec 2013 13:56:50 -0500
changeset 176259 ad9dc3482bd429cb7077eaac7bd53e43ba49b957
parent 176258 afa4bcb0150e7a32900361b2e2c910220f9057cf
child 176260 b6b911ca4dd87f46862fac9e5931661358de6870
push id3343
push userffxbld
push dateMon, 17 Mar 2014 21:55:32 +0000
treeherdermozilla-beta@2f7d3415f79f [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
bugs939614
milestone29.0a1
backs out50cc92857bf755774420a86dc1556b77fcdce4fe
62a6568217da8eee2fd6a977659a65e2a18ddcd8
31d0d40d4a7ce9aac74aa2f4fcad36b47e70595f
2b87186ddb6df93d330d948e7a9bf5eef558ba2d
fa2005c9ca0220a8c4c073b485a64fa2b25a9271
7d3c745a811f383c2a3ddf8c48126cbcd3740fa7
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Backed out 6 changesets (bug 939614) for Hf timeouts on a CLOSED TREE. Backed out changeset 50cc92857bf7 (bug 939614) Backed out changeset 62a6568217da (bug 939614) Backed out changeset 31d0d40d4a7c (bug 939614) Backed out changeset 2b87186ddb6d (bug 939614) Backed out changeset fa2005c9ca02 (bug 939614) Backed out changeset 7d3c745a811f (bug 939614)
js/src/builtin/TestingFunctions.cpp
js/src/jit/AsmJS.cpp
js/src/jit/Bailouts.cpp
js/src/jit/BaselineCompiler.cpp
js/src/jit/BaselineJIT.cpp
js/src/jit/CodeGenerator.cpp
js/src/jit/CodeGenerator.h
js/src/jit/Ion.cpp
js/src/jit/Ion.h
js/src/jit/IonAnalysis.cpp
js/src/jit/IonBuilder.cpp
js/src/jit/IonBuilder.h
js/src/jit/IonCode.h
js/src/jit/IonFrames.cpp
js/src/jit/IonOptimizationLevels.cpp
js/src/jit/IonOptimizationLevels.h
js/src/jit/JitOptions.cpp
js/src/jit/JitOptions.h
js/src/jit/LIR-Common.h
js/src/jit/LOpcodes.h
js/src/jit/LinearScan.cpp
js/src/jit/LiveRangeAllocator.h
js/src/jit/Lowering.cpp
js/src/jit/Lowering.h
js/src/jit/MCallOptimize.cpp
js/src/jit/MIR.h
js/src/jit/MIRGenerator.h
js/src/jit/MIRGraph.cpp
js/src/jit/MOpcodes.h
js/src/jit/ParallelSafetyAnalysis.cpp
js/src/jit/RangeAnalysis.cpp
js/src/jit/UnreachableCodeElimination.cpp
js/src/jit/shared/CodeGenerator-shared.cpp
js/src/jit/shared/Lowering-shared-inl.h
js/src/jsapi.cpp
js/src/jsscript.h
js/src/jsworkers.cpp
js/src/moz.build
js/src/shell/js.cpp
js/src/vm/ForkJoin.cpp
--- a/js/src/builtin/TestingFunctions.cpp
+++ b/js/src/builtin/TestingFunctions.cpp
@@ -951,17 +951,17 @@ DisableSPSProfiling(JSContext *cx, unsig
         cx->runtime()->spsProfiler.enable(false);
     return true;
 }
 
 static bool
 EnableOsiPointRegisterChecks(JSContext *, unsigned, jsval *vp)
 {
 #if defined(JS_ION) && defined(CHECK_OSIPOINT_REGISTERS)
-    jit::js_JitOptions.checkOsiPointRegisters = true;
+    jit::js_IonOptions.checkOsiPointRegisters = true;
 #endif
     JS_SET_RVAL(cx, vp, JSVAL_VOID);
     return true;
 }
 
 static bool
 DisplayName(JSContext *cx, unsigned argc, jsval *vp)
 {
@@ -1120,17 +1120,17 @@ SetJitCompilerOption(JSContext *cx, unsi
     return true;
 }
 
 static bool
 SetIonCheckGraphCoherency(JSContext *cx, unsigned argc, jsval *vp)
 {
     CallArgs args = CallArgsFromVp(argc, vp);
 #ifdef JS_ION
-    jit::js_JitOptions.checkGraphConsistency = ToBoolean(args.get(0));
+    jit::js_IonOptions.checkGraphConsistency = ToBoolean(args.get(0));
 #endif
     args.rval().setUndefined();
     return true;
 }
 
 class CloneBufferObject : public JSObject {
     static const JSPropertySpec props_[2];
     static const size_t DATA_SLOT   = 0;
--- a/js/src/jit/AsmJS.cpp
+++ b/js/src/jit/AsmJS.cpp
@@ -1931,19 +1931,17 @@ class FunctionCompiler
     {
         JS_ASSERT(locals_.count() == argTypes.length() + varInitializers_.length());
 
         alloc_  = lifo_.new_<TempAllocator>(&lifo_);
         ionContext_.construct(m_.cx(), alloc_);
 
         graph_  = lifo_.new_<MIRGraph>(alloc_);
         info_   = lifo_.new_<CompileInfo>(locals_.count(), SequentialExecution);
-        const OptimizationInfo *optimizationInfo = js_IonOptimizations.get(Optimization_AsmJS);
-        mirGen_ = lifo_.new_<MIRGenerator>(CompileCompartment::get(cx()->compartment()), alloc_,
-                                           graph_, info_, optimizationInfo);
+        mirGen_ = lifo_.new_<MIRGenerator>(CompileCompartment::get(cx()->compartment()), alloc_, graph_, info_);
 
         if (!newBlock(/* pred = */ nullptr, &curBlock_, fn_))
             return false;
 
         curBlock_->add(MAsmJSCheckOverRecursed::New(alloc(), &m_.stackOverflowLabel()));
 
         for (ABIArgTypeIter i = argTypes; !i.done(); i++) {
             MAsmJSParameter *ins = MAsmJSParameter::New(alloc(), *i, i.mirType());
--- a/js/src/jit/Bailouts.cpp
+++ b/js/src/jit/Bailouts.cpp
@@ -191,17 +191,17 @@ jit::EnsureHasScopeObjects(JSContext *cx
 bool
 jit::CheckFrequentBailouts(JSContext *cx, JSScript *script)
 {
     if (script->hasIonScript()) {
         // Invalidate if this script keeps bailing out without invalidation. Next time
         // we compile this script LICM will be disabled.
         IonScript *ionScript = script->ionScript();
 
-        if (ionScript->numBailouts() >= js_JitOptions.frequentBailoutThreshold &&
+        if (ionScript->numBailouts() >= js_IonOptions.frequentBailoutThreshold &&
             !script->hadFrequentBailouts())
         {
             script->setHadFrequentBailouts();
 
             IonSpew(IonSpew_Invalidate, "Invalidating due to too many bailouts");
 
             if (!Invalidate(cx, script))
                 return false;
--- a/js/src/jit/BaselineCompiler.cpp
+++ b/js/src/jit/BaselineCompiler.cpp
@@ -632,18 +632,17 @@ BaselineCompiler::emitUseCountIncrement(
     // count but don't attempt OSR (Ion only compiles the try block).
     if (analysis_.info(pc).loopEntryInCatchOrFinally) {
         JS_ASSERT(JSOp(*pc) == JSOP_LOOPENTRY);
         return true;
     }
 
     Label skipCall;
 
-    const OptimizationInfo *info = js_IonOptimizations.get(js_IonOptimizations.firstLevel());
-    uint32_t minUses = info->usesBeforeCompile(script, pc);
+    uint32_t minUses = UsesBeforeIonRecompile(script, pc);
     masm.branch32(Assembler::LessThan, countReg, Imm32(minUses), &skipCall);
 
     masm.branchPtr(Assembler::Equal,
                    Address(scriptReg, JSScript::offsetOfIonScript()),
                    ImmPtr(ION_COMPILING_SCRIPT), &skipCall);
 
     // Call IC.
     ICUseCount_Fallback::Compiler stubCompiler(cx);
--- a/js/src/jit/BaselineJIT.cpp
+++ b/js/src/jit/BaselineJIT.cpp
@@ -271,17 +271,17 @@ CanEnterBaselineJIT(JSContext *cx, Handl
     // Also eagerly compile if we are in parallel warmup, the point of which
     // is to gather type information so that the script may be compiled for
     // parallel execution. We want to avoid the situation of OSRing during
     // warmup and only gathering type information for the loop, and not the
     // rest of the function.
     if (IsJSDEnabled(cx) || cx->runtime()->parallelWarmup > 0) {
         if (osr)
             return Method_Skipped;
-    } else if (script->incUseCount() <= js_JitOptions.baselineUsesBeforeCompile) {
+    } else if (script->incUseCount() <= js_IonOptions.baselineUsesBeforeCompile) {
         return Method_Skipped;
     }
 
     if (script->isCallsiteClone()) {
         // Ensure the original function is compiled too, so that bailouts from
         // Ion code have a BaselineScript to resume into.
         RootedScript original(cx, script->originalFunction()->nonLazyScript());
         JS_ASSERT(original != script);
--- a/js/src/jit/CodeGenerator.cpp
+++ b/js/src/jit/CodeGenerator.cpp
@@ -17,17 +17,16 @@
 #include "builtin/Eval.h"
 #include "builtin/TypedObject.h"
 #ifdef JSGC_GENERATIONAL
 # include "gc/Nursery.h"
 #endif
 #include "jit/ExecutionModeInlines.h"
 #include "jit/IonCaches.h"
 #include "jit/IonLinker.h"
-#include "jit/IonOptimizationLevels.h"
 #include "jit/IonSpewer.h"
 #include "jit/MIRGenerator.h"
 #include "jit/MoveEmitter.h"
 #include "jit/ParallelFunctions.h"
 #include "jit/ParallelSafetyAnalysis.h"
 #include "jit/RangeAnalysis.h"
 #include "vm/ForkJoin.h"
 
@@ -5853,19 +5852,17 @@ CodeGenerator::generate()
     return !masm.oom();
 }
 
 bool
 CodeGenerator::link(JSContext *cx, types::CompilerConstraintList *constraints)
 {
     RootedScript script(cx, gen->info().script());
     ExecutionMode executionMode = gen->info().executionMode();
-    OptimizationLevel optimizationLevel = gen->optimizationInfo().level();
-
-    JS_ASSERT_IF(HasIonScript(script, executionMode), executionMode == SequentialExecution);
+    JS_ASSERT(!HasIonScript(script, executionMode));
 
     // Check to make sure we didn't have a mid-build invalidation. If so, we
     // will trickle to jit::Compile() and return Method_Skipped.
     types::RecompileInfo recompileInfo;
     if (!types::FinishCompilation(cx, script, executionMode, constraints, &recompileInfo))
         return true;
 
     uint32_t scriptFrameSize = frameClass_ == FrameSizeClass::None()
@@ -5883,17 +5880,17 @@ CodeGenerator::link(JSContext *cx, types
 
     IonScript *ionScript =
       IonScript::New(cx, recompileInfo,
                      graph.totalSlotCount(), scriptFrameSize, snapshots_.size(),
                      bailouts_.length(), graph.numConstants(),
                      safepointIndices_.length(), osiIndices_.length(),
                      cacheList_.length(), runtimeData_.length(),
                      safepoints_.size(), callTargets.length(),
-                     patchableBackedges_.length(), optimizationLevel);
+                     patchableBackedges_.length());
     if (!ionScript) {
         recompileInfo.compilerOutput(cx->compartment()->types)->invalidate();
         return false;
     }
 
     // Lock the runtime against operation callbacks during the link.
     // We don't want an operation callback to protect the code for the script
     // before it has been filled in, as we could segv before the runtime's
@@ -7926,29 +7923,10 @@ CodeGenerator::visitAssertRangeV(LAssert
         masm.bind(&isNotDouble);
     }
 
     masm.assumeUnreachable("Incorrect range for Value.");
     masm.bind(&done);
     return true;
 }
 
-typedef bool (*RecompileFn)(JSContext *);
-static const VMFunction RecompileFnInfo = FunctionInfo<RecompileFn>(Recompile);
-
-bool
-CodeGenerator::visitRecompileCheck(LRecompileCheck *ins)
-{
-    Register useCount = ToRegister(ins->scratch());
-
-    masm.movePtr(ImmPtr(ins->mir()->script()->addressOfUseCount()), useCount);
-    Address ptr(useCount, 0);
-    masm.add32(Imm32(1), ptr);
-
-    OutOfLineCode *ool = oolCallVM(RecompileFnInfo, ins, (ArgList()), StoreRegisterTo(useCount));
-    masm.branch32(Assembler::Above, ptr, Imm32(ins->mir()->useCount()), ool->entry());
-    masm.bind(ool->rejoin());
-
-    return true;
-}
-
 } // namespace jit
 } // namespace js
--- a/js/src/jit/CodeGenerator.h
+++ b/js/src/jit/CodeGenerator.h
@@ -331,18 +331,16 @@ class CodeGenerator : public CodeGenerat
     bool visitNameIC(OutOfLineUpdateCache *ool, DataPtr<NameIC> &ic);
     bool visitCallsiteCloneIC(OutOfLineUpdateCache *ool, DataPtr<CallsiteCloneIC> &ic);
 
     bool visitAssertRangeI(LAssertRangeI *ins);
     bool visitAssertRangeD(LAssertRangeD *ins);
     bool visitAssertRangeF(LAssertRangeF *ins);
     bool visitAssertRangeV(LAssertRangeV *ins);
 
-    bool visitRecompileCheck(LRecompileCheck *ins);
-
     IonScriptCounts *extractUnassociatedScriptCounts() {
         IonScriptCounts *counts = unassociatedScriptCounts_;
         unassociatedScriptCounts_ = nullptr;  // prevent delete in dtor
         return counts;
     }
 
   private:
     bool addGetPropertyCache(LInstruction *ins, RegisterSet liveRegs, Register objReg,
--- a/js/src/jit/Ion.cpp
+++ b/js/src/jit/Ion.cpp
@@ -22,17 +22,16 @@
 #include "jit/BaselineInspector.h"
 #include "jit/BaselineJIT.h"
 #include "jit/CodeGenerator.h"
 #include "jit/EdgeCaseAnalysis.h"
 #include "jit/EffectiveAddressAnalysis.h"
 #include "jit/ExecutionModeInlines.h"
 #include "jit/IonAnalysis.h"
 #include "jit/IonBuilder.h"
-#include "jit/IonOptimizationLevels.h"
 #include "jit/IonSpewer.h"
 #include "jit/JitCompartment.h"
 #include "jit/LICM.h"
 #include "jit/LinearScan.h"
 #include "jit/LIR.h"
 #include "jit/Lowering.h"
 #include "jit/ParallelSafetyAnalysis.h"
 #include "jit/PerfSpewer.h"
@@ -45,16 +44,19 @@
 #include "jscompartmentinlines.h"
 #include "jsgcinlines.h"
 #include "jsinferinlines.h"
 #include "jsobjinlines.h"
 
 using namespace js;
 using namespace js::jit;
 
+// Global variables.
+IonOptions jit::js_IonOptions;
+
 // Assert that IonCode is gc::Cell aligned.
 JS_STATIC_ASSERT(sizeof(IonCode) % gc::CellSize == 0);
 
 #ifdef JS_THREADSAFE
 static bool IonTLSInitialized = false;
 static unsigned IonTLSIndex;
 
 static inline IonContext *
@@ -754,18 +756,17 @@ IonScript::IonScript()
 {
 }
 
 IonScript *
 IonScript::New(JSContext *cx, types::RecompileInfo recompileInfo,
                uint32_t frameSlots, uint32_t frameSize, size_t snapshotsSize,
                size_t bailoutEntries, size_t constants, size_t safepointIndices,
                size_t osiIndices, size_t cacheEntries, size_t runtimeSize,
-               size_t safepointsSize, size_t callTargetEntries, size_t backedgeEntries,
-               OptimizationLevel optimizationLevel)
+               size_t safepointsSize, size_t callTargetEntries, size_t backedgeEntries)
 {
     static const int DataAlignment = sizeof(void *);
 
     if (snapshotsSize >= MAX_BUFFER_SIZE ||
         (bailoutEntries >= MAX_BUFFER_SIZE / sizeof(uint32_t)))
     {
         js_ReportOutOfMemory(cx);
         return nullptr;
@@ -842,17 +843,16 @@ IonScript::New(JSContext *cx, types::Rec
     script->backedgeList_ = offsetCursor;
     script->backedgeEntries_ = backedgeEntries;
     offsetCursor += paddedBackedgeSize;
 
     script->frameSlots_ = frameSlots;
     script->frameSize_ = frameSize;
 
     script->recompileInfo_ = recompileInfo;
-    script->optimizationLevel_ = optimizationLevel;
 
     return script;
 }
 
 void
 IonScript::trace(JSTracer *trc)
 {
     if (method_)
@@ -1228,19 +1228,17 @@ OptimizeMIR(MIRGenerator *mir)
     if (graph.entryBlock()->info().executionMode() == ParallelExecution) {
         ParallelSafetyAnalysis analysis(mir, graph);
         if (!analysis.analyze())
             return false;
     }
 
     // Alias analysis is required for LICM and GVN so that we don't move
     // loads across stores.
-    if (mir->optimizationInfo().licmEnabled() ||
-        mir->optimizationInfo().gvnEnabled())
-    {
+    if (js_IonOptions.licm || js_IonOptions.gvn) {
         AliasAnalysis analysis(mir, graph);
         if (!analysis.analyze())
             return false;
         IonSpewPass("Alias analysis");
         AssertExtendedGraphCoherency(graph);
 
         if (mir->shouldCancel("Alias analysis"))
             return false;
@@ -1250,56 +1248,56 @@ OptimizeMIR(MIRGenerator *mir)
         // alias analysis.
         if (!EliminateDeadResumePointOperands(mir, graph))
             return false;
 
         if (mir->shouldCancel("Eliminate dead resume point operands"))
             return false;
     }
 
-    if (mir->optimizationInfo().gvnEnabled()) {
-        ValueNumberer gvn(mir, graph, mir->optimizationInfo().gvnKind() == GVN_Optimistic);
+    if (js_IonOptions.gvn) {
+        ValueNumberer gvn(mir, graph, js_IonOptions.gvnIsOptimistic);
         if (!gvn.analyze())
             return false;
         IonSpewPass("GVN");
         AssertExtendedGraphCoherency(graph);
 
         if (mir->shouldCancel("GVN"))
             return false;
     }
 
-    if (mir->optimizationInfo().uceEnabled()) {
+    if (js_IonOptions.uce) {
         UnreachableCodeElimination uce(mir, graph);
         if (!uce.analyze())
             return false;
         IonSpewPass("UCE");
         AssertExtendedGraphCoherency(graph);
     }
 
     if (mir->shouldCancel("UCE"))
         return false;
 
-    if (mir->optimizationInfo().licmEnabled()) {
+    if (js_IonOptions.licm) {
         // LICM can hoist instructions from conditional branches and trigger
         // repeated bailouts. Disable it if this script is known to bailout
         // frequently.
         JSScript *script = mir->info().script();
         if (!script || !script->hadFrequentBailouts()) {
             LICM licm(mir, graph);
             if (!licm.analyze())
                 return false;
             IonSpewPass("LICM");
             AssertExtendedGraphCoherency(graph);
 
             if (mir->shouldCancel("LICM"))
                 return false;
         }
     }
 
-    if (mir->optimizationInfo().rangeAnalysisEnabled()) {
+    if (js_IonOptions.rangeAnalysis) {
         RangeAnalysis r(mir, graph);
         if (!r.addBetaNodes())
             return false;
         IonSpewPass("Beta");
         AssertExtendedGraphCoherency(graph);
 
         if (mir->shouldCancel("RA Beta"))
             return false;
@@ -1315,17 +1313,17 @@ OptimizeMIR(MIRGenerator *mir)
         if (!r.removeBetaNodes())
             return false;
         IonSpewPass("De-Beta");
         AssertExtendedGraphCoherency(graph);
 
         if (mir->shouldCancel("RA De-Beta"))
             return false;
 
-        if (mir->optimizationInfo().uceEnabled()) {
+        if (js_IonOptions.uce) {
             bool shouldRunUCE = false;
             if (!r.prepareForUCE(&shouldRunUCE))
                 return false;
             IonSpewPass("RA check UCE");
             AssertExtendedGraphCoherency(graph);
 
             if (mir->shouldCancel("RA check UCE"))
                 return false;
@@ -1347,17 +1345,17 @@ OptimizeMIR(MIRGenerator *mir)
             return false;
         IonSpewPass("Truncate Doubles");
         AssertExtendedGraphCoherency(graph);
 
         if (mir->shouldCancel("Truncate Doubles"))
             return false;
     }
 
-    if (mir->optimizationInfo().eaaEnabled()) {
+    if (js_IonOptions.eaa) {
         EffectiveAddressAnalysis eaa(graph);
         if (!eaa.analyze())
             return false;
         IonSpewPass("Effective Address Analysis");
         AssertExtendedGraphCoherency(graph);
 
         if (mir->shouldCancel("Effective Address Analysis"))
             return false;
@@ -1369,28 +1367,28 @@ OptimizeMIR(MIRGenerator *mir)
     AssertExtendedGraphCoherency(graph);
 
     if (mir->shouldCancel("DCE"))
         return false;
 
     // Passes after this point must not move instructions; these analyses
     // depend on knowing the final order in which instructions will execute.
 
-    if (mir->optimizationInfo().edgeCaseAnalysisEnabled()) {
+    if (js_IonOptions.edgeCaseAnalysis && !mir->compilingAsmJS()) {
         EdgeCaseAnalysis edgeCaseAnalysis(mir, graph);
         if (!edgeCaseAnalysis.analyzeLate())
             return false;
         IonSpewPass("Edge Case Analysis (Late)");
         AssertGraphCoherency(graph);
 
         if (mir->shouldCancel("Edge Case Analysis (Late)"))
             return false;
     }
 
-    if (mir->optimizationInfo().eliminateRedundantChecksEnabled()) {
+    if (!mir->compilingAsmJS()) {
         // Note: check elimination has to run after all other passes that move
         // instructions. Since check uses are replaced with the actual index,
         // code motion after this pass could incorrectly move a load or store
         // before its bounds check.
         if (!EliminateRedundantChecks(graph))
             return false;
         IonSpewPass("Bounds Check Elimination");
         AssertGraphCoherency(graph);
@@ -1413,17 +1411,17 @@ GenerateLIR(MIRGenerator *mir)
         return nullptr;
     IonSpewPass("Generate LIR");
 
     if (mir->shouldCancel("Generate LIR"))
         return nullptr;
 
     AllocationIntegrityState integrity(*lir);
 
-    switch (mir->optimizationInfo().registerAllocator()) {
+    switch (js_IonOptions.registerAllocator) {
       case RegisterAllocator_LSRA: {
 #ifdef DEBUG
         if (!integrity.record())
             return nullptr;
 #endif
 
         LinearScanAllocator regalloc(mir, &lirgen, *lir);
         if (!regalloc.go())
@@ -1625,27 +1623,24 @@ TrackPropertiesForSingletonScopes(JSCont
         if (scope->is<CallObject>() && scope->hasSingletonType())
             TrackAllProperties(cx, scope);
     }
 }
 
 static AbortReason
 IonCompile(JSContext *cx, JSScript *script,
            BaselineFrame *baselineFrame, jsbytecode *osrPc, bool constructing,
-           ExecutionMode executionMode, bool recompile,
-           OptimizationLevel optimizationLevel)
+           ExecutionMode executionMode, bool recompile)
 {
 #if JS_TRACE_LOGGING
     AutoTraceLog logger(TraceLogging::defaultLogger(),
                         TraceLogging::ION_COMPILE_START,
                         TraceLogging::ION_COMPILE_STOP,
                         script);
 #endif
-    JS_ASSERT(optimizationLevel > Optimization_DontCompile);
-
     TrackPropertiesForSingletonScopes(cx, script, baselineFrame);
 
     LifoAlloc *alloc = cx->new_<LifoAlloc>(BUILDER_LIFO_ALLOC_PRIMARY_CHUNK_SIZE);
     if (!alloc)
         return AbortReason_Alloc;
 
     ScopedJSDeletePtr<LifoAlloc> autoDelete(alloc);
 
@@ -1683,34 +1678,31 @@ IonCompile(JSContext *cx, JSScript *scri
 
     AutoFlushCache afc("IonCompile", cx->runtime()->jitRuntime());
 
     AutoTempAllocatorRooter root(cx, temp);
     types::CompilerConstraintList *constraints = types::NewCompilerConstraintList(*temp);
     if (!constraints)
         return AbortReason_Alloc;
 
-    const OptimizationInfo *optimizationInfo = js_IonOptimizations.get(optimizationLevel);
-
     IonBuilder *builder = alloc->new_<IonBuilder>((JSContext *) nullptr,
                                                   CompileCompartment::get(cx->compartment()),
                                                   temp, graph, constraints,
-                                                  &inspector, info, optimizationInfo,
-                                                  baselineFrameInspector);
+                                                  &inspector, info, baselineFrameInspector);
     if (!builder)
         return AbortReason_Alloc;
 
     JS_ASSERT(recompile == HasIonScript(builder->script(), executionMode));
     JS_ASSERT(CanIonCompile(builder->script(), executionMode));
 
     RootedScript builderScript(cx, builder->script());
     IonSpewNewFunction(graph, builderScript);
 
     mozilla::Maybe<AutoProtectHeapForCompilation> protect;
-    if (js_JitOptions.checkThreadSafety &&
+    if (js_IonOptions.checkThreadSafety &&
         cx->runtime()->gcIncrementalState == gc::NO_INCREMENTAL &&
         !cx->runtime()->profilingScripts &&
         !cx->runtime()->spsProfiler.enabled())
     {
         protect.construct(cx->runtime());
     }
 
     bool succeeded = builder->build();
@@ -1721,25 +1713,25 @@ IonCompile(JSContext *cx, JSScript *scri
             IonSpew(IonSpew_Abort, "Builder raised exception.");
             return AbortReason_Error;
         }
 
         IonSpew(IonSpew_Abort, "Builder failed to build.");
         return builder->abortReason();
     }
 
-    if (recompile) {
-        JS_ASSERT(executionMode == SequentialExecution);
-        builderScript->ionScript()->setRecompiling();
-    } else {
-        SetIonScript(builder->script(), executionMode, ION_COMPILING_SCRIPT);
-    }
-
     // If possible, compile the script off thread.
     if (OffThreadCompilationAvailable(cx)) {
+        if (recompile) {
+            JS_ASSERT(executionMode == SequentialExecution);
+            builderScript->ionScript()->setRecompiling();
+        } else {
+            SetIonScript(builder->script(), executionMode, ION_COMPILING_SCRIPT);
+        }
+
         if (!StartOffThreadIonCompile(cx, builder)) {
             IonSpew(IonSpew_Abort, "Unable to start off-thread ion compilation.");
             return AbortReason_Alloc;
         }
 
         // The allocator and associated data will be destroyed after being
         // processed in the finishedOffThreadCompilations list.
         autoDelete.forget();
@@ -1797,20 +1789,31 @@ CheckScript(JSContext *cx, JSScript *scr
     if (!script->compileAndGo()) {
         IonSpew(IonSpew_Abort, "not compile-and-go");
         return false;
     }
 
     return true;
 }
 
+// Longer scripts can only be compiled off thread, as these compilations
+// can be expensive and stall the main thread for too long.
+static const uint32_t MAX_OFF_THREAD_SCRIPT_SIZE = 100 * 1000;
+static const uint32_t MAX_MAIN_THREAD_SCRIPT_SIZE = 2 * 1000;
+static const uint32_t MAX_MAIN_THREAD_LOCALS_AND_ARGS = 256;
+
+// DOM Worker runtimes don't have off thread compilation, but can also compile
+// larger scripts since this doesn't stall the main thread.
+static const uint32_t MAX_DOM_WORKER_SCRIPT_SIZE = 16 * 1000;
+static const uint32_t MAX_DOM_WORKER_LOCALS_AND_ARGS = 2048;
+
 static MethodStatus
 CheckScriptSize(JSContext *cx, JSScript* script)
 {
-    if (!js_JitOptions.limitScriptSize)
+    if (!js_IonOptions.limitScriptSize)
         return Method_Compiled;
 
     if (script->length() > MAX_OFF_THREAD_SCRIPT_SIZE) {
         // Some scripts are so large we never try to Ion compile them.
         IonSpew(IonSpew_Abort, "Script too large (%u bytes)", script->length());
         return Method_CantCompile;
     }
 
@@ -1859,36 +1862,23 @@ bool
 CanIonCompileScript(JSContext *cx, HandleScript script, bool osr)
 {
     if (!script->canIonCompile() || !CheckScript(cx, script, osr))
         return false;
 
     return CheckScriptSize(cx, script) == Method_Compiled;
 }
 
-static OptimizationLevel
-GetOptimizationLevel(HandleScript script, jsbytecode *pc, ExecutionMode executionMode)
-{
-    if (executionMode == ParallelExecution)
-        return Optimization_Normal;
-
-    JS_ASSERT(executionMode == SequentialExecution);
-
-    return js_IonOptimizations.levelForScript(script, pc);
-}
-
 static MethodStatus
 Compile(JSContext *cx, HandleScript script, BaselineFrame *osrFrame, jsbytecode *osrPc,
         bool constructing, ExecutionMode executionMode)
 {
     JS_ASSERT(jit::IsIonEnabled(cx));
     JS_ASSERT(jit::IsBaselineEnabled(cx));
     JS_ASSERT_IF(osrPc != nullptr, (JSOp)*osrPc == JSOP_LOOPENTRY);
-    JS_ASSERT_IF(executionMode == ParallelExecution, !osrFrame && !osrPc);
-    JS_ASSERT_IF(executionMode == ParallelExecution, !HasIonScript(script, executionMode));
 
     if (!script->hasBaselineScript())
         return Method_Skipped;
 
     if (cx->compartment()->debugMode()) {
         IonSpew(IonSpew_Abort, "debugging");
         return Method_CantCompile;
     }
@@ -1900,60 +1890,33 @@ Compile(JSContext *cx, HandleScript scri
 
     MethodStatus status = CheckScriptSize(cx, script);
     if (status != Method_Compiled) {
         IonSpew(IonSpew_Abort, "Aborted compilation of %s:%d", script->filename(), script->lineno());
         return status;
     }
 
     bool recompile = false;
-    OptimizationLevel optimizationLevel = GetOptimizationLevel(script, osrPc, executionMode);
-    if (optimizationLevel == Optimization_DontCompile)
-        return Method_Skipped;
 
     IonScript *scriptIon = GetIonScript(script, executionMode);
     if (scriptIon) {
         if (!scriptIon->method())
             return Method_CantCompile;
-
-        MethodStatus failedState = Method_Compiled;
-
-        // If we keep failing to enter the script due to an OSR pc mismatch,
-        // recompile with the right pc.
-        if (osrPc && script->ionScript()->osrPc() != osrPc) {
-            uint32_t count = script->ionScript()->incrOsrPcMismatchCounter();
-            if (count <= js_JitOptions.osrPcMismatchesBeforeRecompile)
-                return Method_Skipped;
-
-            failedState = Method_Skipped;
-        }
-
-        // Don't recompile/overwrite higher optimized code,
-        // with a lower optimization level.
-        if (optimizationLevel < scriptIon->optimizationLevel())
-            return failedState;
-
-        if (optimizationLevel == scriptIon->optimizationLevel() &&
-            (!osrPc || script->ionScript()->osrPc() == osrPc))
-        {
-            return failedState;
-        }
-
-        // Don't start compiling if already compiling
-        if (scriptIon->isRecompiling())
-            return failedState;
-
-        if (osrPc)
-            script->ionScript()->resetOsrPcMismatchCounter();
-
-        recompile = true;
+        return Method_Compiled;
+    }
+
+    if (executionMode == SequentialExecution) {
+        // Use getUseCount instead of incUseCount to avoid bumping the
+        // use count twice.
+        if (script->getUseCount() < UsesBeforeIonRecompile(script, osrPc ? osrPc : script->code()))
+            return Method_Skipped;
     }
 
     AbortReason reason = IonCompile(cx, script, osrFrame, osrPc, constructing, executionMode,
-                                    recompile, optimizationLevel);
+                                    recompile);
     if (reason == AbortReason_Error)
         return Method_Error;
 
     if (reason == AbortReason_Disable)
         return Method_CantCompile;
 
     if (reason == AbortReason_Alloc) {
         js_ReportOutOfMemory(cx);
@@ -1984,38 +1947,48 @@ jit::CanEnterAtBranch(JSContext *cx, JSS
     if (script->isIonCompilingOffThread())
         return Method_Skipped;
 
     // Skip if the code is expected to result in a bailout.
     if (script->hasIonScript() && script->ionScript()->bailoutExpected())
         return Method_Skipped;
 
     // Optionally ignore on user request.
-    if (!js_JitOptions.osr)
+    if (!js_IonOptions.osr)
         return Method_Skipped;
 
     // Mark as forbidden if frame can't be handled.
     if (!CheckFrame(osrFrame)) {
         ForbidCompilation(cx, script);
         return Method_CantCompile;
     }
 
-    // Attempt compilation.
-    // - Returns Method_Compiled if the right ionscript is present
-    //   (Meaning it was present or a sequantial compile finished)
-    // - Returns Method_Skipped if pc doesn't match
-    //   (This means a background thread compilation with that pc could have started or not.)
+    // Attempt compilation. Returns Method_Compiled if already compiled.
     RootedScript rscript(cx, script);
     MethodStatus status = Compile(cx, rscript, osrFrame, pc, isConstructing, SequentialExecution);
     if (status != Method_Compiled) {
         if (status == Method_CantCompile)
             ForbidCompilation(cx, script);
         return status;
     }
 
+    if (script->ionScript()->osrPc() != pc) {
+        // If we keep failing to enter the script due to an OSR pc mismatch,
+        // invalidate the script to force a recompile.
+        uint32_t count = script->ionScript()->incrOsrPcMismatchCounter();
+
+        if (count > js_IonOptions.osrPcMismatchesBeforeRecompile) {
+            if (!Invalidate(cx, script, SequentialExecution, true))
+                return Method_Error;
+        }
+        return Method_Skipped;
+    }
+
+    script->ionScript()->resetOsrPcMismatchCounter();
+
     return Method_Compiled;
 }
 
 MethodStatus
 jit::CanEnter(JSContext *cx, RunState &state)
 {
     JS_ASSERT(jit::IsIonEnabled(cx));
 
@@ -2067,17 +2040,17 @@ jit::CanEnter(JSContext *cx, RunState &s
         IonSpew(IonSpew_Abort, "generator frame");
         ForbidCompilation(cx, script);
         return Method_CantCompile;
     }
 
     // If --ion-eager is used, compile with Baseline first, so that we
     // can directly enter IonMonkey.
     RootedScript rscript(cx, script);
-    if (js_JitOptions.eagerCompilation && !rscript->hasBaselineScript()) {
+    if (js_IonOptions.eagerCompilation && !rscript->hasBaselineScript()) {
         MethodStatus status = CanEnterBaselineMethod(cx, state);
         if (status != Method_Compiled)
             return status;
     }
 
     // Attempt compilation. Returns Method_Compiled if already compiled.
     bool constructing = state.isInvoke() && state.asInvoke()->constructing();
     MethodStatus status =
@@ -2720,16 +2693,46 @@ jit::ForbidCompilation(JSContext *cx, JS
 
       default:
         MOZ_ASSUME_UNREACHABLE("No such execution mode");
     }
 
     MOZ_ASSUME_UNREACHABLE("No such execution mode");
 }
 
+uint32_t
+jit::UsesBeforeIonRecompile(JSScript *script, jsbytecode *pc)
+{
+    JS_ASSERT(pc == script->code() || JSOp(*pc) == JSOP_LOOPENTRY);
+
+    uint32_t minUses = js_IonOptions.usesBeforeCompile;
+
+    // If the script is too large to compile on the main thread, we can still
+    // compile it off thread. In these cases, increase the use count threshold
+    // to improve the compilation's type information and hopefully avoid later
+    // recompilation.
+
+    if (script->length() > MAX_MAIN_THREAD_SCRIPT_SIZE)
+        minUses = minUses * (script->length() / (double) MAX_MAIN_THREAD_SCRIPT_SIZE);
+
+    uint32_t numLocalsAndArgs = analyze::TotalSlots(script);
+    if (numLocalsAndArgs > MAX_MAIN_THREAD_LOCALS_AND_ARGS)
+        minUses = minUses * (numLocalsAndArgs / (double) MAX_MAIN_THREAD_LOCALS_AND_ARGS);
+
+    if (JSOp(*pc) != JSOP_LOOPENTRY || js_IonOptions.eagerCompilation)
+        return minUses;
+
+    // It's more efficient to enter outer loops, rather than inner loops, via OSR.
+    // To accomplish this, we use a slightly higher threshold for inner loops.
+    // Note that the loop depth is always > 0 so we will prefer non-OSR over OSR.
+    uint32_t loopDepth = GET_UINT8(pc);
+    JS_ASSERT(loopDepth > 0);
+    return minUses + loopDepth * 100;
+}
+
 void
 AutoFlushCache::updateTop(uintptr_t p, size_t len)
 {
     IonContext *ictx = MaybeGetIonContext();
     JitRuntime *jrt = (ictx != nullptr) ? const_cast<JitRuntime *>(ictx->runtime->jitRuntime()) : nullptr;
     if (!jrt || !jrt->flusher())
         JSC::ExecutableAllocator::cacheFlush((void*)p, len);
     else
--- a/js/src/jit/Ion.h
+++ b/js/src/jit/Ion.h
@@ -11,23 +11,258 @@
 
 #include "mozilla/MemoryReporting.h"
 
 #include "jscntxt.h"
 #include "jscompartment.h"
 
 #include "jit/CompileInfo.h"
 #include "jit/CompileWrappers.h"
-#include "jit/JitOptions.h"
 
 namespace js {
 namespace jit {
 
 class TempAllocator;
 
+// Possible register allocators which may be used.
+enum IonRegisterAllocator {
+    RegisterAllocator_LSRA,
+    RegisterAllocator_Backtracking,
+    RegisterAllocator_Stupid
+};
+
+struct IonOptions
+{
+    // Toggles whether global value numbering is used.
+    //
+    // Default: true
+    bool gvn;
+
+    // Toggles whether global value numbering is optimistic (true) or
+    // pessimistic (false).
+    //
+    // Default: true
+    bool gvnIsOptimistic;
+
+    // Toggles whether loop invariant code motion is performed.
+    //
+    // Default: true
+    bool licm;
+
+    // Toggles whether functions may be entered at loop headers.
+    //
+    // Default: true
+    bool osr;
+
+    // Toggles whether large scripts are rejected.
+    //
+    // Default: true
+    bool limitScriptSize;
+
+    // Describes which register allocator to use.
+    //
+    // Default: LSRA
+    IonRegisterAllocator registerAllocator;
+
+    // Toggles whether inlining is performed.
+    //
+    // Default: true
+    bool inlining;
+
+    // Toggles whether Edge Case Analysis is used.
+    //
+    // Default: true
+    bool edgeCaseAnalysis;
+
+    // Toggles whether Range Analysis is used.
+    //
+    // Default: true
+    bool rangeAnalysis;
+
+    // Whether to enable extra code to perform dynamic validation of
+    // RangeAnalysis results.
+    //
+    // Default: false
+    bool checkRangeAnalysis;
+
+    // Whether to protect the GC heap during Ion compilation and ensure that
+    // only threadsafe operations are performed on it.
+    //
+    // Default: false
+    bool checkThreadSafety;
+
+    // Whether to perform expensive graph-consistency DEBUG-only assertions.
+    // It can be useful to disable this to reduce DEBUG-compile time of large
+    // asm.js programs.
+    //
+    // Default: true
+    bool checkGraphConsistency;
+
+    // Toggles whether Unreachable Code Elimination is performed.
+    //
+    // Default: true
+    bool uce;
+
+    // Toggles whether Effective Address Analysis is performed.
+    //
+    // Default: true
+    bool eaa;
+
+#ifdef CHECK_OSIPOINT_REGISTERS
+    // Emit extra code to verify live regs at the start of a VM call
+    // are not modified before its OsiPoint.
+    //
+    // Default: false
+    bool checkOsiPointRegisters;
+#endif
+
+    // How many invocations or loop iterations are needed before functions
+    // are compiled with the baseline compiler.
+    //
+    // Default: 10
+    uint32_t baselineUsesBeforeCompile;
+
+    // How many invocations or loop iterations are needed before functions
+    // are compiled.
+    //
+    // Default: 1,000
+    uint32_t usesBeforeCompile;
+
+    // How many invocations or loop iterations are needed before calls
+    // are inlined, as a fraction of usesBeforeCompile.
+    //
+    // Default: .125
+    double usesBeforeInliningFactor;
+
+    // How many times we will try to enter a script via OSR before
+    // invalidating the script.
+    //
+    // Default: 6,000
+    uint32_t osrPcMismatchesBeforeRecompile;
+
+    // Number of bailouts without invalidation before we set
+    // JSScript::hadFrequentBailouts and invalidate.
+    //
+    // Default: 10
+    uint32_t frequentBailoutThreshold;
+
+    // Number of exception bailouts (resuming into catch/finally block) before
+    // we invalidate and forbid Ion compilation.
+    //
+    // Default: 10
+    uint32_t exceptionBailoutThreshold;
+
+    // Whether Ion should compile try-catch statements.
+    //
+    // Default: true
+    bool compileTryCatch;
+
+    // How many actual arguments are accepted on the C stack.
+    //
+    // Default: 4,096
+    uint32_t maxStackArgs;
+
+    // The maximum inlining depth.
+    //
+    // Default: 3
+    uint32_t maxInlineDepth;
+
+    // The maximum inlining depth for functions.
+    //
+    // Inlining small functions has almost no compiling overhead
+    // and removes the otherwise needed call overhead.
+    // The value is currently very low.
+    // Actually it is only needed to make sure we don't blow out the stack.
+    //
+    // Default: 10
+    uint32_t smallFunctionMaxInlineDepth;
+
+    // The bytecode length limit for small function.
+    //
+    // The default for this was arrived at empirically via benchmarking.
+    // We may want to tune it further after other optimizations have gone
+    // in.
+    //
+    // Default: 100
+    uint32_t smallFunctionMaxBytecodeLength;
+
+    // The maximum number of functions to polymorphically inline at a call site.
+    //
+    // Default: 4
+    uint32_t polyInlineMax;
+
+    // The maximum total bytecode size of an inline call site.
+    //
+    // Default: 1000
+    uint32_t inlineMaxTotalBytecodeLength;
+
+    // Whether functions are compiled immediately.
+    //
+    // Default: false
+    bool eagerCompilation;
+
+    // How many uses of a parallel kernel before we attempt compilation.
+    //
+    // Default: 1
+    uint32_t usesBeforeCompilePar;
+
+    // The maximum bytecode length the caller may have,
+    // before we stop inlining large functions in that caller.
+    //
+    // Default: 10000
+    uint32_t inliningMaxCallerBytecodeLength;
+
+    void setEagerCompilation() {
+        eagerCompilation = true;
+        usesBeforeCompile = 0;
+        baselineUsesBeforeCompile = 0;
+    }
+
+    MOZ_CONSTEXPR IonOptions()
+      : gvn(true),
+        gvnIsOptimistic(true),
+        licm(true),
+        osr(true),
+        limitScriptSize(true),
+        registerAllocator(RegisterAllocator_LSRA),
+        inlining(true),
+        edgeCaseAnalysis(true),
+        rangeAnalysis(true),
+        checkRangeAnalysis(false),
+        checkThreadSafety(false),
+        checkGraphConsistency(true),
+        uce(true),
+        eaa(true),
+#ifdef CHECK_OSIPOINT_REGISTERS
+        checkOsiPointRegisters(false),
+#endif
+        baselineUsesBeforeCompile(10),
+        usesBeforeCompile(1000),
+        usesBeforeInliningFactor(.125),
+        osrPcMismatchesBeforeRecompile(6000),
+        frequentBailoutThreshold(10),
+        exceptionBailoutThreshold(10),
+        compileTryCatch(true),
+        maxStackArgs(4096),
+        maxInlineDepth(3),
+        smallFunctionMaxInlineDepth(10),
+        smallFunctionMaxBytecodeLength(100),
+        polyInlineMax(4),
+        inlineMaxTotalBytecodeLength(1000),
+        eagerCompilation(false),
+        usesBeforeCompilePar(1),
+        inliningMaxCallerBytecodeLength(10000)
+    {
+    }
+
+    uint32_t usesBeforeInlining() {
+        return usesBeforeCompile * usesBeforeInliningFactor;
+    }
+};
+
 enum MethodStatus
 {
     Method_Error,
     Method_CantCompile,
     Method_Skipped,
     Method_Compiled
 };
 
@@ -68,16 +303,18 @@ class IonContext
     int getNextAssemblerId() {
         return assemblerCount_++;
     }
   private:
     IonContext *prev_;
     int assemblerCount_;
 };
 
+extern IonOptions js_IonOptions;
+
 // Initialize Ion statically for all JSRuntimes.
 bool InitializeIon();
 
 // Get and set the current Ion context.
 IonContext *GetIonContext();
 IonContext *MaybeGetIonContext();
 
 bool SetIonContext(IonContext *ctx);
@@ -169,21 +406,22 @@ IsIonInlinablePC(jsbytecode *pc) {
     // GETPROP, CALLPROP, and LENGTH. (Inlined Getters)
     // SETPROP, SETNAME, SETGNAME (Inlined Setters)
     return IsCallPC(pc) || IsGetPropPC(pc) || IsSetPropPC(pc);
 }
 
 inline bool
 TooManyArguments(unsigned nargs)
 {
-    return (nargs >= SNAPSHOT_MAX_NARGS || nargs > js_JitOptions.maxStackArgs);
+    return (nargs >= SNAPSHOT_MAX_NARGS || nargs > js_IonOptions.maxStackArgs);
 }
 
 void ForbidCompilation(JSContext *cx, JSScript *script);
 void ForbidCompilation(JSContext *cx, JSScript *script, ExecutionMode mode);
+uint32_t UsesBeforeIonRecompile(JSScript *script, jsbytecode *pc);
 
 void PurgeCaches(JSScript *script, JS::Zone *zone);
 size_t SizeOfIonData(JSScript *script, mozilla::MallocSizeOf mallocSizeOf);
 void DestroyIonScripts(FreeOp *fop, JSScript *script);
 void TraceIonScripts(JSTracer* trc, JSScript *script);
 
 void TriggerOperationCallbackForIonCode(JSRuntime *rt, JSRuntime::OperationCallbackTrigger trigger);
 
--- a/js/src/jit/IonAnalysis.cpp
+++ b/js/src/jit/IonAnalysis.cpp
@@ -7,17 +7,16 @@
 #include "jit/IonAnalysis.h"
 
 #include "jsanalyze.h"
 
 #include "jit/BaselineInspector.h"
 #include "jit/BaselineJIT.h"
 #include "jit/Ion.h"
 #include "jit/IonBuilder.h"
-#include "jit/IonOptimizationLevels.h"
 #include "jit/LIR.h"
 #include "jit/Lowering.h"
 #include "jit/MIRGraph.h"
 
 #include "jsinferinlines.h"
 #include "jsobjinlines.h"
 
 using namespace js;
@@ -1329,32 +1328,32 @@ AssertReversePostOrder(MIRGraph &graph)
     graph.unmarkBlocks();
 }
 #endif
 
 void
 jit::AssertGraphCoherency(MIRGraph &graph)
 {
 #ifdef DEBUG
-    if (!js_JitOptions.checkGraphConsistency)
+    if (!js_IonOptions.checkGraphConsistency)
         return;
     AssertBasicGraphCoherency(graph);
     AssertReversePostOrder(graph);
 #endif
 }
 
 void
 jit::AssertExtendedGraphCoherency(MIRGraph &graph)
 {
     // Checks the basic GraphCoherency but also other conditions that
     // do not hold immediately (such as the fact that critical edges
     // are split)
 
 #ifdef DEBUG
-    if (!js_JitOptions.checkGraphConsistency)
+    if (!js_IonOptions.checkGraphConsistency)
         return;
     AssertGraphCoherency(graph);
 
     uint32_t idx = 0;
     for (MBasicBlockIterator block(graph.begin()); block != graph.end(); block++) {
         JS_ASSERT(block->id() == idx++);
 
         // No critical edges:
@@ -2154,22 +2153,20 @@ jit::AnalyzeNewScriptProperties(JSContex
 
     MIRGraph graph(&temp);
     CompileInfo info(script, fun,
                      /* osrPc = */ nullptr, /* constructing = */ false,
                      DefinitePropertiesAnalysis);
 
     AutoTempAllocatorRooter root(cx, &temp);
 
-    const OptimizationInfo *optimizationInfo = js_IonOptimizations.get(Optimization_Normal);
-
     types::CompilerConstraintList *constraints = types::NewCompilerConstraintList(temp);
     BaselineInspector inspector(script);
     IonBuilder builder(cx, CompileCompartment::get(cx->compartment()), &temp, &graph, constraints,
-                       &inspector, &info, optimizationInfo, /* baselineFrame = */ nullptr);
+                       &inspector, &info, /* baselineFrame = */ nullptr);
 
     if (!builder.build()) {
         if (builder.abortReason() == AbortReason_Alloc)
             return false;
         return true;
     }
 
     if (!SplitCriticalEdges(graph))
--- a/js/src/jit/IonBuilder.cpp
+++ b/js/src/jit/IonBuilder.cpp
@@ -13,17 +13,16 @@
 #include "builtin/Eval.h"
 #include "builtin/TypedObject.h"
 #include "builtin/TypeRepresentation.h"
 #include "frontend/SourceNotes.h"
 #include "jit/BaselineFrame.h"
 #include "jit/BaselineInspector.h"
 #include "jit/ExecutionModeInlines.h"
 #include "jit/Ion.h"
-#include "jit/IonOptimizationLevels.h"
 #include "jit/IonSpewer.h"
 #include "jit/Lowering.h"
 #include "jit/MIRGraph.h"
 
 #include "vm/ArgumentsObject.h"
 #include "vm/RegExpStatics.h"
 
 #include "jsinferinlines.h"
@@ -97,23 +96,21 @@ jit::NewBaselineFrameInspector(TempAlloc
             inspector->varTypes.infallibleAppend(types::Type::UndefinedType());
         else
             inspector->varTypes.infallibleAppend(types::GetValueType(frame->unaliasedVar(i)));
     }
 
     return inspector;
 }
 
-IonBuilder::IonBuilder(JSContext *analysisContext, CompileCompartment *comp, TempAllocator *temp,
-                       MIRGraph *graph, types::CompilerConstraintList *constraints,
-                       BaselineInspector *inspector, CompileInfo *info,
-                       const OptimizationInfo *optimizationInfo,
-                       BaselineFrameInspector *baselineFrame, size_t inliningDepth,
-                       uint32_t loopDepth)
-  : MIRGenerator(comp, temp, graph, info, optimizationInfo),
+IonBuilder::IonBuilder(JSContext *analysisContext, CompileCompartment *comp, TempAllocator *temp, MIRGraph *graph,
+                       types::CompilerConstraintList *constraints,
+                       BaselineInspector *inspector, CompileInfo *info, BaselineFrameInspector *baselineFrame,
+                       size_t inliningDepth, uint32_t loopDepth)
+  : MIRGenerator(comp, temp, graph, info),
     backgroundCodegen_(nullptr),
     analysisContext(analysisContext),
     baselineFrame_(baselineFrame),
     abortReason_(AbortReason_Disable),
     reprSetHash_(nullptr),
     constraints_(constraints),
     analysis_(*temp, info->script()),
     thisTypes(nullptr),
@@ -325,19 +322,16 @@ IonBuilder::DontInline(JSScript *targetS
     }
 
     return InliningDecision_DontInline;
 }
 
 IonBuilder::InliningDecision
 IonBuilder::canInlineTarget(JSFunction *target, CallInfo &callInfo)
 {
-    if (!optimizationInfo().inlineInterpreted())
-        return InliningDecision_DontInline;
-
     if (!target->isInterpreted())
         return DontInline(nullptr, "Non-interpreted target");
 
     // Allow constructing lazy scripts when performing the definite properties
     // analysis, as baseline has not been used to warm the caller up yet.
     if (target->isInterpreted() && info().executionMode() == DefinitePropertiesAnalysis) {
         if (!target->getOrCreateScript(analysisContext))
             return InliningDecision_Error;
@@ -604,27 +598,18 @@ IonBuilder::build()
 {
     if (!init())
         return false;
 
     setCurrentAndSpecializePhis(newBlock(pc));
     if (!current)
         return false;
 
-#ifdef DEBUG
-    if (info().executionMode() == SequentialExecution && script()->hasIonScript()) {
-        IonSpew(IonSpew_Scripts, "Recompiling script %s:%d (%p) (usecount=%d, level=%s)",
-                script()->filename(), script()->lineno(), (void *)script(),
-                (int)script()->getUseCount(), OptimizationLevelString(optimizationInfo().level()));
-    } else {
-        IonSpew(IonSpew_Scripts, "Analyzing script %s:%d (%p) (usecount=%d, level=%s)",
-                script()->filename(), script()->lineno(), (void *)script(),
-                (int)script()->getUseCount(), OptimizationLevelString(optimizationInfo().level()));
-    }
-#endif
+    IonSpew(IonSpew_Scripts, "Analyzing script %s:%d (%p) (usecount=%d)",
+            script()->filename(), script()->lineno(), (void *)script(), (int)script()->getUseCount());
 
     if (!initParameters())
         return false;
 
     // Initialize local variables.
     for (uint32_t i = 0; i < info().nlocals(); i++) {
         MConstant *undef = MConstant::New(alloc(), UndefinedValue());
         current->add(undef);
@@ -701,18 +686,16 @@ IonBuilder::build()
     }
 
     // lazyArguments should never be accessed in |argsObjAliasesFormals| scripts.
     if (info().hasArguments() && !info().argsObjAliasesFormals()) {
         lazyArguments_ = MConstant::New(alloc(), MagicValue(JS_OPTIMIZED_ARGUMENTS));
         current->add(lazyArguments_);
     }
 
-    insertRecompileCheck();
-
     if (!traverseBytecode())
         return false;
 
     if (!maybeAddOsrTypeBarriers())
         return false;
 
     if (!processIterators())
         return false;
@@ -860,18 +843,16 @@ IonBuilder::buildInline(IonBuilder *call
     // +2 for the scope chain and |this|, maybe another +1 for arguments object slot.
     JS_ASSERT(current->entryResumePoint()->numOperands() == info().totalSlots());
 
     if (script_->argumentsHasVarBinding()) {
         lazyArguments_ = MConstant::New(alloc(), MagicValue(JS_OPTIMIZED_ARGUMENTS));
         current->add(lazyArguments_);
     }
 
-    insertRecompileCheck();
-
     if (!traverseBytecode())
         return false;
 
     return true;
 }
 
 void
 IonBuilder::rewriteParameter(uint32_t slotIdx, MDefinition *param, int32_t argIndex)
@@ -2042,17 +2023,17 @@ IonBuilder::finishLoop(CFGState &state, 
     return ControlStatus_Joined;
 }
 
 IonBuilder::ControlStatus
 IonBuilder::restartLoop(CFGState state)
 {
     spew("New types at loop header, restarting loop body");
 
-    if (js_JitOptions.limitScriptSize) {
+    if (js_IonOptions.limitScriptSize) {
         if (++numLoopRestarts_ >= MAX_LOOP_RESTARTS)
             return ControlStatus_Abort;
     }
 
     MBasicBlock *header = state.loop.entry;
 
     // Remove all blocks in the loop body other than the header, which has phis
     // of the appropriate type and incoming edges to preserve.
@@ -3353,17 +3334,16 @@ IonBuilder::jsop_dup2()
 }
 
 bool
 IonBuilder::jsop_loophead(jsbytecode *pc)
 {
     assertValidLoopHeadOp(pc);
 
     current->add(MInterruptCheck::New(alloc()));
-    insertRecompileCheck();
 
     return true;
 }
 
 bool
 IonBuilder::jsop_ifeq(JSOp op)
 {
     // IFEQ always has a forward offset.
@@ -3442,17 +3422,17 @@ IonBuilder::jsop_ifeq(JSOp op)
     return true;
 }
 
 bool
 IonBuilder::jsop_try()
 {
     JS_ASSERT(JSOp(*pc) == JSOP_TRY);
 
-    if (!js_JitOptions.compileTryCatch)
+    if (!js_IonOptions.compileTryCatch)
         return abort("Try-catch support disabled");
 
     // Try-finally is not yet supported.
     if (analysis().hasTryFinally())
         return abort("Has try-finally");
 
     // Try-catch within inline frames is not yet supported.
     JS_ASSERT(script()->uninlineable() && !isInlineBuilder());
@@ -3861,19 +3841,19 @@ IonBuilder::inlineScriptedCall(CallInfo 
                                                      this->info().executionMode());
     if (!info)
         return false;
 
     MIRGraphReturns returns(alloc());
     AutoAccumulateReturns aar(graph(), returns);
 
     // Build the graph.
-    IonBuilder inlineBuilder(analysisContext, compartment, &alloc(), &graph(), constraints(),
-                             &inspector, info, &optimizationInfo(), nullptr, inliningDepth_ + 1,
-                             loopDepth_);
+    IonBuilder inlineBuilder(analysisContext, compartment,
+                             &alloc(), &graph(), constraints(), &inspector, info, nullptr,
+                             inliningDepth_ + 1, loopDepth_);
     if (!inlineBuilder.buildInline(this, outerResumePoint, callInfo)) {
         if (analysisContext && analysisContext->isExceptionPending()) {
             IonSpew(IonSpew_Abort, "Inline builder raised exception.");
             abortReason_ = AbortReason_Error;
             return false;
         }
 
         // Inlining the callee failed. Mark the callee as uninlineable only if
@@ -3975,19 +3955,29 @@ IonBuilder::patchInlinedReturns(CallInfo
             return nullptr;
         phi->addInput(rdef);
     }
 
     bottom->addPhi(phi);
     return phi;
 }
 
+static bool
+IsSmallFunction(JSScript *script)
+{
+    return script->length() <= js_IonOptions.smallFunctionMaxBytecodeLength;
+}
+
 IonBuilder::InliningDecision
 IonBuilder::makeInliningDecision(JSFunction *target, CallInfo &callInfo)
 {
+    // Only inline when inlining is enabled.
+    if (!inliningEnabled())
+        return InliningDecision_DontInline;
+
     // When there is no target, inlining is impossible.
     if (target == nullptr)
         return InliningDecision_DontInline;
 
     // Native functions provide their own detection in inlineNativeCall().
     if (target->isNative())
         return InliningDecision_Inline;
 
@@ -3997,40 +3987,40 @@ IonBuilder::makeInliningDecision(JSFunct
         return decision;
 
     // Heuristics!
     JSScript *targetScript = target->nonLazyScript();
 
     // Skip heuristics if we have an explicit hint to inline.
     if (!targetScript->shouldInline()) {
         // Cap the inlining depth.
-        if (js_JitOptions.isSmallFunction(targetScript)) {
-            if (inliningDepth_ >= optimizationInfo().smallFunctionMaxInlineDepth())
+        if (IsSmallFunction(targetScript)) {
+            if (inliningDepth_ >= js_IonOptions.smallFunctionMaxInlineDepth)
                 return DontInline(targetScript, "Vetoed: exceeding allowed inline depth");
         } else {
-            if (inliningDepth_ >= optimizationInfo().maxInlineDepth())
+            if (inliningDepth_ >= js_IonOptions.maxInlineDepth)
                 return DontInline(targetScript, "Vetoed: exceeding allowed inline depth");
 
             if (targetScript->hasLoops())
                 return DontInline(targetScript, "Vetoed: big function that contains a loop");
 
             // Caller must not be excessively large.
-            if (script()->length() >= optimizationInfo().inliningMaxCallerBytecodeLength())
+            if (script()->length() >= js_IonOptions.inliningMaxCallerBytecodeLength)
                 return DontInline(targetScript, "Vetoed: caller excessively large");
         }
 
         // Callee must not be excessively large.
         // This heuristic also applies to the callsite as a whole.
-        if (targetScript->length() > optimizationInfo().inlineMaxTotalBytecodeLength())
+        if (targetScript->length() > js_IonOptions.inlineMaxTotalBytecodeLength)
             return DontInline(targetScript, "Vetoed: callee excessively large");
 
         // Callee must have been called a few times to have somewhat stable
         // type information, except for definite properties analysis,
         // as the caller has not run yet.
-        if (targetScript->getUseCount() < optimizationInfo().usesBeforeInlining() &&
+        if (targetScript->getUseCount() < js_IonOptions.usesBeforeInlining() &&
             info().executionMode() != DefinitePropertiesAnalysis)
         {
             return DontInline(targetScript, "Vetoed: callee is insufficiently hot.");
         }
     }
 
     // TI calls ObjectStateChange to trigger invalidation of the caller.
     types::TypeObjectKey *targetType = types::TypeObjectKey::get(target);
@@ -4063,17 +4053,17 @@ IonBuilder::selectInliningTargets(Object
           case InliningDecision_Inline:
             inlineable = true;
             break;
         }
 
         // Enforce a maximum inlined bytecode limit at the callsite.
         if (inlineable && target->isInterpreted()) {
             totalSize += target->nonLazyScript()->length();
-            if (totalSize > optimizationInfo().inlineMaxTotalBytecodeLength())
+            if (totalSize > js_IonOptions.inlineMaxTotalBytecodeLength)
                 inlineable = false;
         }
 
         choiceSet.append(inlineable);
         if (inlineable)
             *numInlineable += 1;
     }
 
@@ -4157,16 +4147,19 @@ IonBuilder::inlineSingleCall(CallInfo &c
         return InliningStatus_Error;
     return InliningStatus_Inlined;
 }
 
 IonBuilder::InliningStatus
 IonBuilder::inlineCallsite(ObjectVector &targets, ObjectVector &originals,
                            bool lambda, CallInfo &callInfo)
 {
+    if (!inliningEnabled())
+        return InliningStatus_NotInlined;
+
     if (targets.length() == 0)
         return InliningStatus_NotInlined;
 
     // Is the function provided by an MGetPropertyCache?
     // If so, the cache may be movable to a fallback path, with a dispatch
     // instruction guarding on the incoming TypeObject.
     MGetPropertyCache *propCache = getInlineableGetPropertyCache(callInfo);
 
@@ -5993,44 +5986,16 @@ ClassHasResolveHook(CompileCompartment *
     }
 
     if (clasp->resolve == (JSResolveOp)fun_resolve)
         return FunctionHasResolveHook(comp->runtime()->names(), name);
 
     return true;
 }
 
-void
-IonBuilder::insertRecompileCheck()
-{
-    // PJS doesn't recompile and doesn't need recompile checks.
-    if (info().executionMode() != SequentialExecution)
-        return;
-
-    // No need for recompile checks if this is the highest optimization level.
-    OptimizationLevel curLevel = optimizationInfo().level();
-    if (js_IonOptimizations.isLastLevel(curLevel))
-        return;
-
-    // Add recompile check.
-
-    // Get the topmost builder. The topmost script will get recompiled when
-    // usecount is high enough to justify a higher optimization level.
-    IonBuilder *topBuilder = this;
-    while (topBuilder->callerBuilder_)
-        topBuilder = topBuilder->callerBuilder_;
-
-    // Add recompile check to recompile when the usecount reaches the usecount
-    // of the next optimization level.
-    OptimizationLevel nextLevel = js_IonOptimizations.nextLevel(curLevel);
-    const OptimizationInfo *info = js_IonOptimizations.get(nextLevel);
-    uint32_t useCount = info->usesBeforeCompile(topBuilder->script());
-    current->add(MRecompileCheck::New(alloc(), topBuilder->script(), useCount));
-}
-
 JSObject *
 IonBuilder::testSingletonProperty(JSObject *obj, PropertyName *name)
 {
     // We would like to completely no-op property/global accesses which can
     // produce only a particular JSObject. When indicating the access result is
     // definitely an object, type inference does not account for the
     // possibility that the property is entirely missing from the input object
     // and its prototypes (if this happens, a semantic trigger would be hit and
--- a/js/src/jit/IonBuilder.h
+++ b/js/src/jit/IonBuilder.h
@@ -8,17 +8,16 @@
 #define jit_IonBuilder_h
 
 #ifdef JS_ION
 
 // This file declares the data structures for building a MIRGraph from a
 // JSScript.
 
 #include "jit/BytecodeAnalysis.h"
-#include "jit/IonOptimizationLevels.h"
 #include "jit/MIR.h"
 #include "jit/MIRGenerator.h"
 #include "jit/MIRGraph.h"
 #include "jit/TypeRepresentationSet.h"
 
 namespace js {
 namespace jit {
 
@@ -207,36 +206,39 @@ class IonBuilder : public MIRGenerator
         static CFGState CondSwitch(IonBuilder *builder, jsbytecode *exitpc, jsbytecode *defaultTarget);
         static CFGState Label(jsbytecode *exitpc);
         static CFGState Try(jsbytecode *exitpc, MBasicBlock *successor);
     };
 
     static int CmpSuccessors(const void *a, const void *b);
 
   public:
-    IonBuilder(JSContext *analysisContext, CompileCompartment *comp, TempAllocator *temp,
-               MIRGraph *graph, types::CompilerConstraintList *constraints,
-               BaselineInspector *inspector, CompileInfo *info,
-               const OptimizationInfo *optimizationInfo, BaselineFrameInspector *baselineFrame,
+    IonBuilder(JSContext *analysisContext, CompileCompartment *comp, TempAllocator *temp, MIRGraph *graph,
+               types::CompilerConstraintList *constraints,
+               BaselineInspector *inspector, CompileInfo *info, BaselineFrameInspector *baselineFrame,
                size_t inliningDepth = 0, uint32_t loopDepth = 0);
 
     bool build();
     bool buildInline(IonBuilder *callerBuilder, MResumePoint *callerResumePoint,
                      CallInfo &callInfo);
 
   private:
     bool traverseBytecode();
     ControlStatus snoopControlFlow(JSOp op);
     bool processIterators();
     bool inspectOpcode(JSOp op);
     uint32_t readIndex(jsbytecode *pc);
     JSAtom *readAtom(jsbytecode *pc);
     bool abort(const char *message, ...);
     void spew(const char *message);
 
+    static bool inliningEnabled() {
+        return js_IonOptions.inlining;
+    }
+
     JSFunction *getSingleCallTarget(types::TemporaryTypeSet *calleeTypes);
     bool getPolyCallTargets(types::TemporaryTypeSet *calleeTypes, bool constructing,
                             ObjectVector &targets, uint32_t maxTargets, bool *gotLambda);
 
     void popCfgStack();
     DeferredEdge *filterDeadDeferredEdges(DeferredEdge *edge);
     bool processDeferredContinues(CFGState &state);
     ControlStatus processControlEnd();
@@ -318,18 +320,16 @@ class IonBuilder : public MIRGenerator
 
     // Please see the Big Honkin' Comment about how resume points work in
     // IonBuilder.cpp, near the definition for this function.
     bool resume(MInstruction *ins, jsbytecode *pc, MResumePoint::Mode mode);
     bool resumeAt(MInstruction *ins, jsbytecode *pc);
     bool resumeAfter(MInstruction *ins);
     bool maybeInsertResume();
 
-    void insertRecompileCheck();
-
     bool initParameters();
     void rewriteParameter(uint32_t slotIdx, MDefinition *param, int32_t argIndex);
     void rewriteParameters();
     bool initScopeChain(MDefinition *callee = nullptr);
     bool initArgumentsObject();
     bool pushConstant(const Value &v);
 
     MConstant *constant(const Value &v);
--- a/js/src/jit/IonCode.h
+++ b/js/src/jit/IonCode.h
@@ -9,17 +9,16 @@
 
 #include "mozilla/MemoryReporting.h"
 #include "mozilla/PodOperations.h"
 
 #include "jsinfer.h"
 #include "jstypes.h"
 
 #include "gc/Heap.h"
-#include "jit/IonOptimizationLevels.h"
 #include "jit/IonTypes.h"
 
 namespace JSC {
     class ExecutablePool;
 }
 
 namespace js {
 
@@ -257,19 +256,16 @@ struct IonScript
     uint32_t backedgeEntries_;
 
     // Number of references from invalidation records.
     size_t refcount_;
 
     // Identifier of the compilation which produced this code.
     types::RecompileInfo recompileInfo_;
 
-    // The optimization level this script was compiled in.
-    OptimizationLevel optimizationLevel_;
-
     // Number of times we tried to enter this script via OSR but failed due to
     // a LOOPENTRY pc other than osrPc_.
     uint32_t osrPcMismatchCounter_;
 
     // If non-null, the list of AsmJSModules
     // that contain an optimized call directly into this IonScript.
     Vector<DependentAsmJSModuleExit> *dependentAsmJSModules;
 
@@ -334,18 +330,17 @@ struct IonScript
     // Do not call directly, use IonScript::New. This is public for cx->new_.
     IonScript();
 
     static IonScript *New(JSContext *cx, types::RecompileInfo recompileInfo,
                           uint32_t frameLocals, uint32_t frameSize,
                           size_t snapshotsSize, size_t snapshotEntries,
                           size_t constants, size_t safepointIndexEntries, size_t osiIndexEntries,
                           size_t cacheEntries, size_t runtimeSize, size_t safepointsSize,
-                          size_t callTargetEntries, size_t backedgeEntries,
-                          OptimizationLevel optimizationLevel);
+                          size_t callTargetEntries, size_t backedgeEntries);
     static void Trace(JSTracer *trc, IonScript *script);
     static void Destroy(FreeOp *fop, IonScript *script);
 
     static inline size_t offsetOfMethod() {
         return offsetof(IonScript, method_);
     }
     static inline size_t offsetOfOsrEntryOffset() {
         return offsetof(IonScript, osrEntryOffset_);
@@ -526,19 +521,16 @@ struct IonScript
         JS_ASSERT(refcount_);
         refcount_--;
         if (!refcount_)
             Destroy(fop, this);
     }
     const types::RecompileInfo& recompileInfo() const {
         return recompileInfo_;
     }
-    OptimizationLevel optimizationLevel() const {
-        return optimizationLevel_;
-    }
     uint32_t incrOsrPcMismatchCounter() {
         return ++osrPcMismatchCounter_;
     }
     void resetOsrPcMismatchCounter() {
         osrPcMismatchCounter_ = 0;
     }
 
     void setRecompiling() {
--- a/js/src/jit/IonFrames.cpp
+++ b/js/src/jit/IonFrames.cpp
@@ -1056,17 +1056,17 @@ MarkIonExitFrame(JSTracer *trc, const Io
         }
     }
 }
 
 static void
 MarkJitActivation(JSTracer *trc, const JitActivationIterator &activations)
 {
 #ifdef CHECK_OSIPOINT_REGISTERS
-    if (js_JitOptions.checkOsiPointRegisters) {
+    if (js_IonOptions.checkOsiPointRegisters) {
         // GC can modify spilled registers, breaking our register checks.
         // To handle this, we disable these checks for the current VM call
         // when a GC happens.
         JitActivation *activation = activations.activation()->asJit();
         activation->setCheckRegs(false);
     }
 #endif
 
deleted file mode 100644
--- a/js/src/jit/IonOptimizationLevels.cpp
+++ /dev/null
@@ -1,142 +0,0 @@
-/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
- * 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/. */
-
-#include "jit/IonOptimizationLevels.h"
-
-#include "jsanalyze.h"
-#include "jsscript.h"
-
-using namespace js;
-using namespace js::jit;
-
-namespace js {
-namespace jit {
-
-OptimizationInfos js_IonOptimizations;
-
-void
-OptimizationInfo::initNormalOptimizationInfo()
-{
-    level_ = Optimization_Normal;
-
-    eaa_ = true;
-    edgeCaseAnalysis_ = true;
-    eliminateRedundantChecks_ = true;
-    inlineInterpreted_ = true;
-    inlineNative_ = true;
-    gvn_ = true;
-    gvnKind_ = GVN_Optimistic;
-    licm_ = true;
-    uce_ = true;
-    rangeAnalysis_ = true;
-    registerAllocator_ = RegisterAllocator_LSRA;
-
-    inlineMaxTotalBytecodeLength_ = 1000;
-    inliningMaxCallerBytecodeLength_ = 10000;
-    maxInlineDepth_ = 3;
-    smallFunctionMaxInlineDepth_ = 10;
-    usesBeforeCompile_ = 1000;
-    usesBeforeInliningFactor_ = 0.125;
-}
-
-void
-OptimizationInfo::initAsmjsOptimizationInfo()
-{
-    // The AsmJS optimization level
-    // Disables some passes that don't work well with asmjs.
-
-    // Take normal option values for not specified values.
-    initNormalOptimizationInfo();
-
-    level_ = Optimization_AsmJS;
-    edgeCaseAnalysis_ = false;
-    eliminateRedundantChecks_ = false;
-}
-
-uint32_t
-OptimizationInfo::usesBeforeCompile(JSScript *script, jsbytecode *pc) const
-{
-    JS_ASSERT(pc == nullptr || pc == script->code() || JSOp(*pc) == JSOP_LOOPENTRY);
-
-    if (pc == script->code())
-        pc = nullptr;
-
-    uint32_t minUses = usesBeforeCompile_;
-    if (js_JitOptions.forceDefaultIonUsesBeforeCompile)
-        minUses = js_JitOptions.forcedDefaultIonUsesBeforeCompile;
-
-    // If the script is too large to compile on the main thread, we can still
-    // compile it off thread. In these cases, increase the use count threshold
-    // to improve the compilation's type information and hopefully avoid later
-    // recompilation.
-
-    if (script->length() > MAX_MAIN_THREAD_SCRIPT_SIZE)
-        minUses = minUses * (script->length() / (double) MAX_MAIN_THREAD_SCRIPT_SIZE);
-
-    uint32_t numLocalsAndArgs = analyze::TotalSlots(script);
-    if (numLocalsAndArgs > MAX_MAIN_THREAD_LOCALS_AND_ARGS)
-        minUses = minUses * (numLocalsAndArgs / (double) MAX_MAIN_THREAD_LOCALS_AND_ARGS);
-
-    if (!pc || js_JitOptions.eagerCompilation)
-        return minUses;
-
-    // It's more efficient to enter outer loops, rather than inner loops, via OSR.
-    // To accomplish this, we use a slightly higher threshold for inner loops.
-    // Note that the loop depth is always > 0 so we will prefer non-OSR over OSR.
-    uint32_t loopDepth = GET_UINT8(pc);
-    JS_ASSERT(loopDepth > 0);
-    return minUses + loopDepth * 100;
-}
-
-OptimizationInfos::OptimizationInfos()
-{
-    infos_[Optimization_Normal - 1].initNormalOptimizationInfo();
-    infos_[Optimization_AsmJS - 1].initAsmjsOptimizationInfo();
-}
-
-OptimizationLevel
-OptimizationInfos::nextLevel(OptimizationLevel level) const
-{
-    JS_ASSERT(!isLastLevel(level));
-    switch (level) {
-      case Optimization_DontCompile:
-        return Optimization_Normal;
-      default:
-        MOZ_ASSUME_UNREACHABLE("Unknown optimization level.");
-    }
-}
-
-OptimizationLevel
-OptimizationInfos::firstLevel() const
-{
-    return nextLevel(Optimization_DontCompile);
-}
-
-bool
-OptimizationInfos::isLastLevel(OptimizationLevel level) const
-{
-    return level == Optimization_Normal;
-}
-
-OptimizationLevel
-OptimizationInfos::levelForScript(JSScript *script, jsbytecode *pc) const
-{
-    OptimizationLevel prev = Optimization_DontCompile;
-
-    while (!isLastLevel(prev)) {
-        OptimizationLevel level = nextLevel(prev);
-        const OptimizationInfo *info = get(level);
-        if (script->getUseCount() < info->usesBeforeCompile(script, pc))
-            return prev;
-
-        prev = level;
-    }
-
-    return prev;
-}
-
-} // namespace jit
-} // namespace js
deleted file mode 100644
--- a/js/src/jit/IonOptimizationLevels.h
+++ /dev/null
@@ -1,220 +0,0 @@
-/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
- * 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_IonOptimizationLevels_h
-#define jit_IonOptimizationLevels_h
-
-#include "jsbytecode.h"
-#include "jstypes.h"
-
-#include "jit/JitOptions.h"
-#include "js/TypeDecls.h"
-
-namespace js {
-namespace jit {
-
-enum OptimizationLevel
-{
-    Optimization_DontCompile,
-    Optimization_Normal,
-    Optimization_AsmJS,
-    Optimization_Count
-};
-
-#ifdef DEBUG
-inline const char *
-OptimizationLevelString(OptimizationLevel level)
-{
-    switch (level) {
-      case Optimization_DontCompile:
-        return "Optimization_DontCompile";
-      case Optimization_Normal:
-        return "Optimization_Normal";
-      case Optimization_AsmJS:
-        return "Optimization_AsmJS";
-      default:
-        MOZ_ASSUME_UNREACHABLE("Invalid OptimizationLevel");
-    }
-}
-#endif
-
-class OptimizationInfo
-{
-  public:
-    OptimizationLevel level_;
-
-    // Toggles whether Effective Address Analysis is performed.
-    bool eaa_;
-
-    // Toggles whether Edge Case Analysis is used.
-    bool edgeCaseAnalysis_;
-
-    // Toggles whether redundant checks get removed.
-    bool eliminateRedundantChecks_;
-
-    // Toggles whether interpreted scripts get inlined.
-    bool inlineInterpreted_;
-
-    // Toggles whether native scripts get inlined.
-    bool inlineNative_;
-
-    // Toggles whether global value numbering is used.
-    bool gvn_;
-
-    // Toggles whether global value numbering is optimistic or pessimistic.
-    IonGvnKind gvnKind_;
-
-    // Toggles whether loop invariant code motion is performed.
-    bool licm_;
-
-    // Toggles whether Unreachable Code Elimination is performed.
-    bool uce_;
-
-    // Toggles whether Range Analysis is used.
-    bool rangeAnalysis_;
-
-    // Describes which register allocator to use.
-    IonRegisterAllocator registerAllocator_;
-
-    // The maximum total bytecode size of an inline call site.
-    uint32_t inlineMaxTotalBytecodeLength_;
-
-    // The maximum bytecode length the caller may have,
-    // before we stop inlining large functions in that caller.
-    uint32_t inliningMaxCallerBytecodeLength_;
-
-    // The maximum inlining depth.
-    uint32_t maxInlineDepth_;
-
-    // The maximum inlining depth for functions.
-    //
-    // Inlining small functions has almost no compiling overhead
-    // and removes the otherwise needed call overhead.
-    // The value is currently very low.
-    // Actually it is only needed to make sure we don't blow out the stack.
-    uint32_t smallFunctionMaxInlineDepth_;
-
-    // How many invocations or loop iterations are needed before functions
-    // are compiled.
-    uint32_t usesBeforeCompile_;
-
-    // How many invocations or loop iterations are needed before calls
-    // are inlined, as a fraction of usesBeforeCompile.
-    double usesBeforeInliningFactor_;
-
-    OptimizationInfo()
-    { }
-
-    void initNormalOptimizationInfo();
-    void initAsmjsOptimizationInfo();
-
-    OptimizationLevel level() const {
-        return level_;
-    }
-
-    bool inlineInterpreted() const {
-        return inlineInterpreted_ && !js_JitOptions.disableInlining;
-    }
-
-    bool inlineNative() const {
-        return inlineNative_ && !js_JitOptions.disableInlining;
-    }
-
-    uint32_t usesBeforeCompile(JSScript *script, jsbytecode *pc = nullptr) const;
-
-    bool gvnEnabled() const {
-        return gvn_ && !js_JitOptions.disableGvn;
-    }
-
-    bool licmEnabled() const {
-        return licm_ && !js_JitOptions.disableLicm;
-    }
-
-    bool uceEnabled() const {
-        return uce_ && !js_JitOptions.disableUce;
-    }
-
-    bool rangeAnalysisEnabled() const {
-        return rangeAnalysis_ && !js_JitOptions.disableRangeAnalysis;
-    }
-
-    bool eaaEnabled() const {
-        return eaa_ && !js_JitOptions.disableEaa;
-    }
-
-    bool edgeCaseAnalysisEnabled() const {
-        return edgeCaseAnalysis_ && !js_JitOptions.disableEdgeCaseAnalysis;
-    }
-
-    bool eliminateRedundantChecksEnabled() const {
-        return eliminateRedundantChecks_;
-    }
-
-    IonGvnKind gvnKind() const {
-        if (!js_JitOptions.forceGvnKind)
-            return gvnKind_;
-        return js_JitOptions.forcedGvnKind;
-    }
-
-    IonRegisterAllocator registerAllocator() const {
-        if (!js_JitOptions.forceRegisterAllocator)
-            return registerAllocator_;
-        return js_JitOptions.forcedRegisterAllocator;
-    }
-
-    uint32_t smallFunctionMaxInlineDepth() const {
-        return smallFunctionMaxInlineDepth_;
-    }
-
-    bool isSmallFunction(JSScript *script) const;
-
-    uint32_t maxInlineDepth() const {
-        return maxInlineDepth_;
-    }
-
-    uint32_t inlineMaxTotalBytecodeLength() const {
-        return inlineMaxTotalBytecodeLength_;
-    }
-
-    uint32_t inliningMaxCallerBytecodeLength() const {
-        return inlineMaxTotalBytecodeLength_;
-    }
-
-    uint32_t usesBeforeInlining() const {
-        uint32_t usesBeforeCompile = usesBeforeCompile_;
-        if (js_JitOptions.forceDefaultIonUsesBeforeCompile)
-            usesBeforeCompile = js_JitOptions.forcedDefaultIonUsesBeforeCompile;
-        return usesBeforeCompile * usesBeforeInliningFactor_;
-    }
-};
-
-class OptimizationInfos
-{
-  private:
-    OptimizationInfo infos_[Optimization_Count - 1];
-
-  public:
-    OptimizationInfos();
-
-    const OptimizationInfo *get(OptimizationLevel level) const {
-        JS_ASSERT(level < Optimization_Count);
-        JS_ASSERT(level != Optimization_DontCompile);
-
-        return &infos_[level - 1];
-    }
-
-    OptimizationLevel nextLevel(OptimizationLevel level) const;
-    OptimizationLevel firstLevel() const;
-    bool isLastLevel(OptimizationLevel level) const;
-    OptimizationLevel levelForScript(JSScript *script, jsbytecode *pc = nullptr) const;
-};
-
-extern OptimizationInfos js_IonOptimizations;
-
-} // namespace jit
-} // namespace js
-
-#endif /* jit_IonOptimizationLevels_h */
deleted file mode 100644
--- a/js/src/jit/JitOptions.cpp
+++ /dev/null
@@ -1,162 +0,0 @@
-/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
- * 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/. */
-
-#include "jit/JitOptions.h"
-
-#include "jsscript.h"
-
-using namespace js;
-using namespace js::jit;
-
-namespace js {
-namespace jit {
-
-JitOptions js_JitOptions;
-
-JitOptions::JitOptions()
-{
-    // Whether to perform expensive graph-consistency DEBUG-only assertions.
-    // It can be useful to disable this to reduce DEBUG-compile time of large
-    // asm.js programs.
-    checkGraphConsistency = true;
-
-#ifdef CHECK_OSIPOINT_REGISTERS
-    // Emit extra code to verify live regs at the start of a VM call
-    // are not modified before its OsiPoint.
-    checkOsiPointRegisters = false;
-#endif
-
-    // Whether to enable extra code to perform dynamic validation of
-    // RangeAnalysis results.
-    checkRangeAnalysis = false;
-
-    // Whether to protect the GC heap during Ion compilation and ensure that
-    // only threadsafe operations are performed on it.
-    checkThreadSafety = false;
-
-    // Whether Ion should compile try-catch statements.
-    compileTryCatch = true;
-
-    // Toggle whether global value numbering is globally disabled.
-    disableGvn = false;
-
-    // Toggles whether loop invariant code motion is globally disabled.
-    disableLicm = false;
-
-    // Toggles whether inlining is globally disabled.
-    disableInlining = false;
-
-    // Toggles whether Edge Case Analysis is gobally disabled.
-    disableEdgeCaseAnalysis = false;
-
-    // Toggles whether Range Analysis is globally disabled.
-    disableRangeAnalysis = false;
-
-    // Toggles whether Unreachable Code Elimination is globally disabled.
-    disableUce = false;
-
-    // Toggles whether Effective Address Analysis is globally disabled.
-    disableEaa = false;
-
-    // Whether functions are compiled immediately.
-    eagerCompilation = false;
-
-    // Force how many invocation or loop iterations are needed before compiling
-    // a function with the highest ionmonkey optimization level.
-    // (i.e. OptimizationLevel_Normal)
-    forceDefaultIonUsesBeforeCompile = false;
-    forcedDefaultIonUsesBeforeCompile = 1000;
-
-    // Force the GVN kind to be optimistic or pessimistic instead of letting
-    // the optimization pass decide.
-    forceGvnKind = false;
-    forcedGvnKind = GVN_Optimistic;
-
-    // Force the used register allocator instead of letting the
-    // optimization pass decide.
-    forceRegisterAllocator = false;
-    forcedRegisterAllocator = RegisterAllocator_LSRA;
-
-    // Toggles whether large scripts are rejected.
-    limitScriptSize = true;
-
-    // Toggles whether functions may be entered at loop headers.
-    osr = true;
-
-    // How many invocations or loop iterations are needed before functions
-    // are compiled with the baseline compiler.
-    baselineUsesBeforeCompile = 10;
-
-    // Number of exception bailouts (resuming into catch/finally block) before
-    // we invalidate and forbid Ion compilation.
-    exceptionBailoutThreshold = 10;
-
-    // Number of bailouts without invalidation before we set
-    // JSScript::hadFrequentBailouts and invalidate.
-    frequentBailoutThreshold = 10;
-
-    // How many actual arguments are accepted on the C stack.
-    maxStackArgs = 4096;
-
-    // How many times we will try to enter a script via OSR before
-    // invalidating the script.
-    osrPcMismatchesBeforeRecompile = 6000;
-
-    // The bytecode length limit for small function.
-    //
-    // The default for this was arrived at empirically via benchmarking.
-    // We may want to tune it further after other optimizations have gone
-    // in.
-    smallFunctionMaxBytecodeLength_ = 100;
-
-    // How many uses of a parallel kernel before we attempt compilation.
-    usesBeforeCompilePar = 1;
-}
-
-bool
-JitOptions::isSmallFunction(JSScript *script) const
-{
-    return script->length() <= smallFunctionMaxBytecodeLength_;
-}
-
-void
-JitOptions::setEagerCompilation()
-{
-    eagerCompilation = true;
-    baselineUsesBeforeCompile = 0;
-    forceDefaultIonUsesBeforeCompile = true;
-    forcedDefaultIonUsesBeforeCompile = 0;
-}
-
-void
-JitOptions::setUsesBeforeCompile(uint32_t useCount)
-{
-    forceDefaultIonUsesBeforeCompile = true;
-    forcedDefaultIonUsesBeforeCompile = useCount;
-
-    // Undo eager compilation
-    if (eagerCompilation && useCount != 0) {
-        jit::JitOptions defaultValues;
-        eagerCompilation = false;
-        baselineUsesBeforeCompile = defaultValues.baselineUsesBeforeCompile;
-    }
-}
-
-void
-JitOptions::resetUsesBeforeCompile()
-{
-    forceDefaultIonUsesBeforeCompile = false;
-
-    // Undo eager compilation
-    if (eagerCompilation) {
-        jit::JitOptions defaultValues;
-        eagerCompilation = false;
-        baselineUsesBeforeCompile = defaultValues.baselineUsesBeforeCompile;
-    }
-}
-
-} // namespace jit
-} // namespace js
deleted file mode 100644
--- a/js/src/jit/JitOptions.h
+++ /dev/null
@@ -1,88 +0,0 @@
-/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
- * 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_JitOptions_h
-#define jit_JitOptions_h
-
-#include "jit/IonTypes.h"
-#include "js/TypeDecls.h"
-
-#ifdef JS_ION
-
-namespace js {
-namespace jit {
-
-// Longer scripts can only be compiled off thread, as these compilations
-// can be expensive and stall the main thread for too long.
-static const uint32_t MAX_OFF_THREAD_SCRIPT_SIZE = 100 * 1000;
-static const uint32_t MAX_MAIN_THREAD_SCRIPT_SIZE = 2 * 1000;
-static const uint32_t MAX_MAIN_THREAD_LOCALS_AND_ARGS = 256;
-
-// DOM Worker runtimes don't have off thread compilation, but can also compile
-// larger scripts since this doesn't stall the main thread.
-static const uint32_t MAX_DOM_WORKER_SCRIPT_SIZE = 16 * 1000;
-static const uint32_t MAX_DOM_WORKER_LOCALS_AND_ARGS = 2048;
-
-// Possible register allocators which may be used.
-enum IonRegisterAllocator {
-    RegisterAllocator_LSRA,
-    RegisterAllocator_Backtracking,
-    RegisterAllocator_Stupid
-};
-
-enum IonGvnKind {
-    GVN_Optimistic,
-    GVN_Pessimistic
-};
-
-struct JitOptions
-{
-    bool checkGraphConsistency;
-#ifdef CHECK_OSIPOINT_REGISTERS
-    bool checkOsiPointRegisters;
-#endif
-    bool checkRangeAnalysis;
-    bool checkThreadSafety;
-    bool compileTryCatch;
-    bool disableGvn;
-    bool disableLicm;
-    bool disableInlining;
-    bool disableEdgeCaseAnalysis;
-    bool disableRangeAnalysis;
-    bool disableUce;
-    bool disableEaa;
-    bool eagerCompilation;
-    bool forceDefaultIonUsesBeforeCompile;
-    uint32_t forcedDefaultIonUsesBeforeCompile;
-    bool forceGvnKind;
-    IonGvnKind forcedGvnKind;
-    bool forceRegisterAllocator;
-    IonRegisterAllocator forcedRegisterAllocator;
-    bool limitScriptSize;
-    bool osr;
-    uint32_t baselineUsesBeforeCompile;
-    uint32_t exceptionBailoutThreshold;
-    uint32_t frequentBailoutThreshold;
-    uint32_t maxStackArgs;
-    uint32_t osrPcMismatchesBeforeRecompile;
-    uint32_t smallFunctionMaxBytecodeLength_;
-    uint32_t usesBeforeCompilePar;
-
-    JitOptions();
-    bool isSmallFunction(JSScript *script) const;
-    void setEagerCompilation();
-    void setUsesBeforeCompile(uint32_t useCount);
-    void resetUsesBeforeCompile();
-};
-
-extern JitOptions js_JitOptions;
-
-} // namespace jit
-} // namespace js
-
-#endif // JS_ION
-
-#endif /* jit_JitOptions_h */
--- a/js/src/jit/LIR-Common.h
+++ b/js/src/jit/LIR-Common.h
@@ -5763,29 +5763,12 @@ class LAssertRangeV : public LInstructio
     MAssertRange *mir() {
         return mir_->toAssertRange();
     }
     const Range *range() {
         return mir()->assertedRange();
     }
 };
 
-class LRecompileCheck : public LInstructionHelper<0, 0, 1>
-{
-  public:
-    LIR_HEADER(RecompileCheck)
-
-    LRecompileCheck(const LDefinition &scratch) {
-        setTemp(0, scratch);
-    }
-
-    const LDefinition *scratch() {
-        return getTemp(0);
-    }
-    MRecompileCheck *mir() {
-        return mir_->toRecompileCheck();
-    }
-};
-
 } // namespace jit
 } // namespace js
 
 #endif /* jit_LIR_Common_h */
--- a/js/src/jit/LOpcodes.h
+++ b/js/src/jit/LOpcodes.h
@@ -275,17 +275,16 @@
     _(AsmJSLoadFFIFunc)             \
     _(AsmJSParameter)               \
     _(AsmJSReturn)                  \
     _(AsmJSVoidReturn)              \
     _(AsmJSPassStackArg)            \
     _(AsmJSCall)                    \
     _(AsmJSCheckOverRecursed)       \
     _(CheckInterruptPar)            \
-    _(RecompileCheck)               \
     _(AssertRangeI)                 \
     _(AssertRangeD)                 \
     _(AssertRangeF)                 \
     _(AssertRangeV)
 
 #if defined(JS_CPU_X86)
 # include "jit/x86/LOpcodes-x86.h"
 #elif defined(JS_CPU_X64)
--- a/js/src/jit/LinearScan.cpp
+++ b/js/src/jit/LinearScan.cpp
@@ -1123,17 +1123,17 @@ LinearScanAllocator::canCoexist(LiveInte
  * Ensure intervals appear in exactly the appropriate one of {active,inactive,
  * handled}, and that active and inactive intervals do not conflict. Handled
  * intervals are checked for conflicts in validateAllocations for performance
  * reasons.
  */
 void
 LinearScanAllocator::validateIntervals()
 {
-    if (!js_JitOptions.checkGraphConsistency)
+    if (!js_IonOptions.checkGraphConsistency)
         return;
 
     for (IntervalIterator i(active.begin()); i != active.end(); i++) {
         JS_ASSERT(i->numRanges() > 0);
         JS_ASSERT(i->covers(current->start()));
 
         for (IntervalIterator j(active.begin()); j != i; j++)
             JS_ASSERT(canCoexist(*i, *j));
@@ -1169,17 +1169,17 @@ LinearScanAllocator::validateIntervals()
 
 /*
  * This function performs a nice, expensive check that all intervals
  * in the function can coexist with every other interval.
  */
 void
 LinearScanAllocator::validateAllocations()
 {
-    if (!js_JitOptions.checkGraphConsistency)
+    if (!js_IonOptions.checkGraphConsistency)
         return;
 
     for (IntervalIterator i(handled.begin()); i != handled.end(); i++) {
         for (IntervalIterator j(handled.begin()); j != i; j++) {
             JS_ASSERT(*i != *j);
             JS_ASSERT(canCoexist(*i, *j));
         }
         LinearScanVirtualRegister *reg = &vregs[i->vreg()];
--- a/js/src/jit/LiveRangeAllocator.h
+++ b/js/src/jit/LiveRangeAllocator.h
@@ -595,17 +595,17 @@ class LiveRangeAllocator : protected Reg
         if (!fixedIntervals[reg.code()]->addRangeAtHead(from, to))
             return false;
         return fixedIntervalsUnion->addRangeAtHead(from, to);
     }
 
     void validateVirtualRegisters()
     {
 #ifdef DEBUG
-        if (!js_JitOptions.checkGraphConsistency)
+        if (!js_IonOptions.checkGraphConsistency)
             return;
 
         for (size_t i = 1; i < graph.numVirtualRegisters(); i++) {
             VirtualRegister *reg = &vregs[i];
 
             LiveInterval *prev = nullptr;
             for (size_t j = 0; j < reg->numIntervals(); j++) {
                 LiveInterval *interval = reg->getInterval(j);
--- a/js/src/jit/Lowering.cpp
+++ b/js/src/jit/Lowering.cpp
@@ -518,17 +518,17 @@ bool
 LIRGenerator::visitAssertFloat32(MAssertFloat32 *assertion)
 {
     MIRType type = assertion->input()->type();
     DebugOnly<bool> checkIsFloat32 = assertion->mustBeFloat32();
 
     if (!allowFloat32Optimizations())
         return true;
 
-    if (type != MIRType_Value && !js_JitOptions.eagerCompilation) {
+    if (type != MIRType_Value && !js_IonOptions.eagerCompilation) {
         JS_ASSERT_IF(checkIsFloat32, type == MIRType_Float32);
         JS_ASSERT_IF(!checkIsFloat32, type != MIRType_Float32);
     }
     return true;
 }
 
 bool
 LIRGenerator::visitGetDynamicName(MGetDynamicName *ins)
@@ -3416,25 +3416,16 @@ LIRGenerator::visitGetDOMMember(MGetDOMM
     MOZ_ASSERT(ins->isDomMovable(), "Members had better be movable");
     MOZ_ASSERT(ins->domAliasSet() == JSJitInfo::AliasNone,
                "Members had better not alias anything");
     LGetDOMMember *lir =
         new(alloc()) LGetDOMMember(useRegister(ins->object()));
     return defineBox(lir, ins);
 }
 
-bool
-LIRGenerator::visitRecompileCheck(MRecompileCheck *ins)
-{
-    LRecompileCheck *lir = new(alloc()) LRecompileCheck(temp());
-    if (!add(lir, ins))
-        return false;
-    return assignSafepoint(lir, ins);
-}
-
 static void
 SpewResumePoint(MBasicBlock *block, MInstruction *ins, MResumePoint *resumePoint)
 {
     fprintf(IonSpewFile, "Current resume point %p details:\n", (void *)resumePoint);
     fprintf(IonSpewFile, "    frame count: %u\n", resumePoint->frameCount());
 
     if (ins) {
         fprintf(IonSpewFile, "    taken after: ");
@@ -3545,17 +3536,17 @@ bool
 LIRGenerator::visitBlock(MBasicBlock *block)
 {
     current = block->lir();
     updateResumeState(block);
 
     if (!definePhis())
         return false;
 
-    if (gen->optimizationInfo().registerAllocator() == RegisterAllocator_LSRA) {
+    if (js_IonOptions.registerAllocator == RegisterAllocator_LSRA) {
         if (!add(new(alloc()) LLabel()))
             return false;
     }
 
     for (MInstructionIterator iter = block->begin(); *iter != block->lastIns(); iter++) {
         if (!visitInstruction(*iter))
             return false;
     }
--- a/js/src/jit/Lowering.h
+++ b/js/src/jit/Lowering.h
@@ -256,15 +256,14 @@ class LIRGenerator : public LIRGenerator
     bool visitAsmJSReturn(MAsmJSReturn *ins);
     bool visitAsmJSVoidReturn(MAsmJSVoidReturn *ins);
     bool visitAsmJSPassStackArg(MAsmJSPassStackArg *ins);
     bool visitAsmJSCall(MAsmJSCall *ins);
     bool visitAsmJSCheckOverRecursed(MAsmJSCheckOverRecursed *ins);
     bool visitSetDOMProperty(MSetDOMProperty *ins);
     bool visitGetDOMProperty(MGetDOMProperty *ins);
     bool visitGetDOMMember(MGetDOMMember *ins);
-    bool visitRecompileCheck(MRecompileCheck *ins);
 };
 
 } // namespace jit
 } // namespace js
 
 #endif /* jit_Lowering_h */
--- a/js/src/jit/MCallOptimize.cpp
+++ b/js/src/jit/MCallOptimize.cpp
@@ -19,19 +19,16 @@
 #include "vm/StringObject-inl.h"
 
 namespace js {
 namespace jit {
 
 IonBuilder::InliningStatus
 IonBuilder::inlineNativeCall(CallInfo &callInfo, JSNative native)
 {
-    if (!optimizationInfo().inlineNative())
-        return InliningStatus_NotInlined;
-
     // Array natives.
     if (native == js_Array)
         return inlineArray(callInfo);
     if (native == js::array_pop)
         return inlineArrayPopShift(callInfo, MArrayPopShift::Pop);
     if (native == js::array_shift)
         return inlineArrayPopShift(callInfo, MArrayPopShift::Shift);
     if (native == js::array_push)
--- a/js/src/jit/MIR.h
+++ b/js/src/jit/MIR.h
@@ -9199,51 +9199,16 @@ class MHaveSameClass
     TypePolicy *typePolicy() {
         return this;
     }
     AliasSet getAliasSet() const {
         return AliasSet::None();
     }
 };
 
-// Increase the usecount of the provided script upon execution and test if
-// the usecount surpasses the threshold. Upon hit it will recompile the
-// outermost script (i.e. not the inlined script).
-class MRecompileCheck : public MNullaryInstruction
-{
-    JSScript *script_;
-    uint32_t recompileThreshold_;
-
-    MRecompileCheck(JSScript *script, uint32_t recompileThreshold)
-      : script_(script),
-        recompileThreshold_(recompileThreshold)
-    {
-        setGuard();
-    }
-
-  public:
-    INSTRUCTION_HEADER(RecompileCheck);
-
-    static MRecompileCheck *New(TempAllocator &alloc, JSScript *script_, uint32_t useCount) {
-        return new(alloc) MRecompileCheck(script_, useCount);
-    }
-
-    JSScript *script() const {
-        return script_;
-    }
-
-    uint32_t recompileThreshold() const {
-        return recompileThreshold_;
-    }
-
-    AliasSet getAliasSet() const {
-        return AliasSet::None();
-    }
-};
-
 class MAsmJSNeg : public MUnaryInstruction
 {
     MAsmJSNeg(MDefinition *op, MIRType type)
       : MUnaryInstruction(op)
     {
         setResultType(type);
         setMovable();
     }
--- a/js/src/jit/MIRGenerator.h
+++ b/js/src/jit/MIRGenerator.h
@@ -24,42 +24,37 @@
 #include "jit/RegisterSets.h"
 
 namespace js {
 namespace jit {
 
 class MBasicBlock;
 class MIRGraph;
 class MStart;
-class OptimizationInfo;
 
 class MIRGenerator
 {
   public:
-    MIRGenerator(CompileCompartment *compartment, TempAllocator *alloc, MIRGraph *graph,
-                 CompileInfo *info, const OptimizationInfo *optimizationInfo);
+    MIRGenerator(CompileCompartment *compartment, TempAllocator *alloc, MIRGraph *graph, CompileInfo *info);
 
     TempAllocator &alloc() {
         return *alloc_;
     }
     MIRGraph &graph() {
         return *graph_;
     }
     bool ensureBallast() {
         return alloc().ensureBallast();
     }
     const JitRuntime *jitRuntime() const {
         return GetIonContext()->runtime->jitRuntime();
     }
     CompileInfo &info() {
         return *info_;
     }
-    const OptimizationInfo &optimizationInfo() const {
-        return *optimizationInfo_;
-    }
 
     template <typename T>
     T * allocate(size_t count = 1) {
         return reinterpret_cast<T *>(alloc().allocate(sizeof(T) * count));
     }
 
     // Set an error state and prints a message. Returns false so errors can be
     // propagated up.
@@ -127,17 +122,16 @@ class MIRGenerator
         return asmJSGlobalAccesses_;
     }
 
   public:
     CompileCompartment *compartment;
 
   protected:
     CompileInfo *info_;
-    const OptimizationInfo *optimizationInfo_;
     TempAllocator *alloc_;
     JSFunction *fun_;
     uint32_t nslots_;
     MIRGraph *graph_;
     bool error_;
     size_t cancelBuild_;
 
     uint32_t maxAsmJSStackArgBytes_;
--- a/js/src/jit/MIRGraph.cpp
+++ b/js/src/jit/MIRGraph.cpp
@@ -12,21 +12,19 @@
 #include "jit/IonSpewer.h"
 #include "jit/MIR.h"
 #include "jit/MIRGenerator.h"
 
 using namespace js;
 using namespace js::jit;
 
 MIRGenerator::MIRGenerator(CompileCompartment *compartment,
-                           TempAllocator *alloc, MIRGraph *graph, CompileInfo *info,
-                           const OptimizationInfo *optimizationInfo)
+                           TempAllocator *alloc, MIRGraph *graph, CompileInfo *info)
   : compartment(compartment),
     info_(info),
-    optimizationInfo_(optimizationInfo),
     alloc_(alloc),
     graph_(graph),
     error_(false),
     cancelBuild_(0),
     maxAsmJSStackArgBytes_(0),
     performsAsmJSCall_(false),
     asmJSHeapAccesses_(*alloc),
     asmJSGlobalAccesses_(*alloc),
--- a/js/src/jit/MOpcodes.h
+++ b/js/src/jit/MOpcodes.h
@@ -206,18 +206,17 @@ namespace jit {
     _(NewPar)                                                               \
     _(NewDenseArrayPar)                                                     \
     _(NewDerivedTypedObject)                                                \
     _(AbortPar)                                                             \
     _(LambdaPar)                                                            \
     _(RestPar)                                                              \
     _(ForkJoinSlice)                                                        \
     _(GuardThreadLocalObject)                                               \
-    _(CheckInterruptPar)                                                    \
-    _(RecompileCheck)
+    _(CheckInterruptPar)
 
 // Forward declarations of MIR types.
 #define FORWARD_DECLARE(op) class M##op;
  MIR_OPCODE_LIST(FORWARD_DECLARE)
 #undef FORWARD_DECLARE
 
 class MInstructionVisitor // interface i.e. pure abstract class
 {
--- a/js/src/jit/ParallelSafetyAnalysis.cpp
+++ b/js/src/jit/ParallelSafetyAnalysis.cpp
@@ -306,17 +306,16 @@ class ParallelSafetyVisitor : public MIn
     UNSAFE_OP(AsmJSLoadFuncPtr)
     UNSAFE_OP(AsmJSLoadFFIFunc)
     UNSAFE_OP(AsmJSReturn)
     UNSAFE_OP(AsmJSVoidReturn)
     UNSAFE_OP(AsmJSPassStackArg)
     UNSAFE_OP(AsmJSParameter)
     UNSAFE_OP(AsmJSCall)
     UNSAFE_OP(AsmJSCheckOverRecursed)
-    DROP_OP(RecompileCheck)
 
     // It looks like this could easily be made safe:
     UNSAFE_OP(ConvertElementsToDoubles)
 };
 
 bool
 ParallelSafetyAnalysis::analyze()
 {
--- a/js/src/jit/RangeAnalysis.cpp
+++ b/js/src/jit/RangeAnalysis.cpp
@@ -2035,17 +2035,17 @@ RangeAnalysis::analyze()
     }
 
     return true;
 }
 
 bool
 RangeAnalysis::addRangeAssertions()
 {
-    if (!js_JitOptions.checkRangeAnalysis)
+    if (!js_IonOptions.checkRangeAnalysis)
         return true;
 
     // Check the computed range for this instruction, if the option is set. Note
     // that this code is quite invasive; it adds numerous additional
     // instructions for each MInstruction with a computed range, and it uses
     // registers, so it also affects register allocation.
     for (ReversePostorderIterator iter(graph_.rpoBegin()); iter != graph_.rpoEnd(); iter++) {
         MBasicBlock *block = *iter;
--- a/js/src/jit/UnreachableCodeElimination.cpp
+++ b/js/src/jit/UnreachableCodeElimination.cpp
@@ -77,18 +77,18 @@ UnreachableCodeElimination::removeUnmark
     if (rerunAliasAnalysis_) {
         AliasAnalysis analysis(mir_, graph_);
         if (!analysis.analyze())
             return false;
     }
 
     // Pass 5: It's important for optimizations to re-run GVN (and in
     // turn alias analysis) after UCE if we eliminated branches.
-    if (rerunAliasAnalysis_ && mir_->optimizationInfo().gvnEnabled()) {
-        ValueNumberer gvn(mir_, graph_, mir_->optimizationInfo().gvnKind() == GVN_Optimistic);
+    if (rerunAliasAnalysis_ && js_IonOptions.gvn) {
+        ValueNumberer gvn(mir_, graph_, js_IonOptions.gvnIsOptimistic);
         if (!gvn.clear() || !gvn.analyze())
             return false;
         IonSpewPass("GVN-after-UCE");
         AssertExtendedGraphCoherency(graph_);
 
         if (mir_->shouldCancel("GVN-after-UCE"))
             return false;
     }
--- a/js/src/jit/shared/CodeGenerator-shared.cpp
+++ b/js/src/jit/shared/CodeGenerator-shared.cpp
@@ -598,17 +598,17 @@ CodeGeneratorShared::verifyOsiPointRegs(
 
     masm.bind(&done);
     masm.pop(scratch);
 }
 
 bool
 CodeGeneratorShared::shouldVerifyOsiPointRegs(LSafepoint *safepoint)
 {
-    if (!js_JitOptions.checkOsiPointRegisters)
+    if (!js_IonOptions.checkOsiPointRegisters)
         return false;
 
     if (gen->info().executionMode() != SequentialExecution)
         return false;
 
     if (safepoint->liveRegs().empty(true) && safepoint->liveRegs().empty(false))
         return false; // No registers to check.
 
--- a/js/src/jit/shared/Lowering-shared-inl.h
+++ b/js/src/jit/shared/Lowering-shared-inl.h
@@ -71,17 +71,17 @@ LIRGeneratorShared::defineFixed(LInstruc
     LDefinition def(type, LDefinition::PRESET);
     def.setOutput(output);
 
     // Add an LNop to avoid regalloc problems if the next op uses this value
     // with a fixed or at-start policy.
     if (!define(lir, mir, def))
         return false;
 
-    if (gen->optimizationInfo().registerAllocator() == RegisterAllocator_LSRA) {
+    if (js_IonOptions.registerAllocator == RegisterAllocator_LSRA) {
         if (!add(new(alloc()) LNop))
             return false;
     }
 
     return true;
 }
 
 template <size_t Ops, size_t Temps> bool
@@ -158,17 +158,17 @@ LIRGeneratorShared::defineReturn(LInstru
         lir->setDef(0, LDefinition(vreg, type, LGeneralReg(ReturnReg)));
         break;
     }
 
     mir->setVirtualRegister(vreg);
     if (!add(lir))
         return false;
 
-    if (gen->optimizationInfo().registerAllocator() == RegisterAllocator_LSRA) {
+    if (js_IonOptions.registerAllocator == RegisterAllocator_LSRA) {
         if (!add(new(alloc()) LNop))
             return false;
     }
 
     return true;
 }
 
 // In LIR, we treat booleans and integers as the same low-level type (INTEGER).
--- a/js/src/jsapi.cpp
+++ b/js/src/jsapi.cpp
@@ -5975,33 +5975,30 @@ JS_SetParallelIonCompilationEnabled(JSCo
     cx->runtime()->setParallelIonCompilationEnabled(enabled);
 #endif
 }
 
 JS_PUBLIC_API(void)
 JS_SetGlobalJitCompilerOption(JSContext *cx, JSJitCompilerOption opt, uint32_t value)
 {
 #ifdef JS_ION
+    jit::IonOptions defaultValues;
 
     switch (opt) {
       case JSJITCOMPILER_BASELINE_USECOUNT_TRIGGER:
-        if (value == uint32_t(-1)) {
-            jit::JitOptions defaultValues;
+        if (value == uint32_t(-1))
             value = defaultValues.baselineUsesBeforeCompile;
-        }
-        jit::js_JitOptions.baselineUsesBeforeCompile = value;
+        jit::js_IonOptions.baselineUsesBeforeCompile = value;
         break;
       case JSJITCOMPILER_ION_USECOUNT_TRIGGER:
-        if (value == uint32_t(-1)) {
-            jit::js_JitOptions.resetUsesBeforeCompile();
-            break;
-        }
-        jit::js_JitOptions.setUsesBeforeCompile(value);
+        if (value == uint32_t(-1))
+            value = defaultValues.usesBeforeCompile;
+        jit::js_IonOptions.usesBeforeCompile = value;
         if (value == 0)
-            jit::js_JitOptions.setEagerCompilation();
+            jit::js_IonOptions.setEagerCompilation();
         break;
       case JSJITCOMPILER_ION_ENABLE:
         if (value == 1) {
             JS::ContextOptionsRef(cx).setIon(true);
             IonSpew(js::jit::IonSpew_Scripts, "Enable ion");
         } else if (value == 0) {
             JS::ContextOptionsRef(cx).setIon(false);
             IonSpew(js::jit::IonSpew_Scripts, "Disable ion");
--- a/js/src/jsscript.h
+++ b/js/src/jsscript.h
@@ -585,20 +585,18 @@ class JSScript : public js::gc::Barriere
 
     uint32_t        natoms_;    /* length of atoms array */
 
     /* Range of characters in scriptSource which contains this script's source. */
     uint32_t        sourceStart_;
     uint32_t        sourceEnd_;
 
     uint32_t        useCount;   /* Number of times the script has been called
-                                 * or has had backedges taken. When running in
-                                 * ion, also increased for any inlined scripts.
-                                 * Reset if the script's JIT code is forcibly
-                                 * discarded. */
+                                 * or has had backedges taken. Reset if the
+                                 * script's JIT code is forcibly discarded. */
 
 #ifdef DEBUG
     // Unique identifier within the compartment for this script, used for
     // printing analysis information.
     uint32_t        id_;
     uint32_t        idpad;
 #endif
 
--- a/js/src/jsworkers.cpp
+++ b/js/src/jsworkers.cpp
@@ -741,16 +741,17 @@ WorkerThread::handleIonWorkload(WorkerTh
 {
     JS_ASSERT(state.isLocked());
     JS_ASSERT(state.canStartIonCompile());
     JS_ASSERT(idle());
 
     ionBuilder = state.ionWorklist.popCopy();
 
     DebugOnly<ExecutionMode> executionMode = ionBuilder->info().executionMode();
+    JS_ASSERT(jit::GetIonScript(ionBuilder->script(), executionMode) == ION_COMPILING_SCRIPT);
 
 #if JS_TRACE_LOGGING
     AutoTraceLog logger(TraceLogging::getLogger(TraceLogging::ION_BACKGROUND_COMPILER),
                         TraceLogging::ION_COMPILE_START,
                         TraceLogging::ION_COMPILE_STOP,
                         ionBuilder->script());
 #endif
 
--- a/js/src/moz.build
+++ b/js/src/moz.build
@@ -252,19 +252,17 @@ if CONFIG['ENABLE_ION']:
         'jit/EdgeCaseAnalysis.cpp',
         'jit/EffectiveAddressAnalysis.cpp',
         'jit/Ion.cpp',
         'jit/IonAnalysis.cpp',
         'jit/IonBuilder.cpp',
         'jit/IonCaches.cpp',
         'jit/IonFrames.cpp',
         'jit/IonMacroAssembler.cpp',
-        'jit/IonOptimizationLevels.cpp',
         'jit/IonSpewer.cpp',
-        'jit/JitOptions.cpp',
         'jit/JSONSpewer.cpp',
         'jit/LICM.cpp',
         'jit/LinearScan.cpp',
         'jit/LIR.cpp',
         'jit/LiveRangeAllocator.cpp',
         'jit/Lowering.cpp',
         'jit/MCallOptimize.cpp',
         'jit/MIR.cpp',
--- a/js/src/shell/js.cpp
+++ b/js/src/shell/js.cpp
@@ -5435,120 +5435,113 @@ ProcessArgs(JSContext *cx, JSObject *obj
     }
 
     if (op->getBoolOption("no-baseline")) {
         enableBaseline = false;
         JS::ContextOptionsRef(cx).toggleBaseline();
     }
 
     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;
-        } else if (strcmp(str, "optimistic") == 0) {
-            jit::js_JitOptions.forceGvnKind = true;
-            jit::js_JitOptions.forcedGvnKind = jit::GVN_Optimistic;
-        } else {
+        if (strcmp(str, "off") == 0)
+            jit::js_IonOptions.gvn = false;
+        else if (strcmp(str, "pessimistic") == 0)
+            jit::js_IonOptions.gvnIsOptimistic = false;
+        else if (strcmp(str, "optimistic") == 0)
+            jit::js_IonOptions.gvnIsOptimistic = true;
+        else
             return OptionFailure("ion-gvn", str);
-        }
     }
 
     if (const char *str = op->getStringOption("ion-licm")) {
         if (strcmp(str, "on") == 0)
-            jit::js_JitOptions.disableLicm = false;
+            jit::js_IonOptions.licm = true;
         else if (strcmp(str, "off") == 0)
-            jit::js_JitOptions.disableLicm = true;
+            jit::js_IonOptions.licm = false;
         else
             return OptionFailure("ion-licm", str);
     }
 
     if (const char *str = op->getStringOption("ion-edgecase-analysis")) {
         if (strcmp(str, "on") == 0)
-            jit::js_JitOptions.disableEdgeCaseAnalysis = false;
+            jit::js_IonOptions.edgeCaseAnalysis = true;
         else if (strcmp(str, "off") == 0)
-            jit::js_JitOptions.disableEdgeCaseAnalysis = true;
+            jit::js_IonOptions.edgeCaseAnalysis = false;
         else
             return OptionFailure("ion-edgecase-analysis", str);
     }
 
      if (const char *str = op->getStringOption("ion-range-analysis")) {
          if (strcmp(str, "on") == 0)
-             jit::js_JitOptions.disableRangeAnalysis = false;
+             jit::js_IonOptions.rangeAnalysis = true;
          else if (strcmp(str, "off") == 0)
-             jit::js_JitOptions.disableRangeAnalysis = true;
+             jit::js_IonOptions.rangeAnalysis = false;
          else
              return OptionFailure("ion-range-analysis", str);
      }
 
     if (op->getBoolOption("ion-check-range-analysis"))
-        jit::js_JitOptions.checkRangeAnalysis = true;
+        jit::js_IonOptions.checkRangeAnalysis = true;
 
     if (op->getBoolOption("ion-check-thread-safety"))
-        jit::js_JitOptions.checkThreadSafety = true;
+        jit::js_IonOptions.checkThreadSafety = true;
 
     if (const char *str = op->getStringOption("ion-inlining")) {
         if (strcmp(str, "on") == 0)
-            jit::js_JitOptions.disableInlining = false;
+            jit::js_IonOptions.inlining = true;
         else if (strcmp(str, "off") == 0)
-            jit::js_JitOptions.disableInlining = true;
+            jit::js_IonOptions.inlining = false;
         else
             return OptionFailure("ion-inlining", str);
     }
 
     if (const char *str = op->getStringOption("ion-osr")) {
         if (strcmp(str, "on") == 0)
-            jit::js_JitOptions.osr = true;
+            jit::js_IonOptions.osr = true;
         else if (strcmp(str, "off") == 0)
-            jit::js_JitOptions.osr = false;
+            jit::js_IonOptions.osr = false;
         else
             return OptionFailure("ion-osr", str);
     }
 
     if (const char *str = op->getStringOption("ion-limit-script-size")) {
         if (strcmp(str, "on") == 0)
-            jit::js_JitOptions.limitScriptSize = true;
+            jit::js_IonOptions.limitScriptSize = true;
         else if (strcmp(str, "off") == 0)
-            jit::js_JitOptions.limitScriptSize = false;
+            jit::js_IonOptions.limitScriptSize = false;
         else
             return OptionFailure("ion-limit-script-size", str);
     }
 
     int32_t useCount = op->getIntOption("ion-uses-before-compile");
     if (useCount >= 0)
-        jit::js_JitOptions.setUsesBeforeCompile(useCount);
+        jit::js_IonOptions.usesBeforeCompile = useCount;
 
     useCount = op->getIntOption("baseline-uses-before-compile");
     if (useCount >= 0)
-        jit::js_JitOptions.baselineUsesBeforeCompile = useCount;
+        jit::js_IonOptions.baselineUsesBeforeCompile = useCount;
 
     if (op->getBoolOption("baseline-eager"))
-        jit::js_JitOptions.baselineUsesBeforeCompile = 0;
+        jit::js_IonOptions.baselineUsesBeforeCompile = 0;
 
     if (const char *str = op->getStringOption("ion-regalloc")) {
-        if (strcmp(str, "lsra") == 0) {
-            jit::js_JitOptions.forceRegisterAllocator = true;
-            jit::js_JitOptions.forcedRegisterAllocator = jit::RegisterAllocator_LSRA;
-        } else if (strcmp(str, "backtracking") == 0) {
-            jit::js_JitOptions.forceRegisterAllocator = true;
-            jit::js_JitOptions.forcedRegisterAllocator = jit::RegisterAllocator_Backtracking;
-        } else if (strcmp(str, "stupid") == 0) {
-            jit::js_JitOptions.forceRegisterAllocator = true;
-            jit::js_JitOptions.forcedRegisterAllocator = jit::RegisterAllocator_Stupid;
-        } else {
+        if (strcmp(str, "lsra") == 0)
+            jit::js_IonOptions.registerAllocator = jit::RegisterAllocator_LSRA;
+        else if (strcmp(str, "backtracking") == 0)
+            jit::js_IonOptions.registerAllocator = jit::RegisterAllocator_Backtracking;
+        else if (strcmp(str, "stupid") == 0)
+            jit::js_IonOptions.registerAllocator = jit::RegisterAllocator_Stupid;
+        else
             return OptionFailure("ion-regalloc", str);
-        }
     }
 
     if (op->getBoolOption("ion-eager"))
-        jit::js_JitOptions.setEagerCompilation();
+        jit::js_IonOptions.setEagerCompilation();
 
     if (op->getBoolOption("ion-compile-try-catch"))
-        jit::js_JitOptions.compileTryCatch = true;
+        jit::js_IonOptions.compileTryCatch = true;
 
 #ifdef JS_THREADSAFE
     bool parallelCompilation = false;
     if (const char *str = op->getStringOption("ion-parallel-compile")) {
         if (strcmp(str, "on") == 0) {
             if (cx->runtime()->workerThreadCount() == 0) {
                 fprintf(stderr, "Parallel compilation not available without helper threads");
                 return EXIT_FAILURE;
--- a/js/src/vm/ForkJoin.cpp
+++ b/js/src/vm/ForkJoin.cpp
@@ -2202,14 +2202,14 @@ js::InExclusiveParallelSection()
     return InParallelSection() && ForkJoinSlice::Current()->hasAcquiredContext();
 }
 
 bool
 js::ParallelTestsShouldPass(JSContext *cx)
 {
     return jit::IsIonEnabled(cx) &&
            jit::IsBaselineEnabled(cx) &&
-           !jit::js_JitOptions.eagerCompilation &&
-           jit::js_JitOptions.baselineUsesBeforeCompile != 0 &&
+           !jit::js_IonOptions.eagerCompilation &&
+           jit::js_IonOptions.baselineUsesBeforeCompile != 0 &&
            cx->runtime()->gcZeal() == 0;
 }
 
 #endif // JS_THREADSAFE && JS_ION