зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1395744 - Save scheduled zones at the start of GC in case begin callback changes them r=sfink
This commit is contained in:
Родитель
b39bc4656a
Коммит
5f676753c0
|
@ -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);
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче