Bug 1340597 - Avoid triggering read barrier in DumpHeap and when collecting stats r=sfink

This commit is contained in:
Jon Coppeard 2017-02-23 16:26:14 +00:00
parent 4c4d2e43e2
commit 383736d564
5 changed files with 55 additions and 46 deletions

View File

@ -20,10 +20,10 @@ using namespace js;
using namespace js::gc;
static void
IterateCompartmentsArenasCells(JSContext* cx, Zone* zone, void* data,
JSIterateCompartmentCallback compartmentCallback,
IterateArenaCallback arenaCallback,
IterateCellCallback cellCallback)
IterateCompartmentsArenasCellsUnbarriered(JSContext* cx, Zone* zone, void* data,
JSIterateCompartmentCallback compartmentCallback,
IterateArenaCallback arenaCallback,
IterateCellCallback cellCallback)
{
for (CompartmentsInZoneIter comp(zone); !comp.done(); comp.next())
(*compartmentCallback)(cx, data, comp);
@ -35,40 +35,40 @@ IterateCompartmentsArenasCells(JSContext* cx, Zone* zone, void* data,
for (ArenaIter aiter(zone, thingKind); !aiter.done(); aiter.next()) {
Arena* arena = aiter.get();
(*arenaCallback)(cx->runtime(), data, arena, traceKind, thingSize);
for (ArenaCellIter iter(arena); !iter.done(); iter.next())
for (ArenaCellIterUnbarriered iter(arena); !iter.done(); iter.next())
(*cellCallback)(cx->runtime(), data, iter.getCell(), traceKind, thingSize);
}
}
}
void
js::IterateZonesCompartmentsArenasCells(JSContext* cx, void* data,
IterateZoneCallback zoneCallback,
JSIterateCompartmentCallback compartmentCallback,
IterateArenaCallback arenaCallback,
IterateCellCallback cellCallback)
js::IterateHeapUnbarriered(JSContext* cx, void* data,
IterateZoneCallback zoneCallback,
JSIterateCompartmentCallback compartmentCallback,
IterateArenaCallback arenaCallback,
IterateCellCallback cellCallback)
{
AutoPrepareForTracing prop(cx, WithAtoms);
for (ZonesIter zone(cx->runtime(), WithAtoms); !zone.done(); zone.next()) {
(*zoneCallback)(cx->runtime(), data, zone);
IterateCompartmentsArenasCells(cx, zone, data,
compartmentCallback, arenaCallback, cellCallback);
IterateCompartmentsArenasCellsUnbarriered(cx, zone, data,
compartmentCallback, arenaCallback, cellCallback);
}
}
void
js::IterateZoneCompartmentsArenasCells(JSContext* cx, Zone* zone, void* data,
IterateZoneCallback zoneCallback,
JSIterateCompartmentCallback compartmentCallback,
IterateArenaCallback arenaCallback,
IterateCellCallback cellCallback)
js::IterateHeapUnbarrieredForZone(JSContext* cx, Zone* zone, void* data,
IterateZoneCallback zoneCallback,
JSIterateCompartmentCallback compartmentCallback,
IterateArenaCallback arenaCallback,
IterateCellCallback cellCallback)
{
AutoPrepareForTracing prop(cx, WithAtoms);
(*zoneCallback)(cx->runtime(), data, zone);
IterateCompartmentsArenasCells(cx, zone, data,
compartmentCallback, arenaCallback, cellCallback);
IterateCompartmentsArenasCellsUnbarriered(cx, zone, data,
compartmentCallback, arenaCallback, cellCallback);
}
void

View File

@ -1184,11 +1184,11 @@ js::DumpHeap(JSContext* cx, FILE* fp, js::DumpHeapNurseryBehaviour nurseryBehavi
fprintf(dtrc.output, "==========\n");
dtrc.prefix = "> ";
IterateZonesCompartmentsArenasCells(cx, &dtrc,
DumpHeapVisitZone,
DumpHeapVisitCompartment,
DumpHeapVisitArena,
DumpHeapVisitCell);
IterateHeapUnbarriered(cx, &dtrc,
DumpHeapVisitZone,
DumpHeapVisitCompartment,
DumpHeapVisitArena,
DumpHeapVisitCell);
fflush(dtrc.output);
}

View File

@ -1018,24 +1018,27 @@ typedef void (*IterateCellCallback)(JSRuntime* rt, void* data, void* thing,
* This function calls |zoneCallback| on every zone, |compartmentCallback| on
* every compartment, |arenaCallback| on every in-use arena, and |cellCallback|
* on every in-use cell in the GC heap.
*
* Note that no read barrier is triggered on the cells passed to cellCallback,
* so no these pointers must not escape the callback.
*/
extern void
IterateZonesCompartmentsArenasCells(JSContext* cx, void* data,
IterateZoneCallback zoneCallback,
JSIterateCompartmentCallback compartmentCallback,
IterateArenaCallback arenaCallback,
IterateCellCallback cellCallback);
IterateHeapUnbarriered(JSContext* cx, void* data,
IterateZoneCallback zoneCallback,
JSIterateCompartmentCallback compartmentCallback,
IterateArenaCallback arenaCallback,
IterateCellCallback cellCallback);
/*
* This function is like IterateZonesCompartmentsArenasCells, but does it for a
* single zone.
*/
extern void
IterateZoneCompartmentsArenasCells(JSContext* cx, Zone* zone, void* data,
IterateZoneCallback zoneCallback,
JSIterateCompartmentCallback compartmentCallback,
IterateArenaCallback arenaCallback,
IterateCellCallback cellCallback);
IterateHeapUnbarrieredForZone(JSContext* cx, Zone* zone, void* data,
IterateZoneCallback zoneCallback,
JSIterateCompartmentCallback compartmentCallback,
IterateArenaCallback arenaCallback,
IterateCellCallback cellCallback);
/*
* Invoke chunkCallback on every in-use chunk.

View File

@ -154,8 +154,6 @@ class ArenaCellIterImpl
void init(Arena* arena, CellIterNeedsBarrier mayNeedBarrier) {
MOZ_ASSERT(!initialized);
MOZ_ASSERT(arena);
MOZ_ASSERT_IF(!mayNeedBarrier,
CurrentThreadIsPerformingGC() || CurrentThreadIsGCSweeping());
initialized = true;
AllocKind kind = arena->getAllocKind();
firstThingOffset = Arena::firstThingOffset(kind);
@ -243,6 +241,14 @@ class ArenaCellIterUnderFinalize : public ArenaCellIterImpl
}
};
class ArenaCellIterUnbarriered : public ArenaCellIterImpl
{
public:
explicit ArenaCellIterUnbarriered(Arena* arena)
: ArenaCellIterImpl(arena, CellIterDoesntNeedBarrier)
{}
};
template <typename T>
class ZoneCellIter;

View File

@ -760,11 +760,11 @@ CollectRuntimeStatsHelper(JSContext* cx, RuntimeStats* rtStats, ObjectPrivateVis
StatsClosure closure(rtStats, opv, anonymize);
if (!closure.init())
return false;
IterateZonesCompartmentsArenasCells(cx, &closure,
StatsZoneCallback,
StatsCompartmentCallback,
StatsArenaCallback,
statsCellCallback);
IterateHeapUnbarriered(cx, &closure,
StatsZoneCallback,
StatsCompartmentCallback,
StatsArenaCallback,
statsCellCallback);
// Take the "explicit/js/runtime/" measurements.
rt->addSizeOfIncludingThis(rtStats->mallocSizeOf_, &rtStats->runtime);
@ -906,11 +906,11 @@ AddSizeOfTab(JSContext* cx, HandleObject obj, MallocSizeOf mallocSizeOf, ObjectP
StatsClosure closure(&rtStats, opv, /* anonymize = */ false);
if (!closure.init())
return false;
IterateZoneCompartmentsArenasCells(cx, zone, &closure,
StatsZoneCallback,
StatsCompartmentCallback,
StatsArenaCallback,
StatsCellCallback<CoarseGrained>);
IterateHeapUnbarrieredForZone(cx, zone, &closure,
StatsZoneCallback,
StatsCompartmentCallback,
StatsArenaCallback,
StatsCellCallback<CoarseGrained>);
MOZ_ASSERT(rtStats.zoneStatsVector.length() == 1);
rtStats.zTotals.addSizes(rtStats.zoneStatsVector[0]);