/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- * vim: set ts=8 sts=2 et sw=2 tw=80: * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
/* * High-level interface to the JS garbage collector.
*/
// Options used when starting a GC. enumclass GCOptions : uint32_t { // Normal GC invocation. // // Some objects that are unreachable from the program may still be alive after // collection because of internal references
Normal = 0,
// A shrinking GC. // // Try to release as much memory as possible by clearing internal caches, // aggressively discarding JIT code and decommitting unused chunks. This // ensures all unreferenced objects are removed from the system. // // Finally, compact the GC heap.
Shrink = 1,
// A shutdown GC. // // This does more drastic cleanup as part of system shutdown, including: // - clearing WeakRef kept object sets // - not marking FinalizationRegistry roots // - repeating collection if JS::NotifyGCRootsRemoved was called // - skipping scheduling of various future work that won't be needed // // Note that this assumes that no JS will run after this point!
Shutdown = 2
};
} // namespace JS
typedefenum JSGCParamKey { /** * Maximum nominal heap before last ditch GC. * * Soft limit on the number of bytes we are allowed to allocate in the GC * heap. Attempts to allocate gcthings over this limit will return null and * subsequently invoke the standard OOM machinery, independent of available * physical memory. * * Pref: javascript.options.mem.max * Default: 0xffffffff
*/
JSGC_MAX_BYTES = 0,
/** * Maximum size of the generational GC nurseries. * * This will be rounded to the nearest gc::ChunkSize. * * Pref: javascript.options.mem.nursery.max_kb * Default: JS::DefaultNurseryMaxBytes
*/
JSGC_MAX_NURSERY_BYTES = 2,
/** Amount of bytes allocated by the GC. */
JSGC_BYTES = 3,
/** Number of times GC has been invoked. Includes both major and minor GC. */
JSGC_NUMBER = 4,
/** * Whether incremental GC is enabled. If not, GC will always run to * completion. * * prefs: javascript.options.mem.gc_incremental. * Default: false
*/
JSGC_INCREMENTAL_GC_ENABLED = 5,
/** * Whether per-zone GC is enabled. If not, all zones are collected every time. * * prefs: javascript.options.mem.gc_per_zone * Default: false
*/
JSGC_PER_ZONE_GC_ENABLED = 6,
/** Number of cached empty GC chunks. */
JSGC_UNUSED_CHUNKS = 7,
/** Total number of allocated GC chunks. */
JSGC_TOTAL_CHUNKS = 8,
/** * Max milliseconds to spend in an incremental GC slice. * * A value of zero means there is no maximum. * * Pref: javascript.options.mem.gc_incremental_slice_ms * Default: DefaultTimeBudgetMS.
*/
JSGC_SLICE_TIME_BUDGET_MS = 9,
/** * The "do we collect?" decision depends on various parameters and can be * summarised as: * * ZoneSize > Max(ThresholdBase, LastSize) * GrowthFactor * ThresholdFactor * * Where * ZoneSize: Current size of this zone. * LastSize: Heap size immediately after the most recent collection. * ThresholdBase: The JSGC_ALLOCATION_THRESHOLD parameter * GrowthFactor: A number above 1, calculated based on some of the * following parameters. * See computeZoneHeapGrowthFactorForHeapSize() in GC.cpp * ThresholdFactor: 1.0 to trigger an incremental collections or between * JSGC_SMALL_HEAP_INCREMENTAL_LIMIT and * JSGC_LARGE_HEAP_INCREMENTAL_LIMIT to trigger a * non-incremental collection. * * The RHS of the equation above is calculated and sets * zone->gcHeapThreshold.bytes(). When gcHeapSize.bytes() exeeds * gcHeapThreshold.bytes() for a zone, the zone may be scheduled for a GC.
*/
/** * GCs less than this far apart in milliseconds will be considered * 'high-frequency GCs'. * * Pref: javascript.options.mem.gc_high_frequency_time_limit_ms * Default: HighFrequencyThreshold
*/
JSGC_HIGH_FREQUENCY_TIME_LIMIT = 11,
/** * Upper limit for classifying a heap as small (MB). * * Dynamic heap growth thresholds are based on whether the heap is small, * medium or large. Heaps smaller than this size are classified as small; * larger heaps are classified as medium or large. * * Pref: javascript.options.mem.gc_small_heap_size_max_mb * Default: SmallHeapSizeMaxBytes
*/
JSGC_SMALL_HEAP_SIZE_MAX = 12,
/** * Lower limit for classifying a heap as large (MB). * * Dynamic heap growth thresholds are based on whether the heap is small, * medium or large. Heaps larger than this size are classified as large; * smaller heaps are classified as small or medium. * * Pref: javascript.options.mem.gc_large_heap_size_min_mb * Default: LargeHeapSizeMinBytes
*/
JSGC_LARGE_HEAP_SIZE_MIN = 13,
/** * Heap growth factor for small heaps in the high-frequency GC state. * * Pref: javascript.options.mem.gc_high_frequency_small_heap_growth * Default: HighFrequencySmallHeapGrowth
*/
JSGC_HIGH_FREQUENCY_SMALL_HEAP_GROWTH = 14,
/** * Heap growth factor for large heaps in the high-frequency GC state. * * Pref: javascript.options.mem.gc_high_frequency_large_heap_growth * Default: HighFrequencyLargeHeapGrowth
*/
JSGC_HIGH_FREQUENCY_LARGE_HEAP_GROWTH = 15,
/** * Heap growth factor for low frequency GCs. * * This factor is applied regardless of the size of the heap when not in the * high-frequency GC state. * * Pref: javascript.options.mem.gc_low_frequency_heap_growth * Default: LowFrequencyHeapGrowth
*/
JSGC_LOW_FREQUENCY_HEAP_GROWTH = 16,
/** * Whether balanced heap limits are enabled. * * If this is set to true then heap limits are calculated in a way designed to * balance memory usage optimally between many heaps. * * Otherwise, heap limits are set based on a linear multiple of the retained * size after the last collection. * * Pref: javascript.options.mem.gc_balanced_heap_limits * Default: BalancedHeapLimitsEnabled
*/
JSGC_BALANCED_HEAP_LIMITS_ENABLED = 17,
/** * Heap growth parameter for balanced heap limit calculation. * * This parameter trades off GC time for memory usage. Smaller values result * in lower memory use and larger values result in less time spent collecting. * * Heap limits are set to the heap's retained size plus some extra space. The * extra space is calculated based on several factors but is scaled * proportionally to this parameter. * * Pref: javascript.options.mem.gc_heap_growth_factor * Default: HeapGrowthFactor
*/
JSGC_HEAP_GROWTH_FACTOR = 18,
/** * Lower limit for collecting a zone (MB). * * Zones smaller than this size will not normally be collected. * * Pref: javascript.options.mem.gc_allocation_threshold_mb * Default GCZoneAllocThresholdBase
*/
JSGC_ALLOCATION_THRESHOLD = 19,
/** * We try to keep at least this many unused chunks in the free chunk pool at * all times, even after a shrinking GC. * * Pref: javascript.options.mem.gc_min_empty_chunk_count * Default: MinEmptyChunkCount
*/
JSGC_MIN_EMPTY_CHUNK_COUNT = 21,
/** * Limit of how far over the incremental trigger threshold we allow the heap * to grow before finishing a collection non-incrementally, for small heaps. * * We trigger an incremental GC when a trigger threshold is reached but the * collection may not be fast enough to keep up with the mutator. At some * point we finish the collection non-incrementally. * * Default: SmallHeapIncrementalLimit * Pref: javascript.options.mem.gc_small_heap_incremental_limit
*/
JSGC_SMALL_HEAP_INCREMENTAL_LIMIT = 25,
/** * Limit of how far over the incremental trigger threshold we allow the heap * to grow before finishing a collection non-incrementally, for large heaps. * * Default: LargeHeapIncrementalLimit * Pref: javascript.options.mem.gc_large_heap_incremental_limit
*/
JSGC_LARGE_HEAP_INCREMENTAL_LIMIT = 26,
/** * Free space fraction threshold for eager nursery collection. This is a * percentage (from 0 to 99). * * Default: 25 * Pref: javascript.options.mem.nursery_eager_collection_threshold_percent
*/
JSGC_NURSERY_EAGER_COLLECTION_THRESHOLD_PERCENT = 30,
/** * Minimum size of the generational GC nurseries. * * This value will be rounded to the nearest Nursery::SubChunkStep if below * gc::ChunkSize, otherwise it'll be rounded to the nearest gc::ChunkSize. * * Default: Nursery::SubChunkLimit * Pref: javascript.options.mem.nursery.min_kb
*/
JSGC_MIN_NURSERY_BYTES = 31,
/** * The minimum time to allow between triggering last ditch GCs in seconds. * * Default: 60 seconds * Pref: None
*/
JSGC_MIN_LAST_DITCH_GC_PERIOD = 32,
/** * The delay (in heapsize kilobytes) between slices of an incremental GC. * * Default: ZoneAllocDelayBytes
*/
JSGC_ZONE_ALLOC_DELAY_KB = 33,
/* * The current size of the nursery. * * This parameter is read-only.
*/
JSGC_NURSERY_BYTES = 34,
/** * Retained size base value for calculating malloc heap threshold. * * Default: MallocThresholdBase
*/
JSGC_MALLOC_THRESHOLD_BASE = 35,
/** * The chunk size in bytes for this system. * * This parameter is read-only.
*/
JSGC_CHUNK_BYTES = 38,
/** * The number of background threads to use for parallel GC work for each CPU * core, expressed as an integer percentage. * * Pref: javascript.options.mem.gc_helper_thread_ratio
*/
JSGC_HELPER_THREAD_RATIO = 39,
/** * The maximum number of background threads to use for parallel GC work. * * Pref: javascript.options.mem.gc_max_helper_threads
*/
JSGC_MAX_HELPER_THREADS = 40,
/** * The number of background threads to use for parallel GC work. * * This parameter is read-only and is set based on the * JSGC_HELPER_THREAD_RATIO and JSGC_MAX_HELPER_THREADS parameters.
*/
JSGC_HELPER_THREAD_COUNT = 41,
/** * A number that is incremented on every major GC slice.
*/
JSGC_MAJOR_GC_NUMBER = 44,
/** * A number that is incremented on every minor GC.
*/
JSGC_MINOR_GC_NUMBER = 45,
/** * JS::MaybeRunNurseryCollection will collect the nursery if it hasn't been * collected in this many milliseconds. * * Default: 5000 * Pref: javascript.options.mem.nursery_eager_collection_timeout_ms
*/
JSGC_NURSERY_EAGER_COLLECTION_TIMEOUT_MS = 46,
/** * The system page size in KB. * * This parameter is read-only.
*/
JSGC_SYSTEM_PAGE_SIZE_KB = 47,
/** * In an incremental GC, this determines the point at which to start * increasing the slice budget and frequency of allocation triggered slices to * try to avoid reaching the incremental limit and finishing the collection * synchronously. * * The threshold is calculated by subtracting this value from the heap's * incremental limit.
*/
JSGC_URGENT_THRESHOLD_MB = 48,
/** * Get the number of threads used for parallel marking. * * Pref: None.
*/
JSGC_MARKING_THREAD_COUNT = 49,
/** * The heap size above which to use parallel marking. * * Pref: javascript.options.mem.gc_parallel_marking_threshold_mb * Default: ParallelMarkingThresholdMB
*/
JSGC_PARALLEL_MARKING_THRESHOLD_MB = 50,
/** * Whether the semispace nursery is enabled. * * Pref: javascript.options.mem.gc_experimental_semispace_nursery * Default: SemispaceNurseryEnabled
*/
JSGC_SEMISPACE_NURSERY_ENABLED = 51,
/** * Set the maximum number of threads to use for parallel marking, if enabled. * * The actual number used is calculated based on the number of available * helper threads and can be found by getting the JSGC_MARKING_THREAD_COUNT * parameter. * * Pref: javascript.options.mem.gc_max_parallel_marking_threads * Default: 2.
*/
JSGC_MAX_MARKING_THREADS = 52,
/** * Whether to automatically generate missing allocation sites so data about * them can be gathered. * * Pref: None, this is an internal engine feature. * Default: false.
*/
JSGC_GENERATE_MISSING_ALLOC_SITES = 53,
/** * A number that is incremented every GC slice.
*/
JSGC_SLICE_NUMBER = 54,
/** * Whether the nursery is enabled. * * Pref: javascript.options.mem.gc_generational * Default: true
*/
JSGC_NURSERY_ENABLED = 55,
/* * Whether we are in high frequency GC mode, where the time between * collections is less than that specified by JSGC_HIGH_FREQUENCY_TIME_LIMIT.
*/
JSGC_HIGH_FREQUENCY_MODE = 56,
} JSGCParamKey;
/* * Generic trace operation that calls JS::TraceEdge on each traceable thing's * location reachable from data.
*/ typedefvoid (*JSTraceDataOp)(JSTracer* trc, void* data);
/* * Trace hook used to trace gray roots incrementally. * * This should return whether tracing is finished. It will be called repeatedly * in subsequent GC slices until it returns true. * * While tracing this should check the budget and return false if it has been * exceeded. When passed an unlimited budget it should always return true.
*/ typedefbool (*JSGrayRootsTracer)(JSTracer* trc, JS::SliceBudget& budget, void* data);
typedefenum JSFinalizeStatus { /** * Called when preparing to sweep a group of zones, before anything has been * swept. The collector will not yield to the mutator before calling the * callback with JSFINALIZE_GROUP_START status.
*/
JSFINALIZE_GROUP_PREPARE,
/** * Called after preparing to sweep a group of zones. Weak references to * unmarked things have been removed at this point, but no GC things have * been swept. The collector may yield to the mutator after this point.
*/
JSFINALIZE_GROUP_START,
/** * Called after sweeping a group of zones. All dead GC things have been * swept at this point.
*/
JSFINALIZE_GROUP_END,
/** * Called at the end of collection when everything has been swept.
*/
JSFINALIZE_COLLECTION_END
} JSFinalizeStatus;
/* * This is called to tell the embedding that a FinalizationRegistry object has * cleanup work, and that the engine should be called back at an appropriate * later time to perform this cleanup, by calling the function |doCleanup|. * * This callback must not do anything that could cause GC.
*/ using JSHostCleanupFinalizationRegistryCallback = void (*)(JSFunction* doCleanup, JSObject* incumbentGlobal, void* data);
/** * Each external string has a pointer to JSExternalStringCallbacks. Embedders * can use this to implement custom finalization or memory reporting behavior.
*/ struct JSExternalStringCallbacks { /** * Finalizes external strings created by JS_NewExternalStringLatin1 or * JS_NewExternalUCString. The finalizer can be called off the main * thread.
*/ virtualvoid finalize(JS::Latin1Char* chars) const = 0; virtualvoid finalize(char16_t* chars) const = 0;
/** * Callback used by memory reporting to ask the embedder how much memory an * external string is keeping alive. The embedder is expected to return a * value that corresponds to the size of the allocation that will be released * by the finalizer callback above. * * Implementations of this callback MUST NOT do anything that can cause GC.
*/ virtual size_t sizeOfBuffer(const JS::Latin1Char* chars,
mozilla::MallocSizeOf mallocSizeOf) const = 0; virtual size_t sizeOfBuffer(const char16_t* chars,
mozilla::MallocSizeOf mallocSizeOf) const = 0;
};
/* * For telemetry, we want to keep a fixed max bucket size over time so we * don't have to switch histograms. 100 is conservative; but the cost of extra * buckets seems to be low while the cost of switching histograms is high.
*/
NUM_TELEMETRY_REASONS = 100
};
/** * Get a statically allocated C string explaining the given GC reason.
*/ extern JS_PUBLIC_API constchar* ExplainGCReason(JS::GCReason reason);
/** * Return true if the GC reason is internal to the JS engine.
*/ extern JS_PUBLIC_API bool InternalGCReason(JS::GCReason reason);
/** * Get a statically allocated C string explaining the given Abort reason. * Input is the integral value of the enum.
*/ extern JS_PUBLIC_API constchar* ExplainGCAbortReason(uint32_t reason);
/* * Zone GC: * * SpiderMonkey's GC is capable of performing a collection on an arbitrary * subset of the zones in the system. This allows an embedding to minimize * collection time by only collecting zones that have run code recently, * ignoring the parts of the heap that are unlikely to have changed. * * When triggering a GC using one of the functions below, it is first necessary * to select the zones to be collected. To do this, you can call * PrepareZoneForGC on each zone, or you can call PrepareForFullGC to select * all zones. Failing to select any zone is an error.
*/
/** * Schedule the given zone to be collected as part of the next GC.
*/ extern JS_PUBLIC_API void PrepareZoneForGC(JSContext* cx, Zone* zone);
/** * Schedule all zones to be collected in the next GC.
*/ extern JS_PUBLIC_API void PrepareForFullGC(JSContext* cx);
/** * When performing an incremental GC, the zones that were selected for the * previous incremental slice must be selected in subsequent slices as well. * This function selects those slices automatically.
*/ extern JS_PUBLIC_API void PrepareForIncrementalGC(JSContext* cx);
/** * Returns true if any zone in the system has been scheduled for GC with one of * the functions above or by the JS engine.
*/ extern JS_PUBLIC_API bool IsGCScheduled(JSContext* cx);
/** * Undoes the effect of the Prepare methods above. The given zone will not be * collected in the next GC.
*/ extern JS_PUBLIC_API void SkipZoneForGC(JSContext* cx, Zone* zone);
/* * Non-Incremental GC: * * The following functions perform a non-incremental GC.
*/
/** * Performs a non-incremental collection of all selected zones.
*/ extern JS_PUBLIC_API void NonIncrementalGC(JSContext* cx, JS::GCOptions options,
GCReason reason);
/* * Incremental GC: * * Incremental GC divides the full mark-and-sweep collection into multiple * slices, allowing client JavaScript code to run between each slice. This * allows interactive apps to avoid long collection pauses. Incremental GC does * not make collection take less time, it merely spreads that time out so that * the pauses are less noticable. * * For a collection to be carried out incrementally the following conditions * must be met: * - The collection must be run by calling JS::IncrementalGC() rather than * JS_GC(). * - The GC parameter JSGC_INCREMENTAL_GC_ENABLED must be true. * * Note: Even if incremental GC is enabled and working correctly, * non-incremental collections can still happen when low on memory.
*/
/** * Begin an incremental collection and perform one slice worth of work. When * this function returns, the collection may not be complete. * IncrementalGCSlice() must be called repeatedly until * !IsIncrementalGCInProgress(cx). * * Note: SpiderMonkey's GC is not realtime. Slices in practice may be longer or * shorter than the requested interval.
*/ extern JS_PUBLIC_API void StartIncrementalGC(JSContext* cx,
JS::GCOptions options,
GCReason reason, const JS::SliceBudget& budget);
/** * Perform a slice of an ongoing incremental collection. When this function * returns, the collection may not be complete. It must be called repeatedly * until !IsIncrementalGCInProgress(cx). * * Note: SpiderMonkey's GC is not realtime. Slices in practice may be longer or * shorter than the requested interval.
*/ extern JS_PUBLIC_API void IncrementalGCSlice(JSContext* cx, GCReason reason, const JS::SliceBudget& budget);
/** * Return whether an incremental GC has work to do on the foreground thread and * would make progress if a slice was run now. If this returns false then the GC * is waiting for background threads to finish their work and a slice started * now would return immediately.
*/ extern JS_PUBLIC_API bool IncrementalGCHasForegroundWork(JSContext* cx);
/** * If IsIncrementalGCInProgress(cx), this call finishes the ongoing collection * by performing an arbitrarily long slice. If !IsIncrementalGCInProgress(cx), * this is equivalent to NonIncrementalGC. When this function returns, * IsIncrementalGCInProgress(cx) will always be false.
*/ extern JS_PUBLIC_API void FinishIncrementalGC(JSContext* cx, GCReason reason);
/** * If IsIncrementalGCInProgress(cx), this call aborts the ongoing collection and * performs whatever work needs to be done to return the collector to its idle * state. This may take an arbitrarily long time. When this function returns, * IsIncrementalGCInProgress(cx) will always be false.
*/ extern JS_PUBLIC_API void AbortIncrementalGC(JSContext* cx);
namespace dbg {
// The `JS::dbg::GarbageCollectionEvent` class is essentially a view of the // `js::gcstats::Statistics` data without the uber implementation-specific bits. // It should generally be palatable for web developers. class GarbageCollectionEvent { // The major GC number of the GC cycle this data pertains to.
uint64_t majorGCNumber_;
// Reference to a non-owned, statically allocated C string. This is a very // short reason explaining why a GC was triggered. constchar* reason;
// Reference to a nullable, non-owned, statically allocated C string. If the // collection was forced to be non-incremental, this is a short reason of // why the GC could not perform an incremental collection. constchar* nonincrementalReason;
// Represents a single slice of a possibly multi-slice incremental garbage // collection. struct Collection {
mozilla::TimeStamp startTimestamp;
mozilla::TimeStamp endTimestamp;
};
// The set of garbage collection slices that made up this GC cycle.
mozilla::Vector<Collection> collections;
enum GCProgress { /* * During GC, the GC is bracketed by GC_CYCLE_BEGIN/END callbacks. Each * slice between those (whether an incremental or the sole non-incremental * slice) is bracketed by GC_SLICE_BEGIN/GC_SLICE_END.
*/
/** * The GC slice callback is called at the beginning and end of each slice. This * callback may be used for GC notifications as well as to perform additional * marking.
*/ extern JS_PUBLIC_API GCSliceCallback
SetGCSliceCallback(JSContext* cx, GCSliceCallback callback);
/** * Describes the progress of an observed nursery collection.
*/ enumclass GCNurseryProgress { /** * The nursery collection is starting.
*/
GC_NURSERY_COLLECTION_START, /** * The nursery collection is ending.
*/
GC_NURSERY_COLLECTION_END
};
/** * A nursery collection callback receives the progress of the nursery collection * and the reason for the collection.
*/ using GCNurseryCollectionCallback = void (*)(JSContext* cx,
GCNurseryProgress progress,
GCReason reason, void* data);
/** * Add and remove nursery collection callbacks for the given runtime. These will * be called at the start and end of every nursery collection.
*/ extern JS_PUBLIC_API bool AddGCNurseryCollectionCallback(
JSContext* cx, GCNurseryCollectionCallback callback, void* data); extern JS_PUBLIC_API void RemoveGCNurseryCollectionCallback(
JSContext* cx, GCNurseryCollectionCallback callback, void* data);
/** * The purge gray callback is called after any COMPARTMENT_REVIVED GC in which * the majority of compartments have been marked gray.
*/ extern JS_PUBLIC_API DoCycleCollectionCallback
SetDoCycleCollectionCallback(JSContext* cx, DoCycleCollectionCallback callback);
using CreateSliceBudgetCallback = JS::SliceBudget (*)(JS::GCReason reason,
int64_t millis);
/** * Called when generating a GC slice budget. It allows the embedding to control * the duration of slices and potentially check an interrupt flag as well. For * internally triggered GCs, the given millis parameter is the JS engine's * internal scheduling decision, which the embedding can choose to ignore. * (Otherwise, it will be the value that was passed to eg * JS::IncrementalGCSlice()).
*/ extern JS_PUBLIC_API void SetCreateGCSliceBudgetCallback(
JSContext* cx, CreateSliceBudgetCallback cb);
/** * Returns true if incremental GC is enabled. Simply having incremental GC * enabled is not sufficient to ensure incremental collections are happening. * See the comment "Incremental GC" above for reasons why incremental GC may be * suppressed. Inspection of the "nonincremental reason" field of the * GCDescription returned by GCSliceCallback may help narrow down the cause if * collections are not happening incrementally when expected.
*/ extern JS_PUBLIC_API bool IsIncrementalGCEnabled(JSContext* cx);
/** * Returns true while an incremental GC is ongoing, both when actively * collecting and between slices.
*/ extern JS_PUBLIC_API bool IsIncrementalGCInProgress(JSContext* cx);
/** * Returns true while an incremental GC is ongoing, both when actively * collecting and between slices.
*/ extern JS_PUBLIC_API bool IsIncrementalGCInProgress(JSRuntime* rt);
/** * Returns true if the most recent GC ran incrementally.
*/ extern JS_PUBLIC_API bool WasIncrementalGC(JSRuntime* rt);
/* * Generational GC:
*/
/** * Ensure that generational GC is disabled within some scope. * * This evicts the nursery and discards JIT code so it is not a lightweight * operation.
*/ class JS_PUBLIC_API AutoDisableGenerationalGC {
JSContext* cx;
/** * Returns true if generational allocation and collection is currently enabled * on the given runtime.
*/ extern JS_PUBLIC_API bool IsGenerationalGCEnabled(JSRuntime* rt);
/** * Pass a subclass of this "abstract" class to callees to require that they * never GC. Subclasses can use assertions or the hazard analysis to ensure no * GC happens.
*/ class JS_PUBLIC_API AutoRequireNoGC { protected:
AutoRequireNoGC() = default;
~AutoRequireNoGC() = default;
};
/** * Diagnostic assert (see MOZ_DIAGNOSTIC_ASSERT) that GC cannot occur while this * class is live. This class does not disable the static rooting hazard * analysis. * * This works by entering a GC unsafe region, which is checked on allocation and * on GC.
*/ class JS_PUBLIC_API AutoAssertNoGC : public AutoRequireNoGC { #ifdef MOZ_DIAGNOSTIC_ASSERT_ENABLED protected:
JSContext* cx_; // nullptr if inactive.
public: // Nullptr here means get the context from TLS. It does not mean inactive // (though cx_ may end up nullptr, and thus inactive, if TLS has not yet been // initialized.) explicit AutoAssertNoGC(JSContext* cx = nullptr);
AutoAssertNoGC(AutoAssertNoGC&& other) : cx_(other.cx_) {
other.cx_ = nullptr;
}
~AutoAssertNoGC();
/** * Disable the static rooting hazard analysis in the live region and assert in * debug builds if any allocation that could potentially trigger a GC occurs * while this guard object is live. This is most useful to help the exact * rooting hazard analysis in complex regions, since it cannot understand * dataflow. * * Note: GC behavior is unpredictable even when deterministic and is generally * non-deterministic in practice. The fact that this guard has not * asserted is not a guarantee that a GC cannot happen in the guarded * region. As a rule, anyone performing a GC unsafe action should * understand the GC properties of all code in that region and ensure * that the hazard analysis is correct for that code, rather than relying * on this class.
*/ #ifdef DEBUG class JS_PUBLIC_API AutoSuppressGCAnalysis : public AutoAssertNoGC { public: explicit AutoSuppressGCAnalysis(JSContext* cx = nullptr)
: AutoAssertNoGC(cx) {}
} JS_HAZ_GC_SUPPRESSED; #else class JS_PUBLIC_API AutoSuppressGCAnalysis : public AutoRequireNoGC { public: explicit AutoSuppressGCAnalysis(JSContext* cx = nullptr) {}
} JS_HAZ_GC_SUPPRESSED; #endif
/** * Assert that code is only ever called from a GC callback, disable the static * rooting hazard analysis and assert if any allocation that could potentially * trigger a GC occurs while this guard object is live. * * This is useful to make the static analysis ignore code that runs in GC * callbacks.
*/ class JS_PUBLIC_API AutoAssertGCCallback : public AutoSuppressGCAnalysis { public: #ifdef DEBUG
AutoAssertGCCallback(); #else
AutoAssertGCCallback() {} #endif
};
/** * Place AutoCheckCannotGC in scopes that you believe can never GC. These * annotations will be verified both dynamically via AutoAssertNoGC, and * statically with the rooting hazard analysis (implemented by making the * analysis consider AutoCheckCannotGC to be a GC pointer, and therefore * complain if it is live across a GC call.) It is useful when dealing with * internal pointers to GC things where the GC thing itself may not be present * for the static analysis: e.g. acquiring inline chars from a JSString* on the * heap. * * We only do the assertion checking in DEBUG builds.
*/ #ifdef DEBUG class JS_PUBLIC_API AutoCheckCannotGC : public AutoAssertNoGC { public: explicit AutoCheckCannotGC(JSContext* cx = nullptr) : AutoAssertNoGC(cx) {} # ifdef MOZ_DIAGNOSTIC_ASSERT_ENABLED
AutoCheckCannotGC(const AutoCheckCannotGC& other)
: AutoCheckCannotGC(other.cx_) {} # else
AutoCheckCannotGC(const AutoCheckCannotGC& other) : AutoCheckCannotGC() {} # endif
AutoCheckCannotGC(AutoCheckCannotGC&& other)
: AutoAssertNoGC(std::forward<AutoAssertNoGC>(other)) {} #else class JS_PUBLIC_API AutoCheckCannotGC : public AutoRequireNoGC { public: explicit AutoCheckCannotGC(JSContext* cx = nullptr) {}
AutoCheckCannotGC(const AutoCheckCannotGC& other) : AutoCheckCannotGC() {}
AutoCheckCannotGC(AutoCheckCannotGC&& other) : AutoCheckCannotGC() {} void reset() {} #endif
} JS_HAZ_GC_INVALIDATED JS_HAZ_GC_REF;
/** * Register externally maintained GC roots. * * traceOp: the trace operation. For each root the implementation should call * JS::TraceEdge whenever the root contains a traceable thing. * data: the data argument to pass to each invocation of traceOp.
*/ extern JS_PUBLIC_API bool JS_AddExtraGCRootsTracer(JSContext* cx,
JSTraceDataOp traceOp, void* data);
/** Undo a call to JS_AddExtraGCRootsTracer. */ extern JS_PUBLIC_API void JS_RemoveExtraGCRootsTracer(JSContext* cx,
JSTraceDataOp traceOp, void* data);
/* * Weak pointers and garbage collection * * Weak pointers are by their nature not marked as part of garbage collection, * but they may need to be updated in two cases after a GC: * * 1) Their referent was found not to be live and is about to be finalized * 2) Their referent has been moved by a compacting GC * * To handle this, any part of the system that maintain weak pointers to * JavaScript GC things must register a callback with * JS_(Add,Remove)WeakPointer{ZoneGroup,Compartment}Callback(). This callback * must then call JS_UpdateWeakPointerAfterGC() on all weak pointers it knows * about. * * Since sweeping is incremental, we have several callbacks to avoid repeatedly * having to visit all embedder structures. The WeakPointerZonesCallback is * called once for each strongly connected group of zones, whereas the * WeakPointerCompartmentCallback is called once for each compartment that is * visited while sweeping. Structures that cannot contain references in more * than one compartment should sweep the relevant per-compartment structures * using the latter callback to minimizer per-slice overhead. * * The argument to JS_UpdateWeakPointerAfterGC() is an in-out param. If the * referent is about to be finalized the pointer will be set to null. If the * referent has been moved then the pointer will be updated to point to the new * location. * * The return value of JS_UpdateWeakPointerAfterGC() indicates whether the * referent is still alive. If the referent is is about to be finalized, this * will return false. * * Callers of this method are responsible for updating any state that is * dependent on the object's address. For example, if the object's address is * used as a key in a hashtable, then the object must be removed and * re-inserted with the correct hash.
*/
/** * Create a new JSString whose chars member may refer to external memory. * If a new external string is allocated, |*allocatedExternal| is set to true. * Otherwise the returned string is either not an external string or an * external string allocated by a previous call and |*allocatedExternal| is set * to false. If |*allocatedExternal| is false, |fin| won't be called.
*/ extern JS_PUBLIC_API JSString* JS_NewMaybeExternalStringLatin1(
JSContext* cx, const JS::Latin1Char* chars, size_t length, const JSExternalStringCallbacks* callbacks, bool* allocatedExternal); extern JS_PUBLIC_API JSString* JS_NewMaybeExternalUCString(
JSContext* cx, const char16_t* chars, size_t length, const JSExternalStringCallbacks* callbacks, bool* allocatedExternal);
/** * Similar to JS_NewMaybeExternalStringLatin1. * * Create an external Latin1 string if the utf8 buffer contains only ASCII * chars, otherwise copy the chars into a non-external string.
*/ extern JS_PUBLIC_API JSString* JS_NewMaybeExternalStringUTF8(
JSContext* cx, const JS::UTF8Chars& utf8, const JSExternalStringCallbacks* callbacks, bool* allocatedExternal);
/** * Return the 'callbacks' arg passed to JS_NewExternalStringLatin1, * JS_NewExternalUCString, JS_NewMaybeExternalStringLatin1, * or JS_NewMaybeExternalUCString.
*/ extern JS_PUBLIC_API const JSExternalStringCallbacks*
JS_GetExternalStringCallbacks(JSString* str);
namespace JS {
/** * Check whether the nursery should be eagerly collected, this is before it is * full. * * The idea is that this can be called when the host environment has some idle * time which it can use to for GC activity. * * Returns GCReason::NO_REASON to indicate no collection is desired.
*/ extern JS_PUBLIC_API GCReason WantEagerMinorGC(JSRuntime* rt);
/** * Check whether the nursery should be eagerly collected as per WantEagerMajorGC * above, and if so run a collection. * * The idea is that this can be called when the host environment has some idle * time which it can use to for GC activity.
*/ extern JS_PUBLIC_API void MaybeRunNurseryCollection(JSRuntime* rt,
JS::GCReason reason);
/** * Create an object providing access to the garbage collector's internal notion * of the current state of memory (both GC heap memory and GCthing-controlled * malloc memory.
*/ extern JS_PUBLIC_API JSObject* NewMemoryInfoObject(JSContext* cx);
/* * Get the GCContext for the current context. * * This is here to allow the browser to call finalizers for dead nursery * objects. This is a dangerous operation - only use this if you know what * you're doing!
*/ extern JS_PUBLIC_API JS::GCContext* GetGCContext(JSContext* cx);
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.