mirror of
https://repo.dactyloidae.xyz/Dactyloidae/UXP.git
synced 2026-10-30 19:17:31 +09:00
Simplify incremental GC sweeping
Splitting several parts of `SweepPhase` into constituent parts to separate out sweeping code from code that handles yielding to the mutator and resuming.
This commit is contained in:
parent
661754041c
commit
95a1e4b7a3
4 changed files with 196 additions and 92 deletions
|
|
@ -35,6 +35,12 @@ class MarkingValidator;
|
||||||
class AutoTraceSession;
|
class AutoTraceSession;
|
||||||
struct MovingTracer;
|
struct MovingTracer;
|
||||||
|
|
||||||
|
enum IncrementalProgress
|
||||||
|
{
|
||||||
|
NotFinished = 0,
|
||||||
|
Finished
|
||||||
|
};
|
||||||
|
|
||||||
class ChunkPool
|
class ChunkPool
|
||||||
{
|
{
|
||||||
Chunk* head_;
|
Chunk* head_;
|
||||||
|
|
@ -737,6 +743,8 @@ class GCRuntime
|
||||||
|
|
||||||
bool isShrinkingGC() const { return invocationKind == GC_SHRINK; }
|
bool isShrinkingGC() const { return invocationKind == GC_SHRINK; }
|
||||||
|
|
||||||
|
static bool initializeSweepActions();
|
||||||
|
|
||||||
void setGrayRootsTracer(JSTraceDataOp traceOp, void* data);
|
void setGrayRootsTracer(JSTraceDataOp traceOp, void* data);
|
||||||
MOZ_MUST_USE bool addBlackRootsTracer(JSTraceDataOp traceOp, void* data);
|
MOZ_MUST_USE bool addBlackRootsTracer(JSTraceDataOp traceOp, void* data);
|
||||||
void removeBlackRootsTracer(JSTraceDataOp traceOp, void* data);
|
void removeBlackRootsTracer(JSTraceDataOp traceOp, void* data);
|
||||||
|
|
@ -863,12 +871,6 @@ class GCRuntime
|
||||||
static TenuredCell* refillFreeListInGC(Zone* zone, AllocKind thingKind);
|
static TenuredCell* refillFreeListInGC(Zone* zone, AllocKind thingKind);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
enum IncrementalProgress
|
|
||||||
{
|
|
||||||
NotFinished = 0,
|
|
||||||
Finished
|
|
||||||
};
|
|
||||||
|
|
||||||
// For ArenaLists::allocateFromArena()
|
// For ArenaLists::allocateFromArena()
|
||||||
friend class ArenaLists;
|
friend class ArenaLists;
|
||||||
Chunk* pickChunk(const AutoLockGC& lock,
|
Chunk* pickChunk(const AutoLockGC& lock,
|
||||||
|
|
@ -951,7 +953,15 @@ class GCRuntime
|
||||||
void beginSweepingZoneGroup(AutoLockForExclusiveAccess& lock);
|
void beginSweepingZoneGroup(AutoLockForExclusiveAccess& lock);
|
||||||
bool shouldReleaseObservedTypes();
|
bool shouldReleaseObservedTypes();
|
||||||
void endSweepingZoneGroup();
|
void endSweepingZoneGroup();
|
||||||
IncrementalProgress sweepPhase(SliceBudget& sliceBudget, AutoLockForExclusiveAccess& lock);
|
IncrementalProgress performSweepActions(SliceBudget& sliceBudget, AutoLockForExclusiveAccess& lock);
|
||||||
|
static IncrementalProgress sweepTypeInformation(GCRuntime* gc, FreeOp* fop, Zone* zone,
|
||||||
|
SliceBudget& budget, AllocKind kind);
|
||||||
|
static IncrementalProgress mergeSweptObjectArenas(GCRuntime* gc, FreeOp* fop, Zone* zone,
|
||||||
|
SliceBudget& budget, AllocKind kind);
|
||||||
|
static IncrementalProgress finalizeAllocKind(GCRuntime* gc, FreeOp* fop, Zone* zone,
|
||||||
|
SliceBudget& budget, AllocKind kind);
|
||||||
|
static IncrementalProgress sweepShapeTree(GCRuntime* gc, FreeOp* fop, Zone* zone,
|
||||||
|
SliceBudget& budget, AllocKind kind);
|
||||||
void endSweepPhase(bool lastGC, AutoLockForExclusiveAccess& lock);
|
void endSweepPhase(bool lastGC, AutoLockForExclusiveAccess& lock);
|
||||||
void sweepZones(FreeOp* fop, bool lastGC);
|
void sweepZones(FreeOp* fop, bool lastGC);
|
||||||
void decommitAllWithoutUnlocking(const AutoLockGC& lock);
|
void decommitAllWithoutUnlocking(const AutoLockGC& lock);
|
||||||
|
|
@ -1165,10 +1175,9 @@ class GCRuntime
|
||||||
*/
|
*/
|
||||||
JS::Zone* zoneGroups;
|
JS::Zone* zoneGroups;
|
||||||
JS::Zone* currentZoneGroup;
|
JS::Zone* currentZoneGroup;
|
||||||
bool sweepingTypes;
|
size_t sweepPhaseIndex;
|
||||||
unsigned finalizePhase;
|
|
||||||
JS::Zone* sweepZone;
|
JS::Zone* sweepZone;
|
||||||
AllocKind sweepKind;
|
size_t sweepActionIndex;
|
||||||
bool abortSweepAfterCurrentGroup;
|
bool abortSweepAfterCurrentGroup;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
||||||
272
js/src/jsgc.cpp
272
js/src/jsgc.cpp
|
|
@ -384,6 +384,42 @@ static const FinalizePhase BackgroundFinalizePhases[] = {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Incremental sweeping is controlled by a list of actions that describe what
|
||||||
|
// happens and in what order. Due to the incremental nature of sweeping an
|
||||||
|
// action does not necessarily run to completion so the current state is tracked
|
||||||
|
// in the GCRuntime by the performSweepActions() method.
|
||||||
|
//
|
||||||
|
// Actions are performed in phases run per sweep group, and each action is run
|
||||||
|
// for every zone in the group, i.e. as if by the following pseudocode:
|
||||||
|
//
|
||||||
|
// for each sweep group:
|
||||||
|
// for each phase:
|
||||||
|
// for each zone in sweep group:
|
||||||
|
// for each action in phase:
|
||||||
|
// perform_action
|
||||||
|
|
||||||
|
struct SweepAction
|
||||||
|
{
|
||||||
|
using Func = IncrementalProgress (*)(GCRuntime* gc, FreeOp* fop, Zone* zone,
|
||||||
|
SliceBudget& budget, AllocKind kind);
|
||||||
|
|
||||||
|
Func func;
|
||||||
|
AllocKind kind;
|
||||||
|
|
||||||
|
SweepAction(Func func, AllocKind kind) : func(func), kind(kind) {}
|
||||||
|
};
|
||||||
|
|
||||||
|
using SweepActionVector = Vector<SweepAction, 0, SystemAllocPolicy>;
|
||||||
|
using SweepPhaseVector = Vector<SweepActionVector, 0, SystemAllocPolicy>;
|
||||||
|
|
||||||
|
static SweepPhaseVector SweepPhases;
|
||||||
|
|
||||||
|
bool
|
||||||
|
js::gc::InitializeStaticData()
|
||||||
|
{
|
||||||
|
return GCRuntime::initializeSweepActions();
|
||||||
|
}
|
||||||
|
|
||||||
template<>
|
template<>
|
||||||
JSObject*
|
JSObject*
|
||||||
ArenaCellIterImpl::get<JSObject>() const
|
ArenaCellIterImpl::get<JSObject>() const
|
||||||
|
|
@ -841,8 +877,9 @@ GCRuntime::GCRuntime(JSRuntime* rt) :
|
||||||
zoneGroupIndex(0),
|
zoneGroupIndex(0),
|
||||||
zoneGroups(nullptr),
|
zoneGroups(nullptr),
|
||||||
currentZoneGroup(nullptr),
|
currentZoneGroup(nullptr),
|
||||||
|
sweepPhaseIndex(0),
|
||||||
sweepZone(nullptr),
|
sweepZone(nullptr),
|
||||||
sweepKind(AllocKind::FIRST),
|
sweepActionIndex(0),
|
||||||
abortSweepAfterCurrentGroup(false),
|
abortSweepAfterCurrentGroup(false),
|
||||||
arenasAllocatedDuringSweep(nullptr),
|
arenasAllocatedDuringSweep(nullptr),
|
||||||
startedCompacting(false),
|
startedCompacting(false),
|
||||||
|
|
@ -883,7 +920,7 @@ static const uint64_t JIT_SCRIPT_RELEASE_TYPES_PERIOD = 20;
|
||||||
bool
|
bool
|
||||||
GCRuntime::init(uint32_t maxbytes, uint32_t maxNurseryBytes)
|
GCRuntime::init(uint32_t maxbytes, uint32_t maxNurseryBytes)
|
||||||
{
|
{
|
||||||
InitMemorySubsystem();
|
MOZ_ASSERT(SystemPageSize());
|
||||||
|
|
||||||
if (!rootsHash.init(256))
|
if (!rootsHash.init(256))
|
||||||
return false;
|
return false;
|
||||||
|
|
@ -4667,11 +4704,9 @@ GCRuntime::beginSweepingZoneGroup(AutoLockForExclusiveAccess& lock)
|
||||||
zone->arenas.queueForegroundThingsForSweep(&fop);
|
zone->arenas.queueForegroundThingsForSweep(&fop);
|
||||||
}
|
}
|
||||||
|
|
||||||
sweepingTypes = true;
|
sweepPhaseIndex = 0;
|
||||||
|
|
||||||
finalizePhase = 0;
|
|
||||||
sweepZone = currentZoneGroup;
|
sweepZone = currentZoneGroup;
|
||||||
sweepKind = AllocKind::FIRST;
|
sweepActionIndex = 0;
|
||||||
|
|
||||||
{
|
{
|
||||||
gcstats::AutoPhase ap(stats, gcstats::PHASE_FINALIZE_END);
|
gcstats::AutoPhase ap(stats, gcstats::PHASE_FINALIZE_END);
|
||||||
|
|
@ -4765,7 +4800,7 @@ ArenaLists::foregroundFinalize(FreeOp* fop, AllocKind thingKind, SliceBudget& sl
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
GCRuntime::IncrementalProgress
|
IncrementalProgress
|
||||||
GCRuntime::drainMarkStack(SliceBudget& sliceBudget, gcstats::Phase phase)
|
GCRuntime::drainMarkStack(SliceBudget& sliceBudget, gcstats::Phase phase)
|
||||||
{
|
{
|
||||||
/* Run a marking slice and return whether the stack is now empty. */
|
/* Run a marking slice and return whether the stack is now empty. */
|
||||||
|
|
@ -4810,105 +4845,160 @@ SweepArenaList(Arena** arenasToSweep, SliceBudget& sliceBudget, Args... args)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
GCRuntime::IncrementalProgress
|
/* static */ IncrementalProgress
|
||||||
GCRuntime::sweepPhase(SliceBudget& sliceBudget, AutoLockForExclusiveAccess& lock)
|
GCRuntime::sweepTypeInformation(GCRuntime* gc, FreeOp* fop, Zone* zone, SliceBudget& budget,
|
||||||
|
AllocKind kind)
|
||||||
|
{
|
||||||
|
// Sweep dead type information stored in scripts and object groups, but
|
||||||
|
// don't finalize them yet. We have to sweep dead information from both live
|
||||||
|
// and dead scripts and object groups, so that no dead references remain in
|
||||||
|
// them. Type inference can end up crawling these zones again, such as for
|
||||||
|
// TypeCompartment::markSetsUnknown, and if this happens after sweeping for
|
||||||
|
// the sweep group finishes we won't be able to determine which things in
|
||||||
|
// the zone are live.
|
||||||
|
|
||||||
|
MOZ_ASSERT(kind == AllocKind::LIMIT);
|
||||||
|
|
||||||
|
gcstats::AutoPhase ap1(gc->stats, gcstats::PHASE_SWEEP_COMPARTMENTS);
|
||||||
|
gcstats::AutoPhase ap2(gc->stats, gcstats::PHASE_SWEEP_TYPES);
|
||||||
|
|
||||||
|
ArenaLists& al = zone->arenas;
|
||||||
|
|
||||||
|
AutoClearTypeInferenceStateOnOOM oom(zone);
|
||||||
|
|
||||||
|
if (!SweepArenaList<JSScript>(&al.gcScriptArenasToUpdate, budget, &oom))
|
||||||
|
return NotFinished;
|
||||||
|
|
||||||
|
if (!SweepArenaList<ObjectGroup>(&al.gcObjectGroupArenasToUpdate, budget, &oom))
|
||||||
|
return NotFinished;
|
||||||
|
|
||||||
|
// Finish sweeping type information in the zone.
|
||||||
|
{
|
||||||
|
gcstats::AutoPhase ap(gc->stats, gcstats::PHASE_SWEEP_TYPES_END);
|
||||||
|
zone->types.endSweep(gc->rt);
|
||||||
|
}
|
||||||
|
|
||||||
|
return Finished;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* static */ IncrementalProgress
|
||||||
|
GCRuntime::mergeSweptObjectArenas(GCRuntime* gc, FreeOp* fop, Zone* zone, SliceBudget& budget,
|
||||||
|
AllocKind kind)
|
||||||
|
{
|
||||||
|
// Foreground finalized objects have already been finalized, and now their
|
||||||
|
// arenas can be reclaimed by freeing empty ones and making non-empty ones
|
||||||
|
// available for allocation.
|
||||||
|
|
||||||
|
MOZ_ASSERT(kind == AllocKind::LIMIT);
|
||||||
|
zone->arenas.mergeForegroundSweptObjectArenas();
|
||||||
|
return Finished;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* static */ IncrementalProgress
|
||||||
|
GCRuntime::finalizeAllocKind(GCRuntime* gc, FreeOp* fop, Zone* zone, SliceBudget& budget,
|
||||||
|
AllocKind kind)
|
||||||
|
{
|
||||||
|
// Set the number of things per arena for this AllocKind.
|
||||||
|
size_t thingsPerArena = Arena::thingsPerArena(kind);
|
||||||
|
auto& sweepList = gc->incrementalSweepList;
|
||||||
|
sweepList.setThingsPerArena(thingsPerArena);
|
||||||
|
|
||||||
|
if (!zone->arenas.foregroundFinalize(fop, kind, budget, sweepList))
|
||||||
|
return NotFinished;
|
||||||
|
|
||||||
|
// Reset the slots of the sweep list that we used.
|
||||||
|
sweepList.reset(thingsPerArena);
|
||||||
|
|
||||||
|
return Finished;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* static */ IncrementalProgress
|
||||||
|
GCRuntime::sweepShapeTree(GCRuntime* gc, FreeOp* fop, Zone* zone, SliceBudget& budget,
|
||||||
|
AllocKind kind)
|
||||||
|
{
|
||||||
|
// Remove dead shapes from the shape tree, but don't finalize them yet.
|
||||||
|
|
||||||
|
MOZ_ASSERT(kind == AllocKind::LIMIT);
|
||||||
|
|
||||||
|
gcstats::AutoPhase ap(gc->stats, gcstats::PHASE_SWEEP_SHAPE);
|
||||||
|
|
||||||
|
ArenaLists& al = zone->arenas;
|
||||||
|
|
||||||
|
if (!SweepArenaList<Shape>(&al.gcShapeArenasToUpdate, budget))
|
||||||
|
return NotFinished;
|
||||||
|
|
||||||
|
if (!SweepArenaList<AccessorShape>(&al.gcAccessorShapeArenasToUpdate, budget))
|
||||||
|
return NotFinished;
|
||||||
|
|
||||||
|
return Finished;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
AddSweepPhase(bool* ok)
|
||||||
|
{
|
||||||
|
if (*ok)
|
||||||
|
*ok = SweepPhases.emplaceBack();
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
AddSweepAction(bool* ok, SweepAction::Func func, AllocKind kind = AllocKind::LIMIT)
|
||||||
|
{
|
||||||
|
if (*ok)
|
||||||
|
*ok = SweepPhases.back().emplaceBack(func, kind);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* static */ bool
|
||||||
|
GCRuntime::initializeSweepActions()
|
||||||
|
{
|
||||||
|
bool ok = true;
|
||||||
|
|
||||||
|
AddSweepPhase(&ok);
|
||||||
|
|
||||||
|
AddSweepAction(&ok, GCRuntime::sweepTypeInformation);
|
||||||
|
AddSweepAction(&ok, GCRuntime::mergeSweptObjectArenas);
|
||||||
|
|
||||||
|
for (const auto& finalizePhase : IncrementalFinalizePhases) {
|
||||||
|
AddSweepPhase(&ok);
|
||||||
|
for (auto kind : finalizePhase.kinds)
|
||||||
|
AddSweepAction(&ok, GCRuntime::finalizeAllocKind, kind);
|
||||||
|
}
|
||||||
|
|
||||||
|
AddSweepPhase(&ok);
|
||||||
|
AddSweepAction(&ok, GCRuntime::sweepShapeTree);
|
||||||
|
|
||||||
|
return ok;
|
||||||
|
}
|
||||||
|
|
||||||
|
IncrementalProgress
|
||||||
|
GCRuntime::performSweepActions(SliceBudget& budget, AutoLockForExclusiveAccess& lock)
|
||||||
{
|
{
|
||||||
AutoSetThreadIsSweeping threadIsSweeping;
|
AutoSetThreadIsSweeping threadIsSweeping;
|
||||||
|
|
||||||
gcstats::AutoPhase ap(stats, gcstats::PHASE_SWEEP);
|
gcstats::AutoPhase ap(stats, gcstats::PHASE_SWEEP);
|
||||||
FreeOp fop(rt);
|
FreeOp fop(rt);
|
||||||
|
|
||||||
if (drainMarkStack(sliceBudget, gcstats::PHASE_SWEEP_MARK) == NotFinished)
|
if (drainMarkStack(budget, gcstats::PHASE_SWEEP_MARK) == NotFinished)
|
||||||
return NotFinished;
|
return NotFinished;
|
||||||
|
|
||||||
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
// Sweep dead type information stored in scripts and object groups, but
|
for (; sweepPhaseIndex < SweepPhases.length(); sweepPhaseIndex++) {
|
||||||
// don't finalize them yet. We have to sweep dead information from both
|
const auto& actions = SweepPhases[sweepPhaseIndex];
|
||||||
// live and dead scripts and object groups, so that no dead references
|
|
||||||
// remain in them. Type inference can end up crawling these zones
|
|
||||||
// again, such as for TypeCompartment::markSetsUnknown, and if this
|
|
||||||
// happens after sweeping for the zone group finishes we won't be able
|
|
||||||
// to determine which things in the zone are live.
|
|
||||||
if (sweepingTypes) {
|
|
||||||
gcstats::AutoPhase ap1(stats, gcstats::PHASE_SWEEP_COMPARTMENTS);
|
|
||||||
gcstats::AutoPhase ap2(stats, gcstats::PHASE_SWEEP_TYPES);
|
|
||||||
|
|
||||||
for (; sweepZone; sweepZone = sweepZone->nextNodeInGroup()) {
|
for (; sweepZone; sweepZone = sweepZone->nextNodeInGroup()) {
|
||||||
ArenaLists& al = sweepZone->arenas;
|
for (; sweepActionIndex < actions.length(); sweepActionIndex++) {
|
||||||
|
const auto& action = actions[sweepActionIndex];
|
||||||
AutoClearTypeInferenceStateOnOOM oom(sweepZone);
|
if (action.func(this, &fop, sweepZone, budget, action.kind) == NotFinished)
|
||||||
|
|
||||||
if (!SweepArenaList<JSScript>(&al.gcScriptArenasToUpdate, sliceBudget, &oom))
|
|
||||||
return NotFinished;
|
|
||||||
|
|
||||||
if (!SweepArenaList<ObjectGroup>(
|
|
||||||
&al.gcObjectGroupArenasToUpdate, sliceBudget, &oom))
|
|
||||||
{
|
|
||||||
return NotFinished;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Finish sweeping type information in the zone.
|
|
||||||
{
|
|
||||||
gcstats::AutoPhase ap(stats, gcstats::PHASE_SWEEP_TYPES_END);
|
|
||||||
sweepZone->types.endSweep(rt);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Foreground finalized objects have already been finalized,
|
|
||||||
// and now their arenas can be reclaimed by freeing empty ones
|
|
||||||
// and making non-empty ones available for allocation.
|
|
||||||
al.mergeForegroundSweptObjectArenas();
|
|
||||||
}
|
|
||||||
|
|
||||||
sweepZone = currentZoneGroup;
|
|
||||||
sweepingTypes = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Finalize foreground finalized things. */
|
|
||||||
for (; finalizePhase < ArrayLength(IncrementalFinalizePhases) ; ++finalizePhase) {
|
|
||||||
gcstats::AutoPhase ap(stats, IncrementalFinalizePhases[finalizePhase].statsPhase);
|
|
||||||
|
|
||||||
for (; sweepZone; sweepZone = sweepZone->nextNodeInGroup()) {
|
|
||||||
Zone* zone = sweepZone;
|
|
||||||
|
|
||||||
for (auto kind : SomeAllocKinds(sweepKind, AllocKind::LIMIT)) {
|
|
||||||
if (!IncrementalFinalizePhases[finalizePhase].kinds.contains(kind))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
/* Set the number of things per arena for this AllocKind. */
|
|
||||||
size_t thingsPerArena = Arena::thingsPerArena(kind);
|
|
||||||
incrementalSweepList.setThingsPerArena(thingsPerArena);
|
|
||||||
|
|
||||||
if (!zone->arenas.foregroundFinalize(&fop, kind, sliceBudget,
|
|
||||||
incrementalSweepList))
|
|
||||||
{
|
|
||||||
sweepKind = kind;
|
|
||||||
return NotFinished;
|
return NotFinished;
|
||||||
}
|
|
||||||
|
|
||||||
/* Reset the slots of the sweep list that we used. */
|
|
||||||
incrementalSweepList.reset(thingsPerArena);
|
|
||||||
}
|
}
|
||||||
sweepKind = AllocKind::FIRST;
|
// Reset action index to first.
|
||||||
|
sweepActionIndex = 0;
|
||||||
}
|
}
|
||||||
sweepZone = currentZoneGroup;
|
sweepZone = currentZoneGroup;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Remove dead shapes from the shape tree, but don't finalize them yet. */
|
// Reset phase index.
|
||||||
{
|
sweepPhaseIndex = 0;
|
||||||
gcstats::AutoPhase ap(stats, gcstats::PHASE_SWEEP_SHAPE);
|
|
||||||
|
|
||||||
for (; sweepZone; sweepZone = sweepZone->nextNodeInGroup()) {
|
|
||||||
ArenaLists& al = sweepZone->arenas;
|
|
||||||
|
|
||||||
if (!SweepArenaList<Shape>(&al.gcShapeArenasToUpdate, sliceBudget))
|
|
||||||
return NotFinished;
|
|
||||||
|
|
||||||
if (!SweepArenaList<AccessorShape>(&al.gcAccessorShapeArenasToUpdate, sliceBudget))
|
|
||||||
return NotFinished;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
endSweepingZoneGroup();
|
endSweepingZoneGroup();
|
||||||
getNextZoneGroup();
|
getNextZoneGroup();
|
||||||
if (!currentZoneGroup)
|
if (!currentZoneGroup)
|
||||||
|
|
@ -4999,7 +5089,7 @@ GCRuntime::beginCompactPhase()
|
||||||
startedCompacting = true;
|
startedCompacting = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
GCRuntime::IncrementalProgress
|
IncrementalProgress
|
||||||
GCRuntime::compactPhase(JS::gcreason::Reason reason, SliceBudget& sliceBudget,
|
GCRuntime::compactPhase(JS::gcreason::Reason reason, SliceBudget& sliceBudget,
|
||||||
AutoLockForExclusiveAccess& lock)
|
AutoLockForExclusiveAccess& lock)
|
||||||
{
|
{
|
||||||
|
|
@ -5381,7 +5471,7 @@ GCRuntime::incrementalCollectSlice(SliceBudget& budget, JS::gcreason::Reason rea
|
||||||
MOZ_FALLTHROUGH;
|
MOZ_FALLTHROUGH;
|
||||||
|
|
||||||
case State::Sweep:
|
case State::Sweep:
|
||||||
if (sweepPhase(budget, lock) == NotFinished)
|
if (performSweepActions(budget, lock) == NotFinished)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
endSweepPhase(destroyingRuntime, lock);
|
endSweepPhase(destroyingRuntime, lock);
|
||||||
|
|
|
||||||
|
|
@ -838,6 +838,9 @@ class ArenaLists
|
||||||
/* The number of GC cycles an empty chunk can survive before been released. */
|
/* The number of GC cycles an empty chunk can survive before been released. */
|
||||||
const size_t MAX_EMPTY_CHUNK_AGE = 4;
|
const size_t MAX_EMPTY_CHUNK_AGE = 4;
|
||||||
|
|
||||||
|
extern bool
|
||||||
|
InitializeStaticData();
|
||||||
|
|
||||||
} /* namespace gc */
|
} /* namespace gc */
|
||||||
|
|
||||||
class InterpreterFrame;
|
class InterpreterFrame;
|
||||||
|
|
|
||||||
|
|
@ -102,6 +102,8 @@ JS::detail::InitWithFailureDiagnostic(bool isDebugBuild)
|
||||||
RETURN_IF_FAIL(js::wasm::InitInstanceStaticData());
|
RETURN_IF_FAIL(js::wasm::InitInstanceStaticData());
|
||||||
|
|
||||||
js::gc::InitMemorySubsystem(); // Ensure gc::SystemPageSize() works.
|
js::gc::InitMemorySubsystem(); // Ensure gc::SystemPageSize() works.
|
||||||
|
RETURN_IF_FAIL(js::gc::InitializeStaticData());
|
||||||
|
|
||||||
RETURN_IF_FAIL(js::jit::InitProcessExecutableMemory());
|
RETURN_IF_FAIL(js::jit::InitProcessExecutableMemory());
|
||||||
|
|
||||||
MOZ_ALWAYS_TRUE(js::MemoryProtectionExceptionHandler::install());
|
MOZ_ALWAYS_TRUE(js::MemoryProtectionExceptionHandler::install());
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue