From bb3a58359a268e13758b5b1e4ba2b27990debb16 Mon Sep 17 00:00:00 2001 From: Jon Coppeard Date: Wed, 10 Jul 2024 15:01:49 +0800 Subject: [PATCH] Don't sweep realms that were allocated during incremental GC r=jandem --- js/public/HeapAPI.h | 4 +++- js/src/gc/GC.cpp | 4 ++++ js/src/vm/Realm-inl.h | 12 +++++++++--- js/src/vm/Realm.cpp | 2 ++ js/src/vm/Realm.h | 3 ++- 5 files changed, 20 insertions(+), 5 deletions(-) diff --git a/js/public/HeapAPI.h b/js/public/HeapAPI.h index 593396288d..9c0192488d 100644 --- a/js/public/HeapAPI.h +++ b/js/public/HeapAPI.h @@ -237,7 +237,9 @@ struct Zone { bool isGCSweepingOrCompacting() const { return gcState_ == Sweep || gcState_ == Compact; } - + bool isGCMarkingOrSweeping() const { + return gcState() >= MarkBlackOnly && gcState() <= Sweep; + } static MOZ_ALWAYS_INLINE JS::shadow::Zone* from(JS::Zone* zone) { return reinterpret_cast(zone); } diff --git a/js/src/gc/GC.cpp b/js/src/gc/GC.cpp index 59b56f297a..a30e9fdbdc 100644 --- a/js/src/gc/GC.cpp +++ b/js/src/gc/GC.cpp @@ -6365,6 +6365,10 @@ void GCRuntime::finishCollection() { zone->notifyObservingDebuggers(); zone->updateGCStartThresholds(*this, invocationKind, lock); zone->arenas.checkGCStateNotInUse(); + for (RealmsInZoneIter realm(zone); !realm.done(); realm.next()) { + realm->clearAllocatedDuringGC(); + } + } } diff --git a/js/src/vm/Realm-inl.h b/js/src/vm/Realm-inl.h index 4672d976ad..4f7a000f5a 100644 --- a/js/src/vm/Realm-inl.h +++ b/js/src/vm/Realm-inl.h @@ -46,9 +46,15 @@ inline bool JS::Realm::hasLiveGlobal() const { } inline bool JS::Realm::marked() const { - // Preserve this Realm if it has a live global or if it has been entered (to - // ensure we don't destroy the Realm while we're allocating its global). - return hasLiveGlobal() || hasBeenEnteredIgnoringJit(); + // The Realm survives in the following cases: + // - its global is live + // - it has been entered (to ensure we don't destroy the Realm while we're + // allocating its global) + // - it was allocated after the start of an incremental GC (as there may be + // pointers to it from other GC things) + return hasLiveGlobal() || hasBeenEnteredIgnoringJit() || + allocatedDuringIncrementalGC_; + } /* static */ inline js::ObjectRealm& js::ObjectRealm::get(const JSObject* obj) { diff --git a/js/src/vm/Realm.cpp b/js/src/vm/Realm.cpp index 29a9f14d8d..64d727f191 100644 --- a/js/src/vm/Realm.cpp +++ b/js/src/vm/Realm.cpp @@ -59,6 +59,8 @@ Realm::Realm(Compartment* comp, const JS::RealmOptions& options) varNames_(zone_), randomKeyGenerator_(runtime_->forkRandomKeyGenerator()), debuggers_(zone_), + allocatedDuringIncrementalGC_(zone_->isGCMarkingOrSweeping() || + zone_->isGCFinished()), wasm(runtime_) { MOZ_ASSERT_IF(creationOptions_.mergeable(), creationOptions_.invisibleToDebugger()); diff --git a/js/src/vm/Realm.h b/js/src/vm/Realm.h index 591ac3feab..de7b8204b2 100644 --- a/js/src/vm/Realm.h +++ b/js/src/vm/Realm.h @@ -427,7 +427,7 @@ class JS::Realm : public JS::shadow::Realm { bool isSelfHostingRealm_ = false; bool isSystem_ = false; - + bool allocatedDuringIncrementalGC_; js::UniquePtr lcovRealm_ = nullptr; public: @@ -656,6 +656,7 @@ class JS::Realm : public JS::shadow::Realm { } inline bool marked() const; + void clearAllocatedDuringGC() { allocatedDuringIncrementalGC_ = false; } /* * The principals associated with this realm. Note that the same several -- 2.27.0