blob: bcd167538286777dd20a05ae8c61bcc21bd93faa [file] [log] [blame]
--- jsweakmap.h
+++ jsweakmap.h
@@ -78,17 +78,17 @@ class WeakMapBase {
// Restore information about which weak maps are marked for many compartments.
static void restoreCompartmentMarkedWeakMaps(WeakMapSet& markedWeakMaps);
// Remove a weakmap from its compartment's weakmaps list.
static void removeWeakMapFromList(WeakMapBase* weakmap);
// Object keys must participate in ephemeron marking by overriding this method.
- virtual void maybeMarkEntry(JSTracer* trc, gc::Cell* l) = 0;
+ virtual void maybeMarkEntry(JSTracer* trc, gc::Cell* markedCell, JS::GCCellPtr l) = 0;
protected:
// Instance member functions called by the above. Instantiations of WeakMap override
// these with definitions appropriate for their Key and Value types.
virtual void nonMarkingTraceKeys(JSTracer* tracer) = 0;
virtual void nonMarkingTraceValues(JSTracer* tracer) = 0;
virtual bool markIteratively(JSTracer* tracer) = 0;
virtual void markEphemeronEntries(JSTracer* trc) = 0;
@@ -160,65 +160,76 @@ class WeakMap : public HashMap<Key, Valu
return p;
}
// The WeakMap and some part of the key are marked. Mark the value if the
// key is "fully marked" according to the exact semantics of this WeakMap.
// (For a standard WeakMap, the key is either marked or not, so just mark
// the value here. But a subclass might have multipart keys with more
// complicated semantics.)
- virtual void maybeMarkEntry(JSTracer* trc, gc::Cell* l)
+ virtual void maybeMarkEntry(JSTracer* trc, gc::Cell* markedCell, JS::GCCellPtr origKey)
{
MOZ_ASSERT(marked);
+ gc::Cell* l = origKey.asCell();
Ptr p = Base::lookup(reinterpret_cast<const Lookup&>(l));
Key key(p->key());
- if (gc::IsMarked(&key))
+ if (gc::IsMarked(&key)) {
TraceEdge(trc, &p->value(), "ephemeron value");
+ } else if (keyNeedsMark(key)) {
+ TraceEdge(trc, &p->value(), "WeakMap ephemeron value");
+ TraceEdge(trc, &key, "proxy-preserved WeakMap ephemeron key");
+ MOZ_ASSERT(key == p->key()); // No moving
+ }
key.unsafeSet(nullptr);
}
protected:
+ static void addWeakEntry(JSTracer* trc, JS::GCCellPtr key, gc::WeakMarkable markable)
+ {
+ GCMarker& marker = *static_cast<GCMarker*>(trc);
+
+ auto p = marker.weakKeys.get(key);
+ if (p) {
+ gc::WeakEntryVector& weakEntries = p->value;
+ if (!weakEntries.append(Move(markable)))
+ marker.abortLinearWeakMarking();
+ } else {
+ gc::WeakEntryVector weakEntries;
+ JS_ALWAYS_TRUE(weakEntries.append(Move(markable)));
+ if (!marker.weakKeys.put(JS::GCCellPtr(key), Move(weakEntries)))
+ marker.abortLinearWeakMarking();
+ }
+ }
+
virtual void markEphemeronEntries(JSTracer* trc) {
- gc::WeakKeyTable& weakKeys = static_cast<GCMarker*>(trc)->weakKeys;
-
MOZ_ASSERT(marked);
for (Enum e(*this); !e.empty(); e.popFront()) {
Key key(e.front().key());
// If the entry is live, ensure its key and value are marked.
if (gc::IsMarked(&key)) {
(void) markValue(trc, &e.front().value());
- if (e.front().key() != key)
- entryMoved(e, key);
+ MOZ_ASSERT(key == e.front().key()); // No moving
} else if (keyNeedsMark(key)) {
TraceEdge(trc, &e.front().value(), "WeakMap entry value");
TraceEdge(trc, &key, "proxy-preserved WeakMap entry key");
- if (e.front().key() != key)
- entryMoved(e, key);
+ MOZ_ASSERT(key == e.front().key()); // No moving
} else {
// Entry is not known to be live yet. Record it in the list of
- // weak keys. Or rather, record a pointer to this weakmap, so
- // we can look the key up again when we need to (to allow
- // incremental weak marking.)
- auto p = weakKeys.get(JS::GCCellPtr(key));
- if (p) {
- gc::WeakEntryVector& weakEntries = p->value;
- if (!weakEntries.append(this)) {
- static_cast<GCMarker*>(trc)->endWeakMarkingPhase();
- break;
- }
- } else {
- gc::WeakEntryVector weakEntries;
- JS_ALWAYS_TRUE(weakEntries.append(this));
- if (!weakKeys.put(JS::GCCellPtr(key), Move(weakEntries))) {
- static_cast<GCMarker*>(trc)->endWeakMarkingPhase();
- break;
- }
- }
+ // weak keys. Or rather, record this weakmap and the lookup key
+ // so we can repeat the lookup when we need to (to allow
+ // incremental weak marking, we can't just store a pointer to
+ // the entry.) Also record the delegate, if any, because
+ // marking the delegate must also mark the entry.
+ JS::GCCellPtr weakKey(key);
+ gc::WeakMarkable markable(this, weakKey);
+ addWeakEntry(trc, weakKey, markable);
+ if (JSObject* delegate = getDelegate(key))
+ addWeakEntry(trc, JS::GCCellPtr(delegate), markable);
}
key.unsafeSet(nullptr);
}
}
private:
void exposeGCThingToActiveJS(const JS::Value& v) const { JS::ExposeValueToActiveJS(v); }
void exposeGCThingToActiveJS(JSObject* obj) const { JS::ExposeObjectToActiveJS(obj); }