summaryrefslogtreecommitdiff
path: root/src/third_party/mozjs-45/extract/js/src/jsgc.cpp
diff options
context:
space:
mode:
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.cpp54
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)