Bug 800650 - decouple CompileBackEnd from IonBuilder (r=dvander)
authorLuke Wagner <luke@mozilla.com>
Tue, 16 Oct 2012 16:56:11 -0700
changeset 110675 c816cd711824c633886a76856af102a3467ea1e3
parent 110674 06777f847494fa67e9bd8f41dd9e3e8181b98075
child 110676 875701feacbd7cae42214aede50641f7a420ba3f
push id23708
push userryanvm@gmail.com
push dateFri, 19 Oct 2012 01:28:59 +0000
treeherdermozilla-central@fd5556088388 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersdvander
bugs800650
milestone19.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 800650 - decouple CompileBackEnd from IonBuilder (r=dvander)
js/src/ion/Ion.cpp
js/src/ion/Ion.h
js/src/ion/IonAnalysis.cpp
js/src/ion/IonAnalysis.h
js/src/ion/IonBuilder.cpp
js/src/ion/IonBuilder.h
js/src/jsworkers.cpp
--- a/js/src/ion/Ion.cpp
+++ b/js/src/ion/Ion.cpp
@@ -751,147 +751,146 @@ ion::ToggleBarriers(JSCompartment *comp,
         if (script->hasIonScript())
             script->ion->toggleBarriers(needs);
     }
 }
 
 namespace js {
 namespace ion {
 
-bool
-CompileBackEnd(IonBuilder *builder)
+LIRGraph *
+CompileBackEnd(MIRGenerator *mir)
 {
     IonSpewPass("BuildSSA");
     // Note: don't call AssertGraphCoherency before SplitCriticalEdges,
     // the graph is not in RPO at this point.
 
-    MIRGraph &graph = builder->graph();
+    MIRGraph &graph = mir->graph();
 
-    if (!SplitCriticalEdges(builder, graph))
-        return false;
+    if (!SplitCriticalEdges(graph))
+        return NULL;
     IonSpewPass("Split Critical Edges");
     AssertGraphCoherency(graph);
 
     if (!RenumberBlocks(graph))
-        return false;
+        return NULL;
     IonSpewPass("Renumber Blocks");
     AssertGraphCoherency(graph);
 
     if (!BuildDominatorTree(graph))
-        return false;
+        return NULL;
     // No spew: graph not changed.
 
     // This must occur before any code elimination.
     if (!EliminatePhis(graph))
-        return false;
+        return NULL;
     IonSpewPass("Eliminate phis");
     AssertGraphCoherency(graph);
 
     if (!BuildPhiReverseMapping(graph))
-        return false;
+        return NULL;
     // No spew: graph not changed.
 
     // This pass also removes copies.
     if (!ApplyTypeInformation(graph))
-        return false;
+        return NULL;
     IonSpewPass("Apply types");
     AssertGraphCoherency(graph);
 
     // Alias analysis is required for LICM and GVN so that we don't move
     // loads across stores.
     if (js_IonOptions.licm || js_IonOptions.gvn) {
         AliasAnalysis analysis(graph);
         if (!analysis.analyze())
-            return false;
+            return NULL;
         IonSpewPass("Alias analysis");
         AssertGraphCoherency(graph);
     }
 
     if (js_IonOptions.edgeCaseAnalysis) {
         EdgeCaseAnalysis edgeCaseAnalysis(graph);
         if (!edgeCaseAnalysis.analyzeEarly())
-            return false;
+            return NULL;
         IonSpewPass("Edge Case Analysis (Early)");
         AssertGraphCoherency(graph);
     }
 
     if (js_IonOptions.gvn) {
         ValueNumberer gvn(graph, js_IonOptions.gvnIsOptimistic);
         if (!gvn.analyze())
-            return false;
+            return NULL;
         IonSpewPass("GVN");
         AssertGraphCoherency(graph);
     }
 
     if (js_IonOptions.rangeAnalysis) {
         RangeAnalysis r(graph);
         if (!r.addBetaNobes())
-            return false;
+            return NULL;
         IonSpewPass("Beta");
         AssertGraphCoherency(graph);
 
         if (!r.analyze())
-            return false;
+            return NULL;
         IonSpewPass("Range Analysis");
         AssertGraphCoherency(graph);
 
         if (!r.removeBetaNobes())
-            return false;
+            return NULL;
         IonSpewPass("De-Beta");
         AssertGraphCoherency(graph);
     }
 
     if (!EliminateDeadCode(graph))
-        return false;
+        return NULL;
     IonSpewPass("DCE");
     AssertGraphCoherency(graph);
 
     if (js_IonOptions.licm) {
         LICM licm(graph);
         if (!licm.analyze())
-            return false;
+            return NULL;
         IonSpewPass("LICM");
         AssertGraphCoherency(graph);
     }
 
     if (js_IonOptions.edgeCaseAnalysis) {
         EdgeCaseAnalysis edgeCaseAnalysis(graph);
         if (!edgeCaseAnalysis.analyzeLate())
-            return false;
+            return NULL;
         IonSpewPass("Edge Case Analysis (Late)");
         AssertGraphCoherency(graph);
     }
 
     // Note: bounds check elimination has to run after all other passes that
     // move instructions. Since bounds 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 (!EliminateRedundantBoundsChecks(graph))
-        return false;
+        return NULL;
     IonSpewPass("Bounds Check Elimination");
     AssertGraphCoherency(graph);
 
-    LIRGraph *lir = builder->temp().lifoAlloc()->new_<LIRGraph>(&graph);
+    LIRGraph *lir = mir->temp().lifoAlloc()->new_<LIRGraph>(&graph);
     if (!lir)
-        return false;
+        return NULL;
 
-    LIRGenerator lirgen(builder, graph, *lir);
+    LIRGenerator lirgen(mir, graph, *lir);
     if (!lirgen.generate())
-        return false;
+        return NULL;
     IonSpewPass("Generate LIR");
 
     if (js_IonOptions.lsra) {
         LinearScanAllocator regalloc(&lirgen, *lir);
         if (!regalloc.go())
-            return false;
+            return NULL;
         IonSpewPass("Allocate Registers", &regalloc);
     }
 
-    builder->lir = lir;
-    return true;
+    return lir;
 }
 
 class AutoDestroyAllocator
 {
     LifoAlloc *alloc;
 
   public:
     AutoDestroyAllocator(LifoAlloc *alloc) : alloc(alloc) {}
@@ -922,21 +921,21 @@ AttachFinishedCompilations(JSContext *cx
     OffThreadCompilationVector &compilations = ion->finishedOffThreadCompilations();
 
     // Incorporate any off thread compilations which have finished, failed or
     // have been cancelled, and destroy JM jitcode for any compilations which
     // succeeded, to allow entering the Ion code from the interpreter.
     while (!compilations.empty()) {
         IonBuilder *builder = compilations.popCopy();
 
-        if (builder->lir) {
+        if (builder->backgroundCompiledLir) {
             RootedScript script(cx, builder->script());
             IonContext ictx(cx, cx->compartment, &builder->temp());
 
-            CodeGenerator codegen(builder, *builder->lir);
+            CodeGenerator codegen(builder, *builder->backgroundCompiledLir);
 
             types::AutoEnterCompilation enterCompiler(cx, types::AutoEnterCompilation::Ion);
             enterCompiler.initExisting(builder->recompileInfo);
 
             bool success;
             {
                 // Release the worker thread lock and root the compiler for GC.
                 AutoTempAllocatorRooter root(cx, &builder->temp());
@@ -1028,22 +1027,23 @@ IonCompile(JSContext *cx, JSScript *scri
 
         // The allocator and associated data will be destroyed after being
         // processed in the finishedOffThreadCompilations list.
         autoDestroy.cancel();
 
         return true;
     }
 
-    if (!CompileBackEnd(builder)) {
+    LIRGraph *lir = CompileBackEnd(builder);
+    if (!lir) {
         IonSpew(IonSpew_Abort, "Failed during back-end compilation.");
         return false;
     }
 
-    CodeGenerator codegen(builder, *builder->lir);
+    CodeGenerator codegen(builder, *lir);
     if (!codegen.generate()) {
         IonSpew(IonSpew_Abort, "Failed during code generation.");
         return false;
     }
 
     IonSpewEndFunction();
 
     return true;
--- a/js/src/ion/Ion.h
+++ b/js/src/ion/Ion.h
@@ -247,18 +247,20 @@ void Invalidate(types::TypeCompartment &
 void Invalidate(JSContext *cx, const Vector<types::RecompileInfo> &invalid, bool resetUses = true);
 bool Invalidate(JSContext *cx, JSScript *script, bool resetUses = true);
 
 void MarkFromIon(JSCompartment *comp, Value *vp);
 
 void ToggleBarriers(JSCompartment *comp, bool needs);
 
 class IonBuilder;
+class MIRGenerator;
+class LIRGraph;
 
-bool CompileBackEnd(IonBuilder *builder);
+LIRGraph *CompileBackEnd(MIRGenerator *mir);
 void AttachFinishedCompilations(JSContext *cx);
 void FinishOffThreadBuilder(IonBuilder *builder);
 bool TestIonCompile(JSContext *cx, JSScript *script, JSFunction *fun, jsbytecode *osrPc, bool constructing);
 
 static inline bool IsEnabled(JSContext *cx)
 {
     return cx->hasRunOption(JSOPTION_ION) && cx->typeInferenceEnabled();
 }
--- a/js/src/ion/IonAnalysis.cpp
+++ b/js/src/ion/IonAnalysis.cpp
@@ -12,17 +12,17 @@
 
 using namespace js;
 using namespace js::ion;
 
 // A critical edge is an edge which is neither its successor's only predecessor
 // nor its predecessor's only successor. Critical edges must be split to
 // prevent copy-insertion and code motion from affecting other edges.
 bool
-ion::SplitCriticalEdges(MIRGenerator *gen, MIRGraph &graph)
+ion::SplitCriticalEdges(MIRGraph &graph)
 {
     for (MBasicBlockIterator block(graph.begin()); block != graph.end(); block++) {
         if (block->numSuccessors() < 2)
             continue;
         for (size_t i = 0; i < block->numSuccessors(); i++) {
             MBasicBlock *target = block->getSuccessor(i);
             if (target->numPredecessors() < 2)
                 continue;
--- a/js/src/ion/IonAnalysis.h
+++ b/js/src/ion/IonAnalysis.h
@@ -14,17 +14,17 @@
 
 namespace js {
 namespace ion {
 
 class MIRGenerator;
 class MIRGraph;
 
 bool
-SplitCriticalEdges(MIRGenerator *gen, MIRGraph &graph);
+SplitCriticalEdges(MIRGraph &graph);
 
 bool
 EliminatePhis(MIRGraph &graph);
 
 bool
 EliminateDeadCode(MIRGraph &graph);
 
 bool
--- a/js/src/ion/IonBuilder.cpp
+++ b/js/src/ion/IonBuilder.cpp
@@ -22,17 +22,17 @@
 
 using namespace js;
 using namespace js::ion;
 
 IonBuilder::IonBuilder(JSContext *cx, TempAllocator *temp, MIRGraph *graph,
                        TypeOracle *oracle, CompileInfo *info, size_t inliningDepth, uint32 loopDepth)
   : MIRGenerator(cx->compartment, temp, graph, info),
     recompileInfo(cx->compartment->types.compiledInfo),
-    lir(NULL),
+    backgroundCompiledLir(NULL),
     cx(cx),
     loopDepth_(loopDepth),
     callerResumePoint_(NULL),
     callerBuilder_(NULL),
     oracle(oracle),
     inliningDepth(inliningDepth),
     failedBoundsCheck_(info->script()->failedBoundsCheck),
     lazyArguments_(NULL)
--- a/js/src/ion/IonBuilder.h
+++ b/js/src/ion/IonBuilder.h
@@ -440,17 +440,17 @@ class IonBuilder : public MIRGenerator
     // A builder is inextricably tied to a particular script.
     HeapPtrScript script_;
 
   public:
     // Compilation index for this attempt.
     types::RecompileInfo const recompileInfo;
 
     // If off thread compilation is successful, final LIR is attached here.
-    LIRGraph *lir;
+    LIRGraph *backgroundCompiledLir;
 
     void clearForBackEnd();
 
     Return<JSScript*> script() const { return script_; }
 
   private:
     JSContext *cx;
 
--- a/js/src/jsworkers.cpp
+++ b/js/src/jsworkers.cpp
@@ -290,17 +290,17 @@ WorkerThread::threadLoop()
         ionScript = builder->script();
 
         JS_ASSERT(ionScript->ion == ION_COMPILING_SCRIPT);
 
         state.unlock();
 
         {
             ion::IonContext ictx(NULL, ionScript->compartment(), &builder->temp());
-            ion::CompileBackEnd(builder);
+            builder->backgroundCompiledLir = ion::CompileBackEnd(builder);
         }
 
         state.lock();
 
         ionScript = NULL;
         FinishOffThreadIonCompile(builder);
 
         /*