Bug 1661293 - Give CCGCScheduler an mEagerMajorGCReason field (set in a later patch) to indicate that we would like to do a major GC when convenient. This is in addition to the usual mMajorGCReason for when we definitely want to do a GC. r=smaug

Differential Revision: https://phabricator.services.mozilla.com/D139206
This commit is contained in:
Steve Fink 2022-03-03 04:21:46 +00:00
Родитель b0023fb190
Коммит 9a89af097f
4 изменённых файлов: 36 добавлений и 13 удалений

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

@ -109,7 +109,7 @@
namespace mozilla {
void CCGCScheduler::NoteGCBegin() {
void CCGCScheduler::NoteGCBegin(JS::GCReason aReason) {
// Treat all GC as incremental here; non-incremental GC will just appear to
// be one slice.
mInIncrementalGC = true;
@ -122,10 +122,19 @@ void CCGCScheduler::NoteGCBegin() {
if (child) {
child->StartedGC();
}
// The reason might have come from mMajorReason, mEagerMajorGCReason, or
// in the case of an internally-generated GC, it might come from the
// internal logic (and be passed in here). It's easier to manage a single
// reason state variable, so merge all sources into mMajorGCReason.
MOZ_ASSERT(aReason != JS::GCReason::NO_REASON);
mMajorGCReason = aReason;
mEagerMajorGCReason = JS::GCReason::NO_REASON;
}
void CCGCScheduler::NoteGCEnd() {
mMajorGCReason = JS::GCReason::NO_REASON;
mEagerMajorGCReason = JS::GCReason::NO_REASON;
mInIncrementalGC = false;
mCCBlockStart = TimeStamp();
@ -205,6 +214,7 @@ void CCGCScheduler::NoteCCEnd(TimeStamp aWhen) {
void CCGCScheduler::NoteWontGC() {
mReadyForMajorGC = !mAskParentBeforeMajorGC;
mMajorGCReason = JS::GCReason::NO_REASON;
mEagerMajorGCReason = JS::GCReason::NO_REASON;
mWantAtLeastRegularGC = false;
// Don't clear the WantFullGC state, we will do a full GC the next time a
// GC happens for any other reason.
@ -213,10 +223,11 @@ void CCGCScheduler::NoteWontGC() {
bool CCGCScheduler::GCRunnerFired(TimeStamp aDeadline) {
MOZ_ASSERT(!mDidShutdown, "GCRunner still alive during shutdown");
GCRunnerStep step = GetNextGCRunnerAction();
GCRunnerStep step = GetNextGCRunnerAction(aDeadline);
switch (step.mAction) {
case GCRunnerAction::None:
MOZ_CRASH("Unexpected GCRunnerAction");
KillGCRunner();
return false;
case GCRunnerAction::WaitToMajorGC: {
MOZ_ASSERT(!mHaveAskedParent, "GCRunner alive after asking the parent");
@ -882,18 +893,29 @@ CCRunnerStep CCGCScheduler::AdvanceCCRunner(TimeStamp aDeadline, TimeStamp aNow,
};
}
GCRunnerStep CCGCScheduler::GetNextGCRunnerAction() const {
MOZ_ASSERT(mMajorGCReason != JS::GCReason::NO_REASON);
GCRunnerStep CCGCScheduler::GetNextGCRunnerAction(TimeStamp aDeadline) const {
if (InIncrementalGC()) {
MOZ_ASSERT(mMajorGCReason != JS::GCReason::NO_REASON);
return {GCRunnerAction::GCSlice, mMajorGCReason};
}
if (mReadyForMajorGC) {
return {GCRunnerAction::StartMajorGC, mMajorGCReason};
// Service a non-eager GC request first, even if it requires waiting.
if (mMajorGCReason != JS::GCReason::NO_REASON) {
return {mReadyForMajorGC ? GCRunnerAction::StartMajorGC
: GCRunnerAction::WaitToMajorGC,
mMajorGCReason};
}
return {GCRunnerAction::WaitToMajorGC, mMajorGCReason};
// Now for eager requests, which are ignored unless we're idle.
if (!aDeadline.IsNull()) {
if (mEagerMajorGCReason != JS::GCReason::NO_REASON) {
return {mReadyForMajorGC ? GCRunnerAction::StartMajorGC
: GCRunnerAction::WaitToMajorGC,
mEagerMajorGCReason};
}
}
return {GCRunnerAction::None, JS::GCReason::NO_REASON};
}
js::SliceBudget CCGCScheduler::ComputeForgetSkippableBudget(

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

@ -235,7 +235,7 @@ class CCGCScheduler {
}
// Starting a major GC (incremental or non-incremental).
void NoteGCBegin();
void NoteGCBegin(JS::GCReason aReason);
// Major GC completed.
void NoteGCEnd();
@ -424,7 +424,7 @@ class CCGCScheduler {
mCCReason = CCReason::NO_REASON;
}
GCRunnerStep GetNextGCRunnerAction() const;
GCRunnerStep GetNextGCRunnerAction(TimeStamp aDeadline) const;
CCRunnerStep AdvanceCCRunner(TimeStamp aDeadline, TimeStamp aNow,
uint32_t aSuspectedCCObjects);
@ -496,6 +496,7 @@ class CCGCScheduler {
mozilla::CCReason mCCReason = mozilla::CCReason::NO_REASON;
JS::GCReason mMajorGCReason = JS::GCReason::NO_REASON;
JS::GCReason mEagerMajorGCReason = JS::GCReason::NO_REASON;
bool mIsCompactingOnUserInactive = false;
bool mIsCollectingCycles = false;

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

@ -1691,7 +1691,7 @@ static void DOMGCSliceCallback(JSContext* aCx, JS::GCProgress aProgress,
switch (aProgress) {
case JS::GC_CYCLE_BEGIN: {
// Prevent cycle collections and shrinking during incremental GC.
sScheduler.NoteGCBegin();
sScheduler.NoteGCBegin(aDesc.reason_);
sCurrentGCStartTime = TimeStamp::Now();
break;
}

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

@ -53,7 +53,7 @@ void TestGC::Run(int aNumSlices) {
CCReason neededCCAtStartOfGC =
mScheduler.IsCCNeeded(Now(), SuspectedCCObjects());
mScheduler.NoteGCBegin();
mScheduler.NoteGCBegin(JS::GCReason::API);
for (int slice = 0; slice < aNumSlices; slice++) {
EXPECT_TRUE(mScheduler.InIncrementalGC());