Bug 693406: Set the activeAnalysis flag in the proper compartment when printing TypeCompartments from js_DestroyContext with INFERFLAGS=full. r=bhackett
authorJim Blandy <jimb@mozilla.com>
Mon, 10 Oct 2011 14:31:35 -0700
changeset 79005 818edd78ffacaf37040b618094f630b575daf05c
parent 79004 6d2612f175306c4fa7d0c45f2619207e85568ef1
child 79006 96b2321ec26cc6612a6e89488f6e2ad51bb627e2
push idunknown
push userunknown
push dateunknown
reviewersbhackett
bugs693406
milestone10.0a1
Bug 693406: Set the activeAnalysis flag in the proper compartment when printing TypeCompartments from js_DestroyContext with INFERFLAGS=full. r=bhackett When ISpewResult is enabled, js_DestroyContext walks over all the compartments and dumps their types. However, it doesn't switch the context to each compartment as it does so, so the context passed in to all the print calls may not be in the same compartment as the scripts whose type inference results it's printing. This means that AutoEnterAnalysis enter(cx); sets the activeAnalysis flag in the wrong compartment, leading to assertion failures in functions like js::analyze::ScriptAnalysis::slotEscapes.
js/src/jsanalyze.h
js/src/jsinfer.cpp
--- a/js/src/jsanalyze.h
+++ b/js/src/jsanalyze.h
@@ -1258,33 +1258,39 @@ class ScriptAnalysis
 
     /* 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);
 };
 
 /* Protect analysis structures from GC while they are being used. */
-struct AutoEnterAnalysis
+class AutoEnterAnalysis
 {
-    JSContext *cx;
+    JSCompartment *compartment;
     bool oldActiveAnalysis;
     bool left;
 
-    AutoEnterAnalysis(JSContext *cx)
-        : cx(cx), oldActiveAnalysis(cx->compartment->activeAnalysis), left(false)
+    void construct(JSCompartment *compartment)
     {
-        cx->compartment->activeAnalysis = true;
+        this->compartment = compartment;
+        oldActiveAnalysis = compartment->activeAnalysis;
+        compartment->activeAnalysis = true;
+        left = false;
     }
 
+  public:
+    AutoEnterAnalysis(JSContext *cx) { construct(cx->compartment); }
+    AutoEnterAnalysis(JSCompartment *compartment) { construct(compartment); }
+
     void leave()
     {
         if (!left) {
             left = true;
-            cx->compartment->activeAnalysis = oldActiveAnalysis;
+            compartment->activeAnalysis = oldActiveAnalysis;
         }
     }
 
     ~AutoEnterAnalysis()
     {
         leave();
     }
 };
--- a/js/src/jsinfer.cpp
+++ b/js/src/jsinfer.cpp
@@ -2351,16 +2351,17 @@ ScriptAnalysis::addSingletonTypeBarrier(
     barrier->next = code.typeBarriers;
     code.typeBarriers = barrier;
 }
 
 void
 TypeCompartment::print(JSContext *cx, bool force)
 {
     JSCompartment *compartment = this->compartment();
+    AutoEnterAnalysis enter(compartment);
 
     if (!force && !InferSpewActive(ISpewResult))
         return;
 
     for (gc::CellIter i(cx, compartment, gc::FINALIZE_SCRIPT); !i.done(); i.next()) {
         JSScript *script = i.get<JSScript>();
         if (script->hasAnalysis() && script->analysis()->ranInference())
             script->analysis()->printTypes(cx);
@@ -4719,17 +4720,17 @@ CheckNewScriptProperties(JSContext *cx, 
 
 /////////////////////////////////////////////////////////////////////
 // Printing
 /////////////////////////////////////////////////////////////////////
 
 void
 ScriptAnalysis::printTypes(JSContext *cx)
 {
-    AutoEnterAnalysis enter(cx);
+    AutoEnterAnalysis enter(script->compartment());
     TypeCompartment *compartment = &script->compartment()->types;
 
     /*
      * Check if there are warnings for used values with unknown types, and build
      * statistics about the size of type sets found for stack values.
      */
     for (unsigned offset = 0; offset < script->length; offset++) {
         if (!maybeCode(offset))