Bug 1568151 - Replace `target.getInspector()` by `target.getFront("inspector")`....
[gecko.git] / js / public / GCAPI.h
blob31eaba4a7b72992144ea36456132e7c052f2a215
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/. */
7 /*
8 * High-level interface to the JS garbage collector.
9 */
11 #ifndef js_GCAPI_h
12 #define js_GCAPI_h
14 #include "mozilla/TimeStamp.h"
15 #include "mozilla/Vector.h"
17 #include "js/GCAnnotations.h"
18 #include "js/TypeDecls.h"
19 #include "js/UniquePtr.h"
20 #include "js/Utility.h"
22 struct JSFreeOp;
24 #ifdef JS_BROKEN_GCC_ATTRIBUTE_WARNING
25 # pragma GCC diagnostic push
26 # pragma GCC diagnostic ignored "-Wattributes"
27 #endif // JS_BROKEN_GCC_ATTRIBUTE_WARNING
29 class JS_PUBLIC_API JSTracer;
31 #ifdef JS_BROKEN_GCC_ATTRIBUTE_WARNING
32 # pragma GCC diagnostic pop
33 #endif // JS_BROKEN_GCC_ATTRIBUTE_WARNING
35 namespace js {
36 namespace gc {
37 class GCRuntime;
38 } // namespace gc
39 namespace gcstats {
40 struct Statistics;
41 } // namespace gcstats
42 } // namespace js
44 typedef enum JSGCMode {
45 /** Perform only global GCs. */
46 JSGC_MODE_GLOBAL = 0,
48 /** Perform per-zone GCs until too much garbage has accumulated. */
49 JSGC_MODE_ZONE = 1,
51 /** Collect in short time slices rather than all at once. */
52 JSGC_MODE_INCREMENTAL = 2,
54 /** Both of the above. */
55 JSGC_MODE_ZONE_INCREMENTAL = 3,
56 } JSGCMode;
58 /**
59 * Kinds of js_GC invocation.
61 typedef enum JSGCInvocationKind {
62 /* Normal invocation. */
63 GC_NORMAL = 0,
65 /* Minimize GC triggers and release empty GC chunks right away. */
66 GC_SHRINK = 1
67 } JSGCInvocationKind;
69 typedef enum JSGCParamKey {
70 /**
71 * Maximum nominal heap before last ditch GC.
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.
78 * Pref: javascript.options.mem.max
79 * Default: 0xffffffff
81 JSGC_MAX_BYTES = 0,
83 /**
84 * Maximum size of the generational GC nurseries.
86 * This will be rounded to the nearest gc::ChunkSize.
88 * Pref: javascript.options.mem.nursery.max_kb
89 * Default: JS::DefaultNurseryBytes
91 JSGC_MAX_NURSERY_BYTES = 2,
93 /** Amount of bytes allocated by the GC. */
94 JSGC_BYTES = 3,
96 /** Number of times GC has been invoked. Includes both major and minor GC. */
97 JSGC_NUMBER = 4,
99 /**
100 * Select GC mode.
102 * See: JSGCMode in GCAPI.h
103 * prefs: javascript.options.mem.gc_per_zone and
104 * javascript.options.mem.gc_incremental.
105 * Default: JSGC_MODE_ZONE_INCREMENTAL
107 JSGC_MODE = 6,
109 /** Number of cached empty GC chunks. */
110 JSGC_UNUSED_CHUNKS = 7,
112 /** Total number of allocated GC chunks. */
113 JSGC_TOTAL_CHUNKS = 8,
116 * Max milliseconds to spend in an incremental GC slice.
118 * Pref: javascript.options.mem.gc_incremental_slice_ms
119 * Default: DefaultTimeBudgetMS.
121 JSGC_SLICE_TIME_BUDGET_MS = 9,
124 * Maximum size the GC mark stack can grow to.
126 * Pref: none
127 * Default: MarkStack::DefaultCapacity
129 JSGC_MARK_STACK_LIMIT = 10,
132 * The "do we collect?" decision depends on various parameters and can be
133 * summarised as:
135 * ZoneSize * 1/UsageFactor > Max(ThresholdBase, LastSize) * GrowthFactor
137 * Where
138 * ZoneSize: Current size of this zone.
139 * LastSize: Heap size immediately after the most recent collection.
140 * ThresholdBase: The JSGC_ALLOCATION_THRESHOLD parameter
141 * GrowthFactor: A number above 1, calculated based on some of the
142 * following parameters.
143 * See computeZoneHeapGrowthFactorForHeapSize() in GC.cpp
144 * UsageFactor: JSGC_ALLOCATION_THRESHOLD_FACTOR or
145 * JSGC_ALLOCATION_THRESHOLD_FACTOR_AVOID_INTERRUPT or 1.0 for
146 * non-incremental collections.
148 * The RHS of the equation above is calculated and sets
149 * zone->threshold.gcTriggerBytes(). When usage.gcBytes() surpasses
150 * threshold.gcTriggerBytes() for a zone, the zone may be scheduled for a GC.
154 * GCs less than this far apart in milliseconds will be considered
155 * 'high-frequency GCs'.
157 * Pref: javascript.options.mem.gc_high_frequency_time_limit_ms
158 * Default: HighFrequencyThreshold
160 JSGC_HIGH_FREQUENCY_TIME_LIMIT = 11,
163 * Start of dynamic heap growth (MB).
165 * Pref: javascript.options.mem.gc_high_frequency_low_limit_mb
166 * Default: HighFrequencyLowLimitBytes
168 JSGC_HIGH_FREQUENCY_LOW_LIMIT = 12,
171 * End of dynamic heap growth (MB).
173 * Pref: javascript.options.mem.gc_high_frequency_high_limit_mb
174 * Default: HighFrequencyHighLimitBytes
176 JSGC_HIGH_FREQUENCY_HIGH_LIMIT = 13,
179 * Upper bound of heap growth percentage.
181 * Pref: javascript.options.mem.gc_high_frequency_heap_growth_max
182 * Default: HighFrequencyHeapGrowthMax
184 JSGC_HIGH_FREQUENCY_HEAP_GROWTH_MAX = 14,
187 * Lower bound of heap growth percentage.
189 * Pref: javascript.options.mem.gc_high_frequency_heap_growth_min
190 * Default: HighFrequencyHeapGrowthMin
192 JSGC_HIGH_FREQUENCY_HEAP_GROWTH_MIN = 15,
195 * Heap growth percentage for low frequency GCs.
197 * Pref: javascript.options.mem.gc_low_frequency_heap_growth
198 * Default: LowFrequencyHeapGrowth
200 JSGC_LOW_FREQUENCY_HEAP_GROWTH = 16,
203 * If false, the heap growth factor is fixed at 3. If true, it is determined
204 * based on whether GCs are high- or low- frequency.
206 * Pref: javascript.options.mem.gc_dynamic_heap_growth
207 * Default: DynamicHeapGrowthEnabled
209 JSGC_DYNAMIC_HEAP_GROWTH = 17,
212 * If true, high-frequency GCs will use a longer mark slice.
214 * Pref: javascript.options.mem.gc_dynamic_mark_slice
215 * Default: DynamicMarkSliceEnabled
217 JSGC_DYNAMIC_MARK_SLICE = 18,
220 * Lower limit for collecting a zone.
222 * Zones smaller than this size will not normally be collected.
224 * Pref: javascript.options.mem.gc_allocation_threshold_mb
225 * Default GCZoneAllocThresholdBase
227 JSGC_ALLOCATION_THRESHOLD = 19,
230 * We try to keep at least this many unused chunks in the free chunk pool at
231 * all times, even after a shrinking GC.
233 * Pref: javascript.options.mem.gc_min_empty_chunk_count
234 * Default: MinEmptyChunkCount
236 JSGC_MIN_EMPTY_CHUNK_COUNT = 21,
239 * We never keep more than this many unused chunks in the free chunk
240 * pool.
242 * Pref: javascript.options.mem.gc_min_empty_chunk_count
243 * Default: MinEmptyChunkCount
245 JSGC_MAX_EMPTY_CHUNK_COUNT = 22,
248 * Whether compacting GC is enabled.
250 * Pref: javascript.options.mem.gc_compacting
251 * Default: CompactingEnabled
253 JSGC_COMPACTING_ENABLED = 23,
256 * Percentage for triggering a GC based on zone->threshold.gcTriggerBytes().
258 * When the heap reaches this percentage of the allocation threshold an
259 * incremental collection is started.
261 * Default: ZoneAllocThresholdFactorDefault
262 * Pref: None
264 JSGC_ALLOCATION_THRESHOLD_FACTOR = 25,
267 * Percentage for triggering a GC based on zone->threshold.gcTriggerBytes().
269 * Used instead of the above percentage if if another GC (in different zones)
270 * is already running.
272 * Default: ZoneAllocThresholdFactorAvoidInterruptDefault
273 * Pref: None
275 JSGC_ALLOCATION_THRESHOLD_FACTOR_AVOID_INTERRUPT = 26,
278 * Attempt to run a minor GC in the idle time if the free space falls
279 * below this number of bytes.
281 * Default: NurseryChunkUsableSize / 4
282 * Pref: None
284 JSGC_NURSERY_FREE_THRESHOLD_FOR_IDLE_COLLECTION = 27,
287 * If this percentage of the nursery is tenured and the nursery is at least
288 * 4MB, then proceed to examine which groups we should pretenure.
290 * Default: PretenureThreshold
291 * Pref: None
293 JSGC_PRETENURE_THRESHOLD = 28,
296 * If the above condition is met, then any object group that tenures more than
297 * this number of objects will be pretenured (if it can be).
299 * Default: PretenureGroupThreshold
300 * Pref: None
302 JSGC_PRETENURE_GROUP_THRESHOLD = 29,
305 * Attempt to run a minor GC in the idle time if the free space falls
306 * below this percentage (from 0 to 99).
308 * Default: 25
309 * Pref: None
311 JSGC_NURSERY_FREE_THRESHOLD_FOR_IDLE_COLLECTION_PERCENT = 30,
314 * Minimum size of the generational GC nurseries.
316 * This value will be rounded to the nearest Nursery::SubChunkStep if below
317 * gc::ChunkSize, otherwise it'll be rounded to the nearest gc::ChunkSize.
319 * Default: Nursery::SubChunkLimit
320 * Pref: javascript.options.mem.nursery.min_kb
322 JSGC_MIN_NURSERY_BYTES = 31,
325 * The minimum time to allow between triggering last ditch GCs in seconds.
327 * Default: 60 seconds
328 * Pref: None
330 JSGC_MIN_LAST_DITCH_GC_PERIOD = 32,
333 * The delay (in heapsize kilobytes) between slices of an incremental GC.
335 * Default: ZoneAllocDelayBytes
337 JSGC_ZONE_ALLOC_DELAY_KB = 33,
340 * The current size of the nursery.
342 * read-only.
344 JSGC_NURSERY_BYTES = 34,
347 * Retained size base value for calculating malloc heap threshold.
349 * Default: MallocThresholdBase
351 JSGC_MALLOC_THRESHOLD_BASE = 35,
354 * Growth factor for calculating malloc heap threshold.
356 * Default: MallocGrowthFactor
358 JSGC_MALLOC_GROWTH_FACTOR = 36,
359 } JSGCParamKey;
362 * Generic trace operation that calls JS::TraceEdge on each traceable thing's
363 * location reachable from data.
365 typedef void (*JSTraceDataOp)(JSTracer* trc, void* data);
367 typedef enum JSGCStatus { JSGC_BEGIN, JSGC_END } JSGCStatus;
369 typedef void (*JSGCCallback)(JSContext* cx, JSGCStatus status, void* data);
371 typedef void (*JSObjectsTenuredCallback)(JSContext* cx, void* data);
373 typedef enum JSFinalizeStatus {
375 * Called when preparing to sweep a group of zones, before anything has been
376 * swept. The collector will not yield to the mutator before calling the
377 * callback with JSFINALIZE_GROUP_START status.
379 JSFINALIZE_GROUP_PREPARE,
382 * Called after preparing to sweep a group of zones. Weak references to
383 * unmarked things have been removed at this point, but no GC things have
384 * been swept. The collector may yield to the mutator after this point.
386 JSFINALIZE_GROUP_START,
389 * Called after sweeping a group of zones. All dead GC things have been
390 * swept at this point.
392 JSFINALIZE_GROUP_END,
395 * Called at the end of collection when everything has been swept.
397 JSFINALIZE_COLLECTION_END
398 } JSFinalizeStatus;
400 typedef void (*JSFinalizeCallback)(JSFreeOp* fop, JSFinalizeStatus status,
401 void* data);
403 typedef void (*JSWeakPointerZonesCallback)(JSContext* cx, void* data);
405 typedef void (*JSWeakPointerCompartmentCallback)(JSContext* cx,
406 JS::Compartment* comp,
407 void* data);
410 * Finalizes external strings created by JS_NewExternalString. The finalizer
411 * can be called off the main thread.
413 struct JSStringFinalizer {
414 void (*finalize)(const JSStringFinalizer* fin, char16_t* chars);
417 namespace JS {
419 #define GCREASONS(D) \
420 /* Reasons internal to the JS engine */ \
421 D(API, 0) \
422 D(EAGER_ALLOC_TRIGGER, 1) \
423 D(DESTROY_RUNTIME, 2) \
424 D(ROOTS_REMOVED, 3) \
425 D(LAST_DITCH, 4) \
426 D(TOO_MUCH_MALLOC, 5) \
427 D(ALLOC_TRIGGER, 6) \
428 D(DEBUG_GC, 7) \
429 D(COMPARTMENT_REVIVED, 8) \
430 D(RESET, 9) \
431 D(OUT_OF_NURSERY, 10) \
432 D(EVICT_NURSERY, 11) \
433 D(DELAYED_ATOMS_GC, 12) \
434 D(SHARED_MEMORY_LIMIT, 13) \
435 D(IDLE_TIME_COLLECTION, 14) \
436 D(INCREMENTAL_TOO_SLOW, 15) \
437 D(ABORT_GC, 16) \
438 D(FULL_WHOLE_CELL_BUFFER, 17) \
439 D(FULL_GENERIC_BUFFER, 18) \
440 D(FULL_VALUE_BUFFER, 19) \
441 D(FULL_CELL_PTR_OBJ_BUFFER, 20) \
442 D(FULL_SLOT_BUFFER, 21) \
443 D(FULL_SHAPE_BUFFER, 22) \
444 D(TOO_MUCH_WASM_MEMORY, 23) \
445 D(DISABLE_GENERATIONAL_GC, 24) \
446 D(FINISH_GC, 25) \
447 D(PREPARE_FOR_TRACING, 26) \
448 D(INCREMENTAL_ALLOC_TRIGGER, 27) \
449 D(FULL_CELL_PTR_STR_BUFFER, 28) \
450 D(TOO_MUCH_JIT_CODE, 29) \
452 /* These are reserved for future use. */ \
453 D(RESERVED6, 30) \
454 D(RESERVED7, 31) \
455 D(RESERVED8, 32) \
457 /* Reasons from Firefox */ \
458 D(DOM_WINDOW_UTILS, 33) \
459 D(COMPONENT_UTILS, 34) \
460 D(MEM_PRESSURE, 35) \
461 D(CC_WAITING, 36) \
462 D(CC_FORCED, 37) \
463 D(LOAD_END, 38) \
464 D(UNUSED3, 39) \
465 D(PAGE_HIDE, 40) \
466 D(NSJSCONTEXT_DESTROY, 41) \
467 D(WORKER_SHUTDOWN, 42) \
468 D(SET_DOC_SHELL, 43) \
469 D(DOM_UTILS, 44) \
470 D(DOM_IPC, 45) \
471 D(DOM_WORKER, 46) \
472 D(INTER_SLICE_GC, 47) \
473 D(UNUSED1, 48) \
474 D(FULL_GC_TIMER, 49) \
475 D(SHUTDOWN_CC, 50) \
476 D(UNUSED2, 51) \
477 D(USER_INACTIVE, 52) \
478 D(XPCONNECT_SHUTDOWN, 53) \
479 D(DOCSHELL, 54) \
480 D(HTML_PARSER, 55)
482 enum class GCReason {
483 #define MAKE_REASON(name, val) name = val,
484 GCREASONS(MAKE_REASON)
485 #undef MAKE_REASON
486 NO_REASON,
487 NUM_REASONS,
490 * For telemetry, we want to keep a fixed max bucket size over time so we
491 * don't have to switch histograms. 100 is conservative; but the cost of extra
492 * buckets seems to be low while the cost of switching histograms is high.
494 NUM_TELEMETRY_REASONS = 100
498 * Get a statically allocated C string explaining the given GC reason.
500 extern JS_PUBLIC_API const char* ExplainGCReason(JS::GCReason reason);
503 * Zone GC:
505 * SpiderMonkey's GC is capable of performing a collection on an arbitrary
506 * subset of the zones in the system. This allows an embedding to minimize
507 * collection time by only collecting zones that have run code recently,
508 * ignoring the parts of the heap that are unlikely to have changed.
510 * When triggering a GC using one of the functions below, it is first necessary
511 * to select the zones to be collected. To do this, you can call
512 * PrepareZoneForGC on each zone, or you can call PrepareForFullGC to select
513 * all zones. Failing to select any zone is an error.
517 * Schedule the given zone to be collected as part of the next GC.
519 extern JS_PUBLIC_API void PrepareZoneForGC(Zone* zone);
522 * Schedule all zones to be collected in the next GC.
524 extern JS_PUBLIC_API void PrepareForFullGC(JSContext* cx);
527 * When performing an incremental GC, the zones that were selected for the
528 * previous incremental slice must be selected in subsequent slices as well.
529 * This function selects those slices automatically.
531 extern JS_PUBLIC_API void PrepareForIncrementalGC(JSContext* cx);
534 * Returns true if any zone in the system has been scheduled for GC with one of
535 * the functions above or by the JS engine.
537 extern JS_PUBLIC_API bool IsGCScheduled(JSContext* cx);
540 * Undoes the effect of the Prepare methods above. The given zone will not be
541 * collected in the next GC.
543 extern JS_PUBLIC_API void SkipZoneForGC(Zone* zone);
546 * Non-Incremental GC:
548 * The following functions perform a non-incremental GC.
552 * Performs a non-incremental collection of all selected zones.
554 * If the gckind argument is GC_NORMAL, then some objects that are unreachable
555 * from the program may still be alive afterwards because of internal
556 * references; if GC_SHRINK is passed then caches and other temporary references
557 * to objects will be cleared and all unreferenced objects will be removed from
558 * the system.
560 extern JS_PUBLIC_API void NonIncrementalGC(JSContext* cx,
561 JSGCInvocationKind gckind,
562 GCReason reason);
565 * Incremental GC:
567 * Incremental GC divides the full mark-and-sweep collection into multiple
568 * slices, allowing client JavaScript code to run between each slice. This
569 * allows interactive apps to avoid long collection pauses. Incremental GC does
570 * not make collection take less time, it merely spreads that time out so that
571 * the pauses are less noticable.
573 * For a collection to be carried out incrementally the following conditions
574 * must be met:
575 * - The collection must be run by calling JS::IncrementalGC() rather than
576 * JS_GC().
577 * - The GC mode must have been set to JSGC_MODE_INCREMENTAL or
578 * JSGC_MODE_ZONE_INCREMENTAL with JS_SetGCParameter().
580 * Note: Even if incremental GC is enabled and working correctly,
581 * non-incremental collections can still happen when low on memory.
585 * Begin an incremental collection and perform one slice worth of work. When
586 * this function returns, the collection may not be complete.
587 * IncrementalGCSlice() must be called repeatedly until
588 * !IsIncrementalGCInProgress(cx).
590 * Note: SpiderMonkey's GC is not realtime. Slices in practice may be longer or
591 * shorter than the requested interval.
593 extern JS_PUBLIC_API void StartIncrementalGC(JSContext* cx,
594 JSGCInvocationKind gckind,
595 GCReason reason,
596 int64_t millis = 0);
599 * Perform a slice of an ongoing incremental collection. When this function
600 * returns, the collection may not be complete. It must be called repeatedly
601 * until !IsIncrementalGCInProgress(cx).
603 * Note: SpiderMonkey's GC is not realtime. Slices in practice may be longer or
604 * shorter than the requested interval.
606 extern JS_PUBLIC_API void IncrementalGCSlice(JSContext* cx, GCReason reason,
607 int64_t millis = 0);
610 * Return whether an incremental GC has work to do on the foreground thread and
611 * would make progress if a slice was run now. If this returns false then the GC
612 * is waiting for background threads to finish their work and a slice started
613 * now would return immediately.
615 extern JS_PUBLIC_API bool IncrementalGCHasForegroundWork(JSContext* cx);
618 * If IsIncrementalGCInProgress(cx), this call finishes the ongoing collection
619 * by performing an arbitrarily long slice. If !IsIncrementalGCInProgress(cx),
620 * this is equivalent to NonIncrementalGC. When this function returns,
621 * IsIncrementalGCInProgress(cx) will always be false.
623 extern JS_PUBLIC_API void FinishIncrementalGC(JSContext* cx, GCReason reason);
626 * If IsIncrementalGCInProgress(cx), this call aborts the ongoing collection and
627 * performs whatever work needs to be done to return the collector to its idle
628 * state. This may take an arbitrarily long time. When this function returns,
629 * IsIncrementalGCInProgress(cx) will always be false.
631 extern JS_PUBLIC_API void AbortIncrementalGC(JSContext* cx);
633 namespace dbg {
635 // The `JS::dbg::GarbageCollectionEvent` class is essentially a view of the
636 // `js::gcstats::Statistics` data without the uber implementation-specific bits.
637 // It should generally be palatable for web developers.
638 class GarbageCollectionEvent {
639 // The major GC number of the GC cycle this data pertains to.
640 uint64_t majorGCNumber_;
642 // Reference to a non-owned, statically allocated C string. This is a very
643 // short reason explaining why a GC was triggered.
644 const char* reason;
646 // Reference to a nullable, non-owned, statically allocated C string. If the
647 // collection was forced to be non-incremental, this is a short reason of
648 // why the GC could not perform an incremental collection.
649 const char* nonincrementalReason;
651 // Represents a single slice of a possibly multi-slice incremental garbage
652 // collection.
653 struct Collection {
654 mozilla::TimeStamp startTimestamp;
655 mozilla::TimeStamp endTimestamp;
658 // The set of garbage collection slices that made up this GC cycle.
659 mozilla::Vector<Collection> collections;
661 GarbageCollectionEvent(const GarbageCollectionEvent& rhs) = delete;
662 GarbageCollectionEvent& operator=(const GarbageCollectionEvent& rhs) = delete;
664 public:
665 explicit GarbageCollectionEvent(uint64_t majorGCNum)
666 : majorGCNumber_(majorGCNum),
667 reason(nullptr),
668 nonincrementalReason(nullptr),
669 collections() {}
671 using Ptr = js::UniquePtr<GarbageCollectionEvent>;
672 static Ptr Create(JSRuntime* rt, ::js::gcstats::Statistics& stats,
673 uint64_t majorGCNumber);
675 JSObject* toJSObject(JSContext* cx) const;
677 uint64_t majorGCNumber() const { return majorGCNumber_; }
680 } // namespace dbg
682 enum GCProgress {
684 * During GC, the GC is bracketed by GC_CYCLE_BEGIN/END callbacks. Each
685 * slice between those (whether an incremental or the sole non-incremental
686 * slice) is bracketed by GC_SLICE_BEGIN/GC_SLICE_END.
689 GC_CYCLE_BEGIN,
690 GC_SLICE_BEGIN,
691 GC_SLICE_END,
692 GC_CYCLE_END
695 struct JS_PUBLIC_API GCDescription {
696 bool isZone_;
697 bool isComplete_;
698 JSGCInvocationKind invocationKind_;
699 GCReason reason_;
701 GCDescription(bool isZone, bool isComplete, JSGCInvocationKind kind,
702 GCReason reason)
703 : isZone_(isZone),
704 isComplete_(isComplete),
705 invocationKind_(kind),
706 reason_(reason) {}
708 char16_t* formatSliceMessage(JSContext* cx) const;
709 char16_t* formatSummaryMessage(JSContext* cx) const;
711 mozilla::TimeStamp startTime(JSContext* cx) const;
712 mozilla::TimeStamp endTime(JSContext* cx) const;
713 mozilla::TimeStamp lastSliceStart(JSContext* cx) const;
714 mozilla::TimeStamp lastSliceEnd(JSContext* cx) const;
716 char16_t* formatJSONTelemetry(JSContext* cx, uint64_t timestamp) const;
718 JS::UniqueChars sliceToJSONProfiler(JSContext* cx) const;
719 JS::UniqueChars formatJSONProfiler(JSContext* cx) const;
721 JS::dbg::GarbageCollectionEvent::Ptr toGCEvent(JSContext* cx) const;
724 extern JS_PUBLIC_API UniqueChars MinorGcToJSON(JSContext* cx);
726 typedef void (*GCSliceCallback)(JSContext* cx, GCProgress progress,
727 const GCDescription& desc);
730 * The GC slice callback is called at the beginning and end of each slice. This
731 * callback may be used for GC notifications as well as to perform additional
732 * marking.
734 extern JS_PUBLIC_API GCSliceCallback
735 SetGCSliceCallback(JSContext* cx, GCSliceCallback callback);
738 * Describes the progress of an observed nursery collection.
740 enum class GCNurseryProgress {
742 * The nursery collection is starting.
744 GC_NURSERY_COLLECTION_START,
746 * The nursery collection is ending.
748 GC_NURSERY_COLLECTION_END
752 * A nursery collection callback receives the progress of the nursery collection
753 * and the reason for the collection.
755 using GCNurseryCollectionCallback = void (*)(JSContext* cx,
756 GCNurseryProgress progress,
757 GCReason reason);
760 * Set the nursery collection callback for the given runtime. When set, it will
761 * be called at the start and end of every nursery collection.
763 extern JS_PUBLIC_API GCNurseryCollectionCallback SetGCNurseryCollectionCallback(
764 JSContext* cx, GCNurseryCollectionCallback callback);
766 typedef void (*DoCycleCollectionCallback)(JSContext* cx);
769 * The purge gray callback is called after any COMPARTMENT_REVIVED GC in which
770 * the majority of compartments have been marked gray.
772 extern JS_PUBLIC_API DoCycleCollectionCallback
773 SetDoCycleCollectionCallback(JSContext* cx, DoCycleCollectionCallback callback);
776 * Incremental GC defaults to enabled, but may be disabled for testing or in
777 * embeddings that have not yet implemented barriers on their native classes.
778 * There is not currently a way to re-enable incremental GC once it has been
779 * disabled on the runtime.
781 extern JS_PUBLIC_API void DisableIncrementalGC(JSContext* cx);
784 * Returns true if incremental GC is enabled. Simply having incremental GC
785 * enabled is not sufficient to ensure incremental collections are happening.
786 * See the comment "Incremental GC" above for reasons why incremental GC may be
787 * suppressed. Inspection of the "nonincremental reason" field of the
788 * GCDescription returned by GCSliceCallback may help narrow down the cause if
789 * collections are not happening incrementally when expected.
791 extern JS_PUBLIC_API bool IsIncrementalGCEnabled(JSContext* cx);
794 * Returns true while an incremental GC is ongoing, both when actively
795 * collecting and between slices.
797 extern JS_PUBLIC_API bool IsIncrementalGCInProgress(JSContext* cx);
800 * Returns true while an incremental GC is ongoing, both when actively
801 * collecting and between slices.
803 extern JS_PUBLIC_API bool IsIncrementalGCInProgress(JSRuntime* rt);
806 * Returns true if the most recent GC ran incrementally.
808 extern JS_PUBLIC_API bool WasIncrementalGC(JSRuntime* rt);
811 * Generational GC:
813 * Note: Generational GC is not yet enabled by default. The following class
814 * is non-functional unless SpiderMonkey was configured with
815 * --enable-gcgenerational.
818 /** Ensure that generational GC is disabled within some scope. */
819 class JS_PUBLIC_API AutoDisableGenerationalGC {
820 JSContext* cx;
822 public:
823 explicit AutoDisableGenerationalGC(JSContext* cx);
824 ~AutoDisableGenerationalGC();
828 * Returns true if generational allocation and collection is currently enabled
829 * on the given runtime.
831 extern JS_PUBLIC_API bool IsGenerationalGCEnabled(JSRuntime* rt);
834 * Pass a subclass of this "abstract" class to callees to require that they
835 * never GC. Subclasses can use assertions or the hazard analysis to ensure no
836 * GC happens.
838 class JS_PUBLIC_API AutoRequireNoGC {
839 protected:
840 AutoRequireNoGC() {}
841 ~AutoRequireNoGC() {}
845 * Diagnostic assert (see MOZ_DIAGNOSTIC_ASSERT) that GC cannot occur while this
846 * class is live. This class does not disable the static rooting hazard
847 * analysis.
849 * This works by entering a GC unsafe region, which is checked on allocation and
850 * on GC.
852 class JS_PUBLIC_API AutoAssertNoGC : public AutoRequireNoGC {
853 #ifdef MOZ_DIAGNOSTIC_ASSERT_ENABLED
854 JSContext* cx_;
856 public:
857 // This gets the context from TLS if it is not passed in.
858 explicit AutoAssertNoGC(JSContext* cx = nullptr);
859 ~AutoAssertNoGC();
860 #else
861 public:
862 explicit AutoAssertNoGC(JSContext* cx = nullptr) {}
863 ~AutoAssertNoGC() {}
864 #endif
868 * Disable the static rooting hazard analysis in the live region and assert in
869 * debug builds if any allocation that could potentially trigger a GC occurs
870 * while this guard object is live. This is most useful to help the exact
871 * rooting hazard analysis in complex regions, since it cannot understand
872 * dataflow.
874 * Note: GC behavior is unpredictable even when deterministic and is generally
875 * non-deterministic in practice. The fact that this guard has not
876 * asserted is not a guarantee that a GC cannot happen in the guarded
877 * region. As a rule, anyone performing a GC unsafe action should
878 * understand the GC properties of all code in that region and ensure
879 * that the hazard analysis is correct for that code, rather than relying
880 * on this class.
882 #ifdef DEBUG
883 class JS_PUBLIC_API AutoSuppressGCAnalysis : public AutoAssertNoGC {
884 public:
885 explicit AutoSuppressGCAnalysis(JSContext* cx = nullptr)
886 : AutoAssertNoGC(cx) {}
887 } JS_HAZ_GC_SUPPRESSED;
888 #else
889 class JS_PUBLIC_API AutoSuppressGCAnalysis : public AutoRequireNoGC {
890 public:
891 explicit AutoSuppressGCAnalysis(JSContext* cx = nullptr) {}
892 } JS_HAZ_GC_SUPPRESSED;
893 #endif
896 * Assert that code is only ever called from a GC callback, disable the static
897 * rooting hazard analysis and assert if any allocation that could potentially
898 * trigger a GC occurs while this guard object is live.
900 * This is useful to make the static analysis ignore code that runs in GC
901 * callbacks.
903 class JS_PUBLIC_API AutoAssertGCCallback : public AutoSuppressGCAnalysis {
904 public:
905 #ifdef DEBUG
906 AutoAssertGCCallback();
907 #else
908 AutoAssertGCCallback() {}
909 #endif
913 * Place AutoCheckCannotGC in scopes that you believe can never GC. These
914 * annotations will be verified both dynamically via AutoAssertNoGC, and
915 * statically with the rooting hazard analysis (implemented by making the
916 * analysis consider AutoCheckCannotGC to be a GC pointer, and therefore
917 * complain if it is live across a GC call.) It is useful when dealing with
918 * internal pointers to GC things where the GC thing itself may not be present
919 * for the static analysis: e.g. acquiring inline chars from a JSString* on the
920 * heap.
922 * We only do the assertion checking in DEBUG builds.
924 #ifdef DEBUG
925 class JS_PUBLIC_API AutoCheckCannotGC : public AutoAssertNoGC {
926 public:
927 explicit AutoCheckCannotGC(JSContext* cx = nullptr) : AutoAssertNoGC(cx) {}
928 } JS_HAZ_GC_INVALIDATED;
929 #else
930 class JS_PUBLIC_API AutoCheckCannotGC : public AutoRequireNoGC {
931 public:
932 explicit AutoCheckCannotGC(JSContext* cx = nullptr) {}
933 } JS_HAZ_GC_INVALIDATED;
934 #endif
936 extern JS_PUBLIC_API void SetLowMemoryState(JSContext* cx, bool newState);
939 * Internal to Firefox.
941 extern JS_FRIEND_API void NotifyGCRootsRemoved(JSContext* cx);
943 } /* namespace JS */
946 * Register externally maintained GC roots.
948 * traceOp: the trace operation. For each root the implementation should call
949 * JS::TraceEdge whenever the root contains a traceable thing.
950 * data: the data argument to pass to each invocation of traceOp.
952 extern JS_PUBLIC_API bool JS_AddExtraGCRootsTracer(JSContext* cx,
953 JSTraceDataOp traceOp,
954 void* data);
956 /** Undo a call to JS_AddExtraGCRootsTracer. */
957 extern JS_PUBLIC_API void JS_RemoveExtraGCRootsTracer(JSContext* cx,
958 JSTraceDataOp traceOp,
959 void* data);
961 extern JS_PUBLIC_API void JS_GC(JSContext* cx,
962 JS::GCReason reason = JS::GCReason::API);
964 extern JS_PUBLIC_API void JS_MaybeGC(JSContext* cx);
966 extern JS_PUBLIC_API void JS_SetGCCallback(JSContext* cx, JSGCCallback cb,
967 void* data);
969 extern JS_PUBLIC_API void JS_SetObjectsTenuredCallback(
970 JSContext* cx, JSObjectsTenuredCallback cb, void* data);
972 extern JS_PUBLIC_API bool JS_AddFinalizeCallback(JSContext* cx,
973 JSFinalizeCallback cb,
974 void* data);
976 extern JS_PUBLIC_API void JS_RemoveFinalizeCallback(JSContext* cx,
977 JSFinalizeCallback cb);
980 * Weak pointers and garbage collection
982 * Weak pointers are by their nature not marked as part of garbage collection,
983 * but they may need to be updated in two cases after a GC:
985 * 1) Their referent was found not to be live and is about to be finalized
986 * 2) Their referent has been moved by a compacting GC
988 * To handle this, any part of the system that maintain weak pointers to
989 * JavaScript GC things must register a callback with
990 * JS_(Add,Remove)WeakPointer{ZoneGroup,Compartment}Callback(). This callback
991 * must then call JS_UpdateWeakPointerAfterGC() on all weak pointers it knows
992 * about.
994 * Since sweeping is incremental, we have several callbacks to avoid repeatedly
995 * having to visit all embedder structures. The WeakPointerZonesCallback is
996 * called once for each strongly connected group of zones, whereas the
997 * WeakPointerCompartmentCallback is called once for each compartment that is
998 * visited while sweeping. Structures that cannot contain references in more
999 * than one compartment should sweep the relevant per-compartment structures
1000 * using the latter callback to minimizer per-slice overhead.
1002 * The argument to JS_UpdateWeakPointerAfterGC() is an in-out param. If the
1003 * referent is about to be finalized the pointer will be set to null. If the
1004 * referent has been moved then the pointer will be updated to point to the new
1005 * location.
1007 * Callers of this method are responsible for updating any state that is
1008 * dependent on the object's address. For example, if the object's address is
1009 * used as a key in a hashtable, then the object must be removed and
1010 * re-inserted with the correct hash.
1013 extern JS_PUBLIC_API bool JS_AddWeakPointerZonesCallback(
1014 JSContext* cx, JSWeakPointerZonesCallback cb, void* data);
1016 extern JS_PUBLIC_API void JS_RemoveWeakPointerZonesCallback(
1017 JSContext* cx, JSWeakPointerZonesCallback cb);
1019 extern JS_PUBLIC_API bool JS_AddWeakPointerCompartmentCallback(
1020 JSContext* cx, JSWeakPointerCompartmentCallback cb, void* data);
1022 extern JS_PUBLIC_API void JS_RemoveWeakPointerCompartmentCallback(
1023 JSContext* cx, JSWeakPointerCompartmentCallback cb);
1025 namespace JS {
1026 template <typename T>
1027 class Heap;
1030 extern JS_PUBLIC_API void JS_UpdateWeakPointerAfterGC(
1031 JS::Heap<JSObject*>* objp);
1033 extern JS_PUBLIC_API void JS_UpdateWeakPointerAfterGCUnbarriered(
1034 JSObject** objp);
1036 extern JS_PUBLIC_API void JS_SetGCParameter(JSContext* cx, JSGCParamKey key,
1037 uint32_t value);
1039 extern JS_PUBLIC_API void JS_ResetGCParameter(JSContext* cx, JSGCParamKey key);
1041 extern JS_PUBLIC_API uint32_t JS_GetGCParameter(JSContext* cx,
1042 JSGCParamKey key);
1044 extern JS_PUBLIC_API void JS_SetGCParametersBasedOnAvailableMemory(
1045 JSContext* cx, uint32_t availMem);
1048 * Create a new JSString whose chars member refers to external memory, i.e.,
1049 * memory requiring application-specific finalization.
1051 extern JS_PUBLIC_API JSString* JS_NewExternalString(
1052 JSContext* cx, const char16_t* chars, size_t length,
1053 const JSStringFinalizer* fin);
1056 * Create a new JSString whose chars member may refer to external memory.
1057 * If a new external string is allocated, |*allocatedExternal| is set to true.
1058 * Otherwise the returned string is either not an external string or an
1059 * external string allocated by a previous call and |*allocatedExternal| is set
1060 * to false. If |*allocatedExternal| is false, |fin| won't be called.
1062 extern JS_PUBLIC_API JSString* JS_NewMaybeExternalString(
1063 JSContext* cx, const char16_t* chars, size_t length,
1064 const JSStringFinalizer* fin, bool* allocatedExternal);
1067 * Return whether 'str' was created with JS_NewExternalString or
1068 * JS_NewExternalStringWithClosure.
1070 extern JS_PUBLIC_API bool JS_IsExternalString(JSString* str);
1073 * Return the 'fin' arg passed to JS_NewExternalString.
1075 extern JS_PUBLIC_API const JSStringFinalizer* JS_GetExternalStringFinalizer(
1076 JSString* str);
1078 namespace JS {
1080 extern JS_PUBLIC_API bool IsIdleGCTaskNeeded(JSRuntime* rt);
1082 extern JS_PUBLIC_API void RunIdleTimeGCTask(JSRuntime* rt);
1084 } // namespace JS
1086 namespace js {
1087 namespace gc {
1090 * Create an object providing access to the garbage collector's internal notion
1091 * of the current state of memory (both GC heap memory and GCthing-controlled
1092 * malloc memory.
1094 extern JS_PUBLIC_API JSObject* NewMemoryInfoObject(JSContext* cx);
1096 } /* namespace gc */
1097 } /* namespace js */
1099 #endif /* js_GCAPI_h */