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/objects.h"
16 : #include "src/utils.h"
17 :
18 : namespace v8 {
19 : namespace internal {
20 :
21 : class HeapStats;
22 : class RootVisitor;
23 :
24 : // Structure for tracking global handles.
25 : // A single list keeps all the allocated global handles.
26 : // Destroyed handles stay in the list but is added to the free list.
27 : // At GC the destroyed global handles are removed from the free list
28 : // and deallocated.
29 :
30 : enum WeaknessType {
31 : // Embedder gets a handle to the dying object.
32 : FINALIZER_WEAK,
33 : // In the following cases, the embedder gets the parameter they passed in
34 : // earlier, and 0 or 2 first embedder fields. Note that the internal
35 : // fields must contain aligned non-V8 pointers. Getting pointers to V8
36 : // objects through this interface would be GC unsafe so in that case the
37 : // embedder gets a null pointer instead.
38 : PHANTOM_WEAK,
39 : PHANTOM_WEAK_2_EMBEDDER_FIELDS,
40 : // The handle is automatically reset by the garbage collector when
41 : // the object is no longer reachable.
42 : PHANTOM_WEAK_RESET_HANDLE
43 : };
44 :
45 : class GlobalHandles {
46 : public:
47 : ~GlobalHandles();
48 :
49 : // Creates a new global handle that is alive until Destroy is called.
50 : Handle<Object> Create(Object value);
51 : Handle<Object> Create(Address value);
52 :
53 : template <typename T>
54 : Handle<T> Create(T value) {
55 : static_assert(std::is_base_of<Object, T>::value, "static type violation");
56 : // The compiler should only pick this method if T is not Object.
57 : static_assert(!std::is_same<Object, T>::value, "compiler error");
58 4158960 : return Handle<T>::cast(Create(Object(value)));
59 : }
60 :
61 : // Copy a global handle
62 : static Handle<Object> CopyGlobal(Address* location);
63 :
64 : // Destroy a global handle.
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 :
80 : static void MakeWeak(Address** location_addr);
81 :
82 : static void AnnotateStrongRetainer(Address* location, const char* label);
83 :
84 : void RecordStats(HeapStats* stats);
85 :
86 : // Returns the current number of handles to global objects.
87 : int global_handles_count() const {
88 : return number_of_global_handles_;
89 : }
90 :
91 : size_t NumberOfPhantomHandleResets() {
92 : return number_of_phantom_handle_resets_;
93 : }
94 :
95 : void ResetNumberOfPhantomHandleResets() {
96 15 : number_of_phantom_handle_resets_ = 0;
97 : }
98 :
99 0 : size_t NumberOfNewSpaceNodes() { return new_space_nodes_.size(); }
100 :
101 : // Clear the weakness of a global handle.
102 : static void* ClearWeakness(Address* location);
103 :
104 : // Tells whether global handle is near death.
105 : static bool IsNearDeath(Address* location);
106 :
107 : // Tells whether global handle is weak.
108 : static bool IsWeak(Address* location);
109 :
110 : int InvokeFirstPassWeakCallbacks();
111 :
112 : // Process pending weak handles.
113 : // Returns the number of freed nodes.
114 : int PostGarbageCollectionProcessing(
115 : GarbageCollector collector, const v8::GCCallbackFlags gc_callback_flags);
116 :
117 : void IterateStrongRoots(RootVisitor* v);
118 :
119 : void IterateWeakRoots(RootVisitor* v);
120 :
121 : void IterateAllRoots(RootVisitor* v);
122 :
123 : void IterateAllNewSpaceRoots(RootVisitor* v);
124 : void IterateNewSpaceRoots(RootVisitor* v, size_t start, size_t end);
125 :
126 : // Iterates over all handles that have embedder-assigned class ID.
127 : void IterateAllRootsWithClassIds(v8::PersistentHandleVisitor* v);
128 :
129 : // Iterates over all handles in the new space that have embedder-assigned
130 : // class ID.
131 : void IterateAllRootsInNewSpaceWithClassIds(v8::PersistentHandleVisitor* v);
132 :
133 : // Iterate over all handles in the new space that are weak, unmodified
134 : // and have class IDs
135 : void IterateWeakRootsInNewSpaceWithClassIds(v8::PersistentHandleVisitor* v);
136 :
137 : // Iterates over weak roots on the heap.
138 : void IterateWeakRootsForFinalizers(RootVisitor* v);
139 : void IterateWeakRootsForPhantomHandles(
140 : WeakSlotCallbackWithHeap should_reset_handle);
141 :
142 : // Marks all handles that should be finalized based on the predicate
143 : // |should_reset_handle| as pending.
144 : void IdentifyWeakHandles(WeakSlotCallbackWithHeap should_reset_handle);
145 :
146 : // NOTE: Five ...NewSpace... functions below are used during
147 : // scavenge collections and iterate over sets of handles that are
148 : // guaranteed to contain all handles holding new space objects (but
149 : // may also include old space objects).
150 :
151 : // Iterates over strong and dependent handles. See the note above.
152 : void IterateNewSpaceStrongAndDependentRoots(RootVisitor* v);
153 :
154 : // Iterates over strong and dependent handles. See the note above.
155 : // Also marks unmodified nodes in the same iteration.
156 : void IterateNewSpaceStrongAndDependentRootsAndIdentifyUnmodified(
157 : RootVisitor* v, size_t start, size_t end);
158 :
159 : // Marks weak unmodified handles satisfying |is_dead| as pending.
160 : void MarkNewSpaceWeakUnmodifiedObjectsPending(
161 : WeakSlotCallbackWithHeap is_dead);
162 :
163 : // Iterates over weak independent or unmodified handles.
164 : // See the note above.
165 : void IterateNewSpaceWeakUnmodifiedRootsForFinalizers(RootVisitor* v);
166 : void IterateNewSpaceWeakUnmodifiedRootsForPhantomHandles(
167 : RootVisitor* v, WeakSlotCallbackWithHeap should_reset_handle);
168 :
169 : // Identify unmodified objects that are in weak state and marks them
170 : // unmodified
171 : void IdentifyWeakUnmodifiedObjects(WeakSlotCallback is_unmodified);
172 :
173 : // Tear down the global handle structure.
174 : void TearDown();
175 :
176 13956144 : Isolate* isolate() { return isolate_; }
177 :
178 : #ifdef DEBUG
179 : void PrintStats();
180 : void Print();
181 : #endif // DEBUG
182 :
183 : void InvokeSecondPassPhantomCallbacks();
184 :
185 : private:
186 : // Internal node structures.
187 : class Node;
188 : template <class NodeType>
189 : class NodeBlock;
190 : template <class BlockType>
191 : class NodeIterator;
192 : template <class NodeType>
193 : class NodeSpace;
194 : class PendingPhantomCallback;
195 :
196 : explicit GlobalHandles(Isolate* isolate);
197 :
198 : void InvokeSecondPassPhantomCallbacksFromTask();
199 : int PostScavengeProcessing(int initial_post_gc_processing_count);
200 : int PostMarkSweepProcessing(int initial_post_gc_processing_count);
201 : void InvokeOrScheduleSecondPassPhantomCallbacks(bool synchronous_second_pass);
202 : void UpdateListOfNewSpaceNodes();
203 : void ApplyPersistentHandleVisitor(v8::PersistentHandleVisitor* visitor,
204 : Node* node);
205 :
206 : Isolate* isolate_;
207 :
208 : std::unique_ptr<NodeSpace<Node>> regular_nodes_;
209 : // Contains all nodes holding new space objects. Note: when the list
210 : // is accessed, some of the objects may have been promoted already.
211 : std::vector<Node*> new_space_nodes_;
212 :
213 : // Field always containing the number of handles to global objects.
214 : int number_of_global_handles_;
215 :
216 : int post_gc_processing_count_;
217 :
218 : size_t number_of_phantom_handle_resets_;
219 :
220 : std::vector<PendingPhantomCallback> pending_phantom_callbacks_;
221 : std::vector<PendingPhantomCallback> second_pass_callbacks_;
222 : bool second_pass_callbacks_task_posted_ = false;
223 :
224 : friend class Isolate;
225 :
226 : DISALLOW_COPY_AND_ASSIGN(GlobalHandles);
227 : };
228 :
229 :
230 : class GlobalHandles::PendingPhantomCallback {
231 : public:
232 : typedef v8::WeakCallbackInfo<void> Data;
233 : PendingPhantomCallback(
234 : Node* node, Data::Callback callback, void* parameter,
235 : void* embedder_fields[v8::kEmbedderFieldsInWeakCallback])
236 3680826 : : node_(node), callback_(callback), parameter_(parameter) {
237 7361652 : for (int i = 0; i < v8::kEmbedderFieldsInWeakCallback; ++i) {
238 7361652 : embedder_fields_[i] = embedder_fields[i];
239 : }
240 : }
241 :
242 : void Invoke(Isolate* isolate);
243 :
244 : Node* node() { return node_; }
245 : Data::Callback callback() { return callback_; }
246 :
247 : private:
248 : Node* node_;
249 : Data::Callback callback_;
250 : void* parameter_;
251 : void* embedder_fields_[v8::kEmbedderFieldsInWeakCallback];
252 : };
253 :
254 :
255 : class EternalHandles {
256 : public:
257 : EternalHandles();
258 : ~EternalHandles();
259 :
260 : int NumberOfHandles() { return size_; }
261 :
262 : // Create an EternalHandle, overwriting the index.
263 : void Create(Isolate* isolate, Object object, int* index);
264 :
265 : // Grab the handle for an existing EternalHandle.
266 : inline Handle<Object> Get(int index) {
267 : return Handle<Object>(GetLocation(index));
268 : }
269 :
270 : // Iterates over all handles.
271 : void IterateAllRoots(RootVisitor* visitor);
272 : // Iterates over all handles which might be in new space.
273 : void IterateNewSpaceRoots(RootVisitor* visitor);
274 : // Rebuilds new space list.
275 : void PostGarbageCollectionProcessing();
276 :
277 : private:
278 : static const int kInvalidIndex = -1;
279 : static const int kShift = 8;
280 : static const int kSize = 1 << kShift;
281 : static const int kMask = 0xff;
282 :
283 : // Gets the slot for an index. This returns an Address* rather than an
284 : // ObjectSlot in order to avoid #including slots.h in this header file.
285 : inline Address* GetLocation(int index) {
286 : DCHECK(index >= 0 && index < size_);
287 152822 : return &blocks_[index >> kShift][index & kMask];
288 : }
289 :
290 : int size_;
291 : std::vector<Address*> blocks_;
292 : std::vector<int> new_space_indices_;
293 :
294 : DISALLOW_COPY_AND_ASSIGN(EternalHandles);
295 : };
296 :
297 :
298 : } // namespace internal
299 : } // namespace v8
300 :
301 : #endif // V8_GLOBAL_HANDLES_H_
|