Bug 708156: Ensure that JM compilation doesn't used out-of-date ScriptAnalysis structures. r=bhackett
authorJim Blandy <jimb@mozilla.com>
Thu, 15 Dec 2011 18:08:00 -0800
changeset 84385 7a0d03046d428854c35b797161129b8eab14b83d
parent 84384 ea39fc88f948868333facd4b7523b56413e1ec8e
child 84386 7a510c246bf24c11fbdf208a13ccc0c36f92952e
push idunknown
push userunknown
push dateunknown
reviewersbhackett
bugs708156
milestone11.0a1
Bug 708156: Ensure that JM compilation doesn't used out-of-date ScriptAnalysis structures. r=bhackett
js/src/jsanalyze.cpp
js/src/jsanalyze.h
js/src/jscompartment.cpp
js/src/methodjit/Compiler.cpp
--- a/js/src/jsanalyze.cpp
+++ b/js/src/jsanalyze.cpp
@@ -1889,12 +1889,18 @@ SSAValue::print() const
         printf("phi:%05u#%u", phiOffset(), phiSlot());
         break;
 
       default:
         JS_NOT_REACHED("Bad kind");
     }
 }
 
+void
+ScriptAnalysis::assertMatchingDebugMode()
+{
+    JS_ASSERT(!!script->compartment()->debugMode() == !!originalDebugMode_);
+}
+
 #endif  /* DEBUG */
 
 } /* namespace analyze */
 } /* namespace js */
--- a/js/src/jsanalyze.h
+++ b/js/src/jsanalyze.h
@@ -817,16 +817,21 @@ class ScriptAnalysis
     JSPackedBool *escapedSlots;
 
     /* Which analyses have been performed. */
     bool ranBytecode_;
     bool ranSSA_;
     bool ranLifetimes_;
     bool ranInference_;
 
+#ifdef DEBUG
+    /* Whether the compartment was in debug mode when we performed the analysis. */
+    bool originalDebugMode_: 1;
+#endif
+
     /* --------- Bytecode analysis --------- */
 
     bool usesReturnValue_:1;
     bool usesScopeChain_:1;
     bool usesThisValue_:1;
     bool hasFunctionCalls_:1;
     bool modifiesArguments_:1;
     bool extendsScope_:1;
@@ -838,17 +843,23 @@ class ScriptAnalysis
     uint32 numReturnSites_;
 
     /* --------- Lifetime analysis --------- */
 
     LifetimeVariable *lifetimes;
 
   public:
 
-    ScriptAnalysis(JSScript *script) { PodZero(this); this->script = script; }
+    ScriptAnalysis(JSScript *script) { 
+        PodZero(this);
+        this->script = script;
+#ifdef DEBUG
+        this->originalDebugMode_ = script->compartment()->debugMode();
+#endif        
+    }
 
     bool ranBytecode() { return ranBytecode_; }
     bool ranSSA() { return ranSSA_; }
     bool ranLifetimes() { return ranLifetimes_; }
     bool ranInference() { return ranInference_; }
 
     void analyzeBytecode(JSContext *cx);
     void analyzeSSA(JSContext *cx);
@@ -1159,16 +1170,23 @@ class ScriptAnalysis
             : phiNodes(cx), hasGetSet(false), hasHole(false), forTypes(NULL)
         {}
     };
 
     /* Type inference helpers */
     bool analyzeTypesBytecode(JSContext *cx, unsigned offset, TypeInferenceState &state);
     bool followEscapingArguments(JSContext *cx, const SSAValue &v, Vector<SSAValue> *seen);
     bool followEscapingArguments(JSContext *cx, SSAUseChain *use, Vector<SSAValue> *seen);
+
+  public:
+#ifdef DEBUG
+    void assertMatchingDebugMode();
+#else
+    void assertMatchingDebugMode() { }
+#endif
 };
 
 /* Protect analysis structures from GC while they are being used. */
 class AutoEnterAnalysis
 {
     JSCompartment *compartment;
     bool oldActiveAnalysis;
     bool left;
--- a/js/src/jscompartment.cpp
+++ b/js/src/jscompartment.cpp
@@ -634,23 +634,24 @@ JSCompartment::updateForDebugMode(JSCont
     if (enabled) {
         JS_ASSERT(!hasScriptsOnStack(cx));
     } else if (hasScriptsOnStack(cx)) {
         hasDebugModeCodeToDrop = true;
         return;
     }
 
     /*
-     * Discard JIT code for any scripts that change debugMode. This assumes
-     * that 'comp' is in the same thread as 'cx'.
+     * Discard JIT code and bytecode analyses for any scripts that change
+     * debugMode. This assumes that 'comp' is in the same thread as 'cx'.
      */
     for (gc::CellIter i(cx, this, gc::FINALIZE_SCRIPT); !i.done(); i.next()) {
         JSScript *script = i.get<JSScript>();
         if (script->debugMode != enabled) {
             mjit::ReleaseScriptCode(cx, script);
+            script->clearAnalysis();
             script->debugMode = enabled;
         }
     }
     hasDebugModeCodeToDrop = false;
 #endif
 }
 
 bool
--- a/js/src/methodjit/Compiler.cpp
+++ b/js/src/methodjit/Compiler.cpp
@@ -184,16 +184,17 @@ mjit::Compiler::checkAnalysis(JSScript *
     }
 
     if (!script->ensureRanAnalysis(cx, NULL))
         return Compile_Error;
     if (cx->typeInferenceEnabled() && !script->ensureRanInference(cx))
         return Compile_Error;
 
     ScriptAnalysis *analysis = script->analysis();
+    analysis->assertMatchingDebugMode();
     if (analysis->failed()) {
         JaegerSpew(JSpew_Abort, "couldn't analyze bytecode; probably switchX or OOM\n");
         return Compile_Abort;
     }
 
     return Compile_Okay;
 }