tor-browser

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

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