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 */