• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2011 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 V8_HANDLES_GLOBAL_HANDLES_H_
6 #define V8_HANDLES_GLOBAL_HANDLES_H_
7 
8 #include <memory>
9 #include <type_traits>
10 #include <utility>
11 #include <vector>
12 
13 #include "include/v8-callbacks.h"
14 #include "include/v8-persistent-handle.h"
15 #include "include/v8-profiler.h"
16 #include "include/v8-traced-handle.h"
17 #include "src/handles/handles.h"
18 #include "src/heap/heap.h"
19 #include "src/objects/heap-object.h"
20 #include "src/objects/objects.h"
21 #include "src/utils/utils.h"
22 
23 namespace v8 {
24 namespace internal {
25 
26 class HeapStats;
27 class RootVisitor;
28 
29 enum WeaknessType {
30   // Embedder gets a handle to the dying object.
31   FINALIZER_WEAK,
32   // In the following cases, the embedder gets the parameter they passed in
33   // earlier, and 0 or 2 first embedder fields. Note that the internal
34   // fields must contain aligned non-V8 pointers.  Getting pointers to V8
35   // objects through this interface would be GC unsafe so in that case the
36   // embedder gets a null pointer instead.
37   PHANTOM_WEAK,
38   PHANTOM_WEAK_2_EMBEDDER_FIELDS,
39   // The handle is automatically reset by the garbage collector when
40   // the object is no longer reachable.
41   PHANTOM_WEAK_RESET_HANDLE
42 };
43 
44 // Global handles hold handles that are independent of stack-state and can have
45 // callbacks and finalizers attached to them.
46 class V8_EXPORT_PRIVATE GlobalHandles final {
47  public:
48   static void EnableMarkingBarrier(Isolate*);
49   static void DisableMarkingBarrier(Isolate*);
50 
51   GlobalHandles(const GlobalHandles&) = delete;
52   GlobalHandles& operator=(const GlobalHandles&) = delete;
53 
54   template <class NodeType>
55   class NodeBlock;
56 
57   //
58   // API for regular handles.
59   //
60 
61   static void MoveGlobal(Address** from, Address** to);
62 
63   static Handle<Object> CopyGlobal(Address* location);
64 
65   static void Destroy(Address* location);
66 
67   // Make the global handle weak and set the callback parameter for the
68   // handle.  When the garbage collector recognizes that only weak global
69   // handles point to an object the callback function is invoked (for each
70   // handle) with the handle and corresponding parameter as arguments.  By
71   // default the handle still contains a pointer to the object that is being
72   // collected.  For this reason the object is not collected until the next
73   // GC.  For a phantom weak handle the handle is cleared (set to a Smi)
74   // before the callback is invoked, but the handle can still be identified
75   // in the callback by using the location() of the handle.
76   static void MakeWeak(Address* location, void* parameter,
77                        WeakCallbackInfo<void>::Callback weak_callback,
78                        v8::WeakCallbackType type);
79   static void MakeWeak(Address** location_addr);
80 
81   static void AnnotateStrongRetainer(Address* location, const char* label);
82 
83   // Clear the weakness of a global handle.
84   static void* ClearWeakness(Address* location);
85 
86   // Tells whether global handle is weak.
87   static bool IsWeak(Address* location);
88 
89   //
90   // API for traced handles.
91   //
92 
93   static void MoveTracedReference(Address** from, Address** to);
94   static void CopyTracedReference(const Address* const* from, Address** to);
95   static void DestroyTracedReference(Address* location);
96   static void MarkTraced(Address* location);
97 
98   explicit GlobalHandles(Isolate* isolate);
99   ~GlobalHandles();
100 
101   // Creates a new global handle that is alive until Destroy is called.
102   Handle<Object> Create(Object value);
103   Handle<Object> Create(Address value);
104 
105   template <typename T>
106   inline Handle<T> Create(T value);
107 
108   Handle<Object> CreateTraced(Object value, Address* slot,
109                               GlobalHandleStoreMode store_mode,
110                               bool is_on_stack);
111   Handle<Object> CreateTraced(Object value, Address* slot,
112                               GlobalHandleStoreMode store_mode);
113   Handle<Object> CreateTraced(Address value, Address* slot,
114                               GlobalHandleStoreMode store_mode);
115 
116   void RecordStats(HeapStats* stats);
117 
118   size_t InvokeFirstPassWeakCallbacks();
119   void InvokeSecondPassPhantomCallbacks();
120 
121   // Process pending weak handles.
122   // Returns the number of freed nodes.
123   size_t PostGarbageCollectionProcessing(
124       GarbageCollector collector, const v8::GCCallbackFlags gc_callback_flags);
125 
126   void IterateStrongRoots(RootVisitor* v);
127   void IterateStrongStackRoots(RootVisitor* v);
128   void IterateWeakRoots(RootVisitor* v);
129   void IterateAllRoots(RootVisitor* v);
130   void IterateAllYoungRoots(RootVisitor* v);
131 
132   // Iterates over all handles that have embedder-assigned class ID.
133   void IterateAllRootsWithClassIds(v8::PersistentHandleVisitor* v);
134 
135   // Iterates over all handles in the new space that have embedder-assigned
136   // class ID.
137   void IterateAllYoungRootsWithClassIds(v8::PersistentHandleVisitor* v);
138 
139   // Iterate over all handles in the new space that are weak, unmodified
140   // and have class IDs
141   void IterateYoungWeakRootsWithClassIds(v8::PersistentHandleVisitor* v);
142 
143   // Iterates over all traces handles represented by TracedGlobal.
144   void IterateTracedNodes(
145       v8::EmbedderHeapTracer::TracedGlobalHandleVisitor* visitor);
146 
147   // Marks handles with finalizers on the predicate |should_reset_handle| as
148   // pending.
149   void IterateWeakRootsIdentifyFinalizers(
150       WeakSlotCallbackWithHeap should_reset_handle);
151   // Uses the provided visitor |v| to mark handles with finalizers that are
152   // pending.
153   void IterateWeakRootsForFinalizers(RootVisitor* v);
154   // Marks handles that are phantom or have callbacks based on the predicate
155   // |should_reset_handle| as pending.
156   void IterateWeakRootsForPhantomHandles(
157       WeakSlotCallbackWithHeap should_reset_handle);
158 
159   //  Note: The following *Young* methods are used for the Scavenger to
160   //  identify and process handles in the young generation. The set of young
161   //  handles is complete but the methods may encounter handles that are
162   //  already in old space.
163 
164   // Iterates over strong and dependent handles. See the note above.
165   void IterateYoungStrongAndDependentRoots(RootVisitor* v);
166 
167   // Marks weak unmodified handles satisfying |is_dead| as pending.
168   void MarkYoungWeakDeadObjectsPending(WeakSlotCallbackWithHeap is_dead);
169 
170   // Iterates over weak independent or unmodified handles.
171   // See the note above.
172   void IterateYoungWeakDeadObjectsForFinalizers(RootVisitor* v);
173   void IterateYoungWeakObjectsForPhantomHandles(
174       RootVisitor* v, WeakSlotCallbackWithHeap should_reset_handle);
175 
176   // Identify unmodified objects that are in weak state and marks them
177   // unmodified
178   void IdentifyWeakUnmodifiedObjects(WeakSlotCallback is_unmodified);
179 
isolate()180   Isolate* isolate() const { return isolate_; }
181 
182   size_t TotalSize() const;
183   size_t UsedSize() const;
184 
185   // Number of global handles.
186   size_t handles_count() const;
187 
GetAndResetGlobalHandleResetCount()188   size_t GetAndResetGlobalHandleResetCount() {
189     size_t old = number_of_phantom_handle_resets_;
190     number_of_phantom_handle_resets_ = 0;
191     return old;
192   }
193 
194   void SetStackStart(void* stack_start);
195   void NotifyEmptyEmbedderStack();
196   void CleanupOnStackReferencesBelowCurrentStackPosition();
197   size_t NumberOfOnStackHandlesForTesting();
198 
199 #ifdef DEBUG
200   void PrintStats();
201   void Print();
202 #endif  // DEBUG
203 
204  private:
205   // Internal node structures.
206   class Node;
207   template <class BlockType>
208   class NodeIterator;
209   template <class NodeType>
210   class NodeSpace;
211   class PendingPhantomCallback;
212   class TracedNode;
213   class OnStackTracedNodeSpace;
214 
215   static GlobalHandles* From(const TracedNode*);
216 
217   bool InRecursiveGC(unsigned gc_processing_counter);
218 
219   void InvokeSecondPassPhantomCallbacksFromTask();
220   void InvokeOrScheduleSecondPassPhantomCallbacks(bool synchronous_second_pass);
221   size_t PostScavengeProcessing(unsigned post_processing_count);
222   size_t PostMarkSweepProcessing(unsigned post_processing_count);
223 
224   template <typename T>
225   size_t InvokeFirstPassWeakCallbacks(
226       std::vector<std::pair<T*, PendingPhantomCallback>>* pending);
227 
228   template <typename T>
229   void UpdateAndCompactListOfYoungNode(std::vector<T*>* node_list);
230   void UpdateListOfYoungNodes();
231 
232   void ApplyPersistentHandleVisitor(v8::PersistentHandleVisitor* visitor,
233                                     Node* node);
234 
235   Isolate* const isolate_;
236   bool is_marking_ = false;
237 
238   std::unique_ptr<NodeSpace<Node>> regular_nodes_;
239   // Contains all nodes holding young objects. Note: when the list
240   // is accessed, some of the objects may have been promoted already.
241   std::vector<Node*> young_nodes_;
242 
243   std::unique_ptr<NodeSpace<TracedNode>> traced_nodes_;
244   std::vector<TracedNode*> traced_young_nodes_;
245   std::unique_ptr<OnStackTracedNodeSpace> on_stack_nodes_;
246 
247   size_t number_of_phantom_handle_resets_ = 0;
248 
249   std::vector<std::pair<Node*, PendingPhantomCallback>>
250       regular_pending_phantom_callbacks_;
251   std::vector<std::pair<TracedNode*, PendingPhantomCallback>>
252       traced_pending_phantom_callbacks_;
253   std::vector<PendingPhantomCallback> second_pass_callbacks_;
254   bool second_pass_callbacks_task_posted_ = false;
255   bool running_second_pass_callbacks_ = false;
256 
257   // Counter for recursive garbage collections during callback processing.
258   unsigned post_gc_processing_count_ = 0;
259 };
260 
261 class GlobalHandles::PendingPhantomCallback final {
262  public:
263   using Data = v8::WeakCallbackInfo<void>;
264 
265   enum InvocationType { kFirstPass, kSecondPass };
266 
PendingPhantomCallback(Data::Callback callback,void * parameter,void * embedder_fields[v8::kEmbedderFieldsInWeakCallback])267   PendingPhantomCallback(
268       Data::Callback callback, void* parameter,
269       void* embedder_fields[v8::kEmbedderFieldsInWeakCallback])
270       : callback_(callback), parameter_(parameter) {
271     for (int i = 0; i < v8::kEmbedderFieldsInWeakCallback; ++i) {
272       embedder_fields_[i] = embedder_fields[i];
273     }
274   }
275 
276   void Invoke(Isolate* isolate, InvocationType type);
277 
callback()278   Data::Callback callback() const { return callback_; }
279 
280  private:
281   Data::Callback callback_;
282   void* parameter_;
283   void* embedder_fields_[v8::kEmbedderFieldsInWeakCallback];
284 };
285 
286 class EternalHandles final {
287  public:
288   EternalHandles() = default;
289   ~EternalHandles();
290   EternalHandles(const EternalHandles&) = delete;
291   EternalHandles& operator=(const EternalHandles&) = delete;
292 
293   // Create an EternalHandle, overwriting the index.
294   V8_EXPORT_PRIVATE void Create(Isolate* isolate, Object object, int* index);
295 
296   // Grab the handle for an existing EternalHandle.
Get(int index)297   inline Handle<Object> Get(int index) {
298     return Handle<Object>(GetLocation(index));
299   }
300 
301   // Iterates over all handles.
302   void IterateAllRoots(RootVisitor* visitor);
303   // Iterates over all handles which might be in the young generation.
304   void IterateYoungRoots(RootVisitor* visitor);
305   // Rebuilds new space list.
306   void PostGarbageCollectionProcessing();
307 
handles_count()308   size_t handles_count() const { return size_; }
309 
310  private:
311   static const int kInvalidIndex = -1;
312   static const int kShift = 8;
313   static const int kSize = 1 << kShift;
314   static const int kMask = 0xff;
315 
316   // Gets the slot for an index. This returns an Address* rather than an
317   // ObjectSlot in order to avoid #including slots.h in this header file.
GetLocation(int index)318   inline Address* GetLocation(int index) {
319     DCHECK(index >= 0 && index < size_);
320     return &blocks_[index >> kShift][index & kMask];
321   }
322 
323   int size_ = 0;
324   std::vector<Address*> blocks_;
325   std::vector<int> young_node_indices_;
326 };
327 
328 // A vector of global Handles which automatically manages the backing of those
329 // Handles as a vector of strong-rooted addresses. Handles returned by the
330 // vector are valid as long as they are present in the vector.
331 template <typename T>
332 class GlobalHandleVector {
333  public:
334   class Iterator {
335    public:
Iterator(std::vector<Address,StrongRootBlockAllocator>::iterator it)336     explicit Iterator(
337         std::vector<Address, StrongRootBlockAllocator>::iterator it)
338         : it_(it) {}
339     Iterator& operator++() {
340       ++it_;
341       return *this;
342     }
343     Handle<T> operator*() { return Handle<T>(&*it_); }
344     bool operator!=(Iterator& that) { return it_ != that.it_; }
345 
346    private:
347     std::vector<Address, StrongRootBlockAllocator>::iterator it_;
348   };
349 
GlobalHandleVector(Heap * heap)350   explicit GlobalHandleVector(Heap* heap)
351       : locations_(StrongRootBlockAllocator(heap)) {}
352 
353   Handle<T> operator[](size_t i) { return Handle<T>(&locations_[i]); }
354 
size()355   size_t size() const { return locations_.size(); }
empty()356   bool empty() const { return locations_.empty(); }
357 
Push(T val)358   void Push(T val) { locations_.push_back(val.ptr()); }
359   // Handles into the GlobalHandleVector become invalid when they are removed,
360   // so "pop" returns a raw object rather than a handle.
361   inline T Pop();
362 
begin()363   Iterator begin() { return Iterator(locations_.begin()); }
end()364   Iterator end() { return Iterator(locations_.end()); }
365 
366  private:
367   std::vector<Address, StrongRootBlockAllocator> locations_;
368 };
369 
370 }  // namespace internal
371 }  // namespace v8
372 
373 #endif  // V8_HANDLES_GLOBAL_HANDLES_H_
374