9
9
#include " mozilla/dom/ScriptSettings.h"
10
10
#include " nsRefreshDriver.h"
11
11
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
-
109
12
namespace mozilla {
110
13
111
14
void CCGCScheduler::NoteGCBegin () {
@@ -156,7 +59,6 @@ void CCGCScheduler::NoteWontGC() {
156
59
157
60
bool CCGCScheduler::GCRunnerFired (TimeStamp aDeadline) {
158
61
MOZ_ASSERT (!mDidShutdown , " GCRunner still alive during shutdown" );
159
- MOZ_ASSERT (!mHaveAskedParent , " GCRunner alive after asking the parent" );
160
62
161
63
GCRunnerStep step = GetNextGCRunnerAction ();
162
64
switch (step.mAction ) {
@@ -171,12 +73,10 @@ bool CCGCScheduler::GCRunnerFired(TimeStamp aDeadline) {
171
73
break ;
172
74
}
173
75
174
- mHaveAskedParent = true ;
175
76
KillGCRunner ();
176
77
mbPromise->Then (
177
78
GetMainThreadSerialEventTarget (), __func__,
178
79
[this ](bool aMayGC) {
179
- mHaveAskedParent = false ;
180
80
if (aMayGC) {
181
81
if (!NoteReadyForMajorGC ()) {
182
82
// Another GC started and maybe completed while waiting.
@@ -194,7 +94,6 @@ bool CCGCScheduler::GCRunnerFired(TimeStamp aDeadline) {
194
94
}
195
95
},
196
96
[this ](mozilla::ipc::ResponseRejectReason r) {
197
- mHaveAskedParent = false ;
198
97
if (!InIncrementalGC ()) {
199
98
KillGCRunner ();
200
99
NoteWontGC ();
@@ -389,8 +288,8 @@ void CCGCScheduler::PokeGC(JS::GCReason aReason, JSObject* aObj,
389
288
SetNeedsFullGC ();
390
289
}
391
290
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
394
293
return ;
395
294
}
396
295
@@ -416,7 +315,7 @@ void CCGCScheduler::PokeGC(JS::GCReason aReason, JSObject* aObj,
416
315
}
417
316
418
317
void CCGCScheduler::EnsureGCRunner (TimeDuration aDelay) {
419
- if (mGCRunner || mHaveAskedParent ) {
318
+ if (mGCRunner ) {
420
319
return ;
421
320
}
422
321
0 commit comments