Backed out 6 changesets (bug 1732161) for causing linux base toolchains bustages. CLOSED TREE

Backed out changeset 766a1bc74001 (bug 1732161)
Backed out changeset aed63de28354 (bug 1732161)
Backed out changeset 98eaff0d5124 (bug 1732161)
Backed out changeset 76c21ec8ffb6 (bug 1732161)
Backed out changeset 49dcac272f05 (bug 1732161)
Backed out changeset 67d81f8f413e (bug 1732161)
This commit is contained in:
criss 2021-10-14 05:38:08 +03:00
Родитель a145479a09
Коммит 0ecd4a450b
23 изменённых файлов: 124 добавлений и 320 удалений

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

@ -6,7 +6,6 @@
#include "mozilla/StaticPrefs_javascript.h"
#include "mozilla/CycleCollectedJSRuntime.h"
#include "mozilla/ProfilerMarkers.h"
#include "mozilla/dom/ScriptSettings.h"
#include "nsRefreshDriver.h"
@ -34,7 +33,7 @@ void CCGCScheduler::NoteGCEnd() {
mCCBlockStart = TimeStamp();
mReadyForMajorGC = false;
mWantAtLeastRegularGC = false;
mNeedsFullCC = CCReason::GC_FINISHED;
mNeedsFullCC = true;
mHasRunGC = true;
mIsCompactingOnUserInactive = false;
@ -50,61 +49,6 @@ void CCGCScheduler::NoteGCEnd() {
}
}
#ifdef MOZ_GECKO_PROFILER
struct CCIntervalMarker {
static constexpr mozilla::Span<const char> MarkerTypeName() {
return mozilla::MakeStringSpan("CC");
}
static void StreamJSONMarkerData(
baseprofiler::SpliceableJSONWriter& aWriter,
const mozilla::ProfilerString8View& aReason) {
if (aReason.Length()) {
aWriter.StringProperty("reason", aReason);
}
}
static mozilla::MarkerSchema MarkerTypeDisplay() {
using MS = mozilla::MarkerSchema;
MS schema{MS::Location::MarkerChart, MS::Location::MarkerTable,
MS::Location::TimelineMemory};
schema.AddStaticLabelValue(
"Description",
"Summary data for the core part of a cycle collection, possibly "
"encompassing a set of incremental slices. The main thread is not "
"blocked for the entire major CC interval, only for the individual "
"slices.");
schema.AddKeyLabelFormatSearchable("reason", "Reason", MS::Format::String,
MS::Searchable::Searchable);
return schema;
}
};
#endif
void CCGCScheduler::NoteCCBegin(CCReason aReason, TimeStamp aWhen) {
#ifdef MOZ_GECKO_PROFILER
profiler_add_marker(
"CC", baseprofiler::category::GCCC,
MarkerOptions(MarkerTiming::IntervalStart(aWhen)), CCIntervalMarker{},
ProfilerString8View::WrapNullTerminatedString(CCReasonToString(aReason)));
#endif
mIsCollectingCycles = true;
}
void CCGCScheduler::NoteCCEnd(TimeStamp aWhen) {
#ifdef MOZ_GECKO_PROFILER
profiler_add_marker("CC", baseprofiler::category::GCCC,
MarkerOptions(MarkerTiming::IntervalEnd(aWhen)),
CCIntervalMarker{}, nullptr);
#endif
mIsCollectingCycles = false;
mLastCCEndTime = aWhen;
mNeedsFullCC = CCReason::NO_REASON;
// The GC for this CC has already been requested.
mNeedsGCAfterCC = false;
}
void CCGCScheduler::NoteWontGC() {
mReadyForMajorGC = false;
mMajorGCReason = JS::GCReason::NO_REASON;
@ -354,7 +298,7 @@ void CCGCScheduler::PokeGC(JS::GCReason aReason, JSObject* aObj,
if (mCCRunner) {
// Make sure CC is called regardless of the size of the purple buffer, and
// GC after it.
EnsureCCThenGC(CCReason::GC_WAITING);
EnsureCCThenGC();
return;
}
@ -448,13 +392,12 @@ void CCGCScheduler::MaybePokeCC(TimeStamp aNow, uint32_t aSuspectedCCObjects) {
return;
}
CCReason reason = ShouldScheduleCC(aNow, aSuspectedCCObjects);
if (reason != CCReason::NO_REASON) {
if (ShouldScheduleCC(aNow, aSuspectedCCObjects)) {
// We can kill some objects before running forgetSkippable.
nsCycleCollector_dispatchDeferredDeletion();
if (!mCCRunner) {
InitCCRunnerStateMachine(CCRunnerState::ReducePurple, reason);
InitCCRunnerStateMachine(CCRunnerState::ReducePurple);
}
EnsureCCRunner(kCCSkippableDelay, kForgetSkippableSliceDuration);
}
@ -541,16 +484,16 @@ TimeDuration CCGCScheduler::ComputeInterSliceGCBudget(TimeStamp aDeadline,
return std::max(budget, maxSliceGCBudget.MultDouble(percentOfBlockedTime));
}
CCReason CCGCScheduler::ShouldScheduleCC(TimeStamp aNow,
uint32_t aSuspectedCCObjects) const {
bool CCGCScheduler::ShouldScheduleCC(TimeStamp aNow,
uint32_t aSuspectedCCObjects) const {
if (!mHasRunGC) {
return CCReason::NO_REASON;
return false;
}
// Don't run consecutive CCs too often.
if (mCleanupsSinceLastGC && !mLastCCEndTime.IsNull()) {
if (aNow - mLastCCEndTime < kCCDelay) {
return CCReason::NO_REASON;
return false;
}
}
@ -560,7 +503,7 @@ CCReason CCGCScheduler::ShouldScheduleCC(TimeStamp aNow,
!mLastForgetSkippableCycleEndTime.IsNull()) {
if (aNow - mLastForgetSkippableCycleEndTime <
kTimeBetweenForgetSkippableCycles) {
return CCReason::NO_REASON;
return false;
}
}
@ -642,8 +585,7 @@ CCRunnerStep CCGCScheduler::AdvanceCCRunner(TimeStamp aDeadline, TimeStamp aNow,
// For states that aren't just continuations of previous states, check
// whether a CC is still needed (after doing various things to reduce the
// purple buffer).
if (desc.mCanAbortCC &&
IsCCNeeded(aNow, aSuspectedCCObjects) == CCReason::NO_REASON) {
if (desc.mCanAbortCC && !IsCCNeeded(aNow, aSuspectedCCObjects)) {
// If we don't pass the threshold for wanting to cycle collect, stop now
// (after possibly doing a final ForgetSkippable).
mCCRunnerState = CCRunnerState::Canceled;
@ -743,12 +685,8 @@ CCRunnerStep CCGCScheduler::AdvanceCCRunner(TimeStamp aDeadline, TimeStamp aNow,
[[fallthrough]];
// CycleCollecting: continue running slices until done.
case CCRunnerState::CycleCollecting: {
CCRunnerStep step{CCRunnerAction::CycleCollect, Yield};
step.mCCReason = mCCReason;
mCCReason = CCReason::SLICE; // Set reason for following slices.
return step;
}
case CCRunnerState::CycleCollecting:
return {CCRunnerAction::CycleCollect, Yield};
default:
MOZ_CRASH("Unexpected CCRunner state");

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

@ -12,7 +12,6 @@
#include "mozilla/ipc/IdleSchedulerChild.h"
#include "nsCycleCollector.h"
#include "nsJSEnvironment.h"
#include "nsCycleCollectionParticipant.h"
namespace mozilla {
@ -105,9 +104,6 @@ struct CCRunnerStep {
// or not. (ForgetSkippable is the only action requiring a parameter; if
// that changes, this will become a union.)
CCRunnerForgetSkippableRemoveChildless mRemoveChildless;
// If the action is CycleCollect, the reason for the collection.
CCReason mCCReason;
};
class CCGCScheduler {
@ -186,10 +182,9 @@ class CCGCScheduler {
// Ensure that the current runner does a cycle collection, and trigger a GC
// after it finishes.
void EnsureCCThenGC(CCReason aReason) {
void EnsureCCThenGC() {
MOZ_ASSERT(mCCRunnerState != CCRunnerState::Inactive);
MOZ_ASSERT(aReason != CCReason::NO_REASON);
mNeedsFullCC = aReason;
mNeedsFullCC = true;
mNeedsGCAfterCC = true;
}
@ -203,25 +198,11 @@ class CCGCScheduler {
return true;
}
// Starting a major GC (incremental or non-incremental).
void NoteGCBegin();
// Major GC completed.
void NoteGCEnd();
// A timer fired, but then decided not to run a GC.
void NoteWontGC();
// This is invoked when we reach the actual cycle collection portion of the
// overall cycle collection.
void NoteCCBegin(CCReason aReason, TimeStamp aWhen);
// This is invoked when the whole process of collection is done -- i.e., CC
// preparation (eg ForgetSkippables) in addition to the CC itself. There
// really ought to be a separate name for the overall CC as opposed to the
// actual cycle collection portion.
void NoteCCEnd(TimeStamp aWhen);
void NoteGCSliceEnd(TimeDuration aSliceDuration) {
if (mMajorGCReason == JS::GCReason::NO_REASON) {
// Internally-triggered GCs do not wait for the parent's permission to
@ -280,8 +261,17 @@ class CCGCScheduler {
mCCollectedZonesWaitingForGC += aResults.mFreedJSZones;
}
// Test if we are in the NoteCCBegin .. NoteCCEnd interval.
bool IsCollectingCycles() const { return mIsCollectingCycles; }
// This is invoked when the whole process of collection is done -- i.e., CC
// preparation (eg ForgetSkippables), the CC itself, and the optional
// followup GC. There really ought to be a separate name for the overall CC
// as opposed to the actual cycle collection portion.
void NoteCCEnd(TimeStamp aWhen) {
mLastCCEndTime = aWhen;
mNeedsFullCC = false;
// The GC for this CC has already been requested.
mNeedsGCAfterCC = false;
}
// The CC was abandoned without running a slice, so we only did forget
// skippables. Prevent running another cycle soon.
@ -319,22 +309,16 @@ class CCGCScheduler {
// garbage to cycle collect: either we just finished a GC, or the purple
// buffer is getting really big, or it's getting somewhat big and it has been
// too long since the last CC.
CCReason IsCCNeeded(TimeStamp aNow, uint32_t aSuspectedCCObjects) const {
if (mNeedsFullCC != CCReason::NO_REASON) {
return mNeedsFullCC;
bool IsCCNeeded(TimeStamp aNow, uint32_t aSuspectedCCObjects) const {
if (mNeedsFullCC) {
return true;
}
if (aSuspectedCCObjects > kCCPurpleLimit) {
return CCReason::MANY_SUSPECTED;
}
if (aSuspectedCCObjects > kCCForcedPurpleLimit && mLastCCEndTime &&
aNow - mLastCCEndTime > kCCForced) {
return CCReason::TIMED;
}
return CCReason::NO_REASON;
return aSuspectedCCObjects > kCCPurpleLimit ||
(aSuspectedCCObjects > kCCForcedPurpleLimit && mLastCCEndTime &&
aNow - mLastCCEndTime > kCCForced);
}
mozilla::CCReason ShouldScheduleCC(TimeStamp aNow,
uint32_t aSuspectedCCObjects) const;
bool ShouldScheduleCC(TimeStamp aNow, uint32_t aSuspectedCCObjects) const;
// If we collected a substantial amount of cycles, poke the GC since more
// objects might be unreachable now.
@ -362,14 +346,11 @@ class CCGCScheduler {
NumStates
};
void InitCCRunnerStateMachine(CCRunnerState initialState, CCReason aReason) {
void InitCCRunnerStateMachine(CCRunnerState initialState) {
if (mCCRunner) {
return;
}
MOZ_ASSERT(mCCReason == CCReason::NO_REASON);
mCCReason = aReason;
// The state machine should always have been deactivated after the previous
// collection, however far that collection may have gone.
MOZ_ASSERT(mCCRunnerState == CCRunnerState::Inactive,
@ -388,10 +369,7 @@ class CCGCScheduler {
}
}
void DeactivateCCRunner() {
mCCRunnerState = CCRunnerState::Inactive;
mCCReason = CCReason::NO_REASON;
}
void DeactivateCCRunner() { mCCRunnerState = CCRunnerState::Inactive; }
GCRunnerStep GetNextGCRunnerAction() const;
@ -437,7 +415,7 @@ class CCGCScheduler {
// gray bits.
bool mHasRunGC = false;
mozilla::CCReason mNeedsFullCC = CCReason::NO_REASON;
bool mNeedsFullCC = false;
bool mNeedsFullGC = true;
bool mNeedsGCAfterCC = false;
uint32_t mPreviousSuspectedCount = 0;
@ -451,11 +429,9 @@ class CCGCScheduler {
nsITimer* mShrinkingGCTimer = nullptr;
nsITimer* mFullGCTimer = nullptr;
mozilla::CCReason mCCReason = mozilla::CCReason::NO_REASON;
JS::GCReason mMajorGCReason = JS::GCReason::NO_REASON;
bool mIsCompactingOnUserInactive = false;
bool mIsCollectingCycles = false;
bool mUserIsActive = true;
public:

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

@ -50,7 +50,7 @@ void FuzzingFunctions::Crash(const GlobalObject& aGlobalObject,
/* static */
void FuzzingFunctions::CycleCollect(const GlobalObject&) {
nsJSContext::CycleCollectNow(CCReason::API);
nsJSContext::CycleCollectNow();
}
void FuzzingFunctions::MemoryPressure(const GlobalObject&) {

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

@ -1294,14 +1294,14 @@ nsDOMWindowUtils::GarbageCollect(nsICycleCollectorListener* aListener) {
AUTO_PROFILER_LABEL("nsDOMWindowUtils::GarbageCollect", GCCC);
nsJSContext::GarbageCollectNow(JS::GCReason::DOM_UTILS);
nsJSContext::CycleCollectNow(CCReason::API, aListener);
nsJSContext::CycleCollectNow(aListener);
return NS_OK;
}
NS_IMETHODIMP
nsDOMWindowUtils::CycleCollect(nsICycleCollectorListener* aListener) {
nsJSContext::CycleCollectNow(CCReason::API, aListener);
nsJSContext::CycleCollectNow(aListener);
return NS_OK;
}

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

@ -1360,22 +1360,20 @@ void CycleCollectorStats::MaybeNotifyStats(
}
// static
void nsJSContext::CycleCollectNow(CCReason aReason,
nsICycleCollectorListener* aListener) {
void nsJSContext::CycleCollectNow(nsICycleCollectorListener* aListener) {
if (!NS_IsMainThread()) {
return;
}
AUTO_PROFILER_LABEL("nsJSContext::CycleCollectNow", GCCC);
PrepareForCycleCollectionSlice(aReason, TimeStamp());
nsCycleCollector_collect(aReason, aListener);
PrepareForCycleCollectionSlice(TimeStamp());
nsCycleCollector_collect(aListener);
sCCStats.AfterCycleCollectionSlice();
}
// static
void nsJSContext::PrepareForCycleCollectionSlice(CCReason aReason,
TimeStamp aDeadline) {
void nsJSContext::PrepareForCycleCollectionSlice(TimeStamp aDeadline) {
TimeStamp beginTime = TimeStamp::Now();
// Before we begin the cycle collection, make sure there is no active GC.
@ -1384,18 +1382,12 @@ void nsJSContext::PrepareForCycleCollectionSlice(CCReason aReason,
FinishAnyIncrementalGC();
afterGCTime = TimeStamp::Now();
}
if (!sScheduler.IsCollectingCycles()) {
sScheduler.NoteCCBegin(aReason, beginTime);
}
sCCStats.AfterPrepareForCycleCollectionSlice(aDeadline, beginTime,
afterGCTime);
}
// static
void nsJSContext::RunCycleCollectorSlice(CCReason aReason,
TimeStamp aDeadline) {
void nsJSContext::RunCycleCollectorSlice(TimeStamp aDeadline) {
if (!NS_IsMainThread()) {
return;
}
@ -1405,7 +1397,7 @@ void nsJSContext::RunCycleCollectorSlice(CCReason aReason,
AUTO_PROFILER_LABEL("nsJSContext::RunCycleCollectorSlice", GCCC);
PrepareForCycleCollectionSlice(aReason, aDeadline);
PrepareForCycleCollectionSlice(aDeadline);
// Decide how long we want to budget for this slice.
if (sIncrementalCC) {
@ -1413,10 +1405,10 @@ void nsJSContext::RunCycleCollectorSlice(CCReason aReason,
js::SliceBudget budget = sScheduler.ComputeCCSliceBudget(
aDeadline, sCCStats.mBeginTime, sCCStats.mEndSliceTime,
TimeStamp::Now(), &preferShorterSlices);
nsCycleCollector_collectSlice(budget, aReason, preferShorterSlices);
nsCycleCollector_collectSlice(budget, preferShorterSlices);
} else {
js::SliceBudget budget = js::SliceBudget::unlimited();
nsCycleCollector_collectSlice(budget, aReason, false);
nsCycleCollector_collectSlice(budget, false);
}
sCCStats.AfterCycleCollectionSlice();
@ -1430,10 +1422,10 @@ void nsJSContext::RunCycleCollectorWorkSlice(int64_t aWorkBudget) {
AUTO_PROFILER_LABEL("nsJSContext::RunCycleCollectorWorkSlice", GCCC);
PrepareForCycleCollectionSlice(CCReason::API, TimeStamp());
PrepareForCycleCollectionSlice(TimeStamp());
js::SliceBudget budget = js::SliceBudget(js::WorkBudget(aWorkBudget));
nsCycleCollector_collectSlice(budget, CCReason::API);
nsCycleCollector_collectSlice(budget);
sCCStats.AfterCycleCollectionSlice();
}
@ -1447,7 +1439,7 @@ uint32_t nsJSContext::GetMaxCCSliceTimeSinceClear() {
}
// static
void nsJSContext::BeginCycleCollectionCallback(CCReason aReason) {
void nsJSContext::BeginCycleCollectionCallback() {
MOZ_ASSERT(NS_IsMainThread());
TimeStamp startTime = TimeStamp::Now();
@ -1469,7 +1461,7 @@ void nsJSContext::BeginCycleCollectionCallback(CCReason aReason) {
}
sScheduler.InitCCRunnerStateMachine(
mozilla::CCGCScheduler::CCRunnerState::CycleCollecting, aReason);
mozilla::CCGCScheduler::CCRunnerState::CycleCollecting);
sScheduler.EnsureCCRunner(kICCIntersliceDelay, kIdleICCSliceBudget);
}
@ -1551,7 +1543,7 @@ bool CCGCScheduler::CCRunnerFired(TimeStamp aDeadline) {
case CCRunnerAction::CycleCollect:
// Cycle collection slice.
nsJSContext::RunCycleCollectorSlice(step.mCCReason, aDeadline);
nsJSContext::RunCycleCollectorSlice(aDeadline);
break;
case CCRunnerAction::StopRunning:
@ -1644,7 +1636,7 @@ void nsJSContext::DoLowMemoryGC() {
nsJSContext::GarbageCollectNow(JS::GCReason::MEM_PRESSURE,
nsJSContext::NonIncrementalGC,
nsJSContext::ShrinkingGC);
nsJSContext::CycleCollectNow(CCReason::MEM_PRESSURE);
nsJSContext::CycleCollectNow();
if (sScheduler.NeedsGCAfterCC()) {
nsJSContext::GarbageCollectNow(JS::GCReason::MEM_PRESSURE,
nsJSContext::NonIncrementalGC,
@ -1719,8 +1711,7 @@ static void DOMGCSliceCallback(JSContext* aCx, JS::GCProgress aProgress,
sScheduler.KillFullGCTimer();
}
if (sScheduler.IsCCNeeded(now, nsCycleCollector_suspectedCount()) !=
CCReason::NO_REASON) {
if (sScheduler.IsCCNeeded(now, nsCycleCollector_suspectedCount())) {
nsCycleCollector_dispatchDeferredDeletion();
}
@ -1746,8 +1737,7 @@ static void DOMGCSliceCallback(JSContext* aCx, JS::GCProgress aProgress,
}
if (sScheduler.IsCCNeeded(TimeStamp::Now(),
nsCycleCollector_suspectedCount()) !=
CCReason::NO_REASON) {
nsCycleCollector_suspectedCount())) {
nsCycleCollector_dispatchDeferredDeletion();
}

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

@ -69,22 +69,19 @@ class nsJSContext : public nsIScriptContext {
IsShrinking aShrinking = NonShrinkingGC,
int64_t aSliceMillis = 0);
static void CycleCollectNow(mozilla::CCReason aReason,
nsICycleCollectorListener* aListener = nullptr);
static void CycleCollectNow(nsICycleCollectorListener* aListener = nullptr);
// Finish up any in-progress incremental GC.
static void PrepareForCycleCollectionSlice(mozilla::CCReason aReason,
mozilla::TimeStamp aDeadline);
static void PrepareForCycleCollectionSlice(mozilla::TimeStamp aDeadline);
// Run a cycle collector slice, using a heuristic to decide how long to run
// it.
static void RunCycleCollectorSlice(mozilla::CCReason aReason,
mozilla::TimeStamp aDeadline);
static void RunCycleCollectorSlice(mozilla::TimeStamp aDeadline);
// Run a cycle collector slice, using the given work budget.
static void RunCycleCollectorWorkSlice(int64_t aWorkBudget);
static void BeginCycleCollectionCallback(mozilla::CCReason aReason);
static void BeginCycleCollectionCallback();
static void EndCycleCollectionCallback(
mozilla::CycleCollectorResults& aResults);

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

@ -50,8 +50,7 @@ void TestGC::Run(int aNumSlices) {
// Running the GC should not influence whether a CC is currently seen as
// needed. But the first time we run GC, it will be false; later, we will
// have run a GC and set it to true.
CCReason neededCCAtStartOfGC =
mScheduler.IsCCNeeded(Now(), SuspectedCCObjects());
bool neededCCAtStartOfGC = mScheduler.IsCCNeeded(Now(), SuspectedCCObjects());
mScheduler.NoteGCBegin();
@ -103,12 +102,9 @@ class TestCC {
void TestCC::MaybePokeCC() {
// nsJSContext::MaybePokeCC
EXPECT_TRUE(mScheduler.ShouldScheduleCC(Now(), SuspectedCCObjects()));
// In all tests so far, we will be running this just after a GC.
CCReason reason = mScheduler.ShouldScheduleCC(Now(), SuspectedCCObjects());
EXPECT_EQ(reason, CCReason::GC_FINISHED);
mScheduler.InitCCRunnerStateMachine(CCRunnerState::ReducePurple, reason);
mScheduler.InitCCRunnerStateMachine(CCRunnerState::ReducePurple);
EXPECT_TRUE(mScheduler.IsEarlyForgetSkippable());
}
@ -176,7 +172,6 @@ void TestCC::EndCycleCollectionCallback() {
results.mFreedGCed = 10;
results.mFreedJSZones = 2;
mScheduler.NoteCycleCollected(results);
mScheduler.NoteCCEnd(Now());
// Because > 0 zones were freed.
EXPECT_TRUE(mScheduler.NeedsGCAfterCC());
@ -184,8 +179,9 @@ void TestCC::EndCycleCollectionCallback() {
void TestCC::KillCCRunner() {
// nsJSContext::KillCCRunner
mScheduler.UnblockCC();
mScheduler.DeactivateCCRunner();
mScheduler.NoteCCEnd(Now());
mScheduler.KillCCRunner();
}
class TestIdleCC : public TestCC {
@ -296,31 +292,25 @@ static bool BasicScenario(CCGCScheduler& aScheduler, TestGC* aTestGC,
// After a GC, the scheduler should decide to do a full CC regardless of the
// number of purple buffer entries.
SetNumSuspected(3);
EXPECT_EQ(aScheduler.IsCCNeeded(Now(), SuspectedCCObjects()),
CCReason::GC_FINISHED);
EXPECT_TRUE(aScheduler.IsCCNeeded(Now(), SuspectedCCObjects()));
// Now we should want to CC.
EXPECT_EQ(aScheduler.ShouldScheduleCC(Now(), SuspectedCCObjects()),
CCReason::GC_FINISHED);
EXPECT_TRUE(aScheduler.ShouldScheduleCC(Now(), SuspectedCCObjects()));
// Do a 5-slice CC.
aTestCC->Run(5);
// Not enough suspected objects to deserve a CC.
EXPECT_EQ(aScheduler.IsCCNeeded(Now(), SuspectedCCObjects()),
CCReason::NO_REASON);
EXPECT_EQ(aScheduler.ShouldScheduleCC(Now(), SuspectedCCObjects()),
CCReason::NO_REASON);
EXPECT_FALSE(aScheduler.IsCCNeeded(Now(), SuspectedCCObjects()));
EXPECT_FALSE(aScheduler.ShouldScheduleCC(Now(), SuspectedCCObjects()));
SetNumSuspected(10000);
// We shouldn't want to CC again yet, it's too soon.
EXPECT_EQ(aScheduler.ShouldScheduleCC(Now(), SuspectedCCObjects()),
CCReason::NO_REASON);
EXPECT_FALSE(aScheduler.ShouldScheduleCC(Now(), SuspectedCCObjects()));
AdvanceTime(mozilla::kCCDelay);
// *Now* it's time for another CC.
EXPECT_EQ(aScheduler.ShouldScheduleCC(Now(), SuspectedCCObjects()),
CCReason::MANY_SUSPECTED);
EXPECT_TRUE(aScheduler.ShouldScheduleCC(Now(), SuspectedCCObjects()));
// Run a 3-slice incremental GC.
EXPECT_TRUE(!aScheduler.InIncrementalGC());
@ -337,8 +327,7 @@ static TestNonIdleCC ccNonIdle(scheduler);
TEST(TestScheduler, Idle)
{
// Cannot CC until we GC once.
EXPECT_EQ(scheduler.ShouldScheduleCC(Now(), SuspectedCCObjects()),
CCReason::NO_REASON);
EXPECT_FALSE(scheduler.ShouldScheduleCC(Now(), SuspectedCCObjects()));
EXPECT_TRUE(BasicScenario(scheduler, &gc, &ccIdle));
}

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

@ -130,7 +130,7 @@ void MaybeCollectGarbageOnIPCMessage() {
}
nsJSContext::GarbageCollectNow(JS::GCReason::DOM_IPC);
nsJSContext::CycleCollectNow(CCReason::API);
nsJSContext::CycleCollectNow();
#endif // BUILD_GC_ON_IPC_MESSAGES
}

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

@ -2638,7 +2638,7 @@ mozilla::ipc::IPCResult ContentChild::RecvCycleCollect() {
if (obs) {
obs->NotifyObservers(nullptr, "child-cc-request", nullptr);
}
nsJSContext::CycleCollectNow(CCReason::IPC_MESSAGE);
nsJSContext::CycleCollectNow();
return IPC_OK();
}

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

@ -837,8 +837,7 @@ class WorkerJSRuntime final : public mozilla::CycleCollectedJSRuntime {
virtual void PrepareForForgetSkippable() override {}
virtual void BeginCycleCollectionCallback(
mozilla::CCReason aReason) override {}
virtual void BeginCycleCollectionCallback() override {}
virtual void EndCycleCollectionCallback(
CycleCollectorResults& aResults) override {}
@ -859,8 +858,7 @@ class WorkerJSRuntime final : public mozilla::CycleCollectedJSRuntime {
mWorkerPrivate->AssertIsOnWorkerThread();
if (aStatus == JSGC_END) {
bool collectedAnything =
nsCycleCollector_collect(CCReason::GC_FINISHED, nullptr);
bool collectedAnything = nsCycleCollector_collect(nullptr);
mWorkerPrivate->SetCCCollectedAnything(collectedAnything);
}
}

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

@ -5012,7 +5012,7 @@ void WorkerPrivate::GarbageCollectInternal(JSContext* aCx, bool aShrinking,
void WorkerPrivate::CycleCollectInternal(bool aCollectChildren) {
auto data = mWorkerThreadAccessible.Access();
nsCycleCollector_collect(CCReason::WORKER, nullptr);
nsCycleCollector_collect(nullptr);
if (aCollectChildren) {
for (uint32_t index = 0; index < data->mChildWorkers.Length(); index++) {

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

@ -73,8 +73,7 @@ class WorkletJSRuntime final : public mozilla::CycleCollectedJSRuntime {
virtual void PrepareForForgetSkippable() override {}
virtual void BeginCycleCollectionCallback(
mozilla::CCReason aReason) override {}
virtual void BeginCycleCollectionCallback() override {}
virtual void EndCycleCollectionCallback(
CycleCollectorResults& aResults) override {}
@ -92,7 +91,7 @@ class WorkletJSRuntime final : public mozilla::CycleCollectedJSRuntime {
// call can be skipped in this GC as ~CycleCollectedJSContext removes the
// context from |this|.
if (aStatus == JSGC_END && GetContext()) {
nsCycleCollector_collect(CCReason::GC_FINISHED, nullptr);
nsCycleCollector_collect(nullptr);
}
}
};

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

@ -1631,7 +1631,7 @@ nsXPCComponents_Utils::ForceGC(JSContext* aCx) {
NS_IMETHODIMP
nsXPCComponents_Utils::ForceCC(nsICycleCollectorListener* listener) {
nsJSContext::CycleCollectNow(CCReason::API, listener);
nsJSContext::CycleCollectNow(listener);
return NS_OK;
}

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

@ -740,8 +740,8 @@ void XPCJSRuntime::PrepareForForgetSkippable() {
}
}
void XPCJSRuntime::BeginCycleCollectionCallback(CCReason aReason) {
nsJSContext::BeginCycleCollectionCallback(aReason);
void XPCJSRuntime::BeginCycleCollectionCallback() {
nsJSContext::BeginCycleCollectionCallback();
nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
if (obs) {
@ -801,12 +801,9 @@ void XPCJSRuntime::GCSliceCallback(JSContext* cx, JS::GCProgress progress,
void XPCJSRuntime::DoCycleCollectionCallback(JSContext* cx) {
// The GC has detected that a CC at this point would collect a tremendous
// amount of garbage that is being revivified unnecessarily.
//
// The GC_WAITING reason is a little overloaded here, but we want to do
// a CC to allow Realms to be collected when they are referenced by a cycle.
NS_DispatchToCurrentThread(NS_NewRunnableFunction(
"XPCJSRuntime::DoCycleCollectionCallback",
[]() { nsJSContext::CycleCollectNow(CCReason::GC_WAITING, nullptr); }));
NS_DispatchToCurrentThread(
NS_NewRunnableFunction("XPCJSRuntime::DoCycleCollectionCallback",
[]() { nsJSContext::CycleCollectNow(nullptr); }));
XPCJSRuntime* self = nsXPConnect::GetRuntimeInstance();
if (!self) {

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

@ -947,7 +947,7 @@ MOZ_EXPORT void DumpCompleteHeap() {
return;
}
nsJSContext::CycleCollectNow(CCReason::DUMP_HEAP, alltracesListener);
nsJSContext::CycleCollectNow(alltracesListener);
}
} // extern "C"

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

@ -533,7 +533,7 @@ class XPCJSRuntime final : public mozilla::CycleCollectedJSRuntime {
nsCycleCollectionNoteRootCallback& cb) override;
void UnmarkSkippableJSHolders();
void PrepareForForgetSkippable() override;
void BeginCycleCollectionCallback(mozilla::CCReason aReason) override;
void BeginCycleCollectionCallback() override;
void EndCycleCollectionCallback(
mozilla::CycleCollectorResults& aResults) override;
void DispatchDeferredDeletion(bool aContinuation,

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

@ -240,7 +240,7 @@ static int FuzzingRunNetworkHttp(const uint8_t* data, size_t size) {
// Wait for the channel to be destroyed
SpinEventLoopUntil(
"FuzzingRunNetworkHttp(channel == nullptr)"_ns, [&]() -> bool {
nsCycleCollector_collect(CCReason::API, nullptr);
nsCycleCollector_collect(nullptr);
nsCOMPtr<nsIHttpChannel> channel = do_QueryReferent(channelRef);
return channel == nullptr;
});

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

@ -205,7 +205,7 @@ static int FuzzingRunNetworkWebsocket(const uint8_t* data, size_t size) {
// Wait for the channel to be destroyed
SpinEventLoopUntil(
"FuzzingRunNetworkWebsocket(channel == nullptr)"_ns, [&]() -> bool {
nsCycleCollector_collect(CCReason::API, nullptr);
nsCycleCollector_collect(nullptr);
nsCOMPtr<nsIWebSocketChannel> channel = do_QueryReferent(channelRef);
return channel == nullptr;
});

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

@ -305,7 +305,7 @@ class CycleCollectedJSRuntime {
CycleCollectedJSContext::DeferredFinalizeType aType);
virtual void PrepareForForgetSkippable() = 0;
virtual void BeginCycleCollectionCallback(mozilla::CCReason aReason) = 0;
virtual void BeginCycleCollectionCallback() = 0;
virtual void EndCycleCollectionCallback(CycleCollectorResults& aResults) = 0;
virtual void DispatchDeferredDeletion(bool aContinuation,
bool aPurge = false) = 0;

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

@ -42,83 +42,6 @@
} \
}
namespace mozilla {
enum class CCReason : uint8_t {
NO_REASON,
// Purple buffer "overflow": enough objects are suspected to be cycle
// collectable to trigger an immediate CC.
MANY_SUSPECTED,
// The previous collection was kCCForced ago, and there are at least
// kCCForcedPurpleLimit objects suspected of being cycle collectable.
TIMED,
// Run a CC after a GC has completed.
GC_FINISHED,
// Run a slice of a collection.
SLICE,
// Manual reasons are explicitly triggered with a custom listener (as opposed
// to exceeding some internal threshold.) If a CC is already in progress,
// continue it. Otherwise, start a new one.
FIRST_MANUAL_REASON = 128,
// We want to GC, but must finish any ongoing cycle collection first.
GC_WAITING = FIRST_MANUAL_REASON,
// CC requested via an API. Used by tests.
API,
// Collecting in order to dump the heap.
DUMP_HEAP,
// Low memory situation detected.
MEM_PRESSURE,
// IPC message to a content process to trigger a CC. The original reason is not
// tracked.
IPC_MESSAGE,
// Cycle collection on a worker. The triggering reason is not tracked.
WORKER,
// Used for finding leaks.
SHUTDOWN
};
#define FOR_EACH_CCREASON(MACRO) \
MACRO(NO_REASON) \
MACRO(MANY_SUSPECTED) \
MACRO(TIMED) \
MACRO(GC_FINISHED) \
MACRO(SLICE) \
MACRO(GC_WAITING) \
MACRO(API) \
MACRO(DUMP_HEAP) \
MACRO(MEM_PRESSURE) \
MACRO(IPC_MESSAGE) \
MACRO(WORKER) \
MACRO(SHUTDOWN)
static inline bool IsManualCCReason(CCReason reason) {
return reason >= CCReason::FIRST_MANUAL_REASON;
}
static inline const char* CCReasonToString(CCReason aReason) {
switch (aReason) {
#define SET_REASON_STR(name) \
case CCReason::name: \
return #name; \
break;
FOR_EACH_CCREASON(SET_REASON_STR)
}
#undef SET_REASON_STR
}
} // namespace mozilla
/**
* Just holds the IID so NS_GET_IID works.
*/

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

@ -1075,7 +1075,12 @@ enum ccPhase {
CleanupPhase
};
enum ccIsManual { CCIsNotManual = false, CCIsManual = true };
enum ccType {
SliceCC, /* If a CC is in progress, continue it.
Otherwise, start a new one. */
ManualCC, /* Explicitly triggered. */
ShutdownCC /* Shutdown CC, used for finding leaks. */
};
////////////////////////////////////////////////////////////////////////
// Top level structure for the cycle collector.
@ -1156,9 +1161,9 @@ class nsCycleCollector : public nsIMemoryReporter {
void RemoveObjectFromGraph(void* aPtr);
void PrepareForGarbageCollection();
void FinishAnyCurrentCollection(CCReason aReason);
void FinishAnyCurrentCollection();
bool Collect(CCReason aReason, ccIsManual aIsManual, SliceBudget& aBudget,
bool Collect(ccType aCCType, SliceBudget& aBudget,
nsICycleCollectorListener* aManualListener,
bool aPreferShorterSlices = false);
MOZ_CAN_RUN_SCRIPT
@ -1182,9 +1187,9 @@ class nsCycleCollector : public nsIMemoryReporter {
void FixGrayBits(bool aForceGC, TimeLog& aTimeLog);
bool IsIncrementalGCInProgress();
void FinishAnyIncrementalGCInProgress();
bool ShouldMergeZones(ccIsManual aIsManual);
bool ShouldMergeZones(ccType aCCType);
void BeginCollection(CCReason aReason, ccIsManual aIsManual,
void BeginCollection(ccType aCCType,
nsICycleCollectorListener* aManualListener);
void MarkRoots(SliceBudget& aBudget);
void ScanRoots(bool aFullySynchGraphBuild);
@ -3342,8 +3347,7 @@ void nsCycleCollector::ShutdownCollect() {
uint32_t i;
bool collectedAny = true;
for (i = 0; i < DEFAULT_SHUTDOWN_COLLECTIONS && collectedAny; ++i) {
collectedAny = Collect(CCReason::SHUTDOWN, ccIsManual::CCIsManual,
unlimitedBudget, nullptr);
collectedAny = Collect(ShutdownCC, unlimitedBudget, nullptr);
// Run any remaining tasks that may have been enqueued via RunInStableState
// or DispatchToMicroTask. These can hold alive CCed objects, and we want to
// clear them out before we run the CC again or finish shutting down.
@ -3360,8 +3364,7 @@ static void PrintPhase(const char* aPhase) {
#endif
}
bool nsCycleCollector::Collect(CCReason aReason, ccIsManual aIsManual,
SliceBudget& aBudget,
bool nsCycleCollector::Collect(ccType aCCType, SliceBudget& aBudget,
nsICycleCollectorListener* aManualListener,
bool aPreferShorterSlices) {
CheckThreadSafety();
@ -3390,7 +3393,7 @@ bool nsCycleCollector::Collect(CCReason aReason, ccIsManual aIsManual,
timeLog.Checkpoint("Collect::FreeSnowWhite");
}
if (aIsManual == ccIsManual::CCIsManual) {
if (aCCType != SliceCC) {
mResults.mAnyManual = true;
}
@ -3401,7 +3404,7 @@ bool nsCycleCollector::Collect(CCReason aReason, ccIsManual aIsManual,
switch (mIncrementalPhase) {
case IdlePhase:
PrintPhase("BeginCollection");
BeginCollection(aReason, aIsManual, aManualListener);
BeginCollection(aCCType, aManualListener);
break;
case GraphBuildingPhase:
PrintPhase("MarkRoots");
@ -3448,17 +3451,17 @@ bool nsCycleCollector::Collect(CCReason aReason, ccIsManual aIsManual,
// Collect() does something.
mActivelyCollecting = false;
if (aIsManual && !startedIdle) {
if (aCCType != SliceCC && !startedIdle) {
// We were in the middle of an incremental CC (using its own listener).
// Somebody has forced a CC, so after having finished out the current CC,
// run the CC again using the new listener.
MOZ_ASSERT(IsIdle());
if (Collect(aReason, ccIsManual::CCIsManual, aBudget, aManualListener)) {
if (Collect(aCCType, aBudget, aManualListener)) {
collectedAny = true;
}
}
MOZ_ASSERT_IF(aIsManual == CCIsManual, IsIdle());
MOZ_ASSERT_IF(aCCType != SliceCC, IsIdle());
return collectedAny;
}
@ -3477,18 +3480,18 @@ void nsCycleCollector::PrepareForGarbageCollection() {
return;
}
FinishAnyCurrentCollection(CCReason::GC_WAITING);
FinishAnyCurrentCollection();
}
void nsCycleCollector::FinishAnyCurrentCollection(CCReason aReason) {
void nsCycleCollector::FinishAnyCurrentCollection() {
if (IsIdle()) {
return;
}
SliceBudget unlimitedBudget = SliceBudget::unlimited();
PrintPhase("FinishAnyCurrentCollection");
// Use CCIsNotManual because we only want to finish the CC in progress.
Collect(aReason, ccIsManual::CCIsNotManual, unlimitedBudget, nullptr);
// Use SliceCC because we only want to finish the CC in progress.
Collect(SliceCC, unlimitedBudget, nullptr);
// It is only okay for Collect() to have failed to finish the
// current CC if we're reentering the CC at some point past
@ -3504,7 +3507,7 @@ void nsCycleCollector::FinishAnyCurrentCollection(CCReason aReason) {
static const uint32_t kMinConsecutiveUnmerged = 3;
static const uint32_t kMaxConsecutiveMerged = 3;
bool nsCycleCollector::ShouldMergeZones(ccIsManual aIsManual) {
bool nsCycleCollector::ShouldMergeZones(ccType aCCType) {
if (!mCCJSRuntime) {
return false;
}
@ -3523,7 +3526,7 @@ bool nsCycleCollector::ShouldMergeZones(ccIsManual aIsManual) {
return false;
}
if (aIsManual == CCIsNotManual && mCCJSRuntime->UsefulToMergeZones()) {
if (aCCType == SliceCC && mCCJSRuntime->UsefulToMergeZones()) {
mMergedInARow++;
return true;
} else {
@ -3533,8 +3536,7 @@ bool nsCycleCollector::ShouldMergeZones(ccIsManual aIsManual) {
}
void nsCycleCollector::BeginCollection(
CCReason aReason, ccIsManual aIsManual,
nsICycleCollectorListener* aManualListener) {
ccType aCCType, nsICycleCollectorListener* aManualListener) {
TimeLog timeLog;
MOZ_ASSERT(IsIdle());
MOZ_RELEASE_ASSERT(!mScanInProgress);
@ -3542,11 +3544,11 @@ void nsCycleCollector::BeginCollection(
mCollectionStart = TimeStamp::Now();
if (mCCJSRuntime) {
mCCJSRuntime->BeginCycleCollectionCallback(aReason);
mCCJSRuntime->BeginCycleCollectionCallback();
timeLog.Checkpoint("BeginCycleCollectionCallback()");
}
bool isShutdown = (aReason == CCReason::SHUTDOWN);
bool isShutdown = (aCCType == ShutdownCC);
// Set up the listener for this CC.
MOZ_ASSERT_IF(isShutdown, !aManualListener);
@ -3595,8 +3597,8 @@ void nsCycleCollector::BeginCollection(
JS::AutoEnterCycleCollection autocc(mCCJSRuntime->Runtime());
mGraph.Init();
mResults.Init();
mResults.mAnyManual = aIsManual;
bool mergeZones = ShouldMergeZones(aIsManual);
mResults.mAnyManual = (aCCType != SliceCC);
bool mergeZones = ShouldMergeZones(aCCType);
mResults.mMergedZones = mergeZones;
MOZ_ASSERT(!mBuilder, "Forgot to clear mBuilder");
@ -3895,8 +3897,7 @@ already_AddRefed<nsICycleCollectorLogSink> nsCycleCollector_createLogSink() {
return sink.forget();
}
bool nsCycleCollector_collect(CCReason aReason,
nsICycleCollectorListener* aManualListener) {
bool nsCycleCollector_collect(nsICycleCollectorListener* aManualListener) {
CollectorData* data = sCollectorData.get();
// We should have started the cycle collector by now.
@ -3906,11 +3907,10 @@ bool nsCycleCollector_collect(CCReason aReason,
AUTO_PROFILER_LABEL("nsCycleCollector_collect", GCCC);
SliceBudget unlimitedBudget = SliceBudget::unlimited();
return data->mCollector->Collect(aReason, ccIsManual::CCIsManual,
unlimitedBudget, aManualListener);
return data->mCollector->Collect(ManualCC, unlimitedBudget, aManualListener);
}
void nsCycleCollector_collectSlice(SliceBudget& budget, CCReason aReason,
void nsCycleCollector_collectSlice(SliceBudget& budget,
bool aPreferShorterSlices) {
CollectorData* data = sCollectorData.get();
@ -3920,8 +3920,7 @@ void nsCycleCollector_collectSlice(SliceBudget& budget, CCReason aReason,
AUTO_PROFILER_LABEL("nsCycleCollector_collectSlice", GCCC);
data->mCollector->Collect(aReason, ccIsManual::CCIsNotManual, budget, nullptr,
aPreferShorterSlices);
data->mCollector->Collect(SliceCC, budget, nullptr, aPreferShorterSlices);
}
void nsCycleCollector_prepareForGarbageCollection() {
@ -3945,7 +3944,7 @@ void nsCycleCollector_finishAnyCurrentCollection() {
return;
}
data->mCollector->FinishAnyCurrentCollection(CCReason::API);
data->mCollector->FinishAnyCurrentCollection();
}
void nsCycleCollector_shutdown(bool aDoCollect) {

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

@ -53,11 +53,9 @@ already_AddRefed<nsICycleCollectorLogSink> nsCycleCollector_createLogSink();
already_AddRefed<nsICycleCollectorListener> nsCycleCollector_createLogger();
// Run a cycle collection and return whether anything was collected.
bool nsCycleCollector_collect(mozilla::CCReason aReason,
nsICycleCollectorListener* aManualListener);
bool nsCycleCollector_collect(nsICycleCollectorListener* aManualListener);
void nsCycleCollector_collectSlice(js::SliceBudget& budget,
mozilla::CCReason aReason,
bool aPreferShorterSlices = false);
uint32_t nsCycleCollector_suspectedCount();

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

@ -346,7 +346,7 @@ nsMemoryInfoDumper::DumpGCAndCCLogsToFile(
logSink->SetFilenameIdentifier(identifier);
nsJSContext::CycleCollectNow(CCReason::DUMP_HEAP, logger);
nsJSContext::CycleCollectNow(logger);
nsCOMPtr<nsIFile> gcLog, ccLog;
logSink->GetGcLog(getter_AddRefs(gcLog));
@ -369,7 +369,7 @@ nsMemoryInfoDumper::DumpGCAndCCLogsToSink(bool aDumpAllTraces,
logger->SetLogSink(aSink);
nsJSContext::CycleCollectNow(CCReason::DUMP_HEAP, logger);
nsJSContext::CycleCollectNow(logger);
return NS_OK;
}