1 // Copyright 2021 the V8 project authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #ifndef INCLUDE_V8_EMBEDDER_HEAP_H_ 6 #define INCLUDE_V8_EMBEDDER_HEAP_H_ 7 8 #include <stddef.h> 9 #include <stdint.h> 10 11 #include <utility> 12 #include <vector> 13 14 #include "cppgc/common.h" 15 #include "v8-local-handle.h" // NOLINT(build/include_directory) 16 #include "v8-traced-handle.h" // NOLINT(build/include_directory) 17 #include "v8config.h" // NOLINT(build/include_directory) 18 19 namespace v8 { 20 21 class Data; 22 class Isolate; 23 class Value; 24 25 namespace internal { 26 class LocalEmbedderHeapTracer; 27 } // namespace internal 28 29 /** 30 * Handler for embedder roots on non-unified heap garbage collections. 31 */ 32 class V8_EXPORT EmbedderRootsHandler { 33 public: 34 virtual ~EmbedderRootsHandler() = default; 35 36 /** 37 * Returns true if the TracedGlobal handle should be considered as root for 38 * the currently running non-tracing garbage collection and false otherwise. 39 * The default implementation will keep all TracedGlobal references as roots. 40 * 41 * If this returns false, then V8 may decide that the object referred to by 42 * such a handle is reclaimed. In that case: 43 * - No action is required if handles are used with destructors, i.e., by just 44 * using |TracedGlobal|. 45 * - When run without destructors, i.e., by using |TracedReference|, V8 calls 46 * |ResetRoot|. 47 * 48 * Note that the |handle| is different from the handle that the embedder holds 49 * for retaining the object. The embedder may use |WrapperClassId()| to 50 * distinguish cases where it wants handles to be treated as roots from not 51 * being treated as roots. 52 */ 53 virtual bool IsRoot(const v8::TracedReference<v8::Value>& handle) = 0; 54 virtual bool IsRoot(const v8::TracedGlobal<v8::Value>& handle) = 0; 55 56 /** 57 * Used in combination with |IsRoot|. Called by V8 when an 58 * object that is backed by a handle is reclaimed by a non-tracing garbage 59 * collection. It is up to the embedder to reset the original handle. 60 * 61 * Note that the |handle| is different from the handle that the embedder holds 62 * for retaining the object. It is up to the embedder to find the original 63 * handle via the object or class id. 64 */ 65 virtual void ResetRoot(const v8::TracedReference<v8::Value>& handle) = 0; 66 }; 67 68 /** 69 * Interface for tracing through the embedder heap. During a V8 garbage 70 * collection, V8 collects hidden fields of all potential wrappers, and at the 71 * end of its marking phase iterates the collection and asks the embedder to 72 * trace through its heap and use reporter to report each JavaScript object 73 * reachable from any of the given wrappers. 74 */ 75 class V8_EXPORT EmbedderHeapTracer { 76 public: 77 using EmbedderStackState = cppgc::EmbedderStackState; 78 79 enum TraceFlags : uint64_t { 80 kNoFlags = 0, 81 kReduceMemory = 1 << 0, 82 kForced = 1 << 2, 83 }; 84 85 /** 86 * Interface for iterating through TracedGlobal handles. 87 */ 88 class V8_EXPORT TracedGlobalHandleVisitor { 89 public: 90 virtual ~TracedGlobalHandleVisitor() = default; VisitTracedGlobalHandle(const TracedGlobal<Value> & handle)91 virtual void VisitTracedGlobalHandle(const TracedGlobal<Value>& handle) {} VisitTracedReference(const TracedReference<Value> & handle)92 virtual void VisitTracedReference(const TracedReference<Value>& handle) {} 93 }; 94 95 /** 96 * Summary of a garbage collection cycle. See |TraceEpilogue| on how the 97 * summary is reported. 98 */ 99 struct TraceSummary { 100 /** 101 * Time spent managing the retained memory in milliseconds. This can e.g. 102 * include the time tracing through objects in the embedder. 103 */ 104 double time = 0.0; 105 106 /** 107 * Memory retained by the embedder through the |EmbedderHeapTracer| 108 * mechanism in bytes. 109 */ 110 size_t allocated_size = 0; 111 }; 112 113 virtual ~EmbedderHeapTracer() = default; 114 115 /** 116 * Iterates all TracedGlobal handles created for the v8::Isolate the tracer is 117 * attached to. 118 */ 119 void IterateTracedGlobalHandles(TracedGlobalHandleVisitor* visitor); 120 121 /** 122 * Called by the embedder to set the start of the stack which is e.g. used by 123 * V8 to determine whether handles are used from stack or heap. 124 */ 125 void SetStackStart(void* stack_start); 126 127 /** 128 * Called by the embedder to notify V8 of an empty execution stack. 129 */ 130 V8_DEPRECATE_SOON( 131 "This call only optimized internal caches which V8 is able to figure out " 132 "on its own now.") 133 void NotifyEmptyEmbedderStack(); 134 135 /** 136 * Called by v8 to register internal fields of found wrappers. 137 * 138 * The embedder is expected to store them somewhere and trace reachable 139 * wrappers from them when called through |AdvanceTracing|. 140 */ 141 virtual void RegisterV8References( 142 const std::vector<std::pair<void*, void*>>& embedder_fields) = 0; 143 144 void RegisterEmbedderReference(const BasicTracedReference<v8::Data>& ref); 145 146 /** 147 * Called at the beginning of a GC cycle. 148 */ TracePrologue(TraceFlags flags)149 virtual void TracePrologue(TraceFlags flags) {} 150 151 /** 152 * Called to advance tracing in the embedder. 153 * 154 * The embedder is expected to trace its heap starting from wrappers reported 155 * by RegisterV8References method, and report back all reachable wrappers. 156 * Furthermore, the embedder is expected to stop tracing by the given 157 * deadline. A deadline of infinity means that tracing should be finished. 158 * 159 * Returns |true| if tracing is done, and false otherwise. 160 */ 161 virtual bool AdvanceTracing(double deadline_in_ms) = 0; 162 163 /* 164 * Returns true if there no more tracing work to be done (see AdvanceTracing) 165 * and false otherwise. 166 */ 167 virtual bool IsTracingDone() = 0; 168 169 /** 170 * Called at the end of a GC cycle. 171 * 172 * Note that allocation is *not* allowed within |TraceEpilogue|. Can be 173 * overriden to fill a |TraceSummary| that is used by V8 to schedule future 174 * garbage collections. 175 */ TraceEpilogue(TraceSummary * trace_summary)176 virtual void TraceEpilogue(TraceSummary* trace_summary) {} 177 178 /** 179 * Called upon entering the final marking pause. No more incremental marking 180 * steps will follow this call. 181 */ 182 virtual void EnterFinalPause(EmbedderStackState stack_state) = 0; 183 184 /* 185 * Called by the embedder to request immediate finalization of the currently 186 * running tracing phase that has been started with TracePrologue and not 187 * yet finished with TraceEpilogue. 188 * 189 * Will be a noop when currently not in tracing. 190 * 191 * This is an experimental feature. 192 */ 193 void FinalizeTracing(); 194 195 /** 196 * See documentation on EmbedderRootsHandler. 197 */ 198 virtual bool IsRootForNonTracingGC( 199 const v8::TracedReference<v8::Value>& handle); 200 virtual bool IsRootForNonTracingGC(const v8::TracedGlobal<v8::Value>& handle); 201 202 /** 203 * See documentation on EmbedderRootsHandler. 204 */ 205 virtual void ResetHandleInNonTracingGC( 206 const v8::TracedReference<v8::Value>& handle); 207 208 /* 209 * Called by the embedder to immediately perform a full garbage collection. 210 * 211 * Should only be used in testing code. 212 */ 213 void GarbageCollectionForTesting(EmbedderStackState stack_state); 214 215 /* 216 * Called by the embedder to signal newly allocated or freed memory. Not bound 217 * to tracing phases. Embedders should trade off when increments are reported 218 * as V8 may consult global heuristics on whether to trigger garbage 219 * collection on this change. 220 */ 221 void IncreaseAllocatedSize(size_t bytes); 222 void DecreaseAllocatedSize(size_t bytes); 223 224 /* 225 * Returns the v8::Isolate this tracer is attached too and |nullptr| if it 226 * is not attached to any v8::Isolate. 227 */ isolate()228 v8::Isolate* isolate() const { return isolate_; } 229 230 protected: 231 v8::Isolate* isolate_ = nullptr; 232 233 friend class internal::LocalEmbedderHeapTracer; 234 }; 235 236 } // namespace v8 237 238 #endif // INCLUDE_V8_EMBEDDER_HEAP_H_ 239