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 250240 ea414ee32231
parent 250239 10eff960b898
child 250241 5f1674957fe4
push id4524
push userryanvm@gmail.com
push date2015-03-04 18:49 +0000
treeherdermozilla-beta@666a1aafecfd [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersterrence, lsblakk
bugs1137336
milestone37.0
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
@@ -482,16 +482,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"
 
 using namespace js;
@@ -126,18 +127,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))