diff options
Diffstat (limited to 'js/src/gc/GC.h')
-rw-r--r-- | js/src/gc/GC.h | 271 |
1 files changed, 271 insertions, 0 deletions
diff --git a/js/src/gc/GC.h b/js/src/gc/GC.h new file mode 100644 index 0000000000..3b7dec3201 --- /dev/null +++ b/js/src/gc/GC.h @@ -0,0 +1,271 @@ +/* -*- 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/. */ + +/* + * JS engine garbage collector API. + */ + +#ifndef gc_GC_h +#define gc_GC_h + +#include "gc/AllocKind.h" +#include "gc/GCEnum.h" +#include "js/GCAPI.h" +#include "js/HeapAPI.h" +#include "js/RealmIterators.h" +#include "js/TraceKind.h" + +class JSTracer; + +namespace JS { +class RealmOptions; +} + +namespace js { + +class Nursery; + +namespace gc { + +class Arena; +class TenuredChunk; + +} /* namespace gc */ + +// Define name, key and writability for the GC parameters. +#define FOR_EACH_GC_PARAM(_) \ + _("maxBytes", JSGC_MAX_BYTES, true) \ + _("minNurseryBytes", JSGC_MIN_NURSERY_BYTES, true) \ + _("maxNurseryBytes", JSGC_MAX_NURSERY_BYTES, true) \ + _("gcBytes", JSGC_BYTES, false) \ + _("nurseryBytes", JSGC_NURSERY_BYTES, false) \ + _("gcNumber", JSGC_NUMBER, false) \ + _("majorGCNumber", JSGC_MAJOR_GC_NUMBER, false) \ + _("minorGCNumber", JSGC_MINOR_GC_NUMBER, false) \ + _("incrementalGCEnabled", JSGC_INCREMENTAL_GC_ENABLED, true) \ + _("perZoneGCEnabled", JSGC_PER_ZONE_GC_ENABLED, true) \ + _("unusedChunks", JSGC_UNUSED_CHUNKS, false) \ + _("totalChunks", JSGC_TOTAL_CHUNKS, false) \ + _("sliceTimeBudgetMS", JSGC_SLICE_TIME_BUDGET_MS, true) \ + _("highFrequencyTimeLimit", JSGC_HIGH_FREQUENCY_TIME_LIMIT, true) \ + _("smallHeapSizeMax", JSGC_SMALL_HEAP_SIZE_MAX, true) \ + _("largeHeapSizeMin", JSGC_LARGE_HEAP_SIZE_MIN, true) \ + _("highFrequencySmallHeapGrowth", JSGC_HIGH_FREQUENCY_SMALL_HEAP_GROWTH, \ + true) \ + _("highFrequencyLargeHeapGrowth", JSGC_HIGH_FREQUENCY_LARGE_HEAP_GROWTH, \ + true) \ + _("lowFrequencyHeapGrowth", JSGC_LOW_FREQUENCY_HEAP_GROWTH, true) \ + _("balancedHeapLimitsEnabled", JSGC_BALANCED_HEAP_LIMITS_ENABLED, true) \ + _("heapGrowthFactor", JSGC_HEAP_GROWTH_FACTOR, true) \ + _("allocationThreshold", JSGC_ALLOCATION_THRESHOLD, true) \ + _("smallHeapIncrementalLimit", JSGC_SMALL_HEAP_INCREMENTAL_LIMIT, true) \ + _("largeHeapIncrementalLimit", JSGC_LARGE_HEAP_INCREMENTAL_LIMIT, true) \ + _("minEmptyChunkCount", JSGC_MIN_EMPTY_CHUNK_COUNT, true) \ + _("maxEmptyChunkCount", JSGC_MAX_EMPTY_CHUNK_COUNT, true) \ + _("compactingEnabled", JSGC_COMPACTING_ENABLED, true) \ + _("parallelMarkingEnabled", JSGC_PARALLEL_MARKING_ENABLED, true) \ + _("parallelMarkingThresholdMB", JSGC_PARALLEL_MARKING_THRESHOLD_MB, true) \ + _("minLastDitchGCPeriod", JSGC_MIN_LAST_DITCH_GC_PERIOD, true) \ + _("nurseryFreeThresholdForIdleCollection", \ + JSGC_NURSERY_FREE_THRESHOLD_FOR_IDLE_COLLECTION, true) \ + _("nurseryFreeThresholdForIdleCollectionPercent", \ + JSGC_NURSERY_FREE_THRESHOLD_FOR_IDLE_COLLECTION_PERCENT, true) \ + _("nurseryTimeoutForIdleCollectionMS", \ + JSGC_NURSERY_TIMEOUT_FOR_IDLE_COLLECTION_MS, true) \ + _("zoneAllocDelayKB", JSGC_ZONE_ALLOC_DELAY_KB, true) \ + _("mallocThresholdBase", JSGC_MALLOC_THRESHOLD_BASE, true) \ + _("urgentThreshold", JSGC_URGENT_THRESHOLD_MB, true) \ + _("chunkBytes", JSGC_CHUNK_BYTES, false) \ + _("helperThreadRatio", JSGC_HELPER_THREAD_RATIO, true) \ + _("maxHelperThreads", JSGC_MAX_HELPER_THREADS, true) \ + _("helperThreadCount", JSGC_HELPER_THREAD_COUNT, false) \ + _("markingThreadCount", JSGC_MARKING_THREAD_COUNT, true) \ + _("systemPageSizeKB", JSGC_SYSTEM_PAGE_SIZE_KB, false) + +// Get the key and writability give a GC parameter name. +extern bool GetGCParameterInfo(const char* name, JSGCParamKey* keyOut, + bool* writableOut); + +extern void TraceRuntime(JSTracer* trc); + +// Trace roots but don't evict the nursery first; used from DumpHeap. +extern void TraceRuntimeWithoutEviction(JSTracer* trc); + +extern void ReleaseAllJITCode(JS::GCContext* gcx); + +extern void PrepareForDebugGC(JSRuntime* rt); + +/* Functions for managing cross compartment gray pointers. */ + +extern void NotifyGCNukeWrapper(JSContext* cx, JSObject* wrapper); + +extern unsigned NotifyGCPreSwap(JSObject* a, JSObject* b); + +extern void NotifyGCPostSwap(JSObject* a, JSObject* b, unsigned removedFlags); + +using IterateChunkCallback = void (*)(JSRuntime*, void*, gc::TenuredChunk*, + const JS::AutoRequireNoGC&); +using IterateZoneCallback = void (*)(JSRuntime*, void*, JS::Zone*, + const JS::AutoRequireNoGC&); +using IterateArenaCallback = void (*)(JSRuntime*, void*, gc::Arena*, + JS::TraceKind, size_t, + const JS::AutoRequireNoGC&); +using IterateCellCallback = void (*)(JSRuntime*, void*, JS::GCCellPtr, size_t, + const JS::AutoRequireNoGC&); + +/* + * This function calls |zoneCallback| on every zone, |realmCallback| on + * every realm, |arenaCallback| on every in-use arena, and |cellCallback| + * on every in-use cell in the GC heap. + * + * Note that no read barrier is triggered on the cells passed to cellCallback, + * so no these pointers must not escape the callback. + */ +extern void IterateHeapUnbarriered(JSContext* cx, void* data, + IterateZoneCallback zoneCallback, + JS::IterateRealmCallback realmCallback, + IterateArenaCallback arenaCallback, + IterateCellCallback cellCallback); + +/* + * This function is like IterateHeapUnbarriered, but does it for a single zone. + */ +extern void IterateHeapUnbarrieredForZone( + JSContext* cx, JS::Zone* zone, void* data, IterateZoneCallback zoneCallback, + JS::IterateRealmCallback realmCallback, IterateArenaCallback arenaCallback, + IterateCellCallback cellCallback); + +/* + * Invoke chunkCallback on every in-use chunk. + */ +extern void IterateChunks(JSContext* cx, void* data, + IterateChunkCallback chunkCallback); + +using IterateScriptCallback = void (*)(JSRuntime*, void*, BaseScript*, + const JS::AutoRequireNoGC&); + +/* + * Invoke scriptCallback on every in-use script for the given realm or for all + * realms if it is null. The scripts may or may not have bytecode. + */ +extern void IterateScripts(JSContext* cx, JS::Realm* realm, void* data, + IterateScriptCallback scriptCallback); + +JS::Realm* NewRealm(JSContext* cx, JSPrincipals* principals, + const JS::RealmOptions& options); + +namespace gc { + +void FinishGC(JSContext* cx, JS::GCReason = JS::GCReason::FINISH_GC); + +void WaitForBackgroundTasks(JSContext* cx); + +enum VerifierType { PreBarrierVerifier }; + +#ifdef JS_GC_ZEAL + +extern const char ZealModeHelpText[]; + +/* Check that write barriers have been used correctly. See gc/Verifier.cpp. */ +void VerifyBarriers(JSRuntime* rt, VerifierType type); + +void MaybeVerifyBarriers(JSContext* cx, bool always = false); + +void DumpArenaInfo(); + +#else + +static inline void VerifyBarriers(JSRuntime* rt, VerifierType type) {} + +static inline void MaybeVerifyBarriers(JSContext* cx, bool always = false) {} + +#endif + +/* + * Instances of this class prevent GC from happening while they are live. If an + * allocation causes a heap threshold to be exceeded, no GC will be performed + * and the allocation will succeed. Allocation may still fail for other reasons. + * + * Use of this class is highly discouraged, since without GC system memory can + * become exhausted and this can cause crashes at places where we can't handle + * allocation failure. + * + * Use of this is permissible in situations where it would be impossible (or at + * least very difficult) to tolerate GC and where only a fixed number of objects + * are allocated, such as: + * + * - error reporting + * - JIT bailout handling + * - brain transplants (JSObject::swap) + * - debugging utilities not exposed to the browser + * + * This works by updating the |JSContext::suppressGC| counter which is checked + * at the start of GC. + */ +class MOZ_RAII JS_HAZ_GC_SUPPRESSED AutoSuppressGC + : public JS::AutoRequireNoGC { + int32_t& suppressGC_; + + public: + explicit AutoSuppressGC(JSContext* cx); + + ~AutoSuppressGC() { suppressGC_--; } +}; + +const char* StateName(State state); + +} /* namespace gc */ + +/* Use this to avoid assertions when manipulating the wrapper map. */ +class MOZ_RAII AutoDisableProxyCheck { + public: +#ifdef DEBUG + AutoDisableProxyCheck(); + ~AutoDisableProxyCheck(); +#else + AutoDisableProxyCheck() {} +#endif +}; + +struct MOZ_RAII AutoDisableCompactingGC { + explicit AutoDisableCompactingGC(JSContext* cx); + ~AutoDisableCompactingGC(); + + private: + JSContext* cx; +}; + +/* + * Dynamically select the GC heap to allocate into for a graph of GC things. + * + * Initially |heap()| will return Heap::Default to select nursery allocation, + * but when a specified number of nursery collections have been triggered it + * switches to returning Heap::Tenured. + */ +class MOZ_RAII AutoSelectGCHeap { + public: + explicit AutoSelectGCHeap(JSContext* cx, + size_t allowedNurseryCollections = 0); + ~AutoSelectGCHeap(); + + gc::Heap heap() const { return heap_; } + operator gc::Heap() const { return heap_; } + + void onNurseryCollectionEnd(); + + private: + static void NurseryCollectionCallback(JSContext* cx, + JS::GCNurseryProgress progress, + JS::GCReason reason, void* data); + + JSContext* cx_; + size_t allowedNurseryCollections_; + gc::Heap heap_ = gc::Heap::Default; +}; + +} /* namespace js */ + +#endif /* gc_GC_h */ |