From 77e5d2474d81f7a42876cd7ab755044564654d1c Mon Sep 17 00:00:00 2001 From: Andrew McCreight Date: Sun, 4 Sep 2011 11:25:49 -0700 Subject: [PATCH] Bug 681104 - Add JSTracer flag to disable visiting WeakMap mappings. r=billm --- js/src/jsapi.h | 6 ++++++ js/src/jsgc.cpp | 8 +++++++- js/src/jsweakmap.h | 4 +++- js/src/xpconnect/src/nsXPConnect.cpp | 4 ++++ 4 files changed, 20 insertions(+), 2 deletions(-) diff --git a/js/src/jsapi.h b/js/src/jsapi.h index 3efe7cc1804c..f8d5d6fa14aa 100644 --- a/js/src/jsapi.h +++ b/js/src/jsapi.h @@ -1659,6 +1659,10 @@ JSVAL_TRACE_KIND(jsval v) * internal implementation-specific traversal kind. In the latter case the only * operations on thing that the callback can do is to call JS_TraceChildren or * DEBUG-only JS_PrintTraceThingInfo. + * + * If eagerlyTraceWeakMaps is true, when we trace a WeakMap visit all + * of its mappings. This should be used in cases where the tracer + * wants to use the existing liveness of entries. */ typedef void (* JSTraceCallback)(JSTracer *trc, void *thing, JSGCTraceKind kind); @@ -1669,6 +1673,7 @@ struct JSTracer { JSTraceNamePrinter debugPrinter; const void *debugPrintArg; size_t debugPrintIndex; + JSBool eagerlyTraceWeakMaps; }; /* @@ -1768,6 +1773,7 @@ JS_CallTracer(JSTracer *trc, void *thing, JSGCTraceKind kind); (trc)->debugPrinter = NULL; \ (trc)->debugPrintArg = NULL; \ (trc)->debugPrintIndex = (size_t)-1; \ + (trc)->eagerlyTraceWeakMaps = JS_TRUE; \ JS_END_MACRO extern JS_PUBLIC_API(void) diff --git a/js/src/jsgc.cpp b/js/src/jsgc.cpp index 291de7cf1ae1..3c8e31735f0f 100644 --- a/js/src/jsgc.cpp +++ b/js/src/jsgc.cpp @@ -1555,6 +1555,12 @@ GCMarker::GCMarker(JSContext *cx) conservativeDumpFileName = getenv("JS_DUMP_CONSERVATIVE_GC_ROOTS"); memset(&conservativeStats, 0, sizeof(conservativeStats)); #endif + + /* + * The GC is recomputing the liveness of WeakMap entries, so we + * delay visting entries. + */ + eagerlyTraceWeakMaps = JS_FALSE; } GCMarker::~GCMarker() @@ -1579,7 +1585,7 @@ GCMarker::delayMarkingChildren(const void *thing) } static void -MarkDelayedChildren(JSTracer *trc, Arena *a) +MarkDelayedChildren(GCMarker *trc, Arena *a) { AllocKind allocKind = a->aheader.getAllocKind(); JSGCTraceKind traceKind = MapAllocToTraceKind(allocKind); diff --git a/js/src/jsweakmap.h b/js/src/jsweakmap.h index 1d8c09ec3cb3..85842c7adcf8 100644 --- a/js/src/jsweakmap.h +++ b/js/src/jsweakmap.h @@ -144,6 +144,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); JSRuntime *rt = tracer->context->runtime; next = rt->gcWeakMapList; rt->gcWeakMapList = this; @@ -152,7 +153,8 @@ class WeakMapBase { // nicely as needed by the true ephemeral marking algorithm --- custom tracers // must use their own means for cycle detection. So here we do a conservative // approximation: pretend all keys are live. - nonMarkingTrace(tracer); + if (tracer->eagerlyTraceWeakMaps) + nonMarkingTrace(tracer); } } diff --git a/js/src/xpconnect/src/nsXPConnect.cpp b/js/src/xpconnect/src/nsXPConnect.cpp index ee51bc643c7a..61cd83993670 100644 --- a/js/src/xpconnect/src/nsXPConnect.cpp +++ b/js/src/xpconnect/src/nsXPConnect.cpp @@ -880,6 +880,10 @@ nsXPConnect::Traverse(void *p, nsCycleCollectionTraversalCallback &cb) TraversalTracer trc(cb); JS_TRACER_INIT(&trc, cx, NoteJSChild); + // When WeakMaps are properly integrated with the cycle + // collector in Bug 668855, don't eagerly trace weak maps when + // building the cycle collector graph. + // trc.eagerlyTraceWeakMaps = JS_FALSE; JS_TraceChildren(&trc, p, traceKind); if(traceKind != JSTRACE_OBJECT || dontTraverse)