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