Bug 783464 - Fix condition for removing the constrained output vector. r=bhackett
☠☠ backed out by fbba6ea2b076 ☠ ☠
authorNicolas B. Pierron <nicolas.b.pierron@mozilla.com>
Wed, 22 Aug 2012 16:05:08 -0700
changeset 104929 c1b7927df5463f9983688f8574584bbe2bc4cb76
parent 104928 4225ee7e35a0dcc37c4db156e878740ec88d33d5
child 104930 fbba6ea2b0767b8cfff5113838f3528b2b15b1e2
push id1258
push usernpierron@mozilla.com
push dateThu, 23 Aug 2012 03:54:42 +0000
reviewersbhackett
bugs783464
milestone17.0a1
Bug 783464 - Fix condition for removing the constrained output vector. r=bhackett
js/src/jscompartment.cpp
js/src/jscompartment.h
js/src/jsgc.cpp
js/src/jsinfer.cpp
js/src/jsinfer.h
js/src/jsinferinlines.h
--- a/js/src/jscompartment.cpp
+++ b/js/src/jscompartment.cpp
@@ -486,17 +486,17 @@ JSCompartment::markTypes(JSTracer *trc)
     for (CellIterUnderGC i(this, FINALIZE_TYPE_OBJECT); !i.done(); i.next()) {
         types::TypeObject *type = i.get<types::TypeObject>();
         MarkTypeObjectRoot(trc, &type, "mark_types_scan");
         JS_ASSERT(type == i.get<types::TypeObject>());
     }
 }
 
 void
-JSCompartment::discardJitCode(FreeOp *fop)
+JSCompartment::discardJitCode(FreeOp *fop, bool discardConstraints)
 {
 #ifdef JS_METHODJIT
 
     /*
      * Kick all frames on the stack into the interpreter, and release all JIT
      * code in the compartment unless code is being preserved, in which case
      * purge all caches in the JIT scripts. Even if we are not releasing all
      * JIT code, we still need to release code for scripts which are in the
@@ -522,17 +522,17 @@ JSCompartment::discardJitCode(FreeOp *fo
             /*
              * Use counts for scripts are reset on GC. After discarding code we
              * need to let it warm back up to get information such as which
              * opcodes are setting array holes or accessing getter properties.
              */
             script->resetUseCount();
         }
 
-        types.sweepCompilerOutputs(fop);
+        types.sweepCompilerOutputs(fop, discardConstraints);
     }
 
 #endif /* JS_METHODJIT */
 }
 
 bool
 JSCompartment::isDiscardingJitCode(JSTracer *trc)
 {
@@ -542,17 +542,17 @@ JSCompartment::isDiscardingJitCode(JSTra
     return !gcPreserveCode;
 }
 
 void
 JSCompartment::sweep(FreeOp *fop, bool releaseTypes)
 {
     {
         gcstats::AutoPhase ap(rt->gcStats, gcstats::PHASE_SWEEP_DISCARD_CODE);
-        discardJitCode(fop);
+        discardJitCode(fop, !activeAnalysis && !gcPreserveCode);
     }
 
     /* This function includes itself in PHASE_SWEEP_TABLES. */
     sweepCrossCompartmentWrappers();
 
     {
         gcstats::AutoPhase ap(rt->gcStats, gcstats::PHASE_SWEEP_TABLES);
 
@@ -576,16 +576,17 @@ JSCompartment::sweep(FreeOp *fop, bool r
             ionCompartment_->sweep(fop);
 #endif
 
         /* JIT code can hold references on RegExpShared, so sweep regexps after clearing code. */
         regExps.sweep(rt);
     }
 
     if (!activeAnalysis && !gcPreserveCode) {
+        JS_ASSERT(!types.constrainedOutputs);
         gcstats::AutoPhase ap(rt->gcStats, gcstats::PHASE_DISCARD_ANALYSIS);
 
         /*
          * Clear the analysis pool, but don't release its data yet. While
          * sweeping types any live data will be allocated into the pool.
          */
         LifoAlloc oldAlloc(typeLifoAlloc.defaultChunkSize());
         oldAlloc.steal(&typeLifoAlloc);
--- a/js/src/jscompartment.h
+++ b/js/src/jscompartment.h
@@ -342,17 +342,17 @@ struct JSCompartment
     bool wrapId(JSContext *cx, jsid *idp);
     bool wrap(JSContext *cx, js::PropertyOp *op);
     bool wrap(JSContext *cx, js::StrictPropertyOp *op);
     bool wrap(JSContext *cx, js::PropertyDescriptor *desc);
     bool wrap(JSContext *cx, js::AutoIdVector &props);
 
     void mark(JSTracer *trc);
     void markTypes(JSTracer *trc);
-    void discardJitCode(js::FreeOp *fop);
+    void discardJitCode(js::FreeOp *fop, bool discardConstraints);
     bool isDiscardingJitCode(JSTracer *trc);
     void sweep(js::FreeOp *fop, bool releaseTypes);
     void sweepCrossCompartmentWrappers();
     void purge();
 
     void setGCLastBytes(size_t lastBytes, size_t lastMallocBytes, js::JSGCInvocationKind gckind);
     void reduceGCTriggerBytes(size_t amount);
 
--- a/js/src/jsgc.cpp
+++ b/js/src/jsgc.cpp
@@ -3346,17 +3346,17 @@ BeginMarkPhase(JSRuntime *rt)
     rt->gcMarker.start(rt);
     JS_ASSERT(!rt->gcMarker.callback);
     JS_ASSERT(IS_GC_MARKING_TRACER(&rt->gcMarker));
 
     /* For non-incremental GC the following sweep discards the jit code. */
     if (rt->gcIsIncremental) {
         for (GCCompartmentsIter c(rt); !c.done(); c.next()) {
             gcstats::AutoPhase ap(rt->gcStats, gcstats::PHASE_MARK_DISCARD_CODE);
-            c->discardJitCode(rt->defaultFreeOp());
+            c->discardJitCode(rt->defaultFreeOp(), false);
         }
     }
 
     GCMarker *gcmarker = &rt->gcMarker;
 
     rt->gcStartNumber = rt->gcNumber;
 
     /* Reset weak map list. */
--- a/js/src/jsinfer.cpp
+++ b/js/src/jsinfer.cpp
@@ -5844,40 +5844,39 @@ TypeCompartment::sweep(FreeOp *fop)
      * to reallocate if the compartment becomes active again.
      */
     if (pendingArray)
         fop->free_(pendingArray);
 
     pendingArray = NULL;
     pendingCapacity = 0;
 
-    sweepCompilerOutputs(fop);
+    sweepCompilerOutputs(fop, true);
 }
 
 void
-TypeCompartment::sweepCompilerOutputs(FreeOp *fop)
+TypeCompartment::sweepCompilerOutputs(FreeOp *fop, bool discardConstraints)
 {
     if (constrainedOutputs) {
         bool isCompiling = compiledInfo.outputIndex != RecompileInfo::NoCompilerRunning;
-        if (isCompiling && !compartment()->activeAnalysis)
-        {
+        if (discardConstraints) {
+            JS_ASSERT(!isCompiling);
 #if DEBUG
             for (unsigned i = 0; i < constrainedOutputs->length(); i++) {
                 CompilerOutput &co = (*constrainedOutputs)[i];
                 JS_ASSERT(!co.isValid());
             }
 #endif
 
             fop->delete_(constrainedOutputs);
             constrainedOutputs = NULL;
         } else {
-            // A Compilation is running and the AutoEnterCompilation class has
-            // captured an index into the constrained outputs vector and
-            // potentially created multiple types with this index.  Instead, we
-            // invalidate all compilations except the one running now.
+            // Constraints have captured an index to the constrained outputs
+            // vector.  Thus, we invalidate all compilations except the one
+            // which is potentially running now.
             size_t len = constrainedOutputs->length();
             for (unsigned i = 0; i < len; i++) {
                 if (i != compiledInfo.outputIndex) {
                     CompilerOutput &co = (*constrainedOutputs)[i];
                     JS_ASSERT(!co.isValid());
                     co.invalidate();
                 }
             }
--- a/js/src/jsinfer.h
+++ b/js/src/jsinfer.h
@@ -1175,17 +1175,17 @@ struct TypeCompartment
     /* Monitor future effects on a bytecode. */
     void monitorBytecode(JSContext *cx, JSScript *script, uint32_t offset,
                          bool returnOnly = false);
 
     /* Mark any type set containing obj as having a generic object type. */
     void markSetsUnknown(JSContext *cx, TypeObject *obj);
 
     void sweep(FreeOp *fop);
-    void sweepCompilerOutputs(FreeOp *fop);
+    void sweepCompilerOutputs(FreeOp *fop, bool discardConstraints);
     void finalizeObjects();
 };
 
 enum SpewChannel {
     ISpewOps,      /* ops: New constraints and types. */
     ISpewResult,   /* result: Final type sets. */
     SPEW_COUNT
 };
--- a/js/src/jsinferinlines.h
+++ b/js/src/jsinferinlines.h
@@ -331,16 +331,17 @@ struct AutoEnterCompilation
     };
     Compiler mode;
 
     AutoEnterCompilation(JSContext *cx, Compiler mode)
       : cx(cx),
         info(cx->compartment->types.compiledInfo),
         mode(mode)
     {
+        JS_ASSERT(cx->compartment->activeAnalysis);
         JS_ASSERT(info.outputIndex == RecompileInfo::NoCompilerRunning);
     }
 
     bool init(JSScript *script, bool constructing, unsigned chunkIndex)
     {
         CompilerOutput co;
         co.script = script;
         co.isIonFlag = (mode == Ion);