Bug 1703443 - pt 13. Pass in the now timestamp as a parameter r=smaug

By passing this as a parameter we can remove the duplicated Now() procedure.

Differential Revision: https://phabricator.services.mozilla.com/D119362
This commit is contained in:
Paul Bone 2021-07-09 07:14:15 +00:00
Родитель 41182cb7d4
Коммит bfe8bd0b67
4 изменённых файлов: 58 добавлений и 70 удалений

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

@ -10,9 +10,7 @@
namespace mozilla {
// These definitions must match those in nsJSEnvironment.cpp
TimeStamp CCGCScheduler::Now() { return TimeStamp::Now(); }
// This definition must match the one in nsJSEnvironment.cpp
uint32_t CCGCScheduler::SuspectedCCObjects() {
return nsCycleCollector_suspectedCount();
}
@ -332,12 +330,12 @@ void CCGCScheduler::EnsureCCRunner(TimeDuration aDelay, TimeDuration aBudget) {
}
}
void CCGCScheduler::MaybePokeCC() {
void CCGCScheduler::MaybePokeCC(TimeStamp aNow) {
if (mCCRunner || mDidShutdown) {
return;
}
if (ShouldScheduleCC()) {
if (ShouldScheduleCC(aNow)) {
// We can kill some objects before running forgetSkippable.
nsCycleCollector_dispatchDeferredDeletion();

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

@ -112,10 +112,6 @@ class CCGCScheduler {
// are unused in CCGCScheduler.cpp but must be defined there anyway. Keep
// the definitions synchronised.
// Current time. In real usage, this will just return TimeStamp::Now(), but
// tests can reimplement it to return a value controlled by the test.
static inline TimeStamp Now();
// Number of entries in the purple buffer (those objects whose ref counts
// have been decremented since the previous CC, roughly), and are therefore
// "suspected" of being members of cyclic garbage.
@ -151,7 +147,7 @@ class CCGCScheduler {
void PokeGC(JS::GCReason aReason, JSObject* aObj, uint32_t aDelay = 0);
void PokeShrinkingGC();
void PokeFullGC();
void MaybePokeCC();
void MaybePokeCC(TimeStamp aNow);
void UserIsInactive();
void UserIsActive();
@ -299,8 +295,8 @@ class CCGCScheduler {
// The CC was abandoned without running a slice, so we only did forget
// skippables. Prevent running another cycle soon.
void NoteForgetSkippableOnlyCycle() {
mLastForgetSkippableCycleEndTime = Now();
void NoteForgetSkippableOnlyCycle(TimeStamp aNow) {
mLastForgetSkippableCycleEndTime = aNow;
}
void Shutdown() {
@ -316,6 +312,7 @@ class CCGCScheduler {
inline js::SliceBudget ComputeCCSliceBudget(TimeStamp aDeadline,
TimeStamp aCCBeginTime,
TimeStamp aPrevSliceEndTime,
TimeStamp aNow,
bool* aPreferShorterSlices) const;
inline TimeDuration ComputeInterSliceGCBudget(TimeStamp aDeadline,
@ -332,7 +329,7 @@ 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.
bool IsCCNeeded(TimeStamp aNow = Now()) const {
bool IsCCNeeded(TimeStamp aNow) const {
if (mNeedsFullCC) {
return true;
}
@ -342,7 +339,7 @@ class CCGCScheduler {
aNow - mLastCCEndTime > kCCForced);
}
inline bool ShouldScheduleCC() const;
inline bool ShouldScheduleCC(TimeStamp aNow) const;
// If we collected a substantial amount of cycles, poke the GC since more
// objects might be unreachable now.
@ -397,7 +394,7 @@ class CCGCScheduler {
inline GCRunnerStep GetNextGCRunnerAction(TimeStamp aDeadline);
inline CCRunnerStep AdvanceCCRunner(TimeStamp aDeadline);
inline CCRunnerStep AdvanceCCRunner(TimeStamp aDeadline, TimeStamp aNow);
// aStartTimeStamp : when the ForgetSkippable timer fired. This may be some
// time ago, if an incremental GC needed to be finished.
@ -465,14 +462,12 @@ class CCGCScheduler {
js::SliceBudget CCGCScheduler::ComputeCCSliceBudget(
TimeStamp aDeadline, TimeStamp aCCBeginTime, TimeStamp aPrevSliceEndTime,
bool* aPreferShorterSlices) const {
TimeStamp now = Now();
TimeStamp aNow, bool* aPreferShorterSlices) const {
*aPreferShorterSlices =
aDeadline.IsNull() || (aDeadline - now) < kICCSliceBudget;
aDeadline.IsNull() || (aDeadline - aNow) < kICCSliceBudget;
TimeDuration baseBudget =
aDeadline.IsNull() ? kICCSliceBudget : aDeadline - now;
aDeadline.IsNull() ? kICCSliceBudget : aDeadline - aNow;
if (aCCBeginTime.IsNull()) {
// If no CC is in progress, use the standard slice time.
@ -481,8 +476,8 @@ js::SliceBudget CCGCScheduler::ComputeCCSliceBudget(
}
// Only run a limited slice if we're within the max running time.
MOZ_ASSERT(now >= aCCBeginTime);
TimeDuration runningTime = now - aCCBeginTime;
MOZ_ASSERT(aNow >= aCCBeginTime);
TimeDuration runningTime = aNow - aCCBeginTime;
if (runningTime >= kMaxICCDuration) {
return js::SliceBudget::unlimited();
}
@ -491,8 +486,9 @@ js::SliceBudget CCGCScheduler::ComputeCCSliceBudget(
TimeDuration::FromMilliseconds(MainThreadIdlePeriod::GetLongIdlePeriod());
// Try to make up for a delay in running this slice.
MOZ_ASSERT(now >= aPrevSliceEndTime);
double sliceDelayMultiplier = (now - aPrevSliceEndTime) / kICCIntersliceDelay;
MOZ_ASSERT(aNow >= aPrevSliceEndTime);
double sliceDelayMultiplier =
(aNow - aPrevSliceEndTime) / kICCIntersliceDelay;
TimeDuration delaySliceBudget =
std::min(baseBudget.MultDouble(sliceDelayMultiplier), maxSlice);
@ -529,16 +525,14 @@ inline TimeDuration CCGCScheduler::ComputeInterSliceGCBudget(
return std::max(budget, maxSliceGCBudget.MultDouble(percentOfBlockedTime));
}
bool CCGCScheduler::ShouldScheduleCC() const {
bool CCGCScheduler::ShouldScheduleCC(TimeStamp aNow) const {
if (!mHasRunGC) {
return false;
}
TimeStamp now = Now();
// Don't run consecutive CCs too often.
if (mCleanupsSinceLastGC && !mLastCCEndTime.IsNull()) {
if (now - mLastCCEndTime < kCCDelay) {
if (aNow - mLastCCEndTime < kCCDelay) {
return false;
}
}
@ -547,16 +541,17 @@ bool CCGCScheduler::ShouldScheduleCC() const {
// don't start a new cycle too soon.
if ((mCleanupsSinceLastGC > kMajorForgetSkippableCalls) &&
!mLastForgetSkippableCycleEndTime.IsNull()) {
if (now - mLastForgetSkippableCycleEndTime <
if (aNow - mLastForgetSkippableCycleEndTime <
kTimeBetweenForgetSkippableCycles) {
return false;
}
}
return IsCCNeeded(now);
return IsCCNeeded(aNow);
}
CCRunnerStep CCGCScheduler::AdvanceCCRunner(TimeStamp aDeadline) {
CCRunnerStep CCGCScheduler::AdvanceCCRunner(TimeStamp aDeadline,
TimeStamp aNow) {
struct StateDescriptor {
// When in this state, should we first check to see if we still have
// enough reason to CC?
@ -596,11 +591,9 @@ CCRunnerStep CCGCScheduler::AdvanceCCRunner(TimeStamp aDeadline) {
return {CCRunnerAction::StopRunning, Yield};
}
TimeStamp now = Now();
if (InIncrementalGC()) {
if (mCCBlockStart.IsNull()) {
BlockCC(now);
BlockCC(aNow);
// If we have reached the CycleCollecting state, then ignore CC timer
// fires while incremental GC is running. (Running ICC during an IGC
@ -621,7 +614,7 @@ CCRunnerStep CCGCScheduler::AdvanceCCRunner(TimeStamp aDeadline) {
return {CCRunnerAction::None, Yield};
}
if (GetCCBlockedTime(now) < kMaxCCLockedoutTime) {
if (GetCCBlockedTime(aNow) < kMaxCCLockedoutTime) {
return {CCRunnerAction::None, Yield};
}
@ -632,11 +625,11 @@ CCRunnerStep CCGCScheduler::AdvanceCCRunner(TimeStamp aDeadline) {
// 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(now)) {
if (desc.mCanAbortCC && !IsCCNeeded(aNow)) {
// If we don't pass the threshold for wanting to cycle collect, stop now
// (after possibly doing a final ForgetSkippable).
mCCRunnerState = CCRunnerState::Canceled;
NoteForgetSkippableOnlyCycle();
NoteForgetSkippableOnlyCycle(aNow);
// Preserve the previous code's idea of when to check whether a
// ForgetSkippable should be fired.
@ -699,7 +692,7 @@ CCRunnerStep CCGCScheduler::AdvanceCCRunner(TimeStamp aDeadline) {
// Running in an idle callback.
// The deadline passed, so go straight to CC in the next slice.
if (now >= aDeadline) {
if (aNow >= aDeadline) {
mCCRunnerState = CCRunnerState::StartCycleCollection;
return {CCRunnerAction::None, Yield};
}
@ -715,7 +708,7 @@ CCRunnerStep CCGCScheduler::AdvanceCCRunner(TimeStamp aDeadline) {
// Our efforts to avoid a CC have failed. Let the timer fire once more
// to trigger a CC.
mCCRunnerState = CCRunnerState::StartCycleCollection;
if (now >= aDeadline) {
if (aNow >= aDeadline) {
// The deadline passed, go straight to CC in the next slice.
return {CCRunnerAction::None, Yield};
}

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

@ -101,9 +101,7 @@ static bool sShuttingDown;
static CCGCScheduler sScheduler;
// These definitions must match those in CCGCScheduler.cpp
TimeStamp mozilla::CCGCScheduler::Now() { return TimeStamp::Now(); }
// This definition must match the one in CCGCScheduler.cpp
uint32_t mozilla::CCGCScheduler::SuspectedCCObjects() {
return nsCycleCollector_suspectedCount();
}
@ -1409,7 +1407,7 @@ void nsJSContext::RunCycleCollectorSlice(TimeStamp aDeadline) {
bool preferShorterSlices;
js::SliceBudget budget = sScheduler.ComputeCCSliceBudget(
aDeadline, sCCStats.mBeginTime, sCCStats.mEndSliceTime,
&preferShorterSlices);
TimeStamp::Now(), &preferShorterSlices);
nsCycleCollector_collectSlice(budget, preferShorterSlices);
} else {
js::SliceBudget budget = js::SliceBudget::unlimited();
@ -1524,7 +1522,7 @@ bool CCGCScheduler::CCRunnerFired(TimeStamp aDeadline) {
// `Yield` in step.mYield.
CCRunnerStep step;
do {
step = sScheduler.AdvanceCCRunner(aDeadline);
step = sScheduler.AdvanceCCRunner(aDeadline, TimeStamp::Now());
switch (step.mAction) {
case CCRunnerAction::None:
break;
@ -1671,7 +1669,7 @@ void nsJSContext::LowMemoryGC() {
}
// static
void nsJSContext::MaybePokeCC() { sScheduler.MaybePokeCC(); }
void nsJSContext::MaybePokeCC() { sScheduler.MaybePokeCC(TimeStamp::Now()); }
static void DOMGCSliceCallback(JSContext* aCx, JS::GCProgress aProgress,
const JS::GCDescription& aDesc) {
@ -1717,7 +1715,8 @@ static void DOMGCSliceCallback(JSContext* aCx, JS::GCProgress aProgress,
// May need to kill the GC runner
sScheduler.KillGCRunner();
sScheduler.MaybePokeCC();
TimeStamp now = TimeStamp::Now();
sScheduler.MaybePokeCC(now);
if (aDesc.isZone_) {
sScheduler.PokeFullGC();
@ -1726,7 +1725,7 @@ static void DOMGCSliceCallback(JSContext* aCx, JS::GCProgress aProgress,
sScheduler.KillFullGCTimer();
}
if (sScheduler.IsCCNeeded()) {
if (sScheduler.IsCCNeeded(now)) {
nsCycleCollector_dispatchDeferredDeletion();
}
@ -1751,7 +1750,7 @@ static void DOMGCSliceCallback(JSContext* aCx, JS::GCProgress aProgress,
sScheduler.EnsureGCRunner(0);
}
if (sScheduler.IsCCNeeded()) {
if (sScheduler.IsCCNeeded(TimeStamp::Now())) {
nsCycleCollector_dispatchDeferredDeletion();
}

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

@ -19,13 +19,13 @@ static mozilla::TimeStamp sNow = TimeStamp::Now();
static mozilla::TimeStamp sStartupTime = sNow;
inline mozilla::TimeStamp mozilla::CCGCScheduler::Now() { return sNow; }
static mozilla::TimeStamp AdvanceTime(TimeDuration aDuration) {
sNow += aDuration;
return sNow;
}
static TimeStamp Now() { return sNow; }
static uint32_t sSuspected = 0;
inline uint32_t mozilla::CCGCScheduler::SuspectedCCObjects() {
@ -36,8 +36,6 @@ static void SuspectMore(uint32_t n) { sSuspected += n; }
using CCRunnerState = mozilla::CCGCScheduler::CCRunnerState;
static TimeStamp Now() { return sNow; }
class TestGC {
protected:
CCGCScheduler& mScheduler;
@ -56,7 +54,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.
bool neededCCAtStartOfGC = mScheduler.IsCCNeeded();
bool neededCCAtStartOfGC = mScheduler.IsCCNeeded(Now());
mScheduler.NoteGCBegin();
@ -69,7 +67,7 @@ void TestGC::Run(int aNumSlices) {
// Pretend the GC took exactly the budget.
AdvanceTime(budget);
EXPECT_EQ(mScheduler.IsCCNeeded(), neededCCAtStartOfGC);
EXPECT_EQ(mScheduler.IsCCNeeded(Now()), neededCCAtStartOfGC);
// Mutator runs for 1 second.
AdvanceTime(kOneSecond);
@ -107,7 +105,7 @@ class TestCC {
void TestCC::MaybePokeCC() {
// nsJSContext::MaybePokeCC
EXPECT_TRUE(mScheduler.ShouldScheduleCC());
EXPECT_TRUE(mScheduler.ShouldScheduleCC(Now()));
mScheduler.InitCCRunnerStateMachine(CCRunnerState::ReducePurple);
EXPECT_TRUE(mScheduler.IsEarlyForgetSkippable());
@ -120,7 +118,7 @@ void TestCC::TimerFires(int aNumSlices) {
while (true) {
SuspectMore(1000);
TimeStamp idleDeadline = Now() + kOneSecond;
step = mScheduler.AdvanceCCRunner(idleDeadline);
step = mScheduler.AdvanceCCRunner(idleDeadline, Now());
// Should first see a series of ForgetSkippable actions.
if (step.mAction != CCRunnerAction::ForgetSkippable ||
step.mRemoveChildless != KeepChildless) {
@ -132,16 +130,16 @@ void TestCC::TimerFires(int aNumSlices) {
while (step.mYield == Continue) {
TimeStamp idleDeadline = Now() + kOneSecond;
step = mScheduler.AdvanceCCRunner(idleDeadline);
step = mScheduler.AdvanceCCRunner(idleDeadline, Now());
}
EXPECT_EQ(step.mAction, CCRunnerAction::ForgetSkippable);
EXPECT_EQ(step.mRemoveChildless, RemoveChildless);
ForgetSkippable();
TimeStamp idleDeadline = Now() + kOneSecond;
step = mScheduler.AdvanceCCRunner(idleDeadline);
step = mScheduler.AdvanceCCRunner(idleDeadline, Now());
EXPECT_EQ(step.mAction, CCRunnerAction::CleanupContentUnbinder);
step = mScheduler.AdvanceCCRunner(idleDeadline);
step = mScheduler.AdvanceCCRunner(idleDeadline, Now());
EXPECT_EQ(step.mAction, CCRunnerAction::CleanupDeferred);
RunSlices(aNumSlices);
@ -203,7 +201,7 @@ void TestIdleCC::RunSlice(TimeStamp aCCStartTime, TimeStamp aPrevSliceEnd,
TimeStamp idleDeadline = Now() + kTenthSecond;
// The scheduler should request a CycleCollect slice.
step = mScheduler.AdvanceCCRunner(idleDeadline);
step = mScheduler.AdvanceCCRunner(idleDeadline, Now());
EXPECT_EQ(step.mAction, CCRunnerAction::CycleCollect);
// nsJSContext::RunCycleCollectorSlice
@ -211,7 +209,7 @@ void TestIdleCC::RunSlice(TimeStamp aCCStartTime, TimeStamp aPrevSliceEnd,
EXPECT_FALSE(mScheduler.InIncrementalGC());
bool preferShorter;
js::SliceBudget budget = mScheduler.ComputeCCSliceBudget(
idleDeadline, aCCStartTime, aPrevSliceEnd, &preferShorter);
idleDeadline, aCCStartTime, aPrevSliceEnd, Now(), &preferShorter);
// The scheduler will set the budget to our deadline (0.1sec in the future).
EXPECT_NEAR(budget.timeBudget(), kTenthSecond.ToMilliseconds(), 1);
EXPECT_FALSE(preferShorter);
@ -241,7 +239,7 @@ void TestNonIdleCC::RunSlice(TimeStamp aCCStartTime, TimeStamp aPrevSliceEnd,
TimeStamp nullDeadline;
// The scheduler should tell us to run a slice of cycle collection.
step = mScheduler.AdvanceCCRunner(nullDeadline);
step = mScheduler.AdvanceCCRunner(nullDeadline, Now());
EXPECT_EQ(step.mAction, CCRunnerAction::CycleCollect);
// nsJSContext::RunCycleCollectorSlice
@ -250,7 +248,7 @@ void TestNonIdleCC::RunSlice(TimeStamp aCCStartTime, TimeStamp aPrevSliceEnd,
bool preferShorter;
js::SliceBudget budget = mScheduler.ComputeCCSliceBudget(
nullDeadline, aCCStartTime, aPrevSliceEnd, &preferShorter);
nullDeadline, aCCStartTime, aPrevSliceEnd, Now(), &preferShorter);
if (aSliceNum == 0) {
// First slice of the CC, so always use the baseBudget which is
// kICCSliceBudget (3ms) for a non-idle slice.
@ -294,25 +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_TRUE(aScheduler.IsCCNeeded());
EXPECT_TRUE(aScheduler.IsCCNeeded(Now()));
// Now we should want to CC.
EXPECT_TRUE(aScheduler.ShouldScheduleCC());
EXPECT_TRUE(aScheduler.ShouldScheduleCC(Now()));
// Do a 5-slice CC.
aTestCC->Run(5);
// Not enough suspected objects to deserve a CC.
EXPECT_FALSE(aScheduler.IsCCNeeded());
EXPECT_FALSE(aScheduler.ShouldScheduleCC());
EXPECT_FALSE(aScheduler.IsCCNeeded(Now()));
EXPECT_FALSE(aScheduler.ShouldScheduleCC(Now()));
SetNumSuspected(10000);
// We shouldn't want to CC again yet, it's too soon.
EXPECT_FALSE(aScheduler.ShouldScheduleCC());
EXPECT_FALSE(aScheduler.ShouldScheduleCC(Now()));
AdvanceTime(mozilla::kCCDelay);
// *Now* it's time for another CC.
EXPECT_TRUE(aScheduler.ShouldScheduleCC());
EXPECT_TRUE(aScheduler.ShouldScheduleCC(Now()));
// Run a 3-slice incremental GC.
EXPECT_TRUE(!aScheduler.InIncrementalGC());
@ -329,7 +327,7 @@ static TestNonIdleCC ccNonIdle(scheduler);
TEST(TestScheduler, Idle)
{
// Cannot CC until we GC once.
EXPECT_FALSE(scheduler.ShouldScheduleCC());
EXPECT_FALSE(scheduler.ShouldScheduleCC(Now()));
EXPECT_TRUE(BasicScenario(scheduler, &gc, &ccIdle));
}