diff --git a/js/src/gc/Marking.h b/js/src/gc/Marking.h index 94f4fdea1c53..499becc6aad8 100644 --- a/js/src/gc/Marking.h +++ b/js/src/gc/Marking.h @@ -280,6 +280,12 @@ Mark(JSTracer *trc, HeapPtr *code, const char *name) MarkIonCode(trc, code, name); } +inline void +Mark(JSTracer *trc, JSObject **objp, const char *name) +{ + MarkObjectUnbarriered(trc, objp, name); +} + bool IsCellMarked(Cell **thingp); diff --git a/js/src/jsapi.h b/js/src/jsapi.h index 542f9504e5cd..82743e610a4b 100644 --- a/js/src/jsapi.h +++ b/js/src/jsapi.h @@ -2472,7 +2472,8 @@ typedef void enum WeakMapTraceKind { DoNotTraceWeakMaps = 0, - TraceWeakMapValues = 1 + TraceWeakMapValues = 1, + TraceWeakMapKeysValues = 2 }; struct JSTracer { diff --git a/js/src/jsweakmap.h b/js/src/jsweakmap.h index a3d130702292..47a7f42eff72 100644 --- a/js/src/jsweakmap.h +++ b/js/src/jsweakmap.h @@ -50,7 +50,7 @@ class WeakMapBase { // many keys as possible have been marked, and add ourselves to the list of // known-live WeakMaps to be scanned in the iterative marking phase, by // markAllIteratively. - JS_ASSERT(!tracer->eagerlyTraceWeakMaps); + JS_ASSERT(tracer->eagerlyTraceWeakMaps == DoNotTraceWeakMaps); // Add ourselves to the list if we are not already in the list. We can already // be in the list if the weak map is marked more than once due delayed marking. @@ -63,8 +63,12 @@ class WeakMapBase { // nicely as needed by the true ephemeral marking algorithm --- custom tracers // such as the cycle collector must use their own means for cycle detection. // So here we do a conservative approximation: pretend all keys are live. - if (tracer->eagerlyTraceWeakMaps) - nonMarkingTrace(tracer); + if (tracer->eagerlyTraceWeakMaps == DoNotTraceWeakMaps) + return; + + nonMarkingTraceValues(tracer); + if (tracer->eagerlyTraceWeakMaps == TraceWeakMapKeysValues) + nonMarkingTraceKeys(tracer); } } @@ -100,7 +104,8 @@ class WeakMapBase { protected: // Instance member functions called by the above. Instantiations of WeakMap override // these with definitions appropriate for their Key and Value types. - virtual void nonMarkingTrace(JSTracer *tracer) = 0; + virtual void nonMarkingTraceKeys(JSTracer *tracer) = 0; + virtual void nonMarkingTraceValues(JSTracer *tracer) = 0; virtual bool markIteratively(JSTracer *tracer) = 0; virtual void sweep() = 0; virtual void traceMappings(WeakMapTracer *tracer) = 0; @@ -141,7 +146,16 @@ class WeakMap : public HashMap, publ return true; } - void nonMarkingTrace(JSTracer *trc) { + void nonMarkingTraceKeys(JSTracer *trc) { + for (Enum e(*this); !e.empty(); e.popFront()) { + Key key(e.front().key); + gc::Mark(trc, &key, "WeakMap Key"); + if (key != e.front().key) + e.rekeyFront(key, key); + } + } + + void nonMarkingTraceValues(JSTracer *trc) { for (Range r = Base::all(); !r.empty(); r.popFront()) gc::Mark(trc, &r.front().value, "WeakMap entry"); } @@ -190,6 +204,8 @@ class WeakMap : public HashMap, publ Key k(e.front().key); if (gc::IsAboutToBeFinalized(&k)) e.removeFront(); + else if (k != e.front().key) + e.rekeyFront(k, k); } /* * Once we've swept, all remaining edges should stay within the