tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

GCAPI.h (51381B)


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