Bug 1037666. r=billm, a=abillings
authorBrian Hackett <bhackett1024@gmail.com>
Mon, 04 Aug 2014 17:10:51 -0400
changeset 217372 7c8cf25aa8272c370293e02205a1ac1a78171e50
parent 217371 2597220a5926ef85476b09d09f2475956cc32c7c
child 217373 7671c6af65a483e39bf312ce826fc38f8838b79b
push id515
push userraliiev@mozilla.com
push dateMon, 06 Oct 2014 12:51:51 +0000
treeherdermozilla-release@267c7a481bef [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbillm, abillings
bugs1037666
milestone33.0a2
Bug 1037666. r=billm, a=abillings
js/src/vm/HelperThreads.cpp
--- a/js/src/vm/HelperThreads.cpp
+++ b/js/src/vm/HelperThreads.cpp
@@ -693,16 +693,25 @@ GlobalHelperThreadState::canStartCompres
 }
 
 bool
 GlobalHelperThreadState::canStartGCHelperTask()
 {
     return !gcHelperWorklist().empty();
 }
 
+static void
+LeaveParseTaskZone(JSRuntime *rt, ParseTask *task)
+{
+    // Mark the zone as no longer in use by an ExclusiveContext, and available
+    // to be collected by the GC.
+    task->cx->leaveCompartment(task->cx->compartment());
+    rt->clearUsedByExclusiveThread(task->cx->zone());
+}
+
 JSScript *
 GlobalHelperThreadState::finishParseTask(JSContext *maybecx, JSRuntime *rt, void *token)
 {
     ScopedJSDeletePtr<ParseTask> parseTask;
 
     // The token is a ParseTask* which should be in the finished list.
     // Find and remove its entry.
     {
@@ -713,38 +722,39 @@ GlobalHelperThreadState::finishParseTask
                 parseTask = finished[i];
                 remove(finished, &i);
                 break;
             }
         }
     }
     JS_ASSERT(parseTask);
 
-    // Mark the zone as no longer in use by an ExclusiveContext, and available
-    // to be collected by the GC.
-    parseTask->cx->leaveCompartment(parseTask->cx->compartment());
-    rt->clearUsedByExclusiveThread(parseTask->cx->zone());
     if (!maybecx) {
+        LeaveParseTaskZone(rt, parseTask);
         return nullptr;
     }
+
     JSContext *cx = maybecx;
     JS_ASSERT(cx->compartment());
 
     // Make sure we have all the constructors we need for the prototype
     // remapping below, since we can't GC while that's happening.
     Rooted<GlobalObject*> global(cx, &cx->global()->as<GlobalObject>());
     if (!GlobalObject::ensureConstructor(cx, global, JSProto_Object) ||
         !GlobalObject::ensureConstructor(cx, global, JSProto_Array) ||
         !GlobalObject::ensureConstructor(cx, global, JSProto_Function) ||
         !GlobalObject::ensureConstructor(cx, global, JSProto_RegExp) ||
         !GlobalObject::ensureConstructor(cx, global, JSProto_Iterator))
     {
+        LeaveParseTaskZone(rt, parseTask);
         return nullptr;
     }
 
+    LeaveParseTaskZone(rt, parseTask);
+
     // Point the prototypes of any objects in the script's compartment to refer
     // to the corresponding prototype in the new compartment. This will briefly
     // create cross compartment pointers, which will be fixed by the
     // MergeCompartments call below.
     for (gc::ZoneCellIter iter(parseTask->cx->zone(), gc::FINALIZE_TYPE_OBJECT);
          !iter.done();
          iter.next())
     {