mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 817341 - Differentiate marking and sweep-marking in GC stats (r=jonco)
This commit is contained in:
parent
546e48620c
commit
8e805e4167
@ -267,49 +267,55 @@ t(int64_t t)
|
||||
|
||||
struct PhaseInfo
|
||||
{
|
||||
unsigned index;
|
||||
Phase index;
|
||||
const char *name;
|
||||
Phase parent;
|
||||
};
|
||||
|
||||
static const Phase PHASE_NO_PARENT = PHASE_LIMIT;
|
||||
|
||||
static PhaseInfo phases[] = {
|
||||
{ PHASE_GC_BEGIN, "Begin Callback" },
|
||||
{ PHASE_WAIT_BACKGROUND_THREAD, "Wait Background Thread" },
|
||||
{ PHASE_PURGE, "Purge" },
|
||||
{ PHASE_MARK, "Mark" },
|
||||
{ PHASE_MARK_DISCARD_CODE, "Mark Discard Code" },
|
||||
{ PHASE_MARK_ROOTS, "Mark Roots" },
|
||||
{ PHASE_MARK_TYPES, "Mark Types" },
|
||||
{ PHASE_MARK_DELAYED, "Mark Delayed" },
|
||||
{ PHASE_SWEEP, "Sweep" },
|
||||
{ PHASE_SWEEP_MARK_INCOMING_BLACK, "Mark Incoming Black Pointers" },
|
||||
{ PHASE_SWEEP_MARK_WEAK, "Mark Weak" },
|
||||
{ PHASE_SWEEP_MARK_GRAY, "Mark Gray" },
|
||||
{ PHASE_SWEEP_MARK_GRAY_WEAK, "Mark Gray and Weak" },
|
||||
{ PHASE_SWEEP_MARK_INCOMING_GRAY, "Mark Incoming Gray Pointers" },
|
||||
{ PHASE_FINALIZE_START, "Finalize Start Callback" },
|
||||
{ PHASE_SWEEP_ATOMS, "Sweep Atoms" },
|
||||
{ PHASE_SWEEP_COMPARTMENTS, "Sweep Compartments" },
|
||||
{ PHASE_SWEEP_TABLES, "Sweep Tables" },
|
||||
{ PHASE_SWEEP_TABLES_WRAPPER, "Sweep Cross Compartment Wrappers" },
|
||||
{ PHASE_SWEEP_TABLES_BASE_SHAPE, "Sweep Base Shapes" },
|
||||
{ PHASE_SWEEP_TABLES_INITIAL_SHAPE, "Sweep Intital Shapes" },
|
||||
{ PHASE_SWEEP_TABLES_TYPE_OBJECT, "Sweep Type Objects" },
|
||||
{ PHASE_SWEEP_TABLES_BREAKPOINT, "Sweep Breakpoints" },
|
||||
{ PHASE_SWEEP_TABLES_REGEXP, "Sweep Regexps" },
|
||||
{ PHASE_SWEEP_OBJECT, "Sweep Object" },
|
||||
{ PHASE_SWEEP_STRING, "Sweep String" },
|
||||
{ PHASE_SWEEP_SCRIPT, "Sweep Script" },
|
||||
{ PHASE_SWEEP_SHAPE, "Sweep Shape" },
|
||||
{ PHASE_SWEEP_DISCARD_CODE, "Sweep Discard Code" },
|
||||
{ PHASE_DISCARD_ANALYSIS, "Discard Analysis" },
|
||||
{ PHASE_DISCARD_TI, "Discard TI" },
|
||||
{ PHASE_FREE_TI_ARENA, "Free TI Arena" },
|
||||
{ PHASE_SWEEP_TYPES, "Sweep Types" },
|
||||
{ PHASE_CLEAR_SCRIPT_ANALYSIS, "Clear Script Analysis" },
|
||||
{ PHASE_FINALIZE_END, "Finalize End Callback" },
|
||||
{ PHASE_DESTROY, "Deallocate" },
|
||||
{ PHASE_GC_END, "End Callback" },
|
||||
{ 0, NULL }
|
||||
{ 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_PURGE, "Purge", PHASE_NO_PARENT },
|
||||
{ PHASE_MARK, "Mark", PHASE_NO_PARENT },
|
||||
{ PHASE_MARK_ROOTS, "Mark Roots", PHASE_MARK },
|
||||
{ PHASE_MARK_TYPES, "Mark Types", PHASE_MARK_ROOTS },
|
||||
{ PHASE_MARK_DELAYED, "Mark Delayed", PHASE_MARK },
|
||||
{ PHASE_SWEEP, "Sweep", PHASE_NO_PARENT },
|
||||
{ PHASE_SWEEP_MARK, "Mark During Sweeping", PHASE_SWEEP },
|
||||
{ PHASE_SWEEP_MARK_DELAYED, "Mark Delayed During Sweeping", PHASE_SWEEP_MARK },
|
||||
{ PHASE_SWEEP_MARK_INCOMING_BLACK, "Mark Incoming Black Pointers", PHASE_SWEEP_MARK },
|
||||
{ PHASE_SWEEP_MARK_WEAK, "Mark Weak", PHASE_SWEEP_MARK },
|
||||
{ PHASE_SWEEP_MARK_INCOMING_GRAY, "Mark Incoming Gray Pointers", PHASE_SWEEP_MARK },
|
||||
{ PHASE_SWEEP_MARK_GRAY, "Mark Gray", PHASE_SWEEP_MARK },
|
||||
{ PHASE_SWEEP_MARK_GRAY_WEAK, "Mark Gray and Weak", PHASE_SWEEP_MARK },
|
||||
{ PHASE_FINALIZE_START, "Finalize Start Callback", PHASE_SWEEP },
|
||||
{ PHASE_SWEEP_ATOMS, "Sweep Atoms", PHASE_SWEEP },
|
||||
{ PHASE_SWEEP_COMPARTMENTS, "Sweep Compartments", PHASE_SWEEP },
|
||||
{ PHASE_SWEEP_DISCARD_CODE, "Sweep Discard Code", PHASE_SWEEP_COMPARTMENTS },
|
||||
{ PHASE_SWEEP_TABLES, "Sweep Tables", PHASE_SWEEP_COMPARTMENTS },
|
||||
{ PHASE_SWEEP_TABLES_WRAPPER, "Sweep Cross Compartment Wrappers", PHASE_SWEEP_TABLES },
|
||||
{ PHASE_SWEEP_TABLES_BASE_SHAPE, "Sweep Base Shapes", PHASE_SWEEP_TABLES },
|
||||
{ PHASE_SWEEP_TABLES_INITIAL_SHAPE, "Sweep Intital Shapes", PHASE_SWEEP_TABLES },
|
||||
{ PHASE_SWEEP_TABLES_TYPE_OBJECT, "Sweep Type Objects", PHASE_SWEEP_TABLES },
|
||||
{ PHASE_SWEEP_TABLES_BREAKPOINT, "Sweep Breakpoints", PHASE_SWEEP_TABLES },
|
||||
{ PHASE_SWEEP_TABLES_REGEXP, "Sweep Regexps", PHASE_SWEEP_TABLES },
|
||||
{ PHASE_DISCARD_ANALYSIS, "Discard Analysis", PHASE_SWEEP_COMPARTMENTS },
|
||||
{ PHASE_DISCARD_TI, "Discard TI", PHASE_DISCARD_ANALYSIS },
|
||||
{ PHASE_FREE_TI_ARENA, "Free TI Arena", PHASE_DISCARD_ANALYSIS },
|
||||
{ PHASE_SWEEP_TYPES, "Sweep Types", PHASE_DISCARD_ANALYSIS },
|
||||
{ PHASE_CLEAR_SCRIPT_ANALYSIS, "Clear Script Analysis", PHASE_DISCARD_ANALYSIS },
|
||||
{ PHASE_SWEEP_OBJECT, "Sweep Object", PHASE_SWEEP },
|
||||
{ PHASE_SWEEP_STRING, "Sweep String", PHASE_SWEEP },
|
||||
{ PHASE_SWEEP_SCRIPT, "Sweep Script", PHASE_SWEEP },
|
||||
{ PHASE_SWEEP_SHAPE, "Sweep Shape", PHASE_SWEEP },
|
||||
{ PHASE_SWEEP_IONCODE, "Sweep Ion code", PHASE_SWEEP },
|
||||
{ PHASE_FINALIZE_END, "Finalize End Callback", PHASE_SWEEP },
|
||||
{ PHASE_DESTROY, "Deallocate", PHASE_SWEEP },
|
||||
{ PHASE_GC_END, "End Callback", PHASE_NO_PARENT },
|
||||
{ PHASE_LIMIT, NULL, PHASE_NO_PARENT }
|
||||
};
|
||||
|
||||
static void
|
||||
@ -441,7 +447,9 @@ Statistics::Statistics(JSRuntime *rt)
|
||||
gcDepth(0),
|
||||
collectedCount(0),
|
||||
compartmentCount(0),
|
||||
nonincrementalReason(NULL)
|
||||
nonincrementalReason(NULL),
|
||||
preBytes(0),
|
||||
phaseNestingDepth(0)
|
||||
{
|
||||
PodArrayZero(phaseTotals);
|
||||
PodArrayZero(counts);
|
||||
@ -615,6 +623,15 @@ Statistics::beginPhase(Phase phase)
|
||||
/* Guard against re-entry */
|
||||
JS_ASSERT(!phaseStartTimes[phase]);
|
||||
|
||||
#ifdef DEBUG
|
||||
JS_ASSERT(phases[phase].index == phase);
|
||||
Phase parent = phaseNestingDepth ? phaseNesting[phaseNestingDepth - 1] : PHASE_NO_PARENT;
|
||||
JS_ASSERT(phaseNestingDepth < MAX_NESTING);
|
||||
JS_ASSERT_IF(gcDepth == 1, phases[phase].parent == parent);
|
||||
phaseNesting[phaseNestingDepth] = phase;
|
||||
phaseNestingDepth++;
|
||||
#endif
|
||||
|
||||
phaseStartTimes[phase] = PRMJ_Now();
|
||||
|
||||
if (phase == gcstats::PHASE_MARK)
|
||||
@ -626,6 +643,8 @@ Statistics::beginPhase(Phase phase)
|
||||
void
|
||||
Statistics::endPhase(Phase phase)
|
||||
{
|
||||
phaseNestingDepth--;
|
||||
|
||||
int64_t t = PRMJ_Now() - phaseStartTimes[phase];
|
||||
slices.back().phaseTimes[phase] += t;
|
||||
phaseTimes[phase] += t;
|
||||
|
@ -10,6 +10,8 @@
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "mozilla/Util.h"
|
||||
|
||||
#include "jsfriendapi.h"
|
||||
#include "jspubtd.h"
|
||||
#include "jsutil.h"
|
||||
@ -22,21 +24,24 @@ namespace gcstats {
|
||||
enum Phase {
|
||||
PHASE_GC_BEGIN,
|
||||
PHASE_WAIT_BACKGROUND_THREAD,
|
||||
PHASE_MARK_DISCARD_CODE,
|
||||
PHASE_PURGE,
|
||||
PHASE_MARK,
|
||||
PHASE_MARK_DISCARD_CODE,
|
||||
PHASE_MARK_ROOTS,
|
||||
PHASE_MARK_TYPES,
|
||||
PHASE_MARK_DELAYED,
|
||||
PHASE_FINALIZE_START,
|
||||
PHASE_SWEEP,
|
||||
PHASE_SWEEP_MARK,
|
||||
PHASE_SWEEP_MARK_DELAYED,
|
||||
PHASE_SWEEP_MARK_INCOMING_BLACK,
|
||||
PHASE_SWEEP_MARK_WEAK,
|
||||
PHASE_SWEEP_MARK_INCOMING_GRAY,
|
||||
PHASE_SWEEP_MARK_GRAY,
|
||||
PHASE_SWEEP_MARK_GRAY_WEAK,
|
||||
PHASE_FINALIZE_START,
|
||||
PHASE_SWEEP_ATOMS,
|
||||
PHASE_SWEEP_COMPARTMENTS,
|
||||
PHASE_SWEEP_DISCARD_CODE,
|
||||
PHASE_SWEEP_TABLES,
|
||||
PHASE_SWEEP_TABLES_WRAPPER,
|
||||
PHASE_SWEEP_TABLES_BASE_SHAPE,
|
||||
@ -44,17 +49,16 @@ enum Phase {
|
||||
PHASE_SWEEP_TABLES_TYPE_OBJECT,
|
||||
PHASE_SWEEP_TABLES_BREAKPOINT,
|
||||
PHASE_SWEEP_TABLES_REGEXP,
|
||||
PHASE_SWEEP_OBJECT,
|
||||
PHASE_SWEEP_STRING,
|
||||
PHASE_SWEEP_SCRIPT,
|
||||
PHASE_SWEEP_SHAPE,
|
||||
PHASE_SWEEP_IONCODE,
|
||||
PHASE_SWEEP_DISCARD_CODE,
|
||||
PHASE_DISCARD_ANALYSIS,
|
||||
PHASE_DISCARD_TI,
|
||||
PHASE_FREE_TI_ARENA,
|
||||
PHASE_SWEEP_TYPES,
|
||||
PHASE_CLEAR_SCRIPT_ANALYSIS,
|
||||
PHASE_SWEEP_OBJECT,
|
||||
PHASE_SWEEP_STRING,
|
||||
PHASE_SWEEP_SCRIPT,
|
||||
PHASE_SWEEP_SHAPE,
|
||||
PHASE_SWEEP_IONCODE,
|
||||
PHASE_FINALIZE_END,
|
||||
PHASE_DESTROY,
|
||||
PHASE_GC_END,
|
||||
@ -146,6 +150,13 @@ struct Statistics {
|
||||
/* Allocated space before the GC started. */
|
||||
size_t preBytes;
|
||||
|
||||
#ifdef DEBUG
|
||||
/* Phases that are currently on stack. */
|
||||
static const size_t MAX_NESTING = 8;
|
||||
Phase phaseNesting[MAX_NESTING];
|
||||
#endif
|
||||
mozilla::DebugOnly<size_t> phaseNestingDepth;
|
||||
|
||||
/* Sweep times for SCCs of compartments. */
|
||||
Vector<int64_t, 0, SystemAllocPolicy> sccTimes;
|
||||
|
||||
|
@ -1370,6 +1370,7 @@ ArenaLists::queueShapesForSweep(FreeOp *fop)
|
||||
void
|
||||
ArenaLists::queueIonCodeForSweep(FreeOp *fop)
|
||||
{
|
||||
gcstats::AutoPhase ap(fop->runtime()->gcStats, gcstats::PHASE_SWEEP_IONCODE);
|
||||
finalizeNow(fop, FINALIZE_IONCODE);
|
||||
}
|
||||
|
||||
@ -1680,7 +1681,10 @@ GCMarker::markDelayedChildren(ArenaHeader *aheader)
|
||||
bool
|
||||
GCMarker::markDelayedChildren(SliceBudget &budget)
|
||||
{
|
||||
gcstats::AutoPhase ap(runtime->gcStats, gcstats::PHASE_MARK_DELAYED);
|
||||
gcstats::Phase phase = runtime->gcIncrementalState == MARK
|
||||
? gcstats::PHASE_MARK_DELAYED
|
||||
: gcstats::PHASE_SWEEP_MARK_DELAYED;
|
||||
gcstats::AutoPhase ap(runtime->gcStats, phase);
|
||||
|
||||
JS_ASSERT(unmarkedArenaStackTop);
|
||||
do {
|
||||
@ -2710,7 +2714,8 @@ MarkWeakReferences(JSRuntime *rt, gcstats::Phase phase)
|
||||
GCMarker *gcmarker = &rt->gcMarker;
|
||||
JS_ASSERT(gcmarker->isDrained());
|
||||
|
||||
gcstats::AutoPhase ap(rt->gcStats, phase);
|
||||
gcstats::AutoPhase ap(rt->gcStats, gcstats::PHASE_SWEEP_MARK);
|
||||
gcstats::AutoPhase ap1(rt->gcStats, phase);
|
||||
|
||||
for (;;) {
|
||||
bool markedAny = false;
|
||||
@ -2735,7 +2740,8 @@ MarkGrayReferences(JSRuntime *rt)
|
||||
GCMarker *gcmarker = &rt->gcMarker;
|
||||
|
||||
{
|
||||
gcstats::AutoPhase ap(rt->gcStats, gcstats::PHASE_SWEEP_MARK_GRAY);
|
||||
gcstats::AutoPhase ap(rt->gcStats, gcstats::PHASE_SWEEP_MARK);
|
||||
gcstats::AutoPhase ap1(rt->gcStats, gcstats::PHASE_SWEEP_MARK_GRAY);
|
||||
gcmarker->setMarkColorGray();
|
||||
if (gcmarker->hasBufferedGrayRoots()) {
|
||||
gcmarker->markBufferedGrayRoots();
|
||||
@ -3095,6 +3101,7 @@ MarkIncomingCrossCompartmentPointers(JSRuntime *rt, const uint32_t color)
|
||||
{
|
||||
JS_ASSERT(color == BLACK || color == GRAY);
|
||||
|
||||
gcstats::AutoPhase ap(rt->gcStats, gcstats::PHASE_SWEEP_MARK);
|
||||
static const gcstats::Phase statsPhases[] = {
|
||||
gcstats::PHASE_SWEEP_MARK_INCOMING_BLACK,
|
||||
gcstats::PHASE_SWEEP_MARK_INCOMING_GRAY
|
||||
@ -3409,12 +3416,24 @@ ArenaLists::foregroundFinalize(FreeOp *fop, AllocKind thingKind, SliceBudget &sl
|
||||
return FinalizeArenas(fop, &arenaListsToSweep[thingKind], dest, thingKind, sliceBudget);
|
||||
}
|
||||
|
||||
static bool
|
||||
DrainMarkStack(JSRuntime *rt, SliceBudget &sliceBudget, gcstats::Phase phase)
|
||||
{
|
||||
/* Run a marking slice and return whether the stack is now empty. */
|
||||
gcstats::AutoPhase ap(rt->gcStats, phase);
|
||||
return rt->gcMarker.drainMarkStack(sliceBudget);
|
||||
}
|
||||
|
||||
static bool
|
||||
SweepPhase(JSRuntime *rt, SliceBudget &sliceBudget)
|
||||
{
|
||||
gcstats::AutoPhase ap(rt->gcStats, gcstats::PHASE_SWEEP);
|
||||
FreeOp fop(rt, rt->gcSweepOnBackgroundThread);
|
||||
|
||||
bool finished = DrainMarkStack(rt, sliceBudget, gcstats::PHASE_SWEEP_MARK);
|
||||
if (!finished)
|
||||
return false;
|
||||
|
||||
for (;;) {
|
||||
for (; rt->gcSweepPhase < FinalizePhaseCount ; ++rt->gcSweepPhase) {
|
||||
gcstats::AutoPhase ap(rt->gcStats, FinalizePhaseStatsPhase[rt->gcSweepPhase]);
|
||||
@ -3770,14 +3789,6 @@ PushZealSelectedObjects(JSRuntime *rt)
|
||||
#endif
|
||||
}
|
||||
|
||||
static bool
|
||||
DrainMarkStack(JSRuntime *rt, SliceBudget &sliceBudget)
|
||||
{
|
||||
/* Run a marking slice and return whether the stack is now empty. */
|
||||
gcstats::AutoPhase ap(rt->gcStats, gcstats::PHASE_MARK);
|
||||
return rt->gcMarker.drainMarkStack(sliceBudget);
|
||||
}
|
||||
|
||||
static void
|
||||
IncrementalCollectSlice(JSRuntime *rt,
|
||||
int64_t budget,
|
||||
@ -3844,7 +3855,7 @@ IncrementalCollectSlice(JSRuntime *rt,
|
||||
if (!rt->gcMarker.hasBufferedGrayRoots())
|
||||
sliceBudget.reset();
|
||||
|
||||
bool finished = DrainMarkStack(rt, sliceBudget);
|
||||
bool finished = DrainMarkStack(rt, sliceBudget, gcstats::PHASE_MARK);
|
||||
if (!finished)
|
||||
break;
|
||||
|
||||
@ -3884,11 +3895,7 @@ IncrementalCollectSlice(JSRuntime *rt,
|
||||
}
|
||||
|
||||
case SWEEP: {
|
||||
bool finished = DrainMarkStack(rt, sliceBudget);
|
||||
if (!finished)
|
||||
break;
|
||||
|
||||
finished = SweepPhase(rt, sliceBudget);
|
||||
bool finished = SweepPhase(rt, sliceBudget);
|
||||
if (!finished)
|
||||
break;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user