Bug 1607444 - Only collect the self hosting zone once at runtime initialization r=jandem

Differential Revision: https://phabricator.services.mozilla.com/D60153

--HG--
extra : moz-landing-system : lando
This commit is contained in:
Jon Coppeard 2020-01-22 11:22:02 +00:00
Родитель 0d5e5faea7
Коммит 448ebaa6f3
8 изменённых файлов: 55 добавлений и 10 удалений

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

@ -464,9 +464,9 @@ namespace JS {
D(FULL_CELL_PTR_STR_BUFFER, 28) \
D(TOO_MUCH_JIT_CODE, 29) \
D(FULL_CELL_PTR_BIGINT_BUFFER, 30) \
D(INIT_SELF_HOSTING, 31) \
\
/* These are reserved for future use. */ \
D(RESERVED7, 31) \
D(RESERVED8, 32) \
\
/* Reasons from Firefox */ \

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

@ -411,6 +411,8 @@ bool GCRuntime::checkAllocatorState(JSContext* cx, AllocKind kind) {
kind == AllocKind::SCOPE);
MOZ_ASSERT_IF(!cx->zone()->isAtomsZone(),
kind != AllocKind::ATOM && kind != AllocKind::FAT_INLINE_ATOM);
MOZ_ASSERT_IF(cx->zone()->isSelfHostingZone(),
!rt->parentRuntime && !selfHostingZoneFrozen);
MOZ_ASSERT(!JS::RuntimeHeapIsBusy());
#endif

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

@ -1258,6 +1258,21 @@ bool GCRuntime::init(uint32_t maxbytes) {
return true;
}
void GCRuntime::freezeSelfHostingZone() {
MOZ_ASSERT(!selfHostingZoneFrozen);
MOZ_ASSERT(!isIncrementalGCInProgress());
for (ZonesIter zone(this, WithAtoms); !zone.done(); zone.next()) {
MOZ_ASSERT(!zone->isGCScheduled());
if (zone->isSelfHostingZone()) {
zone->scheduleGC();
}
}
gc(GC_SHRINK, JS::GCReason::INIT_SELF_HOSTING);
selfHostingZoneFrozen = true;
}
void GCRuntime::finish() {
// Wait for nursery background free to end and disable it to release memory.
if (nursery().isEnabled()) {
@ -1704,8 +1719,16 @@ AutoDisableCompactingGC::~AutoDisableCompactingGC() {
--cx->compactingDisabledCount;
}
static bool CanRelocateZone(Zone* zone) {
return !zone->isAtomsZone() && !zone->isSelfHostingZone();
bool GCRuntime::canRelocateZone(Zone* zone) const {
if (zone->isAtomsZone()) {
return false;
}
if (zone->isSelfHostingZone() && selfHostingZoneFrozen) {
return false;
}
return true;
}
Arena* ArenaList::removeRemainingArenas(Arena** arenap) {
@ -2018,7 +2041,7 @@ bool GCRuntime::relocateArenas(Zone* zone, JS::GCReason reason,
gcstats::AutoPhase ap(stats(), gcstats::PhaseKind::COMPACT_MOVE);
MOZ_ASSERT(!zone->isPreservingCode());
MOZ_ASSERT(CanRelocateZone(zone));
MOZ_ASSERT(canRelocateZone(zone));
js::CancelOffThreadIonCompile(rt, JS::Zone::Compact);
@ -3841,7 +3864,7 @@ bool GCRuntime::prepareZonesForCollection(JS::GCReason reason,
MOZ_ASSERT(zone->canCollect());
any = true;
zone->changeGCState(Zone::NoGC, Zone::MarkBlackOnly);
} else {
} else if (zone->canCollect()) {
*isFullOut = false;
}
@ -3911,7 +3934,7 @@ void GCRuntime::relazifyFunctionsForShrinkingGC() {
void GCRuntime::purgeShapeCachesForShrinkingGC() {
gcstats::AutoPhase ap(stats(), gcstats::PhaseKind::PURGE_SHAPE_CACHES);
for (GCZonesIter zone(this); !zone.done(); zone.next()) {
if (!CanRelocateZone(zone) || zone->keepShapeCaches()) {
if (!canRelocateZone(zone) || zone->keepShapeCaches()) {
continue;
}
for (auto baseShape = zone->cellIterUnsafe<BaseShape>(); !baseShape.done();
@ -3927,7 +3950,7 @@ void GCRuntime::purgeSourceURLsForShrinkingGC() {
gcstats::AutoPhase ap(stats(), gcstats::PhaseKind::PURGE_SOURCE_URLS);
for (GCZonesIter zone(this); !zone.done(); zone.next()) {
// URLs are not tracked for realms in the system zone.
if (!CanRelocateZone(zone) || zone->isSystem) {
if (!canRelocateZone(zone) || zone->isSystem) {
continue;
}
for (CompartmentsInZoneIter comp(zone); !comp.done(); comp.next()) {
@ -6127,7 +6150,7 @@ void GCRuntime::beginCompactPhase() {
MOZ_ASSERT(zonesToMaybeCompact.ref().isEmpty());
for (GCZonesIter zone(this); !zone.done(); zone.next()) {
if (CanRelocateZone(zone)) {
if (canRelocateZone(zone)) {
zonesToMaybeCompact.ref().append(zone);
}
}

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

@ -137,6 +137,8 @@ void FinishGC(JSContext* cx, JS::GCReason = JS::GCReason::FINISH_GC);
*/
void MergeRealms(JS::Realm* source, JS::Realm* target);
void CollectSelfHostingZone(JSContext* cx);
enum VerifierType { PreBarrierVerifier };
#ifdef JS_GC_ZEAL

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

@ -261,6 +261,9 @@ class GCRuntime {
JS::HeapState heapState() const { return heapState_; }
void freezeSelfHostingZone();
bool isSelfHostingZoneFrozen() const { return selfHostingZoneFrozen; }
inline bool hasZealMode(ZealMode mode);
inline void clearZealMode(ZealMode mode);
inline bool upcomingZealousGC();
@ -734,6 +737,7 @@ class GCRuntime {
void endCompactPhase();
void sweepTypesAfterCompacting(Zone* zone);
void sweepZoneAfterCompacting(MovingTracer* trc, Zone* zone);
bool canRelocateZone(Zone* zone) const;
MOZ_MUST_USE bool relocateArenas(Zone* zone, JS::GCReason reason,
Arena*& relocatedListOut,
SliceBudget& sliceBudget);
@ -862,6 +866,12 @@ class GCRuntime {
mozilla::recordreplay::Behavior::DontPreserve>
numActiveZoneIters;
/*
* The self hosting zone is collected once after initialization. We don't
* allow allocation after this point and we don't collect it again.
*/
WriteOnceData<bool> selfHostingZoneFrozen;
/* During shutdown, the GC needs to clean up every possible object. */
MainThreadData<bool> cleanUpEverything;

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

@ -202,7 +202,6 @@ bool Zone::init(bool isSystemArg) {
}
void Zone::setNeedsIncrementalBarrier(bool needs) {
MOZ_ASSERT_IF(needs, canCollect());
needsIncrementalBarrier_ = needs;
}
@ -498,6 +497,11 @@ bool Zone::canCollect() {
return !runtimeFromAnyThread()->hasHelperThreadZones();
}
// We don't collect the self hosting zone after it has been initialized.
if (isSelfHostingZone()) {
return !runtimeFromAnyThread()->gc.isSelfHostingZoneFrozen();
}
// Zones that will be or are currently used by other threads cannot be
// collected.
return !createdForHelperThread();

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

@ -276,7 +276,7 @@ class Zone : public js::ZoneAllocator, public js::gc::GraphNodeBase<JS::Zone> {
void changeGCState(GCState prev, GCState next) {
MOZ_ASSERT(RuntimeHeapIsBusy());
MOZ_ASSERT(gcState() == prev);
MOZ_ASSERT_IF(next != NoGC, canCollect());
MOZ_ASSERT(canCollect());
gcState_ = next;
}

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

@ -2769,6 +2769,10 @@ bool JSRuntime::initSelfHosting(JSContext* cx) {
return false;
}
// Garbage collect the self hosting zone once when it is created. It should
// not be modified after this point.
cx->runtime()->gc.freezeSelfHostingZone();
return true;
}