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