diff --git a/content/base/src/nsContentUtils.cpp b/content/base/src/nsContentUtils.cpp index 783fa5cfc51..d3b3dd7f820 100644 --- a/content/base/src/nsContentUtils.cpp +++ b/content/base/src/nsContentUtils.cpp @@ -6358,7 +6358,7 @@ public: { } - NS_IMETHOD_(void) NoteWeakMapping(void* map, void* key, void* val) + NS_IMETHOD_(void) NoteWeakMapping(void* map, void* key, void* kdelegate, void* val) { } diff --git a/js/src/jsfriendapi.cpp b/js/src/jsfriendapi.cpp index 1d985a0098f..0cdcd64d9e7 100644 --- a/js/src/jsfriendapi.cpp +++ b/js/src/jsfriendapi.cpp @@ -532,6 +532,14 @@ js::VisitGrayWrapperTargets(JSCompartment *comp, GCThingCallback *callback, void } } +JS_FRIEND_API(JSObject *) +js::GetWeakmapKeyDelegate(JSObject *key) +{ + if (JSWeakmapKeyDelegateOp op = key->getClass()->ext.weakmapKeyDelegateOp) + return op(key); + return NULL; +} + JS_FRIEND_API(void) JS_SetAccumulateTelemetryCallback(JSRuntime *rt, JSAccumulateTelemetryDataCallback callback) { diff --git a/js/src/jsfriendapi.h b/js/src/jsfriendapi.h index 6aa0c8fcdce..a5933eeb44b 100644 --- a/js/src/jsfriendapi.h +++ b/js/src/jsfriendapi.h @@ -265,6 +265,9 @@ typedef void extern JS_FRIEND_API(void) VisitGrayWrapperTargets(JSCompartment *comp, GCThingCallback *callback, void *closure); +extern JS_FRIEND_API(JSObject *) +GetWeakmapKeyDelegate(JSObject *key); + /* * Shadow declarations of JS internal structures, for access by inline access * functions below. Do not use these structures in any other way. When adding diff --git a/js/xpconnect/src/nsXPConnect.cpp b/js/xpconnect/src/nsXPConnect.cpp index 45db61ba67b..feaf1bc8853 100644 --- a/js/xpconnect/src/nsXPConnect.cpp +++ b/js/xpconnect/src/nsXPConnect.cpp @@ -398,6 +398,7 @@ struct NoteWeakMapChildrenTracer : public JSTracer nsCycleCollectionTraversalCallback &mCb; JSObject *mMap; void *mKey; + void *mKeyDelegate; }; static void @@ -412,7 +413,7 @@ TraceWeakMappingChild(JSTracer *trc, void **thingp, JSGCTraceKind kind) if (!xpc_IsGrayGCThing(thing) && !tracer->mCb.WantAllTraces()) return; if (AddToCCKind(kind)) { - tracer->mCb.NoteWeakMapping(tracer->mMap, tracer->mKey, thing); + tracer->mCb.NoteWeakMapping(tracer->mMap, tracer->mKey, tracer->mKeyDelegate, thing); } else { JS_TraceChildren(trc, thing, kind); } @@ -455,11 +456,16 @@ TraceWeakMapping(js::WeakMapTracer *trc, JSObject *m, if (!AddToCCKind(kkind)) k = nullptr; + JSObject *kdelegate = NULL; + if (kkind == JSTRACE_OBJECT) + kdelegate = js::GetWeakmapKeyDelegate((JSObject *)k); + if (AddToCCKind(vkind)) { - tracer->mCb.NoteWeakMapping(m, k, v); + tracer->mCb.NoteWeakMapping(m, k, kdelegate, v); } else { tracer->mChildTracer.mMap = m; tracer->mChildTracer.mKey = k; + tracer->mChildTracer.mKeyDelegate = kdelegate; JS_TraceChildren(&tracer->mChildTracer, v, vkind); } } diff --git a/xpcom/base/nsCycleCollector.cpp b/xpcom/base/nsCycleCollector.cpp index ff571bb0b96..ef97b3929ae 100644 --- a/xpcom/base/nsCycleCollector.cpp +++ b/xpcom/base/nsCycleCollector.cpp @@ -669,6 +669,7 @@ struct WeakMapping // map and key will be null if the corresponding objects are GC marked PtrInfo *mMap; PtrInfo *mKey; + PtrInfo *mKeyDelegate; PtrInfo *mVal; }; @@ -1678,7 +1679,7 @@ public: nsCycleCollectionParticipant *participant); NS_IMETHOD_(void) NoteNextEdgeName(const char* name); - NS_IMETHOD_(void) NoteWeakMapping(void *map, void *key, void *val); + NS_IMETHOD_(void) NoteWeakMapping(void *map, void *key, void *kdelegate, void *val); private: NS_IMETHOD_(void) NoteRoot(void *root, @@ -1968,7 +1969,7 @@ GCGraphBuilder::AddWeakMapNode(void *node) } NS_IMETHODIMP_(void) -GCGraphBuilder::NoteWeakMapping(void *map, void *key, void *val) +GCGraphBuilder::NoteWeakMapping(void *map, void *key, void *kdelegate, void *val) { PtrInfo *valNode = AddWeakMapNode(val); @@ -1978,6 +1979,7 @@ GCGraphBuilder::NoteWeakMapping(void *map, void *key, void *val) WeakMapping *mapping = mWeakMaps.AppendElement(); mapping->mMap = map ? AddWeakMapNode(map) : nullptr; mapping->mKey = key ? AddWeakMapNode(key) : nullptr; + mapping->mKeyDelegate = kdelegate ? AddWeakMapNode(kdelegate) : mapping->mKey; mapping->mVal = valNode; } @@ -2021,7 +2023,7 @@ public: NS_IMETHOD_(void) NoteNativeRoot(void *root, nsCycleCollectionParticipant *helper) {} NS_IMETHOD_(void) NoteNextEdgeName(const char* name) {} - NS_IMETHOD_(void) NoteWeakMapping(void *map, void *key, void *val) {} + NS_IMETHOD_(void) NoteWeakMapping(void *map, void *key, void *kdelegate, void *val) {} bool MayHaveChild() { return mMayHaveChild; } @@ -2206,15 +2208,22 @@ nsCycleCollector::ScanWeakMaps() // If mMap or mKey are null, the original object was marked black. uint32_t mColor = wm->mMap ? wm->mMap->mColor : black; uint32_t kColor = wm->mKey ? wm->mKey->mColor : black; + uint32_t kdColor = wm->mKeyDelegate ? wm->mKeyDelegate->mColor : black; PtrInfo *v = wm->mVal; // All non-null weak mapping maps, keys and values are // roots (in the sense of WalkFromRoots) in the cycle // collector graph, and thus should have been colored // either black or white in ScanRoots(). - NS_ASSERTION(mColor != grey, "Uncolored weak map"); - NS_ASSERTION(kColor != grey, "Uncolored weak map key"); - NS_ASSERTION(v->mColor != grey, "Uncolored weak map value"); + MOZ_ASSERT(mColor != grey, "Uncolored weak map"); + MOZ_ASSERT(kColor != grey, "Uncolored weak map key"); + MOZ_ASSERT(kdColor != grey, "Uncolored weak map key delegate"); + MOZ_ASSERT(v->mColor != grey, "Uncolored weak map value"); + + if (mColor == black && kColor != black && kdColor == black) { + GraphWalker(ScanBlackVisitor(mWhiteNodeCount)).Walk(wm->mKey); + anyChanged = true; + } if (mColor == black && kColor == black && v->mColor != black) { GraphWalker(ScanBlackVisitor(mWhiteNodeCount)).Walk(v); @@ -2471,7 +2480,7 @@ public: NS_IMETHOD_(void) NoteNativeChild(void *child, nsCycleCollectionParticipant *participant) {} NS_IMETHOD_(void) NoteNextEdgeName(const char* name) {} - NS_IMETHOD_(void) NoteWeakMapping(void *map, void *key, void *val) {} + NS_IMETHOD_(void) NoteWeakMapping(void *map, void *key, void *kdelegate, void *val) {} }; char *Suppressor::sSuppressionList = nullptr; diff --git a/xpcom/glue/nsCycleCollectionParticipant.h b/xpcom/glue/nsCycleCollectionParticipant.h index b4ac1843e5b..28c5855683b 100644 --- a/xpcom/glue/nsCycleCollectionParticipant.h +++ b/xpcom/glue/nsCycleCollectionParticipant.h @@ -84,7 +84,7 @@ public: // flags. NS_IMETHOD_(void) NoteNextEdgeName(const char* name) = 0; - NS_IMETHOD_(void) NoteWeakMapping(void *map, void *key, void *val) = 0; + NS_IMETHOD_(void) NoteWeakMapping(void *map, void *key, void *kdelegate, void *val) = 0; enum { // Values for flags: