This does work.

This should work. Test gains.
This commit is contained in:
win7-7 2022-11-02 13:52:09 +02:00 committed by wuggy
commit 24cf030a68
5 changed files with 131 additions and 98 deletions

View file

@ -176,8 +176,6 @@ public:
void
Trace(const TraceCallbacks& aCallbacks, void* aClosure)
{
AssertIsOnOwningThread();
ConsoleCallData* tmp = this;
for (uint32_t i = 0; i < mCopiedArguments.Length(); ++i) {
NS_IMPL_CYCLE_COLLECTION_TRACE_JS_MEMBER_CALLBACK(mCopiedArguments[i])

View file

@ -3805,7 +3805,6 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_END
template <class Derived>
NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN_INHERITED(WorkerPrivateParent<Derived>,
DOMEventTargetHelper)
tmp->AssertIsOnParentThread();
NS_IMPL_CYCLE_COLLECTION_TRACE_END
#ifdef DEBUG

View file

@ -124,15 +124,18 @@ struct DagChildEdge {
* empty. Timings for these phases are thus exclusive of any other phase.
*/
static const PhaseInfo phases[] = {
{ PHASE_MUTATOR, "Mutator Running", PHASE_NO_PARENT },
{ PHASE_GC_BEGIN, "Begin Callback", PHASE_NO_PARENT },
{ PHASE_WAIT_BACKGROUND_THREAD, "Wait Background Thread", PHASE_NO_PARENT },
{ PHASE_MARK_DISCARD_CODE, "Mark Discard Code", PHASE_NO_PARENT },
{ PHASE_RELAZIFY_FUNCTIONS, "Relazify Functions", PHASE_NO_PARENT },
{ PHASE_PURGE, "Purge", PHASE_NO_PARENT },
{ PHASE_MARK, "Mark", PHASE_NO_PARENT },
{ PHASE_UNMARK, "Unmark", PHASE_MARK },
static const PhaseInfo phases[] = {
{ PHASE_MUTATOR, "Mutator Running", PHASE_NO_PARENT},
{ PHASE_GC_BEGIN, "Begin Callback", PHASE_NO_PARENT},
{ PHASE_WAIT_BACKGROUND_THREAD, "Wait Background Thread", PHASE_NO_PARENT},
{ PHASE_PREPARE, "Prepare For Collection", PHASE_NO_PARENT},
{ PHASE_UNMARK, "Unmark", PHASE_PREPARE},
{ PHASE_BUFFER_GRAY_ROOTS, "Buffer Gray Roots", PHASE_PREPARE},
{ PHASE_MARK_DISCARD_CODE, "Mark Discard Code", PHASE_PREPARE},
{ PHASE_RELAZIFY_FUNCTIONS, "Relazify Functions", PHASE_PREPARE},
{ PHASE_PURGE, "Purge", PHASE_PREPARE},
{ PHASE_PURGE_SHAPE_TABLES, "Purge ShapeTables", PHASE_PREPARE},
{ PHASE_MARK, "Mark", PHASE_NO_PARENT},
/* PHASE_MARK_ROOTS */
{ PHASE_MARK_DELAYED, "Mark Delayed", PHASE_MARK },
{ PHASE_SWEEP, "Sweep", PHASE_NO_PARENT },
@ -182,18 +185,15 @@ static const PhaseInfo phases[] = {
/* PHASE_MARK_ROOTS */
{ PHASE_TRACE_HEAP, "Trace Heap", PHASE_NO_PARENT },
/* PHASE_MARK_ROOTS */
{ PHASE_BARRIER, "Barriers", PHASE_NO_PARENT },
{ PHASE_UNMARK_GRAY, "Unmark gray", PHASE_BARRIER },
{ PHASE_MARK_ROOTS, "Mark Roots", PHASE_MULTI_PARENTS },
{ PHASE_BUFFER_GRAY_ROOTS, "Buffer Gray Roots", PHASE_MARK_ROOTS },
{ PHASE_MARK_CCWS, "Mark Cross Compartment Wrappers", PHASE_MARK_ROOTS },
{ PHASE_MARK_STACK, "Mark C and JS stacks", PHASE_MARK_ROOTS },
{ PHASE_MARK_RUNTIME_DATA, "Mark Runtime-wide Data", PHASE_MARK_ROOTS },
{ PHASE_MARK_EMBEDDING, "Mark Embedding", PHASE_MARK_ROOTS },
{ PHASE_MARK_COMPARTMENTS, "Mark Compartments", PHASE_MARK_ROOTS },
{ PHASE_PURGE_SHAPE_TABLES, "Purge ShapeTables", PHASE_NO_PARENT },
{ PHASE_LIMIT, nullptr, PHASE_NO_PARENT }
{ PHASE_BARRIER, "Barriers", PHASE_NO_PARENT},
{ PHASE_UNMARK_GRAY, "Unmark gray", PHASE_BARRIER},
{ PHASE_MARK_ROOTS, "Mark Roots", PHASE_MULTI_PARENTS},
{ PHASE_MARK_CCWS, "Mark Cross Compartment Wrappers", PHASE_MARK_ROOTS},
{ PHASE_MARK_STACK, "Mark C and JS stacks", PHASE_MARK_ROOTS},
{ PHASE_MARK_RUNTIME_DATA, "Mark Runtime-wide Data", PHASE_MARK_ROOTS},
{ PHASE_MARK_EMBEDDING, "Mark Embedding", PHASE_MARK_ROOTS},
{ PHASE_MARK_COMPARTMENTS, "Mark compartments", PHASE_MARK_ROOTS,},
{ PHASE_LIMIT, nullptr, PHASE_NO_PARENT}
};
static ExtraPhaseInfo phaseExtra[PHASE_LIMIT] = { { 0, 0 } };

View file

@ -26,11 +26,14 @@ enum Phase : uint8_t {
PHASE_MUTATOR,
PHASE_GC_BEGIN,
PHASE_WAIT_BACKGROUND_THREAD,
PHASE_PREPARE,
PHASE_UNMARK,
PHASE_BUFFER_GRAY_ROOTS,
PHASE_MARK_DISCARD_CODE,
PHASE_RELAZIFY_FUNCTIONS,
PHASE_PURGE,
PHASE_PURGE_SHAPE_TABLES,
PHASE_MARK,
PHASE_UNMARK,
PHASE_MARK_DELAYED,
PHASE_SWEEP,
PHASE_SWEEP_MARK,
@ -78,13 +81,11 @@ enum Phase : uint8_t {
PHASE_BARRIER,
PHASE_UNMARK_GRAY,
PHASE_MARK_ROOTS,
PHASE_BUFFER_GRAY_ROOTS,
PHASE_MARK_CCWS,
PHASE_MARK_STACK,
PHASE_MARK_RUNTIME_DATA,
PHASE_MARK_EMBEDDING,
PHASE_MARK_COMPARTMENTS,
PHASE_PURGE_SHAPE_TABLES,
PHASE_LIMIT,
PHASE_NONE = PHASE_LIMIT,

View file

@ -866,7 +866,6 @@ GCRuntime::GCRuntime(JSRuntime* rt) :
majorGCNumber(0),
jitReleaseNumber(0),
number(0),
startNumber(0),
isFull(false),
#ifdef DEBUG
disableStrictProxyCheckingCount(0),
@ -3418,10 +3417,38 @@ ArenaLists::checkEmptyArenaList(AllocKind kind)
return num_live == 0;
}
class MOZ_RAII js::gc::AutoRunParallelTask : public GCParallelTask
{
using Func = void (*)(JSRuntime*);
Func func_;
gcstats::Phase phase_;
AutoLockHelperThreadState& lock_;
public:
AutoRunParallelTask(JSRuntime* rt, Func func, gcstats::Phase phase,
AutoLockHelperThreadState& lock)
: GCParallelTask(rt),
func_(func),
phase_(phase),
lock_(lock)
{
runtime()->gc.startTask(*this, phase_, lock_);
}
~AutoRunParallelTask() {
runtime()->gc.joinTask(*this, phase_, lock_);
}
void run() override {
func_(runtime());
}
};
void
GCRuntime::purgeRuntime(AutoLockForExclusiveAccess& lock)
{
gcstats::AutoPhase ap(stats(), gcstats::PhaseKind::PURGE);
gcstats::AutoPhase ap(stats(), gcstats::PHASE_PURGE);
for (GCCompartmentsIter comp(rt); !comp.done(); comp.next())
comp->purge();
@ -3676,7 +3703,7 @@ DiscardJITCodeForIncrementalGC(JSRuntime* rt)
{
js::CancelOffThreadIonCompile(rt, JS::Zone::Mark);
for (GCZonesIter zone(rt); !zone.done(); zone.next()) {
gcstats::AutoPhase ap(rt->gc.stats(), gcstats::PhaseKind::MARK_DISCARD_CODE);
gcstats::AutoPhase ap(rt->gc.stats(), gcstats::PHASE_MARK_DISCARD_CODE);
zone->discardJitCode(rt->defaultFreeOp());
}
}
@ -3684,7 +3711,7 @@ DiscardJITCodeForIncrementalGC(JSRuntime* rt)
static void
RelazifyFunctionsForShrinkingGC(JSRuntime* rt)
{
gcstats::AutoPhase ap(rt->gc.stats(), gcstats::PhaseKind::RELAZIFY_FUNCTIONS);
gcstats::AutoPhase ap(rt->gc.stats(), gcstats::PHASE_RELAZIFY_FUNCTIONS);
for (GCZonesIter zone(rt); !zone.done(); zone.next()) {
if (zone->isSelfHostingZone())
continue;
@ -3696,7 +3723,7 @@ RelazifyFunctionsForShrinkingGC(JSRuntime* rt)
static void
PurgeShapeTablesForShrinkingGC(JSRuntime* rt)
{
gcstats::AutoPhase ap(rt->gc.stats(), gcstats::PhaseKind::PURGE_SHAPE_TABLES);
gcstats::AutoPhase ap(rt->gc.stats(), gcstats::PHASE_PURGE_SHAPE_TABLES);
for (GCZonesIter zone(rt); !zone.done(); zone.next()) {
if (zone->keepShapeTables() || zone->isSelfHostingZone())
continue;
@ -3708,8 +3735,6 @@ PurgeShapeTablesForShrinkingGC(JSRuntime* rt)
static void
UnmarkCollectedZones(JSRuntime* rt)
{
gcstats::AutoPhase ap(rt->gc.stats(), gcstats::PhaseKind::UNMARK);
for (GCZonesIter zone(rt); !zone.done(); zone.next()) {
/* Unmark everything in the zones being collected. */
zone->arenas.unmarkAll();
@ -3721,6 +3746,12 @@ UnmarkCollectedZones(JSRuntime* rt)
}
}
static void
BufferGrayRoots(JSRuntime* rt)
{
rt->gc.bufferGrayRoots();
}
bool
GCRuntime::beginMarkPhase(JS::gcreason::Reason reason, AutoLockForExclusiveAccess& lock)
{
@ -3745,55 +3776,78 @@ GCRuntime::beginMarkPhase(JS::gcreason::Reason reason, AutoLockForExclusiveAcces
marker.start();
GCMarker* gcmarker = &marker;
/* For non-incremental GC the following sweep discards the jit code. */
if (isIncremental)
DiscardJITCodeForIncrementalGC(rt);
/*
* Relazify functions after discarding JIT code (we can't relazify functions
* with JIT code) and before the actual mark phase, so that the current GC
* can collect the JSScripts we're unlinking here. We do this only when
* we're performing a shrinking GC, as too much relazification can cause
* performance issues when we have to reparse the same functions over and
* over.
*/
if (invocationKind == GC_SHRINK) {
RelazifyFunctionsForShrinkingGC(rt);
PurgeShapeTablesForShrinkingGC(rt);
}
updateMallocCountersOnGCStart();
/* Process any queued source compressions during the start of a major GC. */
{
gcstats::AutoPhase ap1(stats(), gcstats::PHASE_PREPARE);
AutoLockHelperThreadState helperLock;
HelperThreadState().startHandlingCompressionTasks(helperLock);
}
/*
* We must purge the runtime at the beginning of an incremental GC. The
* danger if we purge later is that the snapshot invariant of incremental GC
* will be broken, as follows. If some object is reachable only through some
* cache (say the dtoaCache) then it will not be part of the snapshot. If
* we purge after root marking, then the mutator could obtain a pointer to
* the object and start using it. This object might never be marked, so a GC
* hazard would exist.
*/
purgeRuntime(lock);
/*
* Clear all mark state for the zones we are collecting. This is linear
* in the size of the heap we are collecting and so can be slow. Do this
* in parallel with the rest of this block.
*/
AutoRunParallelTask
unmarkCollectedZones(rt, UnmarkCollectedZones, gcstats::PHASE_UNMARK, helperLock);
/*
* Buffer gray roots for incremental collections. This is linear in the
* number of roots which can be in the tens of thousands. Do this in
* parallel with the rest of this block.
*/
Maybe<AutoRunParallelTask> bufferGrayRoots;
if (isIncremental)
bufferGrayRoots.emplace(rt, BufferGrayRoots, gcstats::PHASE_BUFFER_GRAY_ROOTS, helperLock);
AutoUnlockHelperThreadState unlock(helperLock);
/*
* Discard JIT code for incremental collections (for non-incremental
* collections the following sweep discards the jit code).
*/
if (isIncremental)
DiscardJITCodeForIncrementalGC(rt);
/*
* Relazify functions after discarding JIT code (we can't relazify
* functions with JIT code) and before the actual mark phase, so that
* the current GC can collect the JSScripts we're unlinking here. We do
* this only when we're performing a shrinking GC, as too much
* relazification can cause performance issues when we have to reparse
* the same functions over and over.
*/
if (invocationKind == GC_SHRINK) {
RelazifyFunctionsForShrinkingGC(rt);
PurgeShapeTablesForShrinkingGC(rt);
}
/*
* We must purge the runtime at the beginning of an incremental GC. The
* danger if we purge later is that the snapshot invariant of
* incremental GC will be broken, as follows. If some object is
* reachable only through some cache (say the dtoaCache) then it will
* not be part of the snapshot. If we purge after root marking, then
* the mutator could obtain a pointer to the object and start using
* it. This object might never be marked, so a GC hazard would exist.
*/
purgeRuntime(lock);
}
/*
* Mark phase.
*/
gcstats::AutoPhase ap1(stats, gcstats::PHASE_MARK);
UnmarkCollectedZones(rt);
gcstats::AutoPhase ap(stats(), gcstats::PHASE_MARK);
traceRuntimeForMajorGC(gcmarker, lock);
gcstats::AutoPhase ap2(stats, gcstats::PHASE_MARK_ROOTS);
if (isIncremental) {
bufferGrayRoots();
if (isIncremental)
markCompartments();
updateMallocCountersOnGCStart();
/*
* Process any queued source compressions during the start of a major
* GC.
*/
{
AutoLockHelperThreadState helperLock;
HelperThreadState().startHandlingCompressionTasks(helperLock);
}
return true;
@ -3802,7 +3856,8 @@ GCRuntime::beginMarkPhase(JS::gcreason::Reason reason, AutoLockForExclusiveAcces
void
GCRuntime::markCompartments()
{
gcstats::AutoPhase ap(stats, gcstats::PHASE_MARK_COMPARTMENTS);
gcstats::AutoPhase ap1(stats(), gcstats::PHASE_MARK_ROOTS);
gcstats::AutoPhase ap2(stats(), gcstats::PHASE_MARK_COMPARTMENTS);
/*
* This code ensures that if a compartment is "dead", then it will be
@ -4068,7 +4123,7 @@ js::gc::MarkingValidator::nonIncrementalMark(AutoLockForExclusiveAccess& lock)
gc->incrementalState = State::MarkRoots;
{
gcstats::AutoPhase ap(gc->stats(), gcstats::PHASE_MARK);
gcstats::AutoPhase ap(gc->stats(), gcstats::PHASE_PREPARE);
{
gcstats::AutoPhase ap(gc->stats(), gcstats::PHASE_UNMARK);
@ -4082,6 +4137,10 @@ js::gc::MarkingValidator::nonIncrementalMark(AutoLockForExclusiveAccess& lock)
for (auto chunk = gc->allNonEmptyChunks(lock); !chunk.done(); chunk.next())
chunk->bitmap.clear();
}
}
{
gcstats::AutoPhase ap(gc->stats(), gcstats::PHASE_MARK);
gc->traceRuntimeForMajorGC(gcmarker, lock);
@ -5002,30 +5061,6 @@ SweepWeakCachesFromMainThread(JSRuntime* rt)
}
}
static WeakCacheTaskVector
PrepareWeakCacheTasks(JSRuntime* rt)
{
WeakCacheTaskVector out;
for (GCZoneGroupIter zone(rt); !zone.done(); zone.next()) {
for (JS::WeakCache<void*>* cache : zone->weakCaches_) {
if (!out.append(SweepWeakCacheTask(rt, *cache))) {
SweepWeakCachesFromMainThread(rt);
return WeakCacheTaskVector();
}
}
}
return out;
}
~AutoRunParallelTask() {
runtime()->gc.joinTask(*this, phase_, lock_);
}
void run() override {
func_(runtime());
}
};
IncrementalProgress
GCRuntime::beginSweepingSweepGroup(FreeOp* fop, SliceBudget& budget)
{