diff options
Diffstat (limited to 'src/third_party/mozjs-45/extract/js/src/jsgc.cpp')
-rw-r--r-- | src/third_party/mozjs-45/extract/js/src/jsgc.cpp | 54 |
1 files changed, 49 insertions, 5 deletions
diff --git a/src/third_party/mozjs-45/extract/js/src/jsgc.cpp b/src/third_party/mozjs-45/extract/js/src/jsgc.cpp index 776ebef6563..4ff0ca95182 100644 --- a/src/third_party/mozjs-45/extract/js/src/jsgc.cpp +++ b/src/third_party/mozjs-45/extract/js/src/jsgc.cpp @@ -4528,8 +4528,8 @@ DropStringWrappers(JSRuntime* rt) * * If compartment A has an edge to an unmarked object in compartment B, then we * must not sweep A in a later slice than we sweep B. That's because a write - * barrier in A that could lead to the unmarked object in B becoming - * marked. However, if we had already swept that object, we would be in trouble. + * barrier in A could lead to the unmarked object in B becoming marked. + * However, if we had already swept that object, we would be in trouble. * * If we consider these dependencies as a graph, then all the compartments in * any strongly-connected component of this graph must be swept in the same @@ -4573,6 +4573,30 @@ JSCompartment::findOutgoingEdges(ComponentFinder<JS::Zone>& finder) } } +bool +JSCompartment::findDeadProxyZoneEdges(bool* foundAny) +{ + // As an optimization, return whether any dead proxy objects are found in + // this compartment so that if a zone has none, its cross compartment + // wrappers do not need to be scanned. + *foundAny = false; + for (js::WrapperMap::Enum e(crossCompartmentWrappers); !e.empty(); e.popFront()) { + Value value = e.front().value().get(); + if (value.isObject()) { + if (IsDeadProxyObject(&value.toObject())) { + *foundAny = true; + Zone* wrappedZone = static_cast<JSObject*>(e.front().key().wrapped)->zone(); + if (!wrappedZone->isGCMarking()) + continue; + if (!wrappedZone->gcZoneGroupEdges.put(zone())) + return false; + } + } + } + + return true; +} + void Zone::findOutgoingEdges(ComponentFinder<JS::Zone>& finder) { @@ -4596,7 +4620,7 @@ Zone::findOutgoingEdges(ComponentFinder<JS::Zone>& finder) } bool -GCRuntime::findZoneEdgesForWeakMaps() +GCRuntime::findInterZoneEdges() { /* * Weakmaps which have keys with delegates in a different zone introduce the @@ -4613,6 +4637,20 @@ GCRuntime::findZoneEdgesForWeakMaps() return false; } + for (GCZonesIter zone(rt); !zone.done(); zone.next()) { + if (zone->hasDeadProxies) { + bool foundInZone = false; + for (CompartmentsInZoneIter comp(zone); !comp.done(); comp.next()) { + bool foundInCompartment = false; + if (!comp->findDeadProxyZoneEdges(&foundInCompartment)) + return false; + foundInZone = foundInZone || foundInCompartment; + } + if (!foundInZone) + zone->hasDeadProxies = false; + } + } + return true; } @@ -4625,7 +4663,7 @@ GCRuntime::findZoneGroups() #endif ComponentFinder<Zone> finder(rt->mainThread.nativeStackLimit[StackForSystemCode]); - if (!isIncremental || !findZoneEdgesForWeakMaps()) + if (!isIncremental || !findInterZoneEdges()) finder.useOneComponent(); for (GCZonesIter zone(rt); !zone.done(); zone.next()) { @@ -4886,6 +4924,8 @@ js::NotifyGCNukeWrapper(JSObject* obj) * remember to mark it. */ RemoveFromGrayList(obj); + + obj->zone()->hasDeadProxies = true; } enum { @@ -7474,7 +7514,11 @@ JS::IsIncrementalGCInProgress(JSRuntime* rt) JS_PUBLIC_API(bool) JS::IsIncrementalBarrierNeeded(JSRuntime* rt) { - return rt->gc.state() == gc::MARK && !rt->isHeapBusy(); + if (rt->isHeapBusy()) + return false; + + auto state = rt->gc.state(); + return state != gc::NO_INCREMENTAL && state <= gc::SWEEP; } JS_PUBLIC_API(bool) |