• 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_GLOBAL_HANDLES_H_
6 #define V8_GLOBAL_HANDLES_H_
7 
8 #include <type_traits>
9 #include <vector>
10 
11 #include "include/v8.h"
12 #include "include/v8-profiler.h"
13 
14 #include "src/handles.h"
15 #include "src/utils.h"
16 
17 namespace v8 {
18 namespace internal {
19 
20 class HeapStats;
21 class RootVisitor;
22 
23 // Structure for tracking global handles.
24 // A single list keeps all the allocated global handles.
25 // Destroyed handles stay in the list but is added to the free list.
26 // At GC the destroyed global handles are removed from the free list
27 // and deallocated.
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 class GlobalHandles {
45  public:
46   ~GlobalHandles();
47 
48   // Creates a new global handle that is alive until Destroy is called.
49   Handle<Object> Create(Object* value);
50 
51   template <typename T>
Create(T * value)52   Handle<T> Create(T* value) {
53     static_assert(std::is_base_of<Object, T>::value, "static type violation");
54     // The compiler should only pick this method if T is not Object.
55     static_assert(!std::is_same<Object, T>::value, "compiler error");
56     return Handle<T>::cast(Create(static_cast<Object*>(value)));
57   }
58 
59   // Copy a global handle
60   static Handle<Object> CopyGlobal(Object** location);
61 
62   // Destroy a global handle.
63   static void Destroy(Object** location);
64 
65   // Make the global handle weak and set the callback parameter for the
66   // handle.  When the garbage collector recognizes that only weak global
67   // handles point to an object the callback function is invoked (for each
68   // handle) with the handle and corresponding parameter as arguments.  By
69   // default the handle still contains a pointer to the object that is being
70   // collected.  For this reason the object is not collected until the next
71   // GC.  For a phantom weak handle the handle is cleared (set to a Smi)
72   // before the callback is invoked, but the handle can still be identified
73   // in the callback by using the location() of the handle.
74   static void MakeWeak(Object** location, void* parameter,
75                        WeakCallbackInfo<void>::Callback weak_callback,
76                        v8::WeakCallbackType type);
77 
78   static void MakeWeak(Object*** location_addr);
79 
80   static void AnnotateStrongRetainer(Object** location, const char* label);
81 
82   void RecordStats(HeapStats* stats);
83 
84   // Returns the current number of handles to global objects.
global_handles_count()85   int global_handles_count() const {
86     return number_of_global_handles_;
87   }
88 
NumberOfPhantomHandleResets()89   size_t NumberOfPhantomHandleResets() {
90     return number_of_phantom_handle_resets_;
91   }
92 
ResetNumberOfPhantomHandleResets()93   void ResetNumberOfPhantomHandleResets() {
94     number_of_phantom_handle_resets_ = 0;
95   }
96 
NumberOfNewSpaceNodes()97   size_t NumberOfNewSpaceNodes() { return new_space_nodes_.size(); }
98 
99   // Clear the weakness of a global handle.
100   static void* ClearWeakness(Object** location);
101 
102   // Tells whether global handle is near death.
103   static bool IsNearDeath(Object** location);
104 
105   // Tells whether global handle is weak.
106   static bool IsWeak(Object** location);
107 
108   // Process pending weak handles.
109   // Returns the number of freed nodes.
110   int PostGarbageCollectionProcessing(
111       GarbageCollector collector, const v8::GCCallbackFlags gc_callback_flags);
112 
113   void IterateStrongRoots(RootVisitor* v);
114 
115   void IterateWeakRoots(RootVisitor* v);
116 
117   void IterateAllRoots(RootVisitor* v);
118 
119   void IterateAllNewSpaceRoots(RootVisitor* v);
120   void IterateNewSpaceRoots(RootVisitor* v, size_t start, size_t end);
121 
122   // Iterates over all handles that have embedder-assigned class ID.
123   void IterateAllRootsWithClassIds(v8::PersistentHandleVisitor* v);
124 
125   // Iterates over all handles in the new space that have embedder-assigned
126   // class ID.
127   void IterateAllRootsInNewSpaceWithClassIds(v8::PersistentHandleVisitor* v);
128 
129   // Iterate over all handles in the new space that are weak, unmodified
130   // and have class IDs
131   void IterateWeakRootsInNewSpaceWithClassIds(v8::PersistentHandleVisitor* v);
132 
133   // Iterates over weak roots on the heap.
134   void IterateWeakRootsForFinalizers(RootVisitor* v);
135   void IterateWeakRootsForPhantomHandles(
136       WeakSlotCallbackWithHeap should_reset_handle);
137 
138   // Marks all handles that should be finalized based on the predicate
139   // |should_reset_handle| as pending.
140   void IdentifyWeakHandles(WeakSlotCallbackWithHeap should_reset_handle);
141 
142   // NOTE: Five ...NewSpace... functions below are used during
143   // scavenge collections and iterate over sets of handles that are
144   // guaranteed to contain all handles holding new space objects (but
145   // may also include old space objects).
146 
147   // Iterates over strong and dependent handles. See the note above.
148   void IterateNewSpaceStrongAndDependentRoots(RootVisitor* v);
149 
150   // Iterates over strong and dependent handles. See the note above.
151   // Also marks unmodified nodes in the same iteration.
152   void IterateNewSpaceStrongAndDependentRootsAndIdentifyUnmodified(
153       RootVisitor* v, size_t start, size_t end);
154 
155   // Marks weak unmodified handles satisfying |is_dead| as pending.
156   void MarkNewSpaceWeakUnmodifiedObjectsPending(
157       WeakSlotCallbackWithHeap is_dead);
158 
159   // Iterates over weak independent or unmodified handles.
160   // See the note above.
161   void IterateNewSpaceWeakUnmodifiedRootsForFinalizers(RootVisitor* v);
162   void IterateNewSpaceWeakUnmodifiedRootsForPhantomHandles(
163       RootVisitor* v, WeakSlotCallbackWithHeap should_reset_handle);
164 
165   // Identify unmodified objects that are in weak state and marks them
166   // unmodified
167   void IdentifyWeakUnmodifiedObjects(WeakSlotCallback is_unmodified);
168 
169   // Tear down the global handle structure.
170   void TearDown();
171 
isolate()172   Isolate* isolate() { return isolate_; }
173 
174 #ifdef DEBUG
175   void PrintStats();
176   void Print();
177 #endif  // DEBUG
178 
179   void InvokeSecondPassPhantomCallbacks();
180 
181  private:
182   // Internal node structures.
183   class Node;
184   class NodeBlock;
185   class NodeIterator;
186   class PendingPhantomCallback;
187   class PendingPhantomCallbacksSecondPassTask;
188 
189   explicit GlobalHandles(Isolate* isolate);
190 
191   void InvokeSecondPassPhantomCallbacksFromTask();
192   int PostScavengeProcessing(int initial_post_gc_processing_count);
193   int PostMarkSweepProcessing(int initial_post_gc_processing_count);
194   int DispatchPendingPhantomCallbacks(bool synchronous_second_pass);
195   void UpdateListOfNewSpaceNodes();
196   void ApplyPersistentHandleVisitor(v8::PersistentHandleVisitor* visitor,
197                                     Node* node);
198 
199   Isolate* isolate_;
200 
201   // Field always containing the number of handles to global objects.
202   int number_of_global_handles_;
203 
204   // List of all allocated node blocks.
205   NodeBlock* first_block_;
206 
207   // List of node blocks with used nodes.
208   NodeBlock* first_used_block_;
209 
210   // Free list of nodes.
211   Node* first_free_;
212 
213   // Contains all nodes holding new space objects. Note: when the list
214   // is accessed, some of the objects may have been promoted already.
215   std::vector<Node*> new_space_nodes_;
216 
217   int post_gc_processing_count_;
218 
219   size_t number_of_phantom_handle_resets_;
220 
221   std::vector<PendingPhantomCallback> pending_phantom_callbacks_;
222   std::vector<PendingPhantomCallback> second_pass_callbacks_;
223   bool second_pass_callbacks_task_posted_ = false;
224 
225   friend class Isolate;
226 
227   DISALLOW_COPY_AND_ASSIGN(GlobalHandles);
228 };
229 
230 
231 class GlobalHandles::PendingPhantomCallback {
232  public:
233   typedef v8::WeakCallbackInfo<void> Data;
PendingPhantomCallback(Node * node,Data::Callback callback,void * parameter,void * embedder_fields[v8::kEmbedderFieldsInWeakCallback])234   PendingPhantomCallback(
235       Node* node, Data::Callback callback, void* parameter,
236       void* embedder_fields[v8::kEmbedderFieldsInWeakCallback])
237       : node_(node), callback_(callback), parameter_(parameter) {
238     for (int i = 0; i < v8::kEmbedderFieldsInWeakCallback; ++i) {
239       embedder_fields_[i] = embedder_fields[i];
240     }
241   }
242 
243   void Invoke(Isolate* isolate);
244 
node()245   Node* node() { return node_; }
callback()246   Data::Callback callback() { return callback_; }
247 
248  private:
249   Node* node_;
250   Data::Callback callback_;
251   void* parameter_;
252   void* embedder_fields_[v8::kEmbedderFieldsInWeakCallback];
253 };
254 
255 
256 class EternalHandles {
257  public:
258   enum SingletonHandle {
259     DATE_CACHE_VERSION,
260 
261     NUMBER_OF_SINGLETON_HANDLES
262   };
263 
264   EternalHandles();
265   ~EternalHandles();
266 
NumberOfHandles()267   int NumberOfHandles() { return size_; }
268 
269   // Create an EternalHandle, overwriting the index.
270   void Create(Isolate* isolate, Object* object, int* index);
271 
272   // Grab the handle for an existing EternalHandle.
Get(int index)273   inline Handle<Object> Get(int index) {
274     return Handle<Object>(GetLocation(index));
275   }
276 
277   // Grab the handle for an existing SingletonHandle.
GetSingleton(SingletonHandle singleton)278   inline Handle<Object> GetSingleton(SingletonHandle singleton) {
279     DCHECK(Exists(singleton));
280     return Get(singleton_handles_[singleton]);
281   }
282 
283   // Checks whether a SingletonHandle has been assigned.
Exists(SingletonHandle singleton)284   inline bool Exists(SingletonHandle singleton) {
285     return singleton_handles_[singleton] != kInvalidIndex;
286   }
287 
288   // Assign a SingletonHandle to an empty slot and returns the handle.
CreateSingleton(Isolate * isolate,Object * object,SingletonHandle singleton)289   Handle<Object> CreateSingleton(Isolate* isolate,
290                                  Object* object,
291                                  SingletonHandle singleton) {
292     Create(isolate, object, &singleton_handles_[singleton]);
293     return Get(singleton_handles_[singleton]);
294   }
295 
296   // Iterates over all handles.
297   void IterateAllRoots(RootVisitor* visitor);
298   // Iterates over all handles which might be in new space.
299   void IterateNewSpaceRoots(RootVisitor* visitor);
300   // Rebuilds new space list.
301   void PostGarbageCollectionProcessing();
302 
303  private:
304   static const int kInvalidIndex = -1;
305   static const int kShift = 8;
306   static const int kSize = 1 << kShift;
307   static const int kMask = 0xff;
308 
309   // Gets the slot for an index
GetLocation(int index)310   inline Object** GetLocation(int index) {
311     DCHECK(index >= 0 && index < size_);
312     return &blocks_[index >> kShift][index & kMask];
313   }
314 
315   int size_;
316   std::vector<Object**> blocks_;
317   std::vector<int> new_space_indices_;
318   int singleton_handles_[NUMBER_OF_SINGLETON_HANDLES];
319 
320   DISALLOW_COPY_AND_ASSIGN(EternalHandles);
321 };
322 
323 
324 }  // namespace internal
325 }  // namespace v8
326 
327 #endif  // V8_GLOBAL_HANDLES_H_
328