зеркало из https://github.com/mozilla/gecko-dev.git
Bug 728460, part 2: remove childless nodes in slice before CC. r=smaug
This commit is contained in:
Родитель
f578cf1551
Коммит
202cc5f858
|
@ -144,7 +144,11 @@ static PRLogModuleInfo* gJSDiagnostics;
|
|||
|
||||
#define NS_CC_SKIPPABLE_DELAY 400 // ms
|
||||
|
||||
#define NS_CC_FORCED (5 * 60 * PR_USEC_PER_SEC) // 5 min
|
||||
// Force a CC after this long if there's anything in the purple buffer.
|
||||
#define NS_CC_FORCED (2 * 60 * PR_USEC_PER_SEC) // 2 min
|
||||
|
||||
// Trigger a CC if the purple buffer exceeds this size when we check it.
|
||||
#define NS_CC_PURPLE_LIMIT 250
|
||||
|
||||
#define JAVASCRIPT nsIProgrammingLanguage::JAVASCRIPT
|
||||
|
||||
|
@ -3286,46 +3290,70 @@ ShrinkGCBuffersTimerFired(nsITimer *aTimer, void *aClosure)
|
|||
nsJSContext::ShrinkGCBuffersNow();
|
||||
}
|
||||
|
||||
// static
|
||||
void
|
||||
static bool
|
||||
ShouldTriggerCC(PRUint32 aSuspected)
|
||||
{
|
||||
return sNeedsFullCC ||
|
||||
aSuspected > NS_CC_PURPLE_LIMIT ||
|
||||
sLastCCEndTime + NS_CC_FORCED < PR_Now();
|
||||
}
|
||||
|
||||
static void
|
||||
TimerFireForgetSkippable(PRUint32 aSuspected, bool aRemoveChildless)
|
||||
{
|
||||
PRTime startTime = PR_Now();
|
||||
nsCycleCollector_forgetSkippable(aRemoveChildless);
|
||||
sPreviousSuspectedCount = nsCycleCollector_suspectedCount();
|
||||
sCleanupSinceLastGC = true;
|
||||
PRTime delta = PR_Now() - startTime;
|
||||
if (sMinForgetSkippableTime > delta) {
|
||||
sMinForgetSkippableTime = delta;
|
||||
}
|
||||
if (sMaxForgetSkippableTime < delta) {
|
||||
sMaxForgetSkippableTime = delta;
|
||||
}
|
||||
sTotalForgetSkippableTime += delta;
|
||||
sRemovedPurples += (aSuspected - sPreviousSuspectedCount);
|
||||
++sForgetSkippableBeforeCC;
|
||||
}
|
||||
|
||||
static void
|
||||
CCTimerFired(nsITimer *aTimer, void *aClosure)
|
||||
{
|
||||
if (sDidShutdown) {
|
||||
return;
|
||||
}
|
||||
if (sCCLockedOut) {
|
||||
if (sDidShutdown || sCCLockedOut) {
|
||||
return;
|
||||
}
|
||||
++sCCTimerFireCount;
|
||||
if (sCCTimerFireCount < (NS_CC_DELAY / NS_CC_SKIPPABLE_DELAY)) {
|
||||
PRUint32 suspected = nsCycleCollector_suspectedCount();
|
||||
if ((sPreviousSuspectedCount + 100) > suspected) {
|
||||
// Just few new suspected objects, return early.
|
||||
return;
|
||||
}
|
||||
|
||||
PRTime startTime = PR_Now();
|
||||
nsCycleCollector_forgetSkippable();
|
||||
sPreviousSuspectedCount = nsCycleCollector_suspectedCount();
|
||||
sCleanupSinceLastGC = true;
|
||||
PRTime delta = PR_Now() - startTime;
|
||||
if (sMinForgetSkippableTime > delta) {
|
||||
sMinForgetSkippableTime = delta;
|
||||
}
|
||||
if (sMaxForgetSkippableTime < delta) {
|
||||
sMaxForgetSkippableTime = delta;
|
||||
}
|
||||
sTotalForgetSkippableTime += delta;
|
||||
sRemovedPurples += (suspected - sPreviousSuspectedCount);
|
||||
++sForgetSkippableBeforeCC;
|
||||
} else {
|
||||
sPreviousSuspectedCount = 0;
|
||||
nsJSContext::KillCCTimer();
|
||||
if (sNeedsFullCC ||
|
||||
nsCycleCollector_suspectedCount() > 500 ||
|
||||
sLastCCEndTime + NS_CC_FORCED < PR_Now()) {
|
||||
|
||||
// During early timer fires, we only run forgetSkippable. During the first
|
||||
// late timer fire, we decide if we are going to have a second and final
|
||||
// late timer fire, where we may run the CC.
|
||||
const PRUint32 numEarlyTimerFires = NS_CC_DELAY / NS_CC_SKIPPABLE_DELAY - 2;
|
||||
bool isLateTimerFire = sCCTimerFireCount > numEarlyTimerFires;
|
||||
PRUint32 suspected = nsCycleCollector_suspectedCount();
|
||||
if (isLateTimerFire && ShouldTriggerCC(suspected)) {
|
||||
if (sCCTimerFireCount == numEarlyTimerFires + 1) {
|
||||
TimerFireForgetSkippable(suspected, true);
|
||||
if (ShouldTriggerCC(nsCycleCollector_suspectedCount())) {
|
||||
// Our efforts to avoid a CC have failed, so we return to let the
|
||||
// timer fire once more to trigger a CC.
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
// We are in the final timer fire and still meet the conditions for
|
||||
// triggering a CC.
|
||||
nsJSContext::CycleCollectNow();
|
||||
}
|
||||
} else if ((sPreviousSuspectedCount + 100) <= suspected) {
|
||||
// Only do a forget skippable if there are more than a few new objects.
|
||||
TimerFireForgetSkippable(suspected, false);
|
||||
}
|
||||
|
||||
if (isLateTimerFire) {
|
||||
// We have either just run the CC or decided we don't want to run the CC
|
||||
// next time, so kill the timer.
|
||||
sPreviousSuspectedCount = 0;
|
||||
nsJSContext::KillCCTimer();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче