GC.h (12694B)
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 * JS engine garbage collector API. 9 */ 10 11 #ifndef gc_GC_h 12 #define gc_GC_h 13 14 #include "gc/AllocKind.h" 15 #include "gc/GCEnum.h" 16 #include "js/Context.h" 17 #include "js/GCAPI.h" 18 #include "js/HeapAPI.h" 19 #include "js/RealmIterators.h" 20 #include "js/TraceKind.h" 21 #include "vm/GeckoProfiler.h" 22 23 class JSTracer; 24 25 namespace JS { 26 class RealmOptions; 27 } 28 29 namespace js { 30 31 class Nursery; 32 33 namespace gc { 34 35 class Arena; 36 class ArenaChunk; 37 38 } /* namespace gc */ 39 40 // Define name, key and writability for the GC parameters. 41 #define FOR_EACH_GC_PARAM(_) \ 42 _("maxBytes", JSGC_MAX_BYTES, true) \ 43 _("minNurseryBytes", JSGC_MIN_NURSERY_BYTES, true) \ 44 _("maxNurseryBytes", JSGC_MAX_NURSERY_BYTES, true) \ 45 _("gcBytes", JSGC_BYTES, false) \ 46 _("nurseryBytes", JSGC_NURSERY_BYTES, false) \ 47 _("gcNumber", JSGC_NUMBER, false) \ 48 _("majorGCNumber", JSGC_MAJOR_GC_NUMBER, false) \ 49 _("minorGCNumber", JSGC_MINOR_GC_NUMBER, false) \ 50 _("sliceNumber", JSGC_SLICE_NUMBER, false) \ 51 _("incrementalGCEnabled", JSGC_INCREMENTAL_GC_ENABLED, true) \ 52 _("perZoneGCEnabled", JSGC_PER_ZONE_GC_ENABLED, true) \ 53 _("unusedChunks", JSGC_UNUSED_CHUNKS, false) \ 54 _("totalChunks", JSGC_TOTAL_CHUNKS, false) \ 55 _("sliceTimeBudgetMS", JSGC_SLICE_TIME_BUDGET_MS, true) \ 56 _("highFrequencyTimeLimit", JSGC_HIGH_FREQUENCY_TIME_LIMIT, true) \ 57 _("smallHeapSizeMax", JSGC_SMALL_HEAP_SIZE_MAX, true) \ 58 _("largeHeapSizeMin", JSGC_LARGE_HEAP_SIZE_MIN, true) \ 59 _("highFrequencySmallHeapGrowth", JSGC_HIGH_FREQUENCY_SMALL_HEAP_GROWTH, \ 60 true) \ 61 _("highFrequencyLargeHeapGrowth", JSGC_HIGH_FREQUENCY_LARGE_HEAP_GROWTH, \ 62 true) \ 63 _("lowFrequencyHeapGrowth", JSGC_LOW_FREQUENCY_HEAP_GROWTH, true) \ 64 _("balancedHeapLimitsEnabled", JSGC_BALANCED_HEAP_LIMITS_ENABLED, true) \ 65 _("heapGrowthFactor", JSGC_HEAP_GROWTH_FACTOR, true) \ 66 _("allocationThreshold", JSGC_ALLOCATION_THRESHOLD, true) \ 67 _("smallHeapIncrementalLimit", JSGC_SMALL_HEAP_INCREMENTAL_LIMIT, true) \ 68 _("largeHeapIncrementalLimit", JSGC_LARGE_HEAP_INCREMENTAL_LIMIT, true) \ 69 _("minEmptyChunkCount", JSGC_MIN_EMPTY_CHUNK_COUNT, true) \ 70 _("compactingEnabled", JSGC_COMPACTING_ENABLED, true) \ 71 _("nurseryEnabled", JSGC_NURSERY_ENABLED, true) \ 72 _("parallelMarkingEnabled", JSGC_PARALLEL_MARKING_ENABLED, true) \ 73 _("parallelMarkingThresholdMB", JSGC_PARALLEL_MARKING_THRESHOLD_MB, true) \ 74 _("minLastDitchGCPeriod", JSGC_MIN_LAST_DITCH_GC_PERIOD, true) \ 75 _("nurseryEagerCollectionThresholdKB", \ 76 JSGC_NURSERY_EAGER_COLLECTION_THRESHOLD_KB, true) \ 77 _("nurseryEagerCollectionThresholdPercent", \ 78 JSGC_NURSERY_EAGER_COLLECTION_THRESHOLD_PERCENT, true) \ 79 _("nurseryEagerCollectionTimeoutMS", \ 80 JSGC_NURSERY_EAGER_COLLECTION_TIMEOUT_MS, true) \ 81 _("nurseryMaxTimeGoalMS", JSGC_NURSERY_MAX_TIME_GOAL_MS, true) \ 82 _("zoneAllocDelayKB", JSGC_ZONE_ALLOC_DELAY_KB, true) \ 83 _("mallocThresholdBase", JSGC_MALLOC_THRESHOLD_BASE, true) \ 84 _("urgentThreshold", JSGC_URGENT_THRESHOLD_MB, true) \ 85 _("chunkBytes", JSGC_CHUNK_BYTES, false) \ 86 _("helperThreadRatio", JSGC_HELPER_THREAD_RATIO, true) \ 87 _("maxHelperThreads", JSGC_MAX_HELPER_THREADS, true) \ 88 _("helperThreadCount", JSGC_HELPER_THREAD_COUNT, false) \ 89 _("maxMarkingThreads", JSGC_MAX_MARKING_THREADS, true) \ 90 _("markingThreadCount", JSGC_MARKING_THREAD_COUNT, false) \ 91 _("systemPageSizeKB", JSGC_SYSTEM_PAGE_SIZE_KB, false) \ 92 _("semispaceNurseryEnabled", JSGC_SEMISPACE_NURSERY_ENABLED, true) \ 93 _("generateMissingAllocSites", JSGC_GENERATE_MISSING_ALLOC_SITES, true) \ 94 _("highFrequencyMode", JSGC_HIGH_FREQUENCY_MODE, false) \ 95 _("storeBufferEntries", JSGC_STORE_BUFFER_ENTRIES, true) \ 96 _("storeBufferScaling", JSGC_STORE_BUFFER_SCALING, true) 97 98 // Get the key and writability give a GC parameter name. 99 extern bool GetGCParameterInfo(const char* name, JSGCParamKey* keyOut, 100 bool* writableOut); 101 102 namespace gc { 103 104 void FinishGC(JSContext* cx, JS::GCReason = JS::GCReason::FINISH_GC); 105 106 // Abstract base class for exclusive heap access for tracing or GC. 107 class MOZ_RAII AutoHeapSession { 108 public: 109 ~AutoHeapSession(); 110 111 protected: 112 AutoHeapSession(GCRuntime* gc, JS::HeapState state); 113 114 private: 115 AutoHeapSession(const AutoHeapSession&) = delete; 116 void operator=(const AutoHeapSession&) = delete; 117 118 GCRuntime* gc; 119 JS::HeapState prevState; 120 mozilla::Maybe<AutoGeckoProfilerEntry> profilingStackFrame; 121 }; 122 123 class MOZ_RAII AutoTraceSession : public AutoHeapSession, 124 public JS::AutoCheckCannotGC { 125 public: 126 explicit AutoTraceSession(JSRuntime* rt); 127 }; 128 129 struct MOZ_RAII AutoFinishGC { 130 explicit AutoFinishGC(JSContext* cx, JS::GCReason reason) { 131 FinishGC(cx, reason); 132 } 133 }; 134 135 // This class should be used by any code that needs exclusive access to the heap 136 // in order to trace through it. 137 class MOZ_RAII AutoPrepareForTracing : private AutoFinishGC, 138 public AutoTraceSession { 139 public: 140 explicit AutoPrepareForTracing(JSContext* cx) 141 : AutoFinishGC(cx, JS::GCReason::PREPARE_FOR_TRACING), 142 AutoTraceSession(JS_GetRuntime(cx)) {} 143 }; 144 145 } // namespace gc 146 147 extern void TraceRuntime(JSTracer* trc); 148 149 // Trace roots but don't evict the nursery first; used from DumpHeap. 150 extern void TraceRuntimeWithoutEviction(JSTracer* trc); 151 152 extern void ReleaseAllJITCode(JS::GCContext* gcx); 153 154 extern void PrepareForDebugGC(JSRuntime* rt); 155 156 /* Functions for managing cross compartment gray pointers. */ 157 158 extern void NotifyGCNukeWrapper(JSContext* cx, JSObject* wrapper); 159 160 extern unsigned NotifyGCPreSwap(JSObject* a, JSObject* b); 161 162 extern void NotifyGCPostSwap(JSObject* a, JSObject* b, unsigned removedFlags); 163 164 using IterateChunkCallback = void (*)(JSRuntime*, void*, gc::ArenaChunk*, 165 const JS::AutoRequireNoGC&); 166 using IterateZoneCallback = void (*)(JSRuntime*, void*, JS::Zone*, 167 const JS::AutoRequireNoGC&); 168 using IterateArenaCallback = void (*)(JSRuntime*, void*, gc::Arena*, 169 JS::TraceKind, size_t, 170 const JS::AutoRequireNoGC&); 171 using IterateCellCallback = void (*)(JSRuntime*, void*, JS::GCCellPtr, size_t, 172 const JS::AutoRequireNoGC&); 173 174 /* 175 * This function calls |zoneCallback| on every zone, |realmCallback| on 176 * every realm, |arenaCallback| on every in-use arena, and |cellCallback| 177 * on every in-use cell in the GC heap. 178 * 179 * Note that no read barrier is triggered on the cells passed to cellCallback, 180 * so no these pointers must not escape the callback. 181 */ 182 extern void IterateHeapUnbarriered(JSContext* cx, void* data, 183 IterateZoneCallback zoneCallback, 184 JS::IterateRealmCallback realmCallback, 185 IterateArenaCallback arenaCallback, 186 IterateCellCallback cellCallback, 187 const js::gc::AutoTraceSession& session); 188 189 /* 190 * This function is like IterateHeapUnbarriered, but does it for a single zone. 191 */ 192 extern void IterateHeapUnbarrieredForZone( 193 JSContext* cx, JS::Zone* zone, void* data, IterateZoneCallback zoneCallback, 194 JS::IterateRealmCallback realmCallback, IterateArenaCallback arenaCallback, 195 IterateCellCallback cellCallback, const js::gc::AutoTraceSession& session); 196 197 /* 198 * Invoke chunkCallback on every in-use chunk. 199 */ 200 extern void IterateChunks(JSContext* cx, void* data, 201 IterateChunkCallback chunkCallback, 202 const js::gc::AutoTraceSession& session); 203 204 using IterateScriptCallback = void (*)(JSRuntime*, void*, BaseScript*, 205 const JS::AutoRequireNoGC&); 206 207 /* 208 * Invoke scriptCallback on every in-use script for the given realm or for all 209 * realms if it is null. The scripts may or may not have bytecode. 210 */ 211 extern void IterateScripts(JSContext* cx, JS::Realm* realm, void* data, 212 IterateScriptCallback scriptCallback); 213 214 JS::Realm* NewRealm(JSContext* cx, JSPrincipals* principals, 215 const JS::RealmOptions& options); 216 217 namespace gc { 218 219 void WaitForBackgroundTasks(JSContext* cx); 220 221 enum VerifierType { PreBarrierVerifier, PostBarrierVerifier }; 222 223 #ifdef JS_GC_ZEAL 224 225 extern const char ZealModeHelpText[]; 226 227 /* Check that write barriers have been used correctly. See gc/Verifier.cpp. */ 228 void VerifyBarriers(JSRuntime* rt, VerifierType type); 229 230 void MaybeVerifyBarriers(JSContext* cx, bool always = false); 231 232 void DumpArenaInfo(); 233 234 #else 235 236 static inline void VerifyBarriers(JSRuntime* rt, VerifierType type) {} 237 238 static inline void MaybeVerifyBarriers(JSContext* cx, bool always = false) {} 239 240 #endif 241 242 /* 243 * Instances of this class prevent GC from happening while they are live. If an 244 * allocation causes a heap threshold to be exceeded, no GC will be performed 245 * and the allocation will succeed. Allocation may still fail for other reasons. 246 * 247 * Use of this class is highly discouraged, since without GC system memory can 248 * become exhausted and this can cause crashes at places where we can't handle 249 * allocation failure. 250 * 251 * Use of this is permissible in situations where it would be impossible (or at 252 * least very difficult) to tolerate GC and where only a fixed number of objects 253 * are allocated, such as: 254 * 255 * - error reporting 256 * - JIT bailout handling 257 * - brain transplants (JSObject::swap) 258 * - debugging utilities not exposed to the browser 259 * 260 * This works by updating the |JSContext::suppressGC| counter which is checked 261 * at the start of GC. 262 */ 263 class MOZ_RAII JS_HAZ_GC_SUPPRESSED AutoSuppressGC 264 : public JS::AutoRequireNoGC { 265 int32_t& suppressGC_; 266 267 public: 268 explicit AutoSuppressGC(JSContext* cx); 269 270 ~AutoSuppressGC() { suppressGC_--; } 271 }; 272 273 const char* StateName(State state); 274 275 } /* namespace gc */ 276 277 /* Use this to avoid assertions when manipulating the wrapper map. */ 278 class MOZ_RAII AutoDisableProxyCheck { 279 public: 280 #ifdef DEBUG 281 AutoDisableProxyCheck(); 282 ~AutoDisableProxyCheck(); 283 #else 284 AutoDisableProxyCheck() {} 285 #endif 286 }; 287 288 struct MOZ_RAII AutoDisableCompactingGC { 289 explicit AutoDisableCompactingGC(JSContext* cx); 290 ~AutoDisableCompactingGC(); 291 292 private: 293 JSContext* cx; 294 }; 295 296 /* 297 * Dynamically select the GC heap to allocate into for a graph of GC things. 298 * 299 * Initially |heap()| will return Heap::Default to select nursery allocation, 300 * but when a specified number of nursery collections have been triggered it 301 * switches to returning Heap::Tenured. 302 */ 303 class MOZ_RAII AutoSelectGCHeap { 304 public: 305 explicit AutoSelectGCHeap(JSContext* cx, 306 size_t allowedNurseryCollections = 0); 307 ~AutoSelectGCHeap(); 308 309 gc::Heap heap() const { return heap_; } 310 operator gc::Heap() const { return heap_; } 311 312 void onNurseryCollectionEnd(); 313 314 private: 315 static void NurseryCollectionCallback(JSContext* cx, 316 JS::GCNurseryProgress progress, 317 JS::GCReason reason, void* data); 318 319 JSContext* cx_; 320 size_t allowedNurseryCollections_; 321 gc::Heap heap_ = gc::Heap::Default; 322 }; 323 324 } /* namespace js */ 325 326 #endif /* gc_GC_h */