1 // Copyright 2020 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_CPPGC_HEAP_CONSISTENCY_H_ 6 #define INCLUDE_CPPGC_HEAP_CONSISTENCY_H_ 7 8 #include <cstddef> 9 10 #include "cppgc/internal/write-barrier.h" 11 #include "cppgc/macros.h" 12 #include "cppgc/trace-trait.h" 13 #include "v8config.h" // NOLINT(build/include_directory) 14 15 namespace cppgc { 16 17 class HeapHandle; 18 19 namespace subtle { 20 21 /** 22 * **DO NOT USE: Use the appropriate managed types.** 23 * 24 * Consistency helpers that aid in maintaining a consistent internal state of 25 * the garbage collector. 26 */ 27 class HeapConsistency final { 28 public: 29 using WriteBarrierParams = internal::WriteBarrier::Params; 30 using WriteBarrierType = internal::WriteBarrier::Type; 31 32 /** 33 * Gets the required write barrier type for a specific write. 34 * 35 * \param slot Slot containing the pointer to the object. The slot itself 36 * must reside in an object that has been allocated using 37 * `MakeGarbageCollected()`. 38 * \param value The pointer to the object. May be an interior pointer to an 39 * interface of the actual object. 40 * \param params Parameters that may be used for actual write barrier calls. 41 * Only filled if return value indicates that a write barrier is needed. The 42 * contents of the `params` are an implementation detail. 43 * \returns whether a write barrier is needed and which barrier to invoke. 44 */ GetWriteBarrierType(const void * slot,const void * value,WriteBarrierParams & params)45 static V8_INLINE WriteBarrierType GetWriteBarrierType( 46 const void* slot, const void* value, WriteBarrierParams& params) { 47 return internal::WriteBarrier::GetWriteBarrierType(slot, value, params); 48 } 49 50 /** 51 * Gets the required write barrier type for a specific write. 52 * 53 * \param slot Slot to some part of an object. The object must not necessarily 54 have been allocated using `MakeGarbageCollected()` but can also live 55 off-heap or on stack. 56 * \param params Parameters that may be used for actual write barrier calls. 57 * Only filled if return value indicates that a write barrier is needed. The 58 * contents of the `params` are an implementation detail. 59 * \param callback Callback returning the corresponding heap handle. The 60 * callback is only invoked if the heap cannot otherwise be figured out. The 61 * callback must not allocate. 62 * \returns whether a write barrier is needed and which barrier to invoke. 63 */ 64 template <typename HeapHandleCallback> 65 static V8_INLINE WriteBarrierType GetWriteBarrierType(const void * slot,WriteBarrierParams & params,HeapHandleCallback callback)66 GetWriteBarrierType(const void* slot, WriteBarrierParams& params, 67 HeapHandleCallback callback) { 68 return internal::WriteBarrier::GetWriteBarrierType(slot, params, callback); 69 } 70 71 /** 72 * Gets the required write barrier type for a specific write. 73 * This version is meant to be used in conjunction with with a marking write 74 * barrier barrier which doesn't consider the slot. 75 * 76 * \param value The pointer to the object. May be an interior pointer to an 77 * interface of the actual object. 78 * \param params Parameters that may be used for actual write barrier calls. 79 * Only filled if return value indicates that a write barrier is needed. The 80 * contents of the `params` are an implementation detail. 81 * \returns whether a write barrier is needed and which barrier to invoke. 82 */ 83 static V8_INLINE WriteBarrierType GetWriteBarrierType(const void * value,WriteBarrierParams & params)84 GetWriteBarrierType(const void* value, WriteBarrierParams& params) { 85 return internal::WriteBarrier::GetWriteBarrierType(value, params); 86 } 87 88 /** 89 * Conservative Dijkstra-style write barrier that processes an object if it 90 * has not yet been processed. 91 * 92 * \param params The parameters retrieved from `GetWriteBarrierType()`. 93 * \param object The pointer to the object. May be an interior pointer to a 94 * an interface of the actual object. 95 */ DijkstraWriteBarrier(const WriteBarrierParams & params,const void * object)96 static V8_INLINE void DijkstraWriteBarrier(const WriteBarrierParams& params, 97 const void* object) { 98 internal::WriteBarrier::DijkstraMarkingBarrier(params, object); 99 } 100 101 /** 102 * Conservative Dijkstra-style write barrier that processes a range of 103 * elements if they have not yet been processed. 104 * 105 * \param params The parameters retrieved from `GetWriteBarrierType()`. 106 * \param first_element Pointer to the first element that should be processed. 107 * The slot itself must reside in an object that has been allocated using 108 * `MakeGarbageCollected()`. 109 * \param element_size Size of the element in bytes. 110 * \param number_of_elements Number of elements that should be processed, 111 * starting with `first_element`. 112 * \param trace_callback The trace callback that should be invoked for each 113 * element if necessary. 114 */ DijkstraWriteBarrierRange(const WriteBarrierParams & params,const void * first_element,size_t element_size,size_t number_of_elements,TraceCallback trace_callback)115 static V8_INLINE void DijkstraWriteBarrierRange( 116 const WriteBarrierParams& params, const void* first_element, 117 size_t element_size, size_t number_of_elements, 118 TraceCallback trace_callback) { 119 internal::WriteBarrier::DijkstraMarkingBarrierRange( 120 params, first_element, element_size, number_of_elements, 121 trace_callback); 122 } 123 124 /** 125 * Steele-style write barrier that re-processes an object if it has already 126 * been processed. 127 * 128 * \param params The parameters retrieved from `GetWriteBarrierType()`. 129 * \param object The pointer to the object which must point to an object that 130 * has been allocated using `MakeGarbageCollected()`. Interior pointers are 131 * not supported. 132 */ SteeleWriteBarrier(const WriteBarrierParams & params,const void * object)133 static V8_INLINE void SteeleWriteBarrier(const WriteBarrierParams& params, 134 const void* object) { 135 internal::WriteBarrier::SteeleMarkingBarrier(params, object); 136 } 137 138 /** 139 * Generational barrier for maintaining consistency when running with multiple 140 * generations. 141 * 142 * \param params The parameters retrieved from `GetWriteBarrierType()`. 143 * \param slot Slot containing the pointer to the object. The slot itself 144 * must reside in an object that has been allocated using 145 * `MakeGarbageCollected()`. 146 */ GenerationalBarrier(const WriteBarrierParams & params,const void * slot)147 static V8_INLINE void GenerationalBarrier(const WriteBarrierParams& params, 148 const void* slot) { 149 internal::WriteBarrier::GenerationalBarrier(params, slot); 150 } 151 152 /** 153 * Generational barrier for source object that may contain outgoing pointers 154 * to objects in young generation. 155 * 156 * \param params The parameters retrieved from `GetWriteBarrierType()`. 157 * \param inner_pointer Pointer to the source object. 158 */ GenerationalBarrierForSourceObject(const WriteBarrierParams & params,const void * inner_pointer)159 static V8_INLINE void GenerationalBarrierForSourceObject( 160 const WriteBarrierParams& params, const void* inner_pointer) { 161 internal::WriteBarrier::GenerationalBarrierForSourceObject(params, 162 inner_pointer); 163 } 164 165 private: 166 HeapConsistency() = delete; 167 }; 168 169 /** 170 * Disallows garbage collection finalizations. Any garbage collection triggers 171 * result in a crash when in this scope. 172 * 173 * Note that the garbage collector already covers paths that can lead to garbage 174 * collections, so user code does not require checking 175 * `IsGarbageCollectionAllowed()` before allocations. 176 */ 177 class V8_EXPORT V8_NODISCARD DisallowGarbageCollectionScope final { 178 CPPGC_STACK_ALLOCATED(); 179 180 public: 181 /** 182 * \returns whether garbage collections are currently allowed. 183 */ 184 static bool IsGarbageCollectionAllowed(HeapHandle& heap_handle); 185 186 /** 187 * Enters a disallow garbage collection scope. Must be paired with `Leave()`. 188 * Prefer a scope instance of `DisallowGarbageCollectionScope`. 189 * 190 * \param heap_handle The corresponding heap. 191 */ 192 static void Enter(HeapHandle& heap_handle); 193 194 /** 195 * Leaves a disallow garbage collection scope. Must be paired with `Enter()`. 196 * Prefer a scope instance of `DisallowGarbageCollectionScope`. 197 * 198 * \param heap_handle The corresponding heap. 199 */ 200 static void Leave(HeapHandle& heap_handle); 201 202 /** 203 * Constructs a scoped object that automatically enters and leaves a disallow 204 * garbage collection scope based on its lifetime. 205 * 206 * \param heap_handle The corresponding heap. 207 */ 208 explicit DisallowGarbageCollectionScope(HeapHandle& heap_handle); 209 ~DisallowGarbageCollectionScope(); 210 211 DisallowGarbageCollectionScope(const DisallowGarbageCollectionScope&) = 212 delete; 213 DisallowGarbageCollectionScope& operator=( 214 const DisallowGarbageCollectionScope&) = delete; 215 216 private: 217 HeapHandle& heap_handle_; 218 }; 219 220 /** 221 * Avoids invoking garbage collection finalizations. Already running garbage 222 * collection phase are unaffected by this scope. 223 * 224 * Should only be used temporarily as the scope has an impact on memory usage 225 * and follow up garbage collections. 226 */ 227 class V8_EXPORT V8_NODISCARD NoGarbageCollectionScope final { 228 CPPGC_STACK_ALLOCATED(); 229 230 public: 231 /** 232 * Enters a no garbage collection scope. Must be paired with `Leave()`. Prefer 233 * a scope instance of `NoGarbageCollectionScope`. 234 * 235 * \param heap_handle The corresponding heap. 236 */ 237 static void Enter(HeapHandle& heap_handle); 238 239 /** 240 * Leaves a no garbage collection scope. Must be paired with `Enter()`. Prefer 241 * a scope instance of `NoGarbageCollectionScope`. 242 * 243 * \param heap_handle The corresponding heap. 244 */ 245 static void Leave(HeapHandle& heap_handle); 246 247 /** 248 * Constructs a scoped object that automatically enters and leaves a no 249 * garbage collection scope based on its lifetime. 250 * 251 * \param heap_handle The corresponding heap. 252 */ 253 explicit NoGarbageCollectionScope(HeapHandle& heap_handle); 254 ~NoGarbageCollectionScope(); 255 256 NoGarbageCollectionScope(const NoGarbageCollectionScope&) = delete; 257 NoGarbageCollectionScope& operator=(const NoGarbageCollectionScope&) = delete; 258 259 private: 260 HeapHandle& heap_handle_; 261 }; 262 263 } // namespace subtle 264 } // namespace cppgc 265 266 #endif // INCLUDE_CPPGC_HEAP_CONSISTENCY_H_ 267