Bug 1395744 - Save scheduled zones at the start of GC in case begin callback changes them r=sfink

This commit is contained in:
Jon Coppeard 2017-10-12 10:32:24 +01:00
Родитель b39bc4656a
Коммит 5f676753c0
4 изменённых файлов: 59 добавлений и 21 удалений

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

@ -34,6 +34,7 @@ namespace gc {
typedef Vector<ZoneGroup*, 4, SystemAllocPolicy> ZoneGroupVector;
using BlackGrayEdgeVector = Vector<TenuredCell*, 0, SystemAllocPolicy>;
class AutoCallGCCallbacks;
class AutoMaybeStartBackgroundAllocation;
class AutoRunParallelTask;
class AutoTraceSession;
@ -1050,6 +1051,10 @@ class GCRuntime
void incrementalCollectSlice(SliceBudget& budget, JS::gcreason::Reason reason,
AutoLockForExclusiveAccess& lock);
friend class AutoCallGCCallbacks;
void maybeCallBeginCallback();
void maybeCallEndCallback();
void pushZealSelectedObjects();
void purgeRuntime(AutoLockForExclusiveAccess& lock);
MOZ_MUST_USE bool beginMarkPhase(JS::gcreason::Reason reason, AutoLockForExclusiveAccess& lock);
@ -1408,6 +1413,8 @@ class GCRuntime
ActiveThreadData<bool> fullCompartmentChecks;
ActiveThreadData<uint32_t> gcBeginCallbackDepth;
Callback<JSGCCallback> gcCallback;
Callback<JS::DoCycleCollectionCallback> gcDoCycleCollectionCallback;
Callback<JSObjectsTenuredCallback> tenuredCallback;

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

@ -58,6 +58,7 @@ JS::Zone::Zone(JSRuntime* rt, ZoneGroup* group)
#endif
jitZone_(group, nullptr),
gcScheduled_(false),
gcScheduledSaved_(false),
gcPreserveCode_(group, false),
keepShapeTables_(group, false),
listNext_(group, NotOnList)

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

@ -695,6 +695,7 @@ struct Zone : public JS::shadow::Zone,
js::ZoneGroupData<js::jit::JitZone*> jitZone_;
js::ActiveThreadData<bool> gcScheduled_;
js::ActiveThreadData<bool> gcScheduledSaved_;
js::ZoneGroupData<bool> gcPreserveCode_;
js::ZoneGroupData<bool> keepShapeTables_;

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

@ -941,6 +941,7 @@ GCRuntime::GCRuntime(JSRuntime* rt) :
incrementalLimit(0),
#endif
fullCompartmentChecks(false),
gcBeginCallbackDepth(0),
alwaysPreserveCode(false),
#ifdef DEBUG
arenasEmptyAtShutdown(true),
@ -1648,25 +1649,6 @@ GCRuntime::callObjectsTenuredCallback()
tenuredCallback.op(TlsContext.get(), tenuredCallback.data);
}
namespace {
class AutoNotifyGCActivity {
public:
explicit AutoNotifyGCActivity(GCRuntime& gc) : gc_(gc) {
if (!gc_.isIncrementalGCInProgress())
gc_.callGCCallback(JSGC_BEGIN);
}
~AutoNotifyGCActivity() {
if (!gc_.isIncrementalGCInProgress())
gc_.callGCCallback(JSGC_END);
}
private:
GCRuntime& gc_;
};
} // (anon)
bool
GCRuntime::addFinalizeCallback(JSFinalizeCallback callback, void* data)
{
@ -7105,6 +7087,53 @@ class AutoScheduleZonesForGC
} /* anonymous namespace */
class js::gc::AutoCallGCCallbacks {
GCRuntime& gc_;
public:
explicit AutoCallGCCallbacks(GCRuntime& gc) : gc_(gc) {
gc_.maybeCallBeginCallback();
}
~AutoCallGCCallbacks() {
gc_.maybeCallEndCallback();
}
};
void
GCRuntime::maybeCallBeginCallback()
{
if (isIncrementalGCInProgress())
return;
if (gcBeginCallbackDepth == 0) {
// Save scheduled zone information in case the callback changes it.
for (ZonesIter zone(rt, WithAtoms); !zone.done(); zone.next())
zone->gcScheduledSaved_ = zone->gcScheduled_;
}
gcBeginCallbackDepth++;
callGCCallback(JSGC_BEGIN);
MOZ_ASSERT(gcBeginCallbackDepth != 0);
gcBeginCallbackDepth--;
if (gcBeginCallbackDepth == 0) {
// Restore scheduled zone information again.
for (ZonesIter zone(rt, WithAtoms); !zone.done(); zone.next())
zone->gcScheduled_ = zone->gcScheduledSaved_;
}
}
void
GCRuntime::maybeCallEndCallback()
{
if (isIncrementalGCInProgress())
return;
callGCCallback(JSGC_END);
}
/*
* Run one GC "cycle" (either a slice of incremental GC or an entire
* non-incremental GC. We disable inlining to ensure that the bottom of the
@ -7117,8 +7146,8 @@ class AutoScheduleZonesForGC
MOZ_NEVER_INLINE GCRuntime::IncrementalResult
GCRuntime::gcCycle(bool nonincrementalByAPI, SliceBudget& budget, JS::gcreason::Reason reason)
{
// Note that the following is allowed to re-enter GC in the finalizer.
AutoNotifyGCActivity notify(*this);
// Note that GC callbacks are allowed to re-enter GC.
AutoCallGCCallbacks callCallbacks(*this);
gcstats::AutoGCSlice agc(stats(), scanZonesBeforeGC(), invocationKind, budget, reason);