Bug 1137341 - Don't allow GC to observe cross compartment prototype pointers for object groups. r=terrence, a=sledru
authorJon Coppeard <jcoppeard@mozilla.com>
Wed, 04 Mar 2015 10:25:07 +0000
changeset 257792 cad8615a378ce93965d4d7e41a4705509d45fb62
parent 257791 bde39a58935d277f7e0abaecf86969b0a879e89c
child 257793 16167d63e6b86c2ef9b9b06c27446371e8f72547
push id4610
push userjlund@mozilla.com
push dateMon, 30 Mar 2015 18:32:55 +0000
treeherdermozilla-beta@4df54044d9ef [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersterrence, sledru
bugs1137341
milestone38.0a2
Bug 1137341 - Don't allow GC to observe cross compartment prototype pointers for object groups. r=terrence, a=sledru
js/src/jit-test/tests/gc/bug-1137341.js
js/src/vm/HelperThreads.cpp
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/gc/bug-1137341.js
@@ -0,0 +1,8 @@
+if (helperThreadCount() == 0)
+   quit();
+
+schedulegc(this);
+startgc(0, "shrinking");
+var g = newGlobal();
+g.offThreadCompileScript('debugger;', {});
+g.runOffThreadScript();
--- a/js/src/vm/HelperThreads.cpp
+++ b/js/src/vm/HelperThreads.cpp
@@ -8,16 +8,17 @@
 
 #include "mozilla/DebugOnly.h"
 
 #include "jsnativestack.h"
 #include "jsnum.h" // For FIX_FPU()
 #include "prmjtime.h"
 
 #include "frontend/BytecodeCompiler.h"
+#include "gc/GCInternals.h"
 #include "jit/IonBuilder.h"
 #include "vm/Debugger.h"
 #include "vm/TraceLogging.h"
 
 #include "jscntxtinlines.h"
 #include "jscompartmentinlines.h"
 #include "jsobjinlines.h"
 #include "jsscriptinlines.h"
@@ -895,21 +896,25 @@ GlobalHelperThreadState::finishParseTask
         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.
+    // MergeCompartments call below.  It's not safe for a GC to observe this
+    // state, so finish any ongoing GC first and assert that we can't trigger
+    // another one.
+    gc::AutoFinishGC finishGC(rt);
     for (gc::ZoneCellIter iter(parseTask->cx->zone(), gc::FINALIZE_OBJECT_GROUP);
          !iter.done();
          iter.next())
     {
+        JS::AutoAssertNoAlloc noAlloc(rt);
         ObjectGroup *group = iter.get<ObjectGroup>();
         TaggedProto proto(group->proto());
         if (!proto.isObject())
             continue;
 
         JSProtoKey key = JS::IdentifyStandardPrototype(proto.toObject());
         if (key == JSProto_Null)
             continue;