зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1655768 - Part 2: Remove MergeRealms. r=jonco
Differential Revision: https://phabricator.services.mozilla.com/D131374
This commit is contained in:
Родитель
b1241a3ef6
Коммит
aab63687b4
|
@ -322,9 +322,6 @@ class ArenaLists {
|
|||
|
||||
MOZ_ALWAYS_INLINE TenuredCell* allocateFromFreeList(AllocKind thingKind);
|
||||
|
||||
/* Moves all arenas from |fromArenaLists| into |this|. */
|
||||
void adoptArenas(ArenaLists* fromArenaLists, bool targetZoneIsCollecting);
|
||||
|
||||
inline void checkEmptyFreeLists();
|
||||
inline void checkEmptyArenaLists();
|
||||
inline void checkEmptyFreeList(AllocKind kind);
|
||||
|
|
|
@ -188,12 +188,6 @@ void AtomMarkingRuntime::markAtomValue(JSContext* cx, const Value& value) {
|
|||
value.isBigInt());
|
||||
}
|
||||
|
||||
void AtomMarkingRuntime::adoptMarkedAtoms(Zone* target, Zone* source) {
|
||||
MOZ_ASSERT(CurrentThreadCanAccessZone(source));
|
||||
MOZ_ASSERT(CurrentThreadCanAccessZone(target));
|
||||
target->markedAtoms().bitwiseOrWith(source->markedAtoms());
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
template <typename T>
|
||||
bool AtomMarkingRuntime::atomIsMarked(Zone* zone, T* thing) {
|
||||
|
|
|
@ -70,9 +70,6 @@ class AtomMarkingRuntime {
|
|||
void markId(JSContext* cx, jsid id);
|
||||
void markAtomValue(JSContext* cx, const Value& value);
|
||||
|
||||
// Mark all atoms in |source| as being reachable within |target|.
|
||||
void adoptMarkedAtoms(Zone* target, Zone* source);
|
||||
|
||||
#ifdef DEBUG
|
||||
// Return whether |thing/id| is in the atom marking bitmap for |zone|.
|
||||
template <typename T>
|
||||
|
|
165
js/src/gc/GC.cpp
165
js/src/gc/GC.cpp
|
@ -1903,19 +1903,6 @@ void Compartment::sweepRealms(JSFreeOp* fop, bool keepAtleastOne,
|
|||
MOZ_ASSERT_IF(destroyingRuntime, realms().empty());
|
||||
}
|
||||
|
||||
void GCRuntime::deleteEmptyZone(Zone* zone) {
|
||||
MOZ_ASSERT(CurrentThreadCanAccessRuntime(rt));
|
||||
MOZ_ASSERT(zone->compartments().empty());
|
||||
for (auto& i : zones()) {
|
||||
if (i == zone) {
|
||||
zones().erase(&i);
|
||||
zone->destroy(rt->defaultFreeOp());
|
||||
return;
|
||||
}
|
||||
}
|
||||
MOZ_CRASH("Zone not found");
|
||||
}
|
||||
|
||||
void GCRuntime::sweepZones(JSFreeOp* fop, bool destroyingRuntime) {
|
||||
MOZ_ASSERT_IF(destroyingRuntime, numActiveZoneIters == 0);
|
||||
|
||||
|
@ -4204,115 +4191,6 @@ Realm* js::NewRealm(JSContext* cx, JSPrincipals* principals,
|
|||
return realm.release();
|
||||
}
|
||||
|
||||
void gc::MergeRealms(Realm* source, Realm* target) {
|
||||
JSRuntime* rt = source->runtimeFromMainThread();
|
||||
rt->gc.mergeRealms(source, target);
|
||||
rt->gc.maybeTriggerGCAfterAlloc(target->zone());
|
||||
rt->gc.maybeTriggerGCAfterMalloc(target->zone());
|
||||
}
|
||||
|
||||
void GCRuntime::mergeRealms(Realm* source, Realm* target) {
|
||||
// The source realm must be specifically flagged as mergable. This
|
||||
// also implies that the realm is not visible to the debugger.
|
||||
//
|
||||
// TODO: Remove
|
||||
MOZ_ASSERT(false);
|
||||
MOZ_ASSERT(source->creationOptions().invisibleToDebugger());
|
||||
|
||||
MOZ_ASSERT(!source->hasBeenEnteredIgnoringJit());
|
||||
MOZ_ASSERT(source->zone()->compartments().length() == 1);
|
||||
|
||||
JSContext* cx = rt->mainContextFromOwnThread();
|
||||
|
||||
MOZ_ASSERT(!source->zone()->wasGCStarted());
|
||||
JS::AutoAssertNoGC nogc(cx);
|
||||
|
||||
AutoTraceSession session(rt);
|
||||
|
||||
// Cleanup tables and other state in the source realm/zone that will be
|
||||
// meaningless after merging into the target realm/zone.
|
||||
|
||||
source->clearTables();
|
||||
source->zone()->clearTables();
|
||||
source->unsetIsDebuggee();
|
||||
|
||||
#ifdef DEBUG
|
||||
// Release any relocated arenas which we may be holding on to as they might
|
||||
// be in the source zone
|
||||
releaseHeldRelocatedArenas();
|
||||
#endif
|
||||
|
||||
// Fixup realm pointers in source to refer to target, and make sure
|
||||
// type information generations are in sync.
|
||||
|
||||
GlobalObject* global = target->maybeGlobal();
|
||||
MOZ_ASSERT(global);
|
||||
AssertTargetIsNotGray(global);
|
||||
|
||||
for (auto baseShape = source->zone()->cellIterUnsafe<BaseShape>();
|
||||
!baseShape.done(); baseShape.next()) {
|
||||
baseShape->setRealmForMergeRealms(target);
|
||||
}
|
||||
|
||||
// Fixup zone pointers in source's zone to refer to target's zone.
|
||||
|
||||
bool targetZoneIsCollecting = target->zone()->gcState() > Zone::Prepare;
|
||||
for (auto thingKind : AllAllocKinds()) {
|
||||
for (ArenaIter aiter(source->zone(), thingKind); !aiter.done();
|
||||
aiter.next()) {
|
||||
Arena* arena = aiter.get();
|
||||
arena->zone = target->zone();
|
||||
if (MOZ_UNLIKELY(targetZoneIsCollecting)) {
|
||||
// If we are currently collecting the target zone then we must
|
||||
// treat all merged things as if they were allocated during the
|
||||
// collection.
|
||||
for (ArenaCellIter cell(arena); !cell.done(); cell.next()) {
|
||||
MOZ_ASSERT(!cell->isMarkedAny());
|
||||
cell->markBlack();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// The source should be the only realm in its zone.
|
||||
for (RealmsInZoneIter r(source->zone()); !r.done(); r.next()) {
|
||||
MOZ_ASSERT(r.get() == source);
|
||||
}
|
||||
|
||||
// Merge the allocator, stats and UIDs in source's zone into target's zone.
|
||||
target->zone()->arenas.adoptArenas(&source->zone()->arenas,
|
||||
targetZoneIsCollecting);
|
||||
target->zone()->addTenuredAllocsSinceMinorGC(
|
||||
source->zone()->getAndResetTenuredAllocsSinceMinorGC());
|
||||
target->zone()->gcHeapSize.adopt(source->zone()->gcHeapSize);
|
||||
target->zone()->adoptUniqueIds(source->zone());
|
||||
target->zone()->adoptMallocBytes(source->zone());
|
||||
|
||||
// Atoms which are marked in source's zone are now marked in target's zone.
|
||||
atomMarking.adoptMarkedAtoms(target->zone(), source->zone());
|
||||
|
||||
// The source Realm is a parse-only realm and should not have collected any
|
||||
// zone-tracked metadata.
|
||||
Zone* sourceZone = source->zone();
|
||||
MOZ_ASSERT(!sourceZone->scriptLCovMap);
|
||||
MOZ_ASSERT(!sourceZone->scriptCountsMap);
|
||||
MOZ_ASSERT(!sourceZone->debugScriptMap);
|
||||
#ifdef MOZ_VTUNE
|
||||
MOZ_ASSERT(!sourceZone->scriptVTuneIdMap);
|
||||
#endif
|
||||
#ifdef JS_CACHEIR_SPEW
|
||||
MOZ_ASSERT(!sourceZone->scriptFinalWarmUpCountMap);
|
||||
#endif
|
||||
|
||||
// The source realm is now completely empty, and is the only realm in its
|
||||
// compartment, which is the only compartment in its zone. Delete realm,
|
||||
// compartment and zone without waiting for this to be cleaned up by a full
|
||||
// GC.
|
||||
|
||||
sourceZone->deleteEmptyCompartment(source->compartment());
|
||||
deleteEmptyZone(sourceZone);
|
||||
}
|
||||
|
||||
void GCRuntime::runDebugGC() {
|
||||
#ifdef JS_GC_ZEAL
|
||||
if (rt->mainContextFromOwnThread()->suppressGC) {
|
||||
|
@ -4398,49 +4276,6 @@ void GCRuntime::setDeterministic(bool enabled) {
|
|||
}
|
||||
#endif
|
||||
|
||||
void ArenaLists::adoptArenas(ArenaLists* fromArenaLists,
|
||||
bool targetZoneIsCollecting) {
|
||||
// GC may be active so take the lock here so we can mutate the arena lists.
|
||||
AutoLockGC lock(runtime());
|
||||
|
||||
fromArenaLists->clearFreeLists();
|
||||
|
||||
for (auto thingKind : AllAllocKinds()) {
|
||||
MOZ_ASSERT(fromArenaLists->concurrentUse(thingKind) == ConcurrentUse::None);
|
||||
ArenaList* fromList = &fromArenaLists->arenaList(thingKind);
|
||||
ArenaList* toList = &arenaList(thingKind);
|
||||
fromList->check();
|
||||
toList->check();
|
||||
Arena* next;
|
||||
for (Arena* fromArena = fromList->head(); fromArena; fromArena = next) {
|
||||
// Copy fromArena->next before releasing/reinserting.
|
||||
next = fromArena->next;
|
||||
|
||||
#ifdef DEBUG
|
||||
MOZ_ASSERT(!fromArena->isEmpty());
|
||||
if (targetZoneIsCollecting) {
|
||||
fromArena->checkAllCellsMarkedBlack();
|
||||
} else {
|
||||
fromArena->checkNoMarkedCells();
|
||||
}
|
||||
#endif
|
||||
|
||||
// If the target zone is being collected then we need to add the
|
||||
// arenas before the cursor because the collector assumes that the
|
||||
// cursor is always at the end of the list. This has the side-effect
|
||||
// of preventing allocation into any non-full arenas until the end
|
||||
// of the next GC.
|
||||
if (targetZoneIsCollecting) {
|
||||
toList->insertBeforeCursor(fromArena);
|
||||
} else {
|
||||
toList->insertAtCursor(fromArena);
|
||||
}
|
||||
}
|
||||
fromList->clear();
|
||||
toList->check();
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
|
||||
AutoAssertNoNurseryAlloc::AutoAssertNoNurseryAlloc() {
|
||||
|
|
|
@ -110,12 +110,6 @@ void FinishGC(JSContext* cx, JS::GCReason = JS::GCReason::FINISH_GC);
|
|||
|
||||
void WaitForBackgroundTasks(JSContext* cx);
|
||||
|
||||
/*
|
||||
* Merge all contents of source into target. This can only be used if source is
|
||||
* the only realm in its zone.
|
||||
*/
|
||||
void MergeRealms(JS::Realm* source, JS::Realm* target);
|
||||
|
||||
enum VerifierType { PreBarrierVerifier };
|
||||
|
||||
#ifdef JS_GC_ZEAL
|
||||
|
|
|
@ -610,8 +610,6 @@ class GCRuntime {
|
|||
void updateHelperThreadCount();
|
||||
size_t parallelWorkerCount() const;
|
||||
|
||||
void mergeRealms(JS::Realm* source, JS::Realm* target);
|
||||
|
||||
// WeakRefs
|
||||
bool registerWeakRef(HandleObject target, HandleObject weakRef);
|
||||
bool unregisterWeakRefWrapper(JSObject* wrapper);
|
||||
|
@ -628,9 +626,6 @@ class GCRuntime {
|
|||
void updateGCThresholdsAfterCollection(const AutoLockGC& lock);
|
||||
void updateAllGCStartThresholds(const AutoLockGC& lock);
|
||||
|
||||
// Delete an empty zone after its contents have been merged.
|
||||
void deleteEmptyZone(Zone* zone);
|
||||
|
||||
// For ArenaLists::allocateFromArena()
|
||||
friend class ArenaLists;
|
||||
TenuredChunk* pickChunk(AutoLockGCBgAlloc& lock);
|
||||
|
|
|
@ -784,15 +784,6 @@ class HeapSize {
|
|||
parent_->removeBytes(nbytes, wasSwept);
|
||||
}
|
||||
}
|
||||
|
||||
/* Pair to adoptArenas. Adopts the attendant usage statistics. */
|
||||
void adopt(HeapSize& source) {
|
||||
// Skip retainedBytes_: we never adopt zones that are currently being
|
||||
// collected.
|
||||
bytes_ += source.bytes_;
|
||||
source.retainedBytes_ = 0;
|
||||
source.bytes_ = 0;
|
||||
}
|
||||
};
|
||||
|
||||
// Heap size thresholds used to trigger GC. This is an abstract base class for
|
||||
|
|
|
@ -102,16 +102,4 @@ inline void JS::Zone::removeUniqueId(js::gc::Cell* cell) {
|
|||
uniqueIds().remove(cell);
|
||||
}
|
||||
|
||||
inline void JS::Zone::adoptUniqueIds(JS::Zone* source) {
|
||||
js::AutoEnterOOMUnsafeRegion oomUnsafe;
|
||||
for (js::gc::UniqueIdMap::Enum e(source->uniqueIds()); !e.empty();
|
||||
e.popFront()) {
|
||||
MOZ_ASSERT(!uniqueIds().has(e.front().key()));
|
||||
if (!uniqueIds().put(e.front().key(), e.front().value())) {
|
||||
oomUnsafe.crash("failed to transfer unique ids from off-thread");
|
||||
}
|
||||
}
|
||||
source->uniqueIds().clear();
|
||||
}
|
||||
|
||||
#endif // gc_Zone_inl_h
|
||||
|
|
|
@ -591,12 +591,6 @@ Zone* Zone::nextZone() const {
|
|||
return listNext_;
|
||||
}
|
||||
|
||||
void Zone::clearTables() {
|
||||
MOZ_ASSERT(regExps().empty());
|
||||
|
||||
shapeZone().clearTables(runtimeFromMainThread()->defaultFreeOp());
|
||||
}
|
||||
|
||||
void Zone::fixupAfterMovingGC() {
|
||||
ZoneAllocator::fixupAfterMovingGC();
|
||||
shapeZone().fixupPropMapShapeTableAfterMovingGC();
|
||||
|
@ -615,22 +609,6 @@ bool Zone::addRttValueObject(JSContext* cx, HandleObject obj) {
|
|||
return true;
|
||||
}
|
||||
|
||||
void Zone::deleteEmptyCompartment(JS::Compartment* comp) {
|
||||
MOZ_ASSERT(comp->zone() == this);
|
||||
arenas.checkEmptyArenaLists();
|
||||
|
||||
MOZ_ASSERT(compartments().length() == 1);
|
||||
MOZ_ASSERT(compartments()[0] == comp);
|
||||
MOZ_ASSERT(comp->realms().length() == 1);
|
||||
|
||||
Realm* realm = comp->realms()[0];
|
||||
JSFreeOp* fop = runtimeFromMainThread()->defaultFreeOp();
|
||||
realm->destroy(fop);
|
||||
comp->destroy(fop);
|
||||
|
||||
compartments().clear();
|
||||
}
|
||||
|
||||
void Zone::purgeAtomCache() {
|
||||
atomCache().clearAndCompact();
|
||||
|
||||
|
|
|
@ -456,8 +456,6 @@ class Zone : public js::ZoneAllocator, public js::gc::GraphNodeBase<JS::Zone> {
|
|||
|
||||
void notifyObservingDebuggers();
|
||||
|
||||
void clearTables();
|
||||
|
||||
void addTenuredAllocsSinceMinorGC(uint32_t allocs) {
|
||||
tenuredAllocsSinceMinorGC_ += allocs;
|
||||
}
|
||||
|
@ -587,16 +585,9 @@ class Zone : public js::ZoneAllocator, public js::gc::GraphNodeBase<JS::Zone> {
|
|||
// Remove any unique id associated with this Cell.
|
||||
void removeUniqueId(js::gc::Cell* cell);
|
||||
|
||||
// When finished parsing off-thread, transfer any UIDs we created in the
|
||||
// off-thread zone into the target zone.
|
||||
void adoptUniqueIds(JS::Zone* source);
|
||||
|
||||
bool keepPropMapTables() const { return keepPropMapTables_; }
|
||||
void setKeepPropMapTables(bool b) { keepPropMapTables_ = b; }
|
||||
|
||||
// Delete an empty compartment after its contents have been merged.
|
||||
void deleteEmptyCompartment(JS::Compartment* comp);
|
||||
|
||||
void clearRootsForShutdownGC();
|
||||
void finishRoots();
|
||||
|
||||
|
|
|
@ -57,14 +57,6 @@ class ZoneAllocator : public JS::shadow::Zone,
|
|||
void* reallocPtr = nullptr);
|
||||
void reportAllocationOverflow() const;
|
||||
|
||||
void adoptMallocBytes(ZoneAllocator* other) {
|
||||
mallocHeapSize.adopt(other->mallocHeapSize);
|
||||
jitHeapSize.adopt(other->jitHeapSize);
|
||||
#ifdef DEBUG
|
||||
mallocTracker.adopt(other->mallocTracker);
|
||||
#endif
|
||||
}
|
||||
|
||||
void updateMemoryCountersOnGCStart();
|
||||
void updateGCStartThresholds(gc::GCRuntime& gc, const js::AutoLockGC& lock);
|
||||
void setGCSliceThresholds(gc::GCRuntime& gc);
|
||||
|
|
|
@ -593,12 +593,7 @@ bool InitScriptCoverage(JSContext* cx, JSScript* script) {
|
|||
MOZ_ASSERT(script->hasBytecode(),
|
||||
"Only initialize coverage data for fully initialized scripts.");
|
||||
|
||||
// Don't allocate LCovSource if we on helper thread since we will have our
|
||||
// realm migrated. The 'GCRunime::mergeRealms' code will do this
|
||||
// initialization.
|
||||
if (cx->isHelperThreadContext()) {
|
||||
return true;
|
||||
}
|
||||
MOZ_ASSERT(!cx->isHelperThreadContext());
|
||||
|
||||
const char* filename = script->filename();
|
||||
if (!filename) {
|
||||
|
|
|
@ -399,20 +399,6 @@ void Realm::purge() {
|
|||
promiseLookup.purge();
|
||||
}
|
||||
|
||||
void Realm::clearTables() {
|
||||
global_.unbarrieredGet()->releaseData(runtime_->defaultFreeOp());
|
||||
global_.set(nullptr);
|
||||
|
||||
// No scripts should have run in this realm. This is used when merging
|
||||
// a realm that has been used off thread into another realm and zone.
|
||||
compartment()->assertNoCrossCompartmentWrappers();
|
||||
MOZ_ASSERT(!jitRealm_);
|
||||
MOZ_ASSERT(!debugEnvs_);
|
||||
MOZ_ASSERT(objects_.enumerators->next() == objects_.enumerators);
|
||||
|
||||
savedStacks_.clear();
|
||||
}
|
||||
|
||||
// Check to see if this individual realm is recording allocations. Debuggers or
|
||||
// runtimes can try and record allocations, so this method can check to see if
|
||||
// any initialization is needed.
|
||||
|
|
|
@ -442,7 +442,6 @@ class JS::Realm : public JS::shadow::Realm {
|
|||
|
||||
[[nodiscard]] bool init(JSContext* cx, JSPrincipals* principals);
|
||||
void destroy(JSFreeOp* fop);
|
||||
void clearTables();
|
||||
|
||||
void addSizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf,
|
||||
size_t* realmObject, size_t* realmTables,
|
||||
|
|
|
@ -215,9 +215,6 @@ class BaseShape : public gc::TenuredCellWithNonGCPointer<const JSClass> {
|
|||
|
||||
TaggedProto proto() const { return proto_; }
|
||||
|
||||
void setRealmForMergeRealms(JS::Realm* realm) { realm_ = realm; }
|
||||
void setProtoForMergeRealms(TaggedProto proto) { proto_ = proto; }
|
||||
|
||||
/*
|
||||
* Lookup base shapes from the zone's baseShapes table, adding if not
|
||||
* already found.
|
||||
|
|
|
@ -82,14 +82,6 @@ ShapeZone::ShapeZone(Zone* zone)
|
|||
initialShapes(zone),
|
||||
propMapShapes(zone) {}
|
||||
|
||||
void ShapeZone::clearTables(JSFreeOp* fop) {
|
||||
baseShapes.clear();
|
||||
initialPropMaps.clear();
|
||||
initialShapes.clear();
|
||||
propMapShapes.clear();
|
||||
purgeShapeCaches(fop);
|
||||
}
|
||||
|
||||
void ShapeZone::purgeShapeCaches(JSFreeOp* fop) {
|
||||
for (Shape* shape : shapesWithCache) {
|
||||
MaybeForwarded(shape)->purgeCache(fop);
|
||||
|
|
|
@ -160,7 +160,6 @@ struct ShapeZone {
|
|||
|
||||
explicit ShapeZone(Zone* zone);
|
||||
|
||||
void clearTables(JSFreeOp* fop);
|
||||
void purgeShapeCaches(JSFreeOp* fop);
|
||||
|
||||
void addSizeOfExcludingThis(mozilla::MallocSizeOf mallocSizeOf,
|
||||
|
|
Загрузка…
Ссылка в новой задаче