• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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