1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
2  * vim: set ts=8 sts=2 et sw=2 tw=80:
3  * This Source Code Form is subject to the terms of the Mozilla Public
4  * License, v. 2.0. If a copy of the MPL was not distributed with this
5  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 
7 /*
8  * High-level interface to the JS garbage collector.
9  */
10 
11 #ifndef js_GCAPI_h
12 #define js_GCAPI_h
13 
14 #include "mozilla/TimeStamp.h"
15 #include "mozilla/Vector.h"
16 
17 #include "js/GCAnnotations.h"
18 #include "js/shadow/Zone.h"
19 #include "js/SliceBudget.h"
20 #include "js/TypeDecls.h"
21 #include "js/UniquePtr.h"
22 #include "js/Utility.h"
23 
24 class JS_PUBLIC_API JSTracer;
25 
26 namespace js {
27 namespace gc {
28 class GCRuntime;
29 }  // namespace gc
30 class JS_PUBLIC_API SliceBudget;
31 namespace gcstats {
32 struct Statistics;
33 }  // namespace gcstats
34 }  // namespace js
35 
36 namespace JS {
37 
38 // Options used when starting a GC.
39 enum class GCOptions : uint32_t {
40   // Normal GC invocation.
41   //
42   // Some objects that are unreachable from the program may still be alive after
43   // collection because of internal references
44   Normal = 0,
45 
46   // A shrinking GC.
47   //
48   // Try to release as much memory as possible by clearing internal caches,
49   // aggressively discarding JIT code and decommitting unused chunks. This
50   // ensures all unreferenced objects are removed from the system.
51   //
52   // Finally, compact the GC heap.
53   Shrink = 1,
54 
55   // A shutdown GC.
56   //
57   // This does more drastic cleanup as part of system shutdown, including:
58   //  - clearing WeakRef kept object sets
59   //  - not marking FinalizationRegistry roots
60   //  - repeating collection if JS::NotifyGCRootsRemoved was called
61   //  - skipping scheduling of various future work that won't be needed
62   //
63   // Note that this assumes that no JS will run after this point!
64   Shutdown = 2
65 };
66 
67 }  // namespace JS
68 
69 typedef enum JSGCParamKey {
70   /**
71    * Maximum nominal heap before last ditch GC.
72    *
73    * Soft limit on the number of bytes we are allowed to allocate in the GC
74    * heap. Attempts to allocate gcthings over this limit will return null and
75    * subsequently invoke the standard OOM machinery, independent of available
76    * physical memory.
77    *
78    * Pref: javascript.options.mem.max
79    * Default: 0xffffffff
80    */
81   JSGC_MAX_BYTES = 0,
82 
83   /**
84    * Maximum size of the generational GC nurseries.
85    *
86    * This will be rounded to the nearest gc::ChunkSize.
87    *
88    * Pref: javascript.options.mem.nursery.max_kb
89    * Default: JS::DefaultNurseryMaxBytes
90    */
91   JSGC_MAX_NURSERY_BYTES = 2,
92 
93   /** Amount of bytes allocated by the GC. */
94   JSGC_BYTES = 3,
95 
96   /** Number of times GC has been invoked. Includes both major and minor GC. */
97   JSGC_NUMBER = 4,
98 
99   /**
100    * Whether incremental GC is enabled. If not, GC will always run to
101    * completion.
102    *
103    * prefs: javascript.options.mem.gc_incremental.
104    * Default: false
105    */
106   JSGC_INCREMENTAL_GC_ENABLED = 5,
107 
108   /**
109    * Whether per-zone GC is enabled. If not, all zones are collected every time.
110    *
111    * prefs: javascript.options.mem.gc_per_zone
112    * Default: false
113    */
114   JSGC_PER_ZONE_GC_ENABLED = 6,
115 
116   /** Number of cached empty GC chunks. */
117   JSGC_UNUSED_CHUNKS = 7,
118 
119   /** Total number of allocated GC chunks. */
120   JSGC_TOTAL_CHUNKS = 8,
121 
122   /**
123    * Max milliseconds to spend in an incremental GC slice.
124    *
125    * A value of zero means there is no maximum.
126    *
127    * Pref: javascript.options.mem.gc_incremental_slice_ms
128    * Default: DefaultTimeBudgetMS.
129    */
130   JSGC_SLICE_TIME_BUDGET_MS = 9,
131 
132   /**
133    * Maximum size the GC mark stack can grow to.
134    *
135    * Pref: none
136    * Default: MarkStack::DefaultCapacity
137    */
138   JSGC_MARK_STACK_LIMIT = 10,
139 
140   /**
141    * The "do we collect?" decision depends on various parameters and can be
142    * summarised as:
143    *
144    *   ZoneSize > Max(ThresholdBase, LastSize) * GrowthFactor * ThresholdFactor
145    *
146    * Where
147    *   ZoneSize: Current size of this zone.
148    *   LastSize: Heap size immediately after the most recent collection.
149    *   ThresholdBase: The JSGC_ALLOCATION_THRESHOLD parameter
150    *   GrowthFactor: A number above 1, calculated based on some of the
151    *                 following parameters.
152    *                 See computeZoneHeapGrowthFactorForHeapSize() in GC.cpp
153    *   ThresholdFactor: 1.0 to trigger an incremental collections or between
154    *                    JSGC_SMALL_HEAP_INCREMENTAL_LIMIT and
155    *                    JSGC_LARGE_HEAP_INCREMENTAL_LIMIT to trigger a
156    *                    non-incremental collection.
157    *
158    * The RHS of the equation above is calculated and sets
159    * zone->gcHeapThreshold.bytes(). When gcHeapSize.bytes() exeeds
160    * gcHeapThreshold.bytes() for a zone, the zone may be scheduled for a GC.
161    */
162 
163   /**
164    * GCs less than this far apart in milliseconds will be considered
165    * 'high-frequency GCs'.
166    *
167    * Pref: javascript.options.mem.gc_high_frequency_time_limit_ms
168    * Default: HighFrequencyThreshold
169    */
170   JSGC_HIGH_FREQUENCY_TIME_LIMIT = 11,
171 
172   /**
173    * Upper limit for classifying a heap as small (MB).
174    *
175    * Dynamic heap growth thresholds are based on whether the heap is small,
176    * medium or large. Heaps smaller than this size are classified as small;
177    * larger heaps are classified as medium or large.
178    *
179    * Pref: javascript.options.mem.gc_small_heap_size_max_mb
180    * Default: SmallHeapSizeMaxBytes
181    */
182   JSGC_SMALL_HEAP_SIZE_MAX = 12,
183 
184   /**
185    * Lower limit for classifying a heap as large (MB).
186    *
187    * Dynamic heap growth thresholds are based on whether the heap is small,
188    * medium or large. Heaps larger than this size are classified as large;
189    * smaller heaps are classified as small or medium.
190    *
191    * Pref: javascript.options.mem.gc_large_heap_size_min_mb
192    * Default: LargeHeapSizeMinBytes
193    */
194   JSGC_LARGE_HEAP_SIZE_MIN = 13,
195 
196   /**
197    * Heap growth factor for small heaps in the high-frequency GC state.
198    *
199    * Pref: javascript.options.mem.gc_high_frequency_small_heap_growth
200    * Default: HighFrequencySmallHeapGrowth
201    */
202   JSGC_HIGH_FREQUENCY_SMALL_HEAP_GROWTH = 14,
203 
204   /**
205    * Heap growth factor for large heaps in the high-frequency GC state.
206    *
207    * Pref: javascript.options.mem.gc_high_frequency_large_heap_growth
208    * Default: HighFrequencyLargeHeapGrowth
209    */
210   JSGC_HIGH_FREQUENCY_LARGE_HEAP_GROWTH = 15,
211 
212   /**
213    * Heap growth factor for low frequency GCs.
214    *
215    * This factor is applied regardless of the size of the heap when not in the
216    * high-frequency GC state.
217    *
218    * Pref: javascript.options.mem.gc_low_frequency_heap_growth
219    * Default: LowFrequencyHeapGrowth
220    */
221   JSGC_LOW_FREQUENCY_HEAP_GROWTH = 16,
222 
223   /**
224    * Lower limit for collecting a zone (MB).
225    *
226    * Zones smaller than this size will not normally be collected.
227    *
228    * Pref: javascript.options.mem.gc_allocation_threshold_mb
229    * Default GCZoneAllocThresholdBase
230    */
231   JSGC_ALLOCATION_THRESHOLD = 19,
232 
233   /**
234    * We try to keep at least this many unused chunks in the free chunk pool at
235    * all times, even after a shrinking GC.
236    *
237    * Pref: javascript.options.mem.gc_min_empty_chunk_count
238    * Default: MinEmptyChunkCount
239    */
240   JSGC_MIN_EMPTY_CHUNK_COUNT = 21,
241 
242   /**
243    * We never keep more than this many unused chunks in the free chunk
244    * pool.
245    *
246    * Pref: javascript.options.mem.gc_min_empty_chunk_count
247    * Default: MinEmptyChunkCount
248    */
249   JSGC_MAX_EMPTY_CHUNK_COUNT = 22,
250 
251   /**
252    * Whether compacting GC is enabled.
253    *
254    * Pref: javascript.options.mem.gc_compacting
255    * Default: CompactingEnabled
256    */
257   JSGC_COMPACTING_ENABLED = 23,
258 
259   /**
260    * Limit of how far over the incremental trigger threshold we allow the heap
261    * to grow before finishing a collection non-incrementally, for small heaps.
262    *
263    * We trigger an incremental GC when a trigger threshold is reached but the
264    * collection may not be fast enough to keep up with the mutator. At some
265    * point we finish the collection non-incrementally.
266    *
267    * Default: SmallHeapIncrementalLimit
268    * Pref: javascript.options.mem.gc_small_heap_incremental_limit
269    */
270   JSGC_SMALL_HEAP_INCREMENTAL_LIMIT = 25,
271 
272   /**
273    * Limit of how far over the incremental trigger threshold we allow the heap
274    * to grow before finishing a collection non-incrementally, for large heaps.
275    *
276    * Default: LargeHeapIncrementalLimit
277    * Pref: javascript.options.mem.gc_large_heap_incremental_limit
278    */
279   JSGC_LARGE_HEAP_INCREMENTAL_LIMIT = 26,
280 
281   /**
282    * Attempt to run a minor GC in the idle time if the free space falls
283    * below this number of bytes.
284    *
285    * Default: NurseryChunkUsableSize / 4
286    * Pref: None
287    */
288   JSGC_NURSERY_FREE_THRESHOLD_FOR_IDLE_COLLECTION = 27,
289 
290   /**
291    * If this percentage of the nursery is tenured and the nursery is at least
292    * 4MB, then proceed to examine which groups we should pretenure.
293    *
294    * Default: PretenureThreshold
295    * Pref: None
296    */
297   JSGC_PRETENURE_THRESHOLD = 28,
298 
299   /**
300    * If the above condition is met, then any object group that tenures more than
301    * this number of objects will be pretenured (if it can be).
302    *
303    * Default: PretenureGroupThreshold
304    * Pref: None
305    */
306   JSGC_PRETENURE_GROUP_THRESHOLD = 29,
307 
308   /**
309    * Attempt to run a minor GC in the idle time if the free space falls
310    * below this percentage (from 0 to 99).
311    *
312    * Default: 25
313    * Pref: None
314    */
315   JSGC_NURSERY_FREE_THRESHOLD_FOR_IDLE_COLLECTION_PERCENT = 30,
316 
317   /**
318    * Minimum size of the generational GC nurseries.
319    *
320    * This value will be rounded to the nearest Nursery::SubChunkStep if below
321    * gc::ChunkSize, otherwise it'll be rounded to the nearest gc::ChunkSize.
322    *
323    * Default: Nursery::SubChunkLimit
324    * Pref: javascript.options.mem.nursery.min_kb
325    */
326   JSGC_MIN_NURSERY_BYTES = 31,
327 
328   /**
329    * The minimum time to allow between triggering last ditch GCs in seconds.
330    *
331    * Default: 60 seconds
332    * Pref: None
333    */
334   JSGC_MIN_LAST_DITCH_GC_PERIOD = 32,
335 
336   /**
337    * The delay (in heapsize kilobytes) between slices of an incremental GC.
338    *
339    * Default: ZoneAllocDelayBytes
340    */
341   JSGC_ZONE_ALLOC_DELAY_KB = 33,
342 
343   /*
344    * The current size of the nursery.
345    *
346    * This parameter is read-only.
347    */
348   JSGC_NURSERY_BYTES = 34,
349 
350   /**
351    * Retained size base value for calculating malloc heap threshold.
352    *
353    * Default: MallocThresholdBase
354    */
355   JSGC_MALLOC_THRESHOLD_BASE = 35,
356 
357   /**
358    * Whether incremental weakmap marking is enabled.
359    *
360    * Pref: javascript.options.mem.incremental_weakmap
361    * Default: IncrementalWeakMarkEnabled
362    */
363   JSGC_INCREMENTAL_WEAKMAP_ENABLED = 37,
364 
365   /**
366    * The chunk size in bytes for this system.
367    *
368    * This parameter is read-only.
369    */
370   JSGC_CHUNK_BYTES = 38,
371 
372   /**
373    * The number of background threads to use for parallel GC work for each CPU
374    * core, expressed as an integer percentage.
375    *
376    * Pref: javascript.options.mem.gc_helper_thread_ratio
377    */
378   JSGC_HELPER_THREAD_RATIO = 39,
379 
380   /**
381    * The maximum number of background threads to use for parallel GC work.
382    *
383    * Pref: javascript.options.mem.gc_max_helper_threads
384    */
385   JSGC_MAX_HELPER_THREADS = 40,
386 
387   /**
388    * The number of background threads to use for parallel GC work.
389    *
390    * This parameter is read-only and is set based on the
391    * JSGC_HELPER_THREAD_RATIO and JSGC_MAX_HELPER_THREADS parameters.
392    */
393   JSGC_HELPER_THREAD_COUNT = 41,
394 
395   /**
396    * If the percentage of the tenured strings exceeds this threshold, string
397    * will be allocated in tenured heap instead. (Default is allocated in
398    * nursery.)
399    */
400   JSGC_PRETENURE_STRING_THRESHOLD = 42,
401 
402   /**
403    * If the finalization rate of the tenured strings exceeds this threshold,
404    * string will be allocated in nursery.
405    */
406   JSGC_STOP_PRETENURE_STRING_THRESHOLD = 43,
407 
408   /**
409    * A number that is incremented on every major GC slice.
410    */
411   JSGC_MAJOR_GC_NUMBER = 44,
412 
413   /**
414    * A number that is incremented on every minor GC.
415    */
416   JSGC_MINOR_GC_NUMBER = 45,
417 
418   /**
419    * JS::RunIdleTimeGCTask will collect the nursery if it hasn't been collected
420    * in this many milliseconds.
421    *
422    * Default: 5000
423    * Pref: None
424    */
425   JSGC_NURSERY_TIMEOUT_FOR_IDLE_COLLECTION_MS = 46,
426 
427   /**
428    * The system page size in KB.
429    *
430    * This parameter is read-only.
431    */
432   JSGC_SYSTEM_PAGE_SIZE_KB = 47,
433 
434   /**
435    * In an incremental GC, this determines the point at which to start
436    * increasing the slice budget and frequency of allocation triggered slices to
437    * try to avoid reaching the incremental limit and finishing the collection
438    * synchronously.
439    *
440    * The threshold is calculated by subtracting this value from the heap's
441    * incremental limit.
442    */
443   JSGC_URGENT_THRESHOLD_MB = 48,
444 } JSGCParamKey;
445 
446 /*
447  * Generic trace operation that calls JS::TraceEdge on each traceable thing's
448  * location reachable from data.
449  */
450 typedef void (*JSTraceDataOp)(JSTracer* trc, void* data);
451 
452 /*
453  * Trace hook used to trace gray roots incrementally.
454  *
455  * This should return whether tracing is finished. It will be called repeatedly
456  * in subsequent GC slices until it returns true.
457  *
458  * While tracing this should check the budget and return false if it has been
459  * exceeded. When passed an unlimited budget it should always return true.
460  */
461 typedef bool (*JSGrayRootsTracer)(JSTracer* trc, js::SliceBudget& budget,
462                                   void* data);
463 
464 typedef enum JSGCStatus { JSGC_BEGIN, JSGC_END } JSGCStatus;
465 
466 typedef void (*JSObjectsTenuredCallback)(JSContext* cx, void* data);
467 
468 typedef enum JSFinalizeStatus {
469   /**
470    * Called when preparing to sweep a group of zones, before anything has been
471    * swept.  The collector will not yield to the mutator before calling the
472    * callback with JSFINALIZE_GROUP_START status.
473    */
474   JSFINALIZE_GROUP_PREPARE,
475 
476   /**
477    * Called after preparing to sweep a group of zones. Weak references to
478    * unmarked things have been removed at this point, but no GC things have
479    * been swept. The collector may yield to the mutator after this point.
480    */
481   JSFINALIZE_GROUP_START,
482 
483   /**
484    * Called after sweeping a group of zones. All dead GC things have been
485    * swept at this point.
486    */
487   JSFINALIZE_GROUP_END,
488 
489   /**
490    * Called at the end of collection when everything has been swept.
491    */
492   JSFINALIZE_COLLECTION_END
493 } JSFinalizeStatus;
494 
495 typedef void (*JSFinalizeCallback)(JSFreeOp* fop, JSFinalizeStatus status,
496                                    void* data);
497 
498 typedef void (*JSWeakPointerZonesCallback)(JSTracer* trc, void* data);
499 
500 typedef void (*JSWeakPointerCompartmentCallback)(JSTracer* trc,
501                                                  JS::Compartment* comp,
502                                                  void* data);
503 
504 /*
505  * This is called to tell the embedding that a FinalizationRegistry object has
506  * cleanup work, and that the engine should be called back at an appropriate
507  * later time to perform this cleanup, by calling the function |doCleanup|.
508  *
509  * This callback must not do anything that could cause GC.
510  */
511 using JSHostCleanupFinalizationRegistryCallback =
512     void (*)(JSFunction* doCleanup, JSObject* incumbentGlobal, void* data);
513 
514 /**
515  * Each external string has a pointer to JSExternalStringCallbacks. Embedders
516  * can use this to implement custom finalization or memory reporting behavior.
517  */
518 struct JSExternalStringCallbacks {
519   /**
520    * Finalizes external strings created by JS_NewExternalString. The finalizer
521    * can be called off the main thread.
522    */
523   virtual void finalize(char16_t* chars) const = 0;
524 
525   /**
526    * Callback used by memory reporting to ask the embedder how much memory an
527    * external string is keeping alive.  The embedder is expected to return a
528    * value that corresponds to the size of the allocation that will be released
529    * by the finalizer callback above.
530    *
531    * Implementations of this callback MUST NOT do anything that can cause GC.
532    */
533   virtual size_t sizeOfBuffer(const char16_t* chars,
534                               mozilla::MallocSizeOf mallocSizeOf) const = 0;
535 };
536 
537 namespace JS {
538 
539 #define GCREASONS(D)                                                   \
540   /* Reasons internal to the JS engine. */                             \
541   D(API, 0)                                                            \
542   D(EAGER_ALLOC_TRIGGER, 1)                                            \
543   D(DESTROY_RUNTIME, 2)                                                \
544   D(ROOTS_REMOVED, 3)                                                  \
545   D(LAST_DITCH, 4)                                                     \
546   D(TOO_MUCH_MALLOC, 5)                                                \
547   D(ALLOC_TRIGGER, 6)                                                  \
548   D(DEBUG_GC, 7)                                                       \
549   D(COMPARTMENT_REVIVED, 8)                                            \
550   D(RESET, 9)                                                          \
551   D(OUT_OF_NURSERY, 10)                                                \
552   D(EVICT_NURSERY, 11)                                                 \
553   D(SHARED_MEMORY_LIMIT, 13)                                           \
554   D(IDLE_TIME_COLLECTION, 14)                                          \
555   D(BG_TASK_FINISHED, 15)                                              \
556   D(ABORT_GC, 16)                                                      \
557   D(FULL_WHOLE_CELL_BUFFER, 17)                                        \
558   D(FULL_GENERIC_BUFFER, 18)                                           \
559   D(FULL_VALUE_BUFFER, 19)                                             \
560   D(FULL_CELL_PTR_OBJ_BUFFER, 20)                                      \
561   D(FULL_SLOT_BUFFER, 21)                                              \
562   D(FULL_SHAPE_BUFFER, 22)                                             \
563   D(TOO_MUCH_WASM_MEMORY, 23)                                          \
564   D(DISABLE_GENERATIONAL_GC, 24)                                       \
565   D(FINISH_GC, 25)                                                     \
566   D(PREPARE_FOR_TRACING, 26)                                           \
567   D(UNUSED4, 27)                                                       \
568   D(FULL_CELL_PTR_STR_BUFFER, 28)                                      \
569   D(TOO_MUCH_JIT_CODE, 29)                                             \
570   D(FULL_CELL_PTR_BIGINT_BUFFER, 30)                                   \
571   D(UNUSED5, 31)                                                       \
572   D(NURSERY_MALLOC_BUFFERS, 32)                                        \
573                                                                        \
574   /*                                                                   \
575    * Reasons from Firefox.                                             \
576    *                                                                   \
577    * The JS engine attaches special meanings to some of these reasons. \
578    */                                                                  \
579   D(DOM_WINDOW_UTILS, FIRST_FIREFOX_REASON)                            \
580   D(COMPONENT_UTILS, 34)                                               \
581   D(MEM_PRESSURE, 35)                                                  \
582   D(CC_FINISHED, 36)                                                   \
583   D(CC_FORCED, 37)                                                     \
584   D(LOAD_END, 38)                                                      \
585   D(UNUSED3, 39)                                                       \
586   D(PAGE_HIDE, 40)                                                     \
587   D(NSJSCONTEXT_DESTROY, 41)                                           \
588   D(WORKER_SHUTDOWN, 42)                                               \
589   D(SET_DOC_SHELL, 43)                                                 \
590   D(DOM_UTILS, 44)                                                     \
591   D(DOM_IPC, 45)                                                       \
592   D(DOM_WORKER, 46)                                                    \
593   D(INTER_SLICE_GC, 47)                                                \
594   D(UNUSED1, 48)                                                       \
595   D(FULL_GC_TIMER, 49)                                                 \
596   D(SHUTDOWN_CC, 50)                                                   \
597   D(UNUSED2, 51)                                                       \
598   D(USER_INACTIVE, 52)                                                 \
599   D(XPCONNECT_SHUTDOWN, 53)                                            \
600   D(DOCSHELL, 54)                                                      \
601   D(HTML_PARSER, 55)                                                   \
602   D(DOM_TESTUTILS, 56)                                                 \
603                                                                        \
604   /* Reasons reserved for embeddings. */                               \
605   D(RESERVED1, FIRST_RESERVED_REASON)                                  \
606   D(RESERVED2, 91)                                                     \
607   D(RESERVED3, 92)                                                     \
608   D(RESERVED4, 93)                                                     \
609   D(RESERVED5, 94)                                                     \
610   D(RESERVED6, 95)                                                     \
611   D(RESERVED7, 96)                                                     \
612   D(RESERVED8, 97)                                                     \
613   D(RESERVED9, 98)
614 
615 enum class GCReason {
616   FIRST_FIREFOX_REASON = 33,
617   FIRST_RESERVED_REASON = 90,
618 
619 #define MAKE_REASON(name, val) name = val,
620   GCREASONS(MAKE_REASON)
621 #undef MAKE_REASON
622       NO_REASON,
623   NUM_REASONS,
624 
625   /*
626    * For telemetry, we want to keep a fixed max bucket size over time so we
627    * don't have to switch histograms. 100 is conservative; but the cost of extra
628    * buckets seems to be low while the cost of switching histograms is high.
629    */
630   NUM_TELEMETRY_REASONS = 100
631 };
632 
633 /**
634  * Get a statically allocated C string explaining the given GC reason.
635  */
636 extern JS_PUBLIC_API const char* ExplainGCReason(JS::GCReason reason);
637 
638 /**
639  * Return true if the GC reason is internal to the JS engine.
640  */
641 extern JS_PUBLIC_API bool InternalGCReason(JS::GCReason reason);
642 
643 /*
644  * Zone GC:
645  *
646  * SpiderMonkey's GC is capable of performing a collection on an arbitrary
647  * subset of the zones in the system. This allows an embedding to minimize
648  * collection time by only collecting zones that have run code recently,
649  * ignoring the parts of the heap that are unlikely to have changed.
650  *
651  * When triggering a GC using one of the functions below, it is first necessary
652  * to select the zones to be collected. To do this, you can call
653  * PrepareZoneForGC on each zone, or you can call PrepareForFullGC to select
654  * all zones. Failing to select any zone is an error.
655  */
656 
657 /**
658  * Schedule the given zone to be collected as part of the next GC.
659  */
660 extern JS_PUBLIC_API void PrepareZoneForGC(JSContext* cx, Zone* zone);
661 
662 /**
663  * Schedule all zones to be collected in the next GC.
664  */
665 extern JS_PUBLIC_API void PrepareForFullGC(JSContext* cx);
666 
667 /**
668  * When performing an incremental GC, the zones that were selected for the
669  * previous incremental slice must be selected in subsequent slices as well.
670  * This function selects those slices automatically.
671  */
672 extern JS_PUBLIC_API void PrepareForIncrementalGC(JSContext* cx);
673 
674 /**
675  * Returns true if any zone in the system has been scheduled for GC with one of
676  * the functions above or by the JS engine.
677  */
678 extern JS_PUBLIC_API bool IsGCScheduled(JSContext* cx);
679 
680 /**
681  * Undoes the effect of the Prepare methods above. The given zone will not be
682  * collected in the next GC.
683  */
684 extern JS_PUBLIC_API void SkipZoneForGC(JSContext* cx, Zone* zone);
685 
686 /*
687  * Non-Incremental GC:
688  *
689  * The following functions perform a non-incremental GC.
690  */
691 
692 /**
693  * Performs a non-incremental collection of all selected zones.
694  */
695 extern JS_PUBLIC_API void NonIncrementalGC(JSContext* cx, JS::GCOptions options,
696                                            GCReason reason);
697 
698 /*
699  * Incremental GC:
700  *
701  * Incremental GC divides the full mark-and-sweep collection into multiple
702  * slices, allowing client JavaScript code to run between each slice. This
703  * allows interactive apps to avoid long collection pauses. Incremental GC does
704  * not make collection take less time, it merely spreads that time out so that
705  * the pauses are less noticable.
706  *
707  * For a collection to be carried out incrementally the following conditions
708  * must be met:
709  *  - The collection must be run by calling JS::IncrementalGC() rather than
710  *    JS_GC().
711  *  - The GC parameter JSGC_INCREMENTAL_GC_ENABLED must be true.
712  *
713  * Note: Even if incremental GC is enabled and working correctly,
714  *       non-incremental collections can still happen when low on memory.
715  */
716 
717 /**
718  * Begin an incremental collection and perform one slice worth of work. When
719  * this function returns, the collection may not be complete.
720  * IncrementalGCSlice() must be called repeatedly until
721  * !IsIncrementalGCInProgress(cx).
722  *
723  * Note: SpiderMonkey's GC is not realtime. Slices in practice may be longer or
724  *       shorter than the requested interval.
725  */
726 extern JS_PUBLIC_API void StartIncrementalGC(JSContext* cx,
727                                              JS::GCOptions options,
728                                              GCReason reason,
729                                              const js::SliceBudget& budget);
730 
731 /**
732  * Perform a slice of an ongoing incremental collection. When this function
733  * returns, the collection may not be complete. It must be called repeatedly
734  * until !IsIncrementalGCInProgress(cx).
735  *
736  * Note: SpiderMonkey's GC is not realtime. Slices in practice may be longer or
737  *       shorter than the requested interval.
738  */
739 extern JS_PUBLIC_API void IncrementalGCSlice(JSContext* cx, GCReason reason,
740                                              const js::SliceBudget& budget);
741 
742 /**
743  * Return whether an incremental GC has work to do on the foreground thread and
744  * would make progress if a slice was run now. If this returns false then the GC
745  * is waiting for background threads to finish their work and a slice started
746  * now would return immediately.
747  */
748 extern JS_PUBLIC_API bool IncrementalGCHasForegroundWork(JSContext* cx);
749 
750 /**
751  * If IsIncrementalGCInProgress(cx), this call finishes the ongoing collection
752  * by performing an arbitrarily long slice. If !IsIncrementalGCInProgress(cx),
753  * this is equivalent to NonIncrementalGC. When this function returns,
754  * IsIncrementalGCInProgress(cx) will always be false.
755  */
756 extern JS_PUBLIC_API void FinishIncrementalGC(JSContext* cx, GCReason reason);
757 
758 /**
759  * If IsIncrementalGCInProgress(cx), this call aborts the ongoing collection and
760  * performs whatever work needs to be done to return the collector to its idle
761  * state. This may take an arbitrarily long time. When this function returns,
762  * IsIncrementalGCInProgress(cx) will always be false.
763  */
764 extern JS_PUBLIC_API void AbortIncrementalGC(JSContext* cx);
765 
766 namespace dbg {
767 
768 // The `JS::dbg::GarbageCollectionEvent` class is essentially a view of the
769 // `js::gcstats::Statistics` data without the uber implementation-specific bits.
770 // It should generally be palatable for web developers.
771 class GarbageCollectionEvent {
772   // The major GC number of the GC cycle this data pertains to.
773   uint64_t majorGCNumber_;
774 
775   // Reference to a non-owned, statically allocated C string. This is a very
776   // short reason explaining why a GC was triggered.
777   const char* reason;
778 
779   // Reference to a nullable, non-owned, statically allocated C string. If the
780   // collection was forced to be non-incremental, this is a short reason of
781   // why the GC could not perform an incremental collection.
782   const char* nonincrementalReason;
783 
784   // Represents a single slice of a possibly multi-slice incremental garbage
785   // collection.
786   struct Collection {
787     mozilla::TimeStamp startTimestamp;
788     mozilla::TimeStamp endTimestamp;
789   };
790 
791   // The set of garbage collection slices that made up this GC cycle.
792   mozilla::Vector<Collection> collections;
793 
794   GarbageCollectionEvent(const GarbageCollectionEvent& rhs) = delete;
795   GarbageCollectionEvent& operator=(const GarbageCollectionEvent& rhs) = delete;
796 
797  public:
GarbageCollectionEvent(uint64_t majorGCNum)798   explicit GarbageCollectionEvent(uint64_t majorGCNum)
799       : majorGCNumber_(majorGCNum),
800         reason(nullptr),
801         nonincrementalReason(nullptr),
802         collections() {}
803 
804   using Ptr = js::UniquePtr<GarbageCollectionEvent>;
805   static Ptr Create(JSRuntime* rt, ::js::gcstats::Statistics& stats,
806                     uint64_t majorGCNumber);
807 
808   JSObject* toJSObject(JSContext* cx) const;
809 
majorGCNumber()810   uint64_t majorGCNumber() const { return majorGCNumber_; }
811 };
812 
813 }  // namespace dbg
814 
815 enum GCProgress {
816   /*
817    * During GC, the GC is bracketed by GC_CYCLE_BEGIN/END callbacks. Each
818    * slice between those (whether an incremental or the sole non-incremental
819    * slice) is bracketed by GC_SLICE_BEGIN/GC_SLICE_END.
820    */
821 
822   GC_CYCLE_BEGIN,
823   GC_SLICE_BEGIN,
824   GC_SLICE_END,
825   GC_CYCLE_END
826 };
827 
828 struct JS_PUBLIC_API GCDescription {
829   bool isZone_;
830   bool isComplete_;
831   JS::GCOptions options_;
832   GCReason reason_;
833 
GCDescriptionGCDescription834   GCDescription(bool isZone, bool isComplete, JS::GCOptions options,
835                 GCReason reason)
836       : isZone_(isZone),
837         isComplete_(isComplete),
838         options_(options),
839         reason_(reason) {}
840 
841   char16_t* formatSliceMessage(JSContext* cx) const;
842   char16_t* formatSummaryMessage(JSContext* cx) const;
843 
844   mozilla::TimeStamp startTime(JSContext* cx) const;
845   mozilla::TimeStamp endTime(JSContext* cx) const;
846   mozilla::TimeStamp lastSliceStart(JSContext* cx) const;
847   mozilla::TimeStamp lastSliceEnd(JSContext* cx) const;
848 
849   JS::UniqueChars sliceToJSONProfiler(JSContext* cx) const;
850   JS::UniqueChars formatJSONProfiler(JSContext* cx) const;
851 
852   JS::dbg::GarbageCollectionEvent::Ptr toGCEvent(JSContext* cx) const;
853 };
854 
855 extern JS_PUBLIC_API UniqueChars MinorGcToJSON(JSContext* cx);
856 
857 typedef void (*GCSliceCallback)(JSContext* cx, GCProgress progress,
858                                 const GCDescription& desc);
859 
860 /**
861  * The GC slice callback is called at the beginning and end of each slice. This
862  * callback may be used for GC notifications as well as to perform additional
863  * marking.
864  */
865 extern JS_PUBLIC_API GCSliceCallback
866 SetGCSliceCallback(JSContext* cx, GCSliceCallback callback);
867 
868 /**
869  * Describes the progress of an observed nursery collection.
870  */
871 enum class GCNurseryProgress {
872   /**
873    * The nursery collection is starting.
874    */
875   GC_NURSERY_COLLECTION_START,
876   /**
877    * The nursery collection is ending.
878    */
879   GC_NURSERY_COLLECTION_END
880 };
881 
882 /**
883  * A nursery collection callback receives the progress of the nursery collection
884  * and the reason for the collection.
885  */
886 using GCNurseryCollectionCallback = void (*)(JSContext* cx,
887                                              GCNurseryProgress progress,
888                                              GCReason reason);
889 
890 /**
891  * Set the nursery collection callback for the given runtime. When set, it will
892  * be called at the start and end of every nursery collection.
893  */
894 extern JS_PUBLIC_API GCNurseryCollectionCallback SetGCNurseryCollectionCallback(
895     JSContext* cx, GCNurseryCollectionCallback callback);
896 
897 typedef void (*DoCycleCollectionCallback)(JSContext* cx);
898 
899 /**
900  * The purge gray callback is called after any COMPARTMENT_REVIVED GC in which
901  * the majority of compartments have been marked gray.
902  */
903 extern JS_PUBLIC_API DoCycleCollectionCallback
904 SetDoCycleCollectionCallback(JSContext* cx, DoCycleCollectionCallback callback);
905 
906 using CreateSliceBudgetCallback = js::SliceBudget (*)(JS::GCReason reason,
907                                                       int64_t millis);
908 
909 /**
910  * Called when generating a GC slice budget. It allows the embedding to control
911  * the duration of slices and potentially check an interrupt flag as well. For
912  * internally triggered GCs, the given millis parameter is the JS engine's
913  * internal scheduling decision, which the embedding can choose to ignore.
914  * (Otherwise, it will be the value that was passed to eg
915  * JS::IncrementalGCSlice()).
916  */
917 extern JS_PUBLIC_API void SetCreateGCSliceBudgetCallback(
918     JSContext* cx, CreateSliceBudgetCallback cb);
919 
920 /**
921  * Incremental GC defaults to enabled, but may be disabled for testing or in
922  * embeddings that have not yet implemented barriers on their native classes.
923  * There is not currently a way to re-enable incremental GC once it has been
924  * disabled on the runtime.
925  */
926 extern JS_PUBLIC_API void DisableIncrementalGC(JSContext* cx);
927 
928 /**
929  * Returns true if incremental GC is enabled. Simply having incremental GC
930  * enabled is not sufficient to ensure incremental collections are happening.
931  * See the comment "Incremental GC" above for reasons why incremental GC may be
932  * suppressed. Inspection of the "nonincremental reason" field of the
933  * GCDescription returned by GCSliceCallback may help narrow down the cause if
934  * collections are not happening incrementally when expected.
935  */
936 extern JS_PUBLIC_API bool IsIncrementalGCEnabled(JSContext* cx);
937 
938 /**
939  * Returns true while an incremental GC is ongoing, both when actively
940  * collecting and between slices.
941  */
942 extern JS_PUBLIC_API bool IsIncrementalGCInProgress(JSContext* cx);
943 
944 /**
945  * Returns true while an incremental GC is ongoing, both when actively
946  * collecting and between slices.
947  */
948 extern JS_PUBLIC_API bool IsIncrementalGCInProgress(JSRuntime* rt);
949 
950 /**
951  * Returns true if the most recent GC ran incrementally.
952  */
953 extern JS_PUBLIC_API bool WasIncrementalGC(JSRuntime* rt);
954 
955 /*
956  * Generational GC:
957  *
958  * Note: Generational GC is not yet enabled by default. The following class
959  *       is non-functional unless SpiderMonkey was configured with
960  *       --enable-gcgenerational.
961  */
962 
963 /** Ensure that generational GC is disabled within some scope. */
964 class JS_PUBLIC_API AutoDisableGenerationalGC {
965   JSContext* cx;
966 
967  public:
968   explicit AutoDisableGenerationalGC(JSContext* cx);
969   ~AutoDisableGenerationalGC();
970 };
971 
972 /**
973  * Returns true if generational allocation and collection is currently enabled
974  * on the given runtime.
975  */
976 extern JS_PUBLIC_API bool IsGenerationalGCEnabled(JSRuntime* rt);
977 
978 /**
979  * Enable or disable support for pretenuring allocations based on their
980  * allocation site.
981  */
982 extern JS_PUBLIC_API void SetSiteBasedPretenuringEnabled(bool enable);
983 
984 /**
985  * Pass a subclass of this "abstract" class to callees to require that they
986  * never GC. Subclasses can use assertions or the hazard analysis to ensure no
987  * GC happens.
988  */
989 class JS_PUBLIC_API AutoRequireNoGC {
990  protected:
991   AutoRequireNoGC() = default;
992   ~AutoRequireNoGC() = default;
993 };
994 
995 /**
996  * Diagnostic assert (see MOZ_DIAGNOSTIC_ASSERT) that GC cannot occur while this
997  * class is live. This class does not disable the static rooting hazard
998  * analysis.
999  *
1000  * This works by entering a GC unsafe region, which is checked on allocation and
1001  * on GC.
1002  */
1003 class JS_PUBLIC_API AutoAssertNoGC : public AutoRequireNoGC {
1004 #ifdef MOZ_DIAGNOSTIC_ASSERT_ENABLED
1005  protected:
1006   JSContext* cx_;
1007 
1008  public:
1009   // This gets the context from TLS if it is not passed in.
1010   explicit AutoAssertNoGC(JSContext* cx = nullptr);
1011   ~AutoAssertNoGC();
1012 #else
1013  public:
1014   explicit AutoAssertNoGC(JSContext* cx = nullptr) {}
1015   ~AutoAssertNoGC() {}
1016 #endif
1017 };
1018 
1019 /**
1020  * Disable the static rooting hazard analysis in the live region and assert in
1021  * debug builds if any allocation that could potentially trigger a GC occurs
1022  * while this guard object is live. This is most useful to help the exact
1023  * rooting hazard analysis in complex regions, since it cannot understand
1024  * dataflow.
1025  *
1026  * Note: GC behavior is unpredictable even when deterministic and is generally
1027  *       non-deterministic in practice. The fact that this guard has not
1028  *       asserted is not a guarantee that a GC cannot happen in the guarded
1029  *       region. As a rule, anyone performing a GC unsafe action should
1030  *       understand the GC properties of all code in that region and ensure
1031  *       that the hazard analysis is correct for that code, rather than relying
1032  *       on this class.
1033  */
1034 #ifdef DEBUG
1035 class JS_PUBLIC_API AutoSuppressGCAnalysis : public AutoAssertNoGC {
1036  public:
1037   explicit AutoSuppressGCAnalysis(JSContext* cx = nullptr)
AutoAssertNoGC(cx)1038       : AutoAssertNoGC(cx) {}
1039 } JS_HAZ_GC_SUPPRESSED;
1040 #else
1041 class JS_PUBLIC_API AutoSuppressGCAnalysis : public AutoRequireNoGC {
1042  public:
1043   explicit AutoSuppressGCAnalysis(JSContext* cx = nullptr) {}
1044 } JS_HAZ_GC_SUPPRESSED;
1045 #endif
1046 
1047 /**
1048  * Assert that code is only ever called from a GC callback, disable the static
1049  * rooting hazard analysis and assert if any allocation that could potentially
1050  * trigger a GC occurs while this guard object is live.
1051  *
1052  * This is useful to make the static analysis ignore code that runs in GC
1053  * callbacks.
1054  */
1055 class JS_PUBLIC_API AutoAssertGCCallback : public AutoSuppressGCAnalysis {
1056  public:
1057 #ifdef DEBUG
1058   AutoAssertGCCallback();
1059 #else
1060   AutoAssertGCCallback() {}
1061 #endif
1062 };
1063 
1064 /**
1065  * Place AutoCheckCannotGC in scopes that you believe can never GC. These
1066  * annotations will be verified both dynamically via AutoAssertNoGC, and
1067  * statically with the rooting hazard analysis (implemented by making the
1068  * analysis consider AutoCheckCannotGC to be a GC pointer, and therefore
1069  * complain if it is live across a GC call.) It is useful when dealing with
1070  * internal pointers to GC things where the GC thing itself may not be present
1071  * for the static analysis: e.g. acquiring inline chars from a JSString* on the
1072  * heap.
1073  *
1074  * We only do the assertion checking in DEBUG builds.
1075  */
1076 #ifdef DEBUG
1077 class JS_PUBLIC_API AutoCheckCannotGC : public AutoAssertNoGC {
1078  public:
AutoAssertNoGC(cx)1079   explicit AutoCheckCannotGC(JSContext* cx = nullptr) : AutoAssertNoGC(cx) {}
1080 #  ifdef MOZ_DIAGNOSTIC_ASSERT_ENABLED
AutoCheckCannotGC(const AutoCheckCannotGC & other)1081   AutoCheckCannotGC(const AutoCheckCannotGC& other)
1082       : AutoCheckCannotGC(other.cx_) {}
1083 #  else
AutoCheckCannotGC(const AutoCheckCannotGC & other)1084   AutoCheckCannotGC(const AutoCheckCannotGC& other) : AutoCheckCannotGC() {}
1085 #  endif
1086 #else
1087 class JS_PUBLIC_API AutoCheckCannotGC : public AutoRequireNoGC{
1088   public :
1089       explicit AutoCheckCannotGC(JSContext* cx = nullptr){} AutoCheckCannotGC(
1090           const AutoCheckCannotGC& other) : AutoCheckCannotGC(){}
1091 #endif
1092 } JS_HAZ_GC_INVALIDATED;
1093 
1094 extern JS_PUBLIC_API void SetLowMemoryState(JSContext* cx, bool newState);
1095 
1096 /*
1097  * Internal to Firefox.
1098  */
1099 extern JS_PUBLIC_API void NotifyGCRootsRemoved(JSContext* cx);
1100 
1101 } /* namespace JS */
1102 
1103 typedef void (*JSGCCallback)(JSContext* cx, JSGCStatus status,
1104                              JS::GCReason reason, void* data);
1105 
1106 /**
1107  * Register externally maintained GC roots.
1108  *
1109  * traceOp: the trace operation. For each root the implementation should call
1110  *          JS::TraceEdge whenever the root contains a traceable thing.
1111  * data:    the data argument to pass to each invocation of traceOp.
1112  */
1113 extern JS_PUBLIC_API bool JS_AddExtraGCRootsTracer(JSContext* cx,
1114                                                    JSTraceDataOp traceOp,
1115                                                    void* data);
1116 
1117 /** Undo a call to JS_AddExtraGCRootsTracer. */
1118 extern JS_PUBLIC_API void JS_RemoveExtraGCRootsTracer(JSContext* cx,
1119                                                       JSTraceDataOp traceOp,
1120                                                       void* data);
1121 
1122 extern JS_PUBLIC_API void JS_GC(JSContext* cx,
1123                                 JS::GCReason reason = JS::GCReason::API);
1124 
1125 extern JS_PUBLIC_API void JS_MaybeGC(JSContext* cx);
1126 
1127 extern JS_PUBLIC_API void JS_SetGCCallback(JSContext* cx, JSGCCallback cb,
1128                                            void* data);
1129 
1130 extern JS_PUBLIC_API void JS_SetObjectsTenuredCallback(
1131     JSContext* cx, JSObjectsTenuredCallback cb, void* data);
1132 
1133 extern JS_PUBLIC_API bool JS_AddFinalizeCallback(JSContext* cx,
1134                                                  JSFinalizeCallback cb,
1135                                                  void* data);
1136 
1137 extern JS_PUBLIC_API void JS_RemoveFinalizeCallback(JSContext* cx,
1138                                                     JSFinalizeCallback cb);
1139 
1140 /*
1141  * Weak pointers and garbage collection
1142  *
1143  * Weak pointers are by their nature not marked as part of garbage collection,
1144  * but they may need to be updated in two cases after a GC:
1145  *
1146  *  1) Their referent was found not to be live and is about to be finalized
1147  *  2) Their referent has been moved by a compacting GC
1148  *
1149  * To handle this, any part of the system that maintain weak pointers to
1150  * JavaScript GC things must register a callback with
1151  * JS_(Add,Remove)WeakPointer{ZoneGroup,Compartment}Callback(). This callback
1152  * must then call JS_UpdateWeakPointerAfterGC() on all weak pointers it knows
1153  * about.
1154  *
1155  * Since sweeping is incremental, we have several callbacks to avoid repeatedly
1156  * having to visit all embedder structures. The WeakPointerZonesCallback is
1157  * called once for each strongly connected group of zones, whereas the
1158  * WeakPointerCompartmentCallback is called once for each compartment that is
1159  * visited while sweeping. Structures that cannot contain references in more
1160  * than one compartment should sweep the relevant per-compartment structures
1161  * using the latter callback to minimizer per-slice overhead.
1162  *
1163  * The argument to JS_UpdateWeakPointerAfterGC() is an in-out param. If the
1164  * referent is about to be finalized the pointer will be set to null. If the
1165  * referent has been moved then the pointer will be updated to point to the new
1166  * location.
1167  *
1168  * The return value of JS_UpdateWeakPointerAfterGC() indicates whether the
1169  * referent is still alive. If the referent is is about to be finalized, this
1170  * will return false.
1171  *
1172  * Callers of this method are responsible for updating any state that is
1173  * dependent on the object's address. For example, if the object's address is
1174  * used as a key in a hashtable, then the object must be removed and
1175  * re-inserted with the correct hash.
1176  */
1177 
1178 extern JS_PUBLIC_API bool JS_AddWeakPointerZonesCallback(
1179     JSContext* cx, JSWeakPointerZonesCallback cb, void* data);
1180 
1181 extern JS_PUBLIC_API void JS_RemoveWeakPointerZonesCallback(
1182     JSContext* cx, JSWeakPointerZonesCallback cb);
1183 
1184 extern JS_PUBLIC_API bool JS_AddWeakPointerCompartmentCallback(
1185     JSContext* cx, JSWeakPointerCompartmentCallback cb, void* data);
1186 
1187 extern JS_PUBLIC_API void JS_RemoveWeakPointerCompartmentCallback(
1188     JSContext* cx, JSWeakPointerCompartmentCallback cb);
1189 
1190 namespace JS {
1191 template <typename T>
1192 class Heap;
1193 }
1194 
1195 extern JS_PUBLIC_API bool JS_UpdateWeakPointerAfterGC(
1196     JSTracer* trc, JS::Heap<JSObject*>* objp);
1197 
1198 extern JS_PUBLIC_API bool JS_UpdateWeakPointerAfterGCUnbarriered(
1199     JSTracer* trc, JSObject** objp);
1200 
1201 extern JS_PUBLIC_API void JS_SetGCParameter(JSContext* cx, JSGCParamKey key,
1202                                             uint32_t value);
1203 
1204 extern JS_PUBLIC_API void JS_ResetGCParameter(JSContext* cx, JSGCParamKey key);
1205 
1206 extern JS_PUBLIC_API uint32_t JS_GetGCParameter(JSContext* cx,
1207                                                 JSGCParamKey key);
1208 
1209 extern JS_PUBLIC_API void JS_SetGCParametersBasedOnAvailableMemory(
1210     JSContext* cx, uint32_t availMemMB);
1211 
1212 /**
1213  * Create a new JSString whose chars member refers to external memory, i.e.,
1214  * memory requiring application-specific finalization.
1215  */
1216 extern JS_PUBLIC_API JSString* JS_NewExternalString(
1217     JSContext* cx, const char16_t* chars, size_t length,
1218     const JSExternalStringCallbacks* callbacks);
1219 
1220 /**
1221  * Create a new JSString whose chars member may refer to external memory.
1222  * If a new external string is allocated, |*allocatedExternal| is set to true.
1223  * Otherwise the returned string is either not an external string or an
1224  * external string allocated by a previous call and |*allocatedExternal| is set
1225  * to false. If |*allocatedExternal| is false, |fin| won't be called.
1226  */
1227 extern JS_PUBLIC_API JSString* JS_NewMaybeExternalString(
1228     JSContext* cx, const char16_t* chars, size_t length,
1229     const JSExternalStringCallbacks* callbacks, bool* allocatedExternal);
1230 
1231 /**
1232  * Return the 'callbacks' arg passed to JS_NewExternalString or
1233  * JS_NewMaybeExternalString.
1234  */
1235 extern JS_PUBLIC_API const JSExternalStringCallbacks*
1236 JS_GetExternalStringCallbacks(JSString* str);
1237 
1238 namespace JS {
1239 
1240 extern JS_PUBLIC_API bool IsIdleGCTaskNeeded(JSRuntime* rt);
1241 
1242 extern JS_PUBLIC_API void RunIdleTimeGCTask(JSRuntime* rt);
1243 
1244 extern JS_PUBLIC_API void SetHostCleanupFinalizationRegistryCallback(
1245     JSContext* cx, JSHostCleanupFinalizationRegistryCallback cb, void* data);
1246 
1247 /**
1248  * Clear kept alive objects in JS WeakRef.
1249  * https://tc39.es/proposal-weakrefs/#sec-clear-kept-objects
1250  */
1251 extern JS_PUBLIC_API void ClearKeptObjects(JSContext* cx);
1252 
NeedGrayRootsForZone(Zone * zoneArg)1253 inline JS_PUBLIC_API bool NeedGrayRootsForZone(Zone* zoneArg) {
1254   shadow::Zone* zone = shadow::Zone::from(zoneArg);
1255   return zone->isGCMarkingBlackAndGray() || zone->isGCCompacting();
1256 }
1257 
1258 extern JS_PUBLIC_API bool AtomsZoneIsCollecting(JSRuntime* runtime);
1259 extern JS_PUBLIC_API bool IsAtomsZone(Zone* zone);
1260 
1261 }  // namespace JS
1262 
1263 namespace js {
1264 namespace gc {
1265 
1266 /**
1267  * Create an object providing access to the garbage collector's internal notion
1268  * of the current state of memory (both GC heap memory and GCthing-controlled
1269  * malloc memory.
1270  */
1271 extern JS_PUBLIC_API JSObject* NewMemoryInfoObject(JSContext* cx);
1272 
1273 /*
1274  * Run the finalizer of a nursery-allocated JSObject that is known to be dead.
1275  *
1276  * This is a dangerous operation - only use this if you know what you're doing!
1277  *
1278  * This is used by the browser to implement nursery-allocated wrapper cached
1279  * wrappers.
1280  */
1281 extern JS_PUBLIC_API void FinalizeDeadNurseryObject(JSContext* cx,
1282                                                     JSObject* obj);
1283 
1284 } /* namespace gc */
1285 } /* namespace js */
1286 
1287 #ifdef JS_GC_ZEAL
1288 
1289 #  define JS_DEFAULT_ZEAL_FREQ 100
1290 
1291 extern JS_PUBLIC_API void JS_GetGCZealBits(JSContext* cx, uint32_t* zealBits,
1292                                            uint32_t* frequency,
1293                                            uint32_t* nextScheduled);
1294 
1295 extern JS_PUBLIC_API void JS_SetGCZeal(JSContext* cx, uint8_t zeal,
1296                                        uint32_t frequency);
1297 
1298 extern JS_PUBLIC_API void JS_UnsetGCZeal(JSContext* cx, uint8_t zeal);
1299 
1300 extern JS_PUBLIC_API void JS_ScheduleGC(JSContext* cx, uint32_t count);
1301 
1302 #endif
1303 
1304 #endif /* js_GCAPI_h */
1305