Bug 783464 - Fix condition for removing the constrained output vector. r=bhackett
authorNicolas B. Pierron <nicolas.b.pierron@mozilla.com>
Wed, 22 Aug 2012 16:05:08 -0700
changeset 103120 bbf6a7e1598d66d88322515784c7f5a9084d4b9b
parent 103119 17607e337dfd2587a835cae76a6e292f1b294667
child 103121 198ca6edd0aee50da84f7a2c2d28ef504e555d24
child 103140 759b5d914905b34cee5884d97a09c876eec44dda
push id23326
push useremorley@mozilla.com
push dateThu, 23 Aug 2012 10:36:26 +0000
treeherdermozilla-central@198ca6edd0ae [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbhackett
bugs783464
milestone17.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 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
@@ -441,17 +441,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 gcPreserveCode is set, 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
@@ -479,17 +479,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)
 {
@@ -499,17 +499,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);
 
@@ -528,16 +528,17 @@ JSCompartment::sweep(FreeOp *fop, bool r
         if (global_ && !IsObjectMarked(&global_))
             global_ = NULL;
 
         /* 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
@@ -335,17 +335,17 @@ struct JSCompartment
     bool wrap(JSContext *cx, JSObject **objp);
     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 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
@@ -3277,17 +3277,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
@@ -5966,40 +5966,38 @@ 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();
             if (isCompiling) {
                 len--;
                 JS_ASSERT(compiledInfo.outputIndex == len);
             }
             for (unsigned i = 0; i < len; i++) {
                 CompilerOutput &co = (*constrainedOutputs)[i];
                 JS_ASSERT(!co.isValid());
--- a/js/src/jsinfer.h
+++ b/js/src/jsinfer.h
@@ -24,17 +24,16 @@
 namespace JS {
 struct TypeInferenceSizes;
 }
 
 namespace js {
 
 class CallObject;
 
-
 namespace mjit {
     struct JITScript;
 }
 
 namespace types {
 
 /* Type set entry for either a JSObject with singleton type or a non-singleton TypeObject. */
 struct TypeObjectKey {
@@ -1258,17 +1257,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 maybePurgeAnalysis(JSContext *cx, bool force = false);
 
     void finalizeObjects();
 };
 
 enum SpewChannel {
     ISpewOps,      /* ops: New constraints and types. */
--- a/js/src/jsinferinlines.h
+++ b/js/src/jsinferinlines.h
@@ -286,16 +286,17 @@ struct AutoEnterCompilation
 {
     JSContext *cx;
     RecompileInfo &info;
 
     AutoEnterCompilation(JSContext *cx)
       : cx(cx),
         info(cx->compartment->types.compiledInfo)
     {
+        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.constructing = constructing;