99#include " mozilla/dom/ScriptSettings.h"
1010#include " nsRefreshDriver.h"
1111
12- /*
13- * GC Scheduling from Firefox
14- * ==========================
15- *
16- * See also GC Scheduling from SpiderMonkey's perspective here:
17- * https://searchfox.org/mozilla-central/source/js/src/gc/Scheduling.h
18- *
19- * From Firefox's perspective GCs can start in 5 different ways:
20- *
21- * * The JS engine just starts doing a GC for its own reasons (see above).
22- * Firefox finds out about these via a callback in nsJSEnvironment.cpp
23- * * PokeGC()
24- * * PokeFullGC()
25- * * PokeShrinkingGC()
26- * * memory-pressure GCs (via a listener in nsJSEnvironment.cpp).
27- *
28- * PokeGC
29- * ------
30- *
31- * void CCGCScheduler::PokeGC(JS::GCReason aReason, JSObject* aObj,
32- * TimeDuration aDelay)
33- *
34- * PokeGC provides a way for callers to say "Hey, there may be some memory
35- * associated with this object (via Zone) you can collect." PokeGC will:
36- * * add the zone to a set,
37- * * set flags including what kind of GC to run (SetWantMajorGC),
38- * * then creates the mGCRunner with a short delay.
39- *
40- * The delay can allow other calls to PokeGC to add their zones so they can
41- * be collected together.
42- *
43- * See below for what happens when mGCRunner fires.
44- *
45- * PokeFullGC
46- * ----------
47- *
48- * void CCGCScheduler::PokeFullGC()
49- *
50- * PokeFullGC will create a timer that will initiate a "full" (all zones)
51- * collection. This is usually used after a regular collection if a full GC
52- * seems like a good idea (to collect inter-zone references).
53- *
54- * When the timer fires it will:
55- * * set flags (SetWantMajorGC),
56- * * start the mGCRunner with zero delay.
57- *
58- * See below for when mGCRunner fires.
59- *
60- * PokeShrinkingGC
61- * ---------------
62- *
63- * void CCGCScheduler::PokeShrinkingGC()
64- *
65- * PokeShrinkingGC is called when Firefox's user is inactive.
66- * Like PokeFullGC, PokeShrinkingGC uses a timer, but the timeout is longer
67- * which should prevent the ShrinkingGC from starting if the user only
68- * glances away for a brief time. When the timer fires it will:
69- *
70- * * set flags (SetWantMajorGC),
71- * * create the mGCRunner.
72- *
73- * There is a check if the user is still inactive in GCRunnerFired), if the
74- * user has become active the shrinking GC is canceled and either a regular
75- * GC (if requested, see mWantAtLeastRegularGC) or no GC is run.
76- *
77- * When mGCRunner fires
78- * --------------------
79- *
80- * When mGCRunner fires it calls GCRunnerFired. This starts in the
81- * WaitToMajorGC state:
82- *
83- * * If this is a parent process it jumps to the next state
84- * * If this is a content process it will ask the parent if now is a good
85- * time to do a GC. (MayGCNow)
86- * * kill the mGCRunner
87- * * Exit
88- *
89- * Meanwhile the parent process will queue GC requests so that not too many
90- * are running in parallel overwhelming the CPU cores (see
91- * IdleSchedulerParent).
92- *
93- * When the promise from MayGCNow is resolved it will set some
94- * state (NoteReadyForMajorGC) and restore the mGCRunner.
95- *
96- * When the mGCRunner runs a second time (or this is the parent process and
97- * which jumped over the above logic. It will be in the StartMajorGC state.
98- * It will initiate the GC for real, usually. If it's a shrinking GC and the
99- * user is now active again it may abort. See GCRunnerFiredDoGC().
100- *
101- * The runner will then run the first slice of the garbage collection.
102- * Later slices are also run by the runner, the final slice kills the runner
103- * from the GC callback in nsJSEnvironment.cpp.
104- *
105- * There is additional logic in the code to handle concurrent requests of
106- * various kinds.
107- */
108-
10912namespace mozilla {
11013
11114void CCGCScheduler::NoteGCBegin () {
@@ -156,7 +59,6 @@ void CCGCScheduler::NoteWontGC() {
15659
15760bool CCGCScheduler::GCRunnerFired (TimeStamp aDeadline) {
15861 MOZ_ASSERT (!mDidShutdown , " GCRunner still alive during shutdown" );
159- MOZ_ASSERT (!mHaveAskedParent , " GCRunner alive after asking the parent" );
16062
16163 GCRunnerStep step = GetNextGCRunnerAction ();
16264 switch (step.mAction ) {
@@ -171,12 +73,10 @@ bool CCGCScheduler::GCRunnerFired(TimeStamp aDeadline) {
17173 break ;
17274 }
17375
174- mHaveAskedParent = true ;
17576 KillGCRunner ();
17677 mbPromise->Then (
17778 GetMainThreadSerialEventTarget (), __func__,
17879 [this ](bool aMayGC) {
179- mHaveAskedParent = false ;
18080 if (aMayGC) {
18181 if (!NoteReadyForMajorGC ()) {
18282 // Another GC started and maybe completed while waiting.
@@ -194,7 +94,6 @@ bool CCGCScheduler::GCRunnerFired(TimeStamp aDeadline) {
19494 }
19595 },
19696 [this ](mozilla::ipc::ResponseRejectReason r) {
197- mHaveAskedParent = false ;
19897 if (!InIncrementalGC ()) {
19998 KillGCRunner ();
20099 NoteWontGC ();
@@ -389,8 +288,8 @@ void CCGCScheduler::PokeGC(JS::GCReason aReason, JSObject* aObj,
389288 SetNeedsFullGC ();
390289 }
391290
392- if (mGCRunner || mHaveAskedParent ) {
393- // There's already a GC runner, there or will be, so just return.
291+ if (mGCRunner ) {
292+ // There's already a runner for GC'ing, just return
394293 return ;
395294 }
396295
@@ -416,7 +315,7 @@ void CCGCScheduler::PokeGC(JS::GCReason aReason, JSObject* aObj,
416315}
417316
418317void CCGCScheduler::EnsureGCRunner (TimeDuration aDelay) {
419- if (mGCRunner || mHaveAskedParent ) {
318+ if (mGCRunner ) {
420319 return ;
421320 }
422321
0 commit comments