Bug 1137336 - Explicitly disallow WeakMapTracer.callback from GCing. r=terrence, a=lsblakk
authorSteve Fink <sfink@mozilla.com>
Mon, 02 Mar 2015 10:25:16 -0800
changeset 257504 cc28574bd2c5edaf508c0c76d70fcd98d41ba1a2
parent 257503 2a92625b924e1d6c87e686757f01d33b04a6f16e
child 257505 3ebd765486ce4d2fcd499b3ca97288faf0f25ff2
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, lsblakk
bugs1137336
milestone38.0a2
Bug 1137336 - Explicitly disallow WeakMapTracer.callback from GCing. r=terrence, a=lsblakk
js/src/jsfriendapi.h
js/src/jsweakmap.cpp
--- a/js/src/jsfriendapi.h
+++ b/js/src/jsfriendapi.h
@@ -451,16 +451,18 @@ IsInNonStrictPropertySet(JSContext *cx);
 
 struct WeakMapTracer;
 
 /*
  * Weak map tracer callback, called once for every binding of every
  * weak map that was live at the time of the last garbage collection.
  *
  * m will be nullptr if the weak map is not contained in a JS Object.
+ *
+ * The callback should not GC (and will assert in a debug build if it does so.)
  */
 typedef void
 (* WeakMapTraceCallback)(WeakMapTracer *trc, JSObject *m, JS::GCCellPtr key, JS::GCCellPtr value);
 
 struct WeakMapTracer {
     JSRuntime            *runtime;
     WeakMapTraceCallback callback;
 
--- a/js/src/jsweakmap.cpp
+++ b/js/src/jsweakmap.cpp
@@ -9,16 +9,17 @@
 #include <string.h>
 
 #include "jsapi.h"
 #include "jscntxt.h"
 #include "jsfriendapi.h"
 #include "jsobj.h"
 #include "jswrapper.h"
 
+#include "js/GCAPI.h"
 #include "vm/GlobalObject.h"
 #include "vm/WeakMapObject.h"
 
 #include "jsobjinlines.h"
 
 #include "vm/Interpreter-inl.h"
 #include "vm/NativeObject-inl.h"
 
@@ -127,18 +128,21 @@ WeakMapBase::sweepCompartment(JSCompartm
 #endif
 }
 
 void
 WeakMapBase::traceAllMappings(WeakMapTracer *tracer)
 {
     JSRuntime *rt = tracer->runtime;
     for (CompartmentsIter c(rt, SkipAtoms); !c.done(); c.next()) {
-        for (WeakMapBase *m = c->gcWeakMapList; m; m = m->next)
+        for (WeakMapBase *m = c->gcWeakMapList; m; m = m->next) {
+            // The WeakMapTracer callback is not allowed to GC.
+            JS::AutoSuppressGCAnalysis nogc;
             m->traceMappings(tracer);
+        }
     }
 }
 
 bool
 WeakMapBase::saveCompartmentMarkedWeakMaps(JSCompartment *c, WeakMapSet &markedWeakMaps)
 {
     for (WeakMapBase *m = c->gcWeakMapList; m; m = m->next) {
         if (m->marked && !markedWeakMaps.put(m))