Bug 1736604 - Part 1: Replace sweeping with tracing weak edges in WeakRef implementation r=sfink

Differential Revision: https://phabricator.services.mozilla.com/D128901
This commit is contained in:
Jon Coppeard 2021-10-20 09:31:23 +00:00
Родитель 48823d0e19
Коммит 3649131338
4 изменённых файлов: 21 добавлений и 22 удалений

Просмотреть файл

@ -298,23 +298,27 @@ void GCRuntime::traceKeptObjects(JSTracer* trc) {
} // namespace gc
void WeakRefMap::sweep(gc::StoreBuffer* sbToLock) {
static WeakRefObject* UnwrapWeakRef(JSObject* obj) {
MOZ_ASSERT(!JS_IsDeadWrapper(obj));
obj = UncheckedUnwrapWithoutExpose(obj);
return &obj->as<WeakRefObject>();
}
void WeakRefMap::traceWeak(JSTracer* trc, gc::StoreBuffer* sbToLock) {
mozilla::Maybe<typename Base::Enum> e;
for (e.emplace(*this); !e->empty(); e->popFront()) {
// If target is dying, clear the target field of all weakRefs, and remove
// the entry from the map.
if (JS::GCPolicy<HeapPtrObject>::needsSweep(&e->front().mutableKey())) {
auto result =
TraceWeakEdge(trc, &e->front().mutableKey(), "WeakRef target");
if (result.isDead()) {
for (JSObject* obj : e->front().value()) {
MOZ_ASSERT(!JS_IsDeadWrapper(obj));
obj = UncheckedUnwrapWithoutExpose(obj);
WeakRefObject* weakRef = &obj->as<WeakRefObject>();
weakRef->clearTarget();
UnwrapWeakRef(obj)->clearTarget();
}
e->removeFront();
} else {
// Update the target field after compacting.
e->front().value().sweep(e->front().mutableKey());
e->front().value().traceWeak(trc, result.finalTarget());
}
}
@ -326,20 +330,15 @@ void WeakRefMap::sweep(gc::StoreBuffer* sbToLock) {
// Like GCVector::sweep, but this method will also update the target in every
// weakRef in this GCVector.
void WeakRefHeapPtrVector::sweep(HeapPtrObject& target) {
void WeakRefHeapPtrVector::traceWeak(JSTracer* trc, JSObject* target) {
HeapPtrObject* src = begin();
HeapPtrObject* dst = begin();
while (src != end()) {
bool needsSweep = JS::GCPolicy<HeapPtrObject>::needsSweep(src);
JSObject* obj = UncheckedUnwrapWithoutExpose(*src);
MOZ_ASSERT(!JS_IsDeadWrapper(obj));
WeakRefObject* weakRef = &obj->as<WeakRefObject>();
if (needsSweep) {
weakRef->clearTarget();
auto result = TraceWeakEdge(trc, src, "WeakRef");
if (result.isDead()) {
UnwrapWeakRef(result.initialTarget())->clearTarget();
} else {
weakRef->setTargetUnbarriered(target.get());
UnwrapWeakRef(result.finalTarget())->setTargetUnbarriered(target);
if (src != dst) {
*dst = std::move(*src);

Просмотреть файл

@ -457,7 +457,7 @@ void Zone::prepareForCompacting() {
void GCRuntime::sweepZoneAfterCompacting(MovingTracer* trc, Zone* zone) {
MOZ_ASSERT(zone->isCollecting());
traceWeakFinalizationRegistryEdges(trc, zone);
zone->weakRefMap().sweep(&storeBuffer());
zone->weakRefMap().traceWeak(trc, &storeBuffer());
zone->traceWeakMaps(trc);

Просмотреть файл

@ -1276,7 +1276,7 @@ bool UniqueIdGCPolicy::traceWeak(JSTracer* trc, Cell** keyp, uint64_t* valuep) {
void GCRuntime::sweepWeakRefs() {
for (SweepGroupZonesIter zone(this); !zone.done(); zone.next()) {
AutoSetThreadIsSweeping threadIsSweeping(zone);
zone->weakRefMap().sweep(&storeBuffer());
zone->weakRefMap().traceWeak(&sweepingTracer, &storeBuffer());
}
}

Просмотреть файл

@ -116,7 +116,7 @@ class WeakRefHeapPtrVector
using GCVector::GCVector;
// call in compacting, to update the target in each WeakRefObject.
void sweep(js::HeapPtrObject& target);
void traceWeak(JSTracer* trc, JSObject* target);
};
// WeakRefMap is a per-zone GCHashMap, which maps from the target of the JS
@ -128,7 +128,7 @@ class WeakRefMap
using GCHashMap::GCHashMap;
using Base = GCHashMap<HeapPtrObject, WeakRefHeapPtrVector,
MovableCellHasher<HeapPtrObject>, ZoneAllocPolicy>;
void sweep(gc::StoreBuffer* sbToLock);
void traceWeak(JSTracer* trc, gc::StoreBuffer* sbToLock);
};
} // namespace js