Bug 1360526 - Sweep weakmaps in parallel with other sweeping r=sfink

--HG--
extra : rebase_source : 77d50ed900253ce2d37f2b53355fc7d2f462b49f
This commit is contained in:
Jon Coppeard 2017-05-03 11:26:36 +01:00
Родитель 00d998b339
Коммит f9b398f422
6 изменённых файлов: 56 добавлений и 44 удалений

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

@ -276,16 +276,16 @@ struct Zone : public JS::shadow::Zone,
unsigned lastSweepGroupIndex() { return gcLastSweepGroupIndex; }
#endif
using DebuggerVector = js::Vector<js::Debugger*, 0, js::SystemAllocPolicy>;
private:
js::ZoneGroupData<DebuggerVector*> debuggers;
void sweepBreakpoints(js::FreeOp* fop);
void sweepUniqueIds(js::FreeOp* fop);
void sweepWeakMaps();
void sweepCompartments(js::FreeOp* fop, bool keepAtleastOne, bool lastGC);
using DebuggerVector = js::Vector<js::Debugger*, 0, js::SystemAllocPolicy>;
private:
js::ZoneGroupData<DebuggerVector*> debuggers;
js::jit::JitZone* createJitZone(JSContext* cx);
bool isQueuedForBackgroundSweep() {
@ -321,7 +321,7 @@ struct Zone : public JS::shadow::Zone,
private:
/* Live weakmaps in this zone. */
js::ZoneGroupData<mozilla::LinkedList<js::WeakMapBase>> gcWeakMapList_;
js::ZoneGroupOrGCTaskData<mozilla::LinkedList<js::WeakMapBase>> gcWeakMapList_;
public:
mozilla::LinkedList<js::WeakMapBase>& gcWeakMapList() { return gcWeakMapList_.ref(); }
@ -344,7 +344,7 @@ struct Zone : public JS::shadow::Zone,
// preserved for re-scanning during sweeping.
using WeakEdges = js::Vector<js::gc::TenuredCell**, 0, js::SystemAllocPolicy>;
private:
js::ZoneGroupData<WeakEdges> gcWeakRefs_;
js::ZoneGroupOrGCTaskData<WeakEdges> gcWeakRefs_;
public:
WeakEdges& gcWeakRefs() { return gcWeakRefs_.ref(); }
@ -362,7 +362,7 @@ struct Zone : public JS::shadow::Zone,
* Mapping from not yet marked keys to a vector of all values that the key
* maps to in any live weak map.
*/
js::ZoneGroupData<js::gc::WeakKeyTable> gcWeakKeys_;
js::ZoneGroupOrGCTaskData<js::gc::WeakKeyTable> gcWeakKeys_;
public:
js::gc::WeakKeyTable& gcWeakKeys() { return gcWeakKeys_.ref(); }

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

@ -838,13 +838,10 @@ JSCompartment::sweepTemplateLiteralMap()
}
void
JSCompartment::sweepGlobalObject(FreeOp* fop)
JSCompartment::sweepGlobalObject()
{
if (global_ && IsAboutToBeFinalized(&global_)) {
if (isDebuggee())
Debugger::detachAllDebuggersFromGlobal(fop, global_.unbarrieredGet());
if (global_ && IsAboutToBeFinalized(&global_))
global_.set(nullptr);
}
}
void

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

@ -708,7 +708,7 @@ struct JSCompartment
void sweepCrossCompartmentWrappers();
void sweepSavedStacks();
void sweepTemplateLiteralMap();
void sweepGlobalObject(js::FreeOp* fop);
void sweepGlobalObject();
void sweepSelfHostingScriptSource();
void sweepJitCompartment(js::FreeOp* fop);
void sweepRegExps();

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

@ -2217,7 +2217,7 @@ GCRuntime::sweepZoneAfterCompacting(Zone* zone)
c->sweepSavedStacks();
c->sweepTemplateLiteralMap();
c->sweepVarNames();
c->sweepGlobalObject(fop);
c->sweepGlobalObject();
c->sweepSelfHostingScriptSource();
c->sweepDebugEnvironments();
c->sweepJitCompartment(fop);
@ -4971,6 +4971,7 @@ MAKE_GC_SWEEP_TASK(SweepObjectGroupsTask);
MAKE_GC_SWEEP_TASK(SweepRegExpsTask);
MAKE_GC_SWEEP_TASK(SweepMiscTask);
MAKE_GC_SWEEP_TASK(SweepCompressionTasksTask);
MAKE_GC_SWEEP_TASK(SweepWeakMapsTask);
#undef MAKE_GC_SWEEP_TASK
/* virtual */ void
@ -5048,6 +5049,27 @@ SweepCompressionTasksTask::run()
}
}
/* virtual */ void
SweepWeakMapsTask::run()
{
for (GCSweepGroupIter zone(runtime()); !zone.done(); zone.next()) {
/* Clear all weakrefs that point to unmarked things. */
for (auto edge : zone->gcWeakRefs()) {
/* Edges may be present multiple times, so may already be nulled. */
if (*edge && IsAboutToBeFinalizedDuringSweep(**edge))
*edge = nullptr;
}
zone->gcWeakRefs().clear();
/* No need to look up any more weakmap keys from this sweep group. */
AutoEnterOOMUnsafeRegion oomUnsafe;
if (!zone->gcWeakKeys().clear())
oomUnsafe.crash("clearing weak keys in beginSweepingSweepGroup()");
zone->sweepWeakMaps();
}
}
void
GCRuntime::startTask(GCParallelTask& task, gcstats::Phase phase, AutoLockHelperThreadState& locked)
{
@ -5127,23 +5149,9 @@ GCRuntime::beginSweepingSweepGroup(AutoLockForExclusiveAccess& lock)
SweepRegExpsTask sweepRegExpsTask(rt);
SweepMiscTask sweepMiscTask(rt);
SweepCompressionTasksTask sweepCompressionTasksTask(rt);
SweepWeakMapsTask sweepWeakMapsTask(rt);
WeakCacheTaskVector sweepCacheTasks = PrepareWeakCacheTasks(rt);
for (GCSweepGroupIter zone(rt); !zone.done(); zone.next()) {
/* Clear all weakrefs that point to unmarked things. */
for (auto edge : zone->gcWeakRefs()) {
/* Edges may be present multiple times, so may already be nulled. */
if (*edge && IsAboutToBeFinalizedDuringSweep(**edge))
*edge = nullptr;
}
zone->gcWeakRefs().clear();
/* No need to look up any more weakmap keys from this sweep group. */
AutoEnterOOMUnsafeRegion oomUnsafe;
if (!zone->gcWeakKeys().clear())
oomUnsafe.crash("clearing weak keys in beginSweepingSweepGroup()");
}
{
gcstats::AutoPhase ap(stats(), gcstats::PHASE_FINALIZE_START);
callFinalizeCallbacks(&fop, JSFINALIZE_GROUP_PREPARE);
@ -5161,6 +5169,10 @@ GCRuntime::beginSweepingSweepGroup(AutoLockForExclusiveAccess& lock)
callFinalizeCallbacks(&fop, JSFINALIZE_GROUP_START);
}
// Detach unreachable debuggers and global objects from each other.
// This can modify weakmaps and so must happen before weakmap sweeping.
Debugger::sweepAll(&fop);
if (sweepingAtoms) {
AutoLockHelperThreadState helperLock;
startTask(sweepAtomsTask, gcstats::PHASE_SWEEP_ATOMS, helperLock);
@ -5177,6 +5189,7 @@ GCRuntime::beginSweepingSweepGroup(AutoLockForExclusiveAccess& lock)
startTask(sweepRegExpsTask, gcstats::PHASE_SWEEP_REGEXP, helperLock);
startTask(sweepMiscTask, gcstats::PHASE_SWEEP_MISC, helperLock);
startTask(sweepCompressionTasksTask, gcstats::PHASE_SWEEP_MISC, helperLock);
startTask(sweepWeakMapsTask, gcstats::PHASE_SWEEP_MISC, helperLock);
for (auto& task : sweepCacheTasks)
startTask(task, gcstats::PHASE_SWEEP_MISC, helperLock);
}
@ -5190,14 +5203,13 @@ GCRuntime::beginSweepingSweepGroup(AutoLockForExclusiveAccess& lock)
js::CancelOffThreadIonCompile(rt, JS::Zone::Sweep);
for (GCCompartmentGroupIter c(rt); !c.done(); c.next()) {
c->sweepGlobalObject(&fop);
c->sweepGlobalObject();
c->sweepDebugEnvironments();
c->sweepJitCompartment(&fop);
c->sweepTemplateObjects();
}
for (GCSweepGroupIter zone(rt); !zone.done(); zone.next()) {
zone->sweepWeakMaps();
if (jit::JitZone* jitZone = zone->jitZone())
jitZone->sweep(&fop);
}
@ -5208,9 +5220,6 @@ GCRuntime::beginSweepingSweepGroup(AutoLockForExclusiveAccess& lock)
// Collect watch points associated with unreachable objects.
WatchpointMap::sweepAll(rt);
// Detach unreachable debuggers and global objects from each other.
Debugger::sweepAll(&fop);
// Sweep entries containing about-to-be-finalized JitCode and
// update relocated TypeSet::Types inside the JitcodeGlobalTable.
jit::JitRuntime::SweepJitcodeGlobalTable(rt);
@ -5262,6 +5271,7 @@ GCRuntime::beginSweepingSweepGroup(AutoLockForExclusiveAccess& lock)
joinTask(sweepRegExpsTask, gcstats::PHASE_SWEEP_REGEXP, helperLock);
joinTask(sweepMiscTask, gcstats::PHASE_SWEEP_MISC, helperLock);
joinTask(sweepCompressionTasksTask, gcstats::PHASE_SWEEP_MISC, helperLock);
joinTask(sweepWeakMapsTask, gcstats::PHASE_SWEEP_MISC, helperLock);
for (auto& task : sweepCacheTasks)
joinTask(task, gcstats::PHASE_SWEEP_MISC, helperLock);
}

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

@ -3223,16 +3223,20 @@ Debugger::sweepAll(FreeOp* fop)
Debugger* dbg = group->debuggerList().getFirst();
while (dbg) {
Debugger* next = dbg->getNext();
if (IsAboutToBeFinalized(&dbg->object)) {
/*
* dbg is being GC'd. Detach it from its debuggees. The debuggee
* might be GC'd too. Since detaching requires access to both
* objects, this must be done before finalize time.
*/
for (WeakGlobalObjectSet::Enum e(dbg->debuggees); !e.empty(); e.popFront())
// Detach dying debuggers and debuggees from each other. Since this
// requires access to both objects it must be done before either
// object is finalized.
bool debuggerDying = IsAboutToBeFinalized(&dbg->object);
for (WeakGlobalObjectSet::Enum e(dbg->debuggees); !e.empty(); e.popFront()) {
GlobalObject* global = e.front().unbarrieredGet();
if (debuggerDying || IsAboutToBeFinalizedUnbarriered(&global))
dbg->removeDebuggeeGlobal(fop, e.front().unbarrieredGet(), &e);
fop->delete_(dbg);
}
if (debuggerDying)
fop->delete_(dbg);
dbg = next;
}
}

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

@ -162,9 +162,10 @@ class DebuggerWeakMap : private WeakMap<HeapPtr<UnbarrieredKey>, HeapPtr<JSObjec
private:
/* Override sweep method to also update our edge cache. */
void sweep() {
MOZ_ASSERT(CurrentThreadIsPerformingGC());
for (Enum e(*static_cast<Base*>(this)); !e.empty(); e.popFront()) {
if (gc::IsAboutToBeFinalized(&e.front().mutableKey())) {
decZoneCount(e.front().key()->zone());
decZoneCount(e.front().key()->zoneFromAnyThread());
e.removeFront();
}
}