Bug 1252453: make Debugger::slowPathOnLogAllocationSite apply a read barrier to Debugger objects. r=terrence
authorJim Blandy <jimb@mozilla.com>
Mon, 07 Mar 2016 17:21:29 -0800
changeset 287140 1d94c77de685b57c7279435cd2cd2ab24adc98da
parent 287139 69448e1e7e45d1ae79da63b75c4d90b613f5adc4
child 287141 ae16b59ad2809f4e6a80af90cc691c789a42c316
push id73074
push userjblandy@mozilla.com
push dateTue, 08 Mar 2016 07:41:03 +0000
treeherdermozilla-inbound@1d94c77de685 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersterrence
bugs1252453
milestone47.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 1252453: make Debugger::slowPathOnLogAllocationSite apply a read barrier to Debugger objects. r=terrence
js/src/jit-test/tests/debug/bug1252453.js
js/src/vm/Debugger.cpp
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/debug/bug1252453.js
@@ -0,0 +1,21 @@
+// |jit-test| --no-threads
+
+lfcode = new Array();
+gczeal(8,2);
+lfcode.push(`
+const root = newGlobal();
+const dbg = new Debugger;
+const wrappedRoot = dbg.addDebuggee(root);
+dbg.memory.trackingAllocationSites = 1;
+root.eval("(" + function immediate() { '_'  << foo } + "())");
+`);
+file = lfcode.shift();
+loadFile(file);
+function loadFile(lfVarx) {
+    try {
+        function newFunc(x) Function(x)();
+        newFunc(lfVarx)();
+    } catch (lfVare) {
+        print(lfVare)
+    }
+}
--- a/js/src/vm/Debugger.cpp
+++ b/js/src/vm/Debugger.cpp
@@ -1936,16 +1936,21 @@ Debugger::slowPathOnLogAllocationSite(JS
     // appendAllocationSite calls JSCompartment::wrap, and thus can GC.
     //
     // SpiderMonkey protocol is generally for the caller to prove that it has
     // rooted the stuff it's asking you to operate on (i.e. by passing a
     // Handle), but in this case, we're iterating over a global's list of
     // Debuggers, and globals only hold their Debuggers weakly.
     Rooted<GCVector<JSObject*>> activeDebuggers(cx, GCVector<JSObject*>(cx));
     for (Debugger** dbgp = dbgs.begin(); dbgp < dbgs.end(); dbgp++) {
+        // Since we're pulling these Debugger objects out of the GlobalObject's
+        // debugger array, which holds them only weakly, we need to let the
+        // incremental GC know that a possibly previously unreachable Debugger
+        // object just became reachable.
+        InternalBarrierMethods<JSObject*>::readBarrier((*dbgp)->object);
         if (!activeDebuggers.append((*dbgp)->object))
             return false;
     }
 
     for (Debugger** dbgp = dbgs.begin(); dbgp < dbgs.end(); dbgp++) {
         // The set of debuggers had better not change while we're iterating,
         // such that the vector gets reallocated.
         MOZ_ASSERT(dbgs.begin() == begin);