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 : #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>
52 11314 : 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 733290 : 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 : void RecordStats(HeapStats* stats);
81 :
82 : // Returns the current number of handles to global objects.
83 : int global_handles_count() const {
84 : return number_of_global_handles_;
85 : }
86 :
87 : size_t NumberOfPhantomHandleResets() {
88 : return number_of_phantom_handle_resets_;
89 : }
90 :
91 : void ResetNumberOfPhantomHandleResets() {
92 15 : number_of_phantom_handle_resets_ = 0;
93 : }
94 :
95 0 : size_t NumberOfNewSpaceNodes() { return new_space_nodes_.size(); }
96 :
97 : // Clear the weakness of a global handle.
98 : static void* ClearWeakness(Object** location);
99 :
100 : // Mark the reference to this object independent.
101 : static void MarkIndependent(Object** location);
102 :
103 : static bool IsIndependent(Object** location);
104 :
105 : // Tells whether global handle is near death.
106 : static bool IsNearDeath(Object** location);
107 :
108 : // Tells whether global handle is weak.
109 : static bool IsWeak(Object** location);
110 :
111 : // Process pending weak handles.
112 : // Returns the number of freed nodes.
113 : int PostGarbageCollectionProcessing(
114 : GarbageCollector collector, const v8::GCCallbackFlags gc_callback_flags);
115 :
116 : // Iterates over all strong handles.
117 : void IterateStrongRoots(RootVisitor* v);
118 :
119 : // Iterates over all handles.
120 : void IterateAllRoots(RootVisitor* v);
121 :
122 : void IterateAllNewSpaceRoots(RootVisitor* v);
123 : void IterateNewSpaceRoots(RootVisitor* v, size_t start, size_t end);
124 :
125 : // Iterates over all handles that have embedder-assigned class ID.
126 : void IterateAllRootsWithClassIds(v8::PersistentHandleVisitor* v);
127 :
128 : // Iterates over all handles in the new space that have embedder-assigned
129 : // class ID.
130 : void IterateAllRootsInNewSpaceWithClassIds(v8::PersistentHandleVisitor* v);
131 :
132 : // Iterate over all handles in the new space that are weak, unmodified
133 : // and have class IDs
134 : void IterateWeakRootsInNewSpaceWithClassIds(v8::PersistentHandleVisitor* v);
135 :
136 : // Iterates over all weak roots in heap.
137 : void IterateWeakRoots(RootVisitor* v);
138 :
139 : // Find all weak handles satisfying the callback predicate, mark
140 : // them as pending.
141 : void IdentifyWeakHandles(WeakSlotCallback f);
142 :
143 : // NOTE: Five ...NewSpace... functions below are used during
144 : // scavenge collections and iterate over sets of handles that are
145 : // guaranteed to contain all handles holding new space objects (but
146 : // may also include old space objects).
147 :
148 : // Iterates over strong and dependent handles. See the note above.
149 : void IterateNewSpaceStrongAndDependentRoots(RootVisitor* v);
150 :
151 : // Iterates over strong and dependent handles. See the note above.
152 : // Also marks unmodified nodes in the same iteration.
153 : void IterateNewSpaceStrongAndDependentRootsAndIdentifyUnmodified(
154 : RootVisitor* v, size_t start, size_t end);
155 :
156 : // Finds weak independent or unmodified handles satisfying
157 : // the callback predicate and marks them as pending. See the note above.
158 : void MarkNewSpaceWeakUnmodifiedObjectsPending(
159 : WeakSlotCallbackWithHeap is_unscavenged);
160 :
161 : // Iterates over weak independent or unmodified handles.
162 : // See the note above.
163 : void IterateNewSpaceWeakUnmodifiedRoots(RootVisitor* v);
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 :
172 : Isolate* isolate() { return isolate_; }
173 :
174 : #ifdef DEBUG
175 : void PrintStats();
176 : void Print();
177 : #endif // DEBUG
178 :
179 : private:
180 : // Internal node structures.
181 : class Node;
182 : class NodeBlock;
183 : class NodeIterator;
184 : class PendingPhantomCallback;
185 : class PendingPhantomCallbacksSecondPassTask;
186 :
187 : explicit GlobalHandles(Isolate* isolate);
188 :
189 : // Helpers for PostGarbageCollectionProcessing.
190 : static void InvokeSecondPassPhantomCallbacks(
191 : std::vector<PendingPhantomCallback>* callbacks, Isolate* isolate);
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 :
223 : friend class Isolate;
224 :
225 : DISALLOW_COPY_AND_ASSIGN(GlobalHandles);
226 : };
227 :
228 :
229 : class GlobalHandles::PendingPhantomCallback {
230 : public:
231 : typedef v8::WeakCallbackInfo<void> Data;
232 : PendingPhantomCallback(
233 : Node* node, Data::Callback callback, void* parameter,
234 : void* embedder_fields[v8::kEmbedderFieldsInWeakCallback])
235 122694 : : node_(node), callback_(callback), parameter_(parameter) {
236 245388 : for (int i = 0; i < v8::kEmbedderFieldsInWeakCallback; ++i) {
237 245388 : embedder_fields_[i] = embedder_fields[i];
238 : }
239 : }
240 :
241 : void Invoke(Isolate* isolate);
242 :
243 : Node* node() { return node_; }
244 : Data::Callback callback() { return callback_; }
245 :
246 : private:
247 : Node* node_;
248 : Data::Callback callback_;
249 : void* parameter_;
250 : void* embedder_fields_[v8::kEmbedderFieldsInWeakCallback];
251 : };
252 :
253 :
254 : class EternalHandles {
255 : public:
256 : enum SingletonHandle {
257 : DATE_CACHE_VERSION,
258 :
259 : NUMBER_OF_SINGLETON_HANDLES
260 : };
261 :
262 : EternalHandles();
263 : ~EternalHandles();
264 :
265 : int NumberOfHandles() { return size_; }
266 :
267 : // Create an EternalHandle, overwriting the index.
268 : void Create(Isolate* isolate, Object* object, int* index);
269 :
270 : // Grab the handle for an existing EternalHandle.
271 : inline Handle<Object> Get(int index) {
272 : return Handle<Object>(GetLocation(index));
273 : }
274 :
275 : // Grab the handle for an existing SingletonHandle.
276 73337 : inline Handle<Object> GetSingleton(SingletonHandle singleton) {
277 : DCHECK(Exists(singleton));
278 146674 : return Get(singleton_handles_[singleton]);
279 : }
280 :
281 : // Checks whether a SingletonHandle has been assigned.
282 73337 : inline bool Exists(SingletonHandle singleton) {
283 73343 : return singleton_handles_[singleton] != kInvalidIndex;
284 : }
285 :
286 : // Assign a SingletonHandle to an empty slot and returns the handle.
287 83 : Handle<Object> CreateSingleton(Isolate* isolate,
288 : Object* object,
289 : SingletonHandle singleton) {
290 83 : Create(isolate, object, &singleton_handles_[singleton]);
291 166 : return Get(singleton_handles_[singleton]);
292 : }
293 :
294 : // Iterates over all handles.
295 : void IterateAllRoots(RootVisitor* visitor);
296 : // Iterates over all handles which might be in new space.
297 : void IterateNewSpaceRoots(RootVisitor* visitor);
298 : // Rebuilds new space list.
299 : void PostGarbageCollectionProcessing(Heap* heap);
300 :
301 : private:
302 : static const int kInvalidIndex = -1;
303 : static const int kShift = 8;
304 : static const int kSize = 1 << kShift;
305 : static const int kMask = 0xff;
306 :
307 : // Gets the slot for an index
308 : inline Object** GetLocation(int index) {
309 : DCHECK(index >= 0 && index < size_);
310 299464 : return &blocks_[index >> kShift][index & kMask];
311 : }
312 :
313 : int size_;
314 : std::vector<Object**> blocks_;
315 : std::vector<int> new_space_indices_;
316 : int singleton_handles_[NUMBER_OF_SINGLETON_HANDLES];
317 :
318 : DISALLOW_COPY_AND_ASSIGN(EternalHandles);
319 : };
320 :
321 :
322 : } // namespace internal
323 : } // namespace v8
324 :
325 : #endif // V8_GLOBAL_HANDLES_H_
|