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 <utility>
10 : #include <vector>
11 :
12 : #include "include/v8.h"
13 : #include "include/v8-profiler.h"
14 :
15 : #include "src/handles.h"
16 : #include "src/objects.h"
17 : #include "src/utils.h"
18 :
19 : namespace v8 {
20 : namespace internal {
21 :
22 : class HeapStats;
23 : class RootVisitor;
24 :
25 : enum WeaknessType {
26 : // Embedder gets a handle to the dying object.
27 : FINALIZER_WEAK,
28 : // In the following cases, the embedder gets the parameter they passed in
29 : // earlier, and 0 or 2 first embedder fields. Note that the internal
30 : // fields must contain aligned non-V8 pointers. Getting pointers to V8
31 : // objects through this interface would be GC unsafe so in that case the
32 : // embedder gets a null pointer instead.
33 : PHANTOM_WEAK,
34 : PHANTOM_WEAK_2_EMBEDDER_FIELDS,
35 : // The handle is automatically reset by the garbage collector when
36 : // the object is no longer reachable.
37 : PHANTOM_WEAK_RESET_HANDLE
38 : };
39 :
40 : // Global handles hold handles that are independent of stack-state and can have
41 : // callbacks and finalizers attached to them.
42 : class GlobalHandles final {
43 : public:
44 : template <class NodeType>
45 : class NodeBlock;
46 :
47 : //
48 : // API for regular handles.
49 : //
50 :
51 : static void MoveGlobal(Address** from, Address** to);
52 :
53 : static Handle<Object> CopyGlobal(Address* location);
54 :
55 : static void Destroy(Address* location);
56 :
57 : // Make the global handle weak and set the callback parameter for the
58 : // handle. When the garbage collector recognizes that only weak global
59 : // handles point to an object the callback function is invoked (for each
60 : // handle) with the handle and corresponding parameter as arguments. By
61 : // default the handle still contains a pointer to the object that is being
62 : // collected. For this reason the object is not collected until the next
63 : // GC. For a phantom weak handle the handle is cleared (set to a Smi)
64 : // before the callback is invoked, but the handle can still be identified
65 : // in the callback by using the location() of the handle.
66 : static void MakeWeak(Address* location, void* parameter,
67 : WeakCallbackInfo<void>::Callback weak_callback,
68 : v8::WeakCallbackType type);
69 : static void MakeWeak(Address** location_addr);
70 :
71 : static void AnnotateStrongRetainer(Address* location, const char* label);
72 :
73 : // Clear the weakness of a global handle.
74 : static void* ClearWeakness(Address* location);
75 :
76 : // Tells whether global handle is near death.
77 : static bool IsNearDeath(Address* location);
78 :
79 : // Tells whether global handle is weak.
80 : static bool IsWeak(Address* location);
81 :
82 : //
83 : // API for traced handles.
84 : //
85 :
86 : static void MoveTracedGlobal(Address** from, Address** to);
87 : static void DestroyTraced(Address* location);
88 : static void SetFinalizationCallbackForTraced(
89 : Address* location, void* parameter,
90 : WeakCallbackInfo<void>::Callback callback);
91 :
92 : explicit GlobalHandles(Isolate* isolate);
93 : ~GlobalHandles();
94 :
95 : // Creates a new global handle that is alive until Destroy is called.
96 : Handle<Object> Create(Object value);
97 : Handle<Object> Create(Address value);
98 :
99 : template <typename T>
100 : Handle<T> Create(T value) {
101 : static_assert(std::is_base_of<Object, T>::value, "static type violation");
102 : // The compiler should only pick this method if T is not Object.
103 : static_assert(!std::is_same<Object, T>::value, "compiler error");
104 3400428 : return Handle<T>::cast(Create(Object(value)));
105 : }
106 :
107 : Handle<Object> CreateTraced(Object value, Address* slot);
108 : Handle<Object> CreateTraced(Address value, Address* slot);
109 :
110 : void RecordStats(HeapStats* stats);
111 :
112 : size_t InvokeFirstPassWeakCallbacks();
113 : void InvokeSecondPassPhantomCallbacks();
114 :
115 : // Process pending weak handles.
116 : // Returns the number of freed nodes.
117 : size_t PostGarbageCollectionProcessing(
118 : GarbageCollector collector, const v8::GCCallbackFlags gc_callback_flags);
119 :
120 : void IterateStrongRoots(RootVisitor* v);
121 : void IterateWeakRoots(RootVisitor* v);
122 : void IterateAllRoots(RootVisitor* v);
123 : void IterateAllYoungRoots(RootVisitor* v);
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 IterateAllYoungRootsWithClassIds(v8::PersistentHandleVisitor* v);
131 :
132 : // Iterate over all handles in the new space that are weak, unmodified
133 : // and have class IDs
134 : void IterateYoungWeakRootsWithClassIds(v8::PersistentHandleVisitor* v);
135 :
136 : // Iterates over all traces handles represented by TracedGlobal.
137 : void IterateTracedNodes(
138 : v8::EmbedderHeapTracer::TracedGlobalHandleVisitor* visitor);
139 :
140 : // Marks handles with finalizers on the predicate |should_reset_handle| as
141 : // pending.
142 : void IterateWeakRootsIdentifyFinalizers(
143 : WeakSlotCallbackWithHeap should_reset_handle);
144 : // Uses the provided visitor |v| to mark handles with finalizers that are
145 : // pending.
146 : void IterateWeakRootsForFinalizers(RootVisitor* v);
147 : // Marks handles that are phantom or have callbacks based on the predicate
148 : // |should_reset_handle| as pending.
149 : void IterateWeakRootsForPhantomHandles(
150 : WeakSlotCallbackWithHeap should_reset_handle);
151 :
152 : // Note: The following *Young* methods are used for the Scavenger to
153 : // identify and process handles in the young generation. The set of young
154 : // handles is complete but the methods may encounter handles that are
155 : // already in old space.
156 :
157 : // Iterates over strong and dependent handles. See the note above.
158 : void IterateYoungStrongAndDependentRoots(RootVisitor* v);
159 :
160 : // Marks weak unmodified handles satisfying |is_dead| as pending.
161 : void MarkYoungWeakUnmodifiedObjectsPending(WeakSlotCallbackWithHeap is_dead);
162 :
163 : // Iterates over weak independent or unmodified handles.
164 : // See the note above.
165 : void IterateYoungWeakUnmodifiedRootsForFinalizers(RootVisitor* v);
166 : void IterateYoungWeakUnmodifiedRootsForPhantomHandles(
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 12539026 : Isolate* isolate() const { return isolate_; }
174 :
175 : // Number of global handles.
176 : size_t handles_count() const { return handles_count_; }
177 :
178 : size_t GetAndResetGlobalHandleResetCount() {
179 15 : size_t old = number_of_phantom_handle_resets_;
180 15 : number_of_phantom_handle_resets_ = 0;
181 : return old;
182 : }
183 :
184 : #ifdef DEBUG
185 : void PrintStats();
186 : void Print();
187 : #endif // DEBUG
188 :
189 : private:
190 : // Internal node structures.
191 : class Node;
192 : template <class BlockType>
193 : class NodeIterator;
194 : template <class NodeType>
195 : class NodeSpace;
196 : class PendingPhantomCallback;
197 : class TracedNode;
198 :
199 : bool InRecursiveGC(unsigned gc_processing_counter);
200 :
201 : void InvokeSecondPassPhantomCallbacksFromTask();
202 : void InvokeOrScheduleSecondPassPhantomCallbacks(bool synchronous_second_pass);
203 : size_t PostScavengeProcessing(unsigned post_processing_count);
204 : size_t PostMarkSweepProcessing(unsigned post_processing_count);
205 :
206 : template <typename T>
207 : size_t InvokeFirstPassWeakCallbacks(
208 : std::vector<std::pair<T*, PendingPhantomCallback>>* pending);
209 :
210 : template <typename T>
211 : void UpdateAndCompactListOfYoungNode(std::vector<T*>* node_list);
212 : void UpdateListOfYoungNodes();
213 :
214 : void ApplyPersistentHandleVisitor(v8::PersistentHandleVisitor* visitor,
215 : Node* node);
216 :
217 : Isolate* const isolate_;
218 :
219 : std::unique_ptr<NodeSpace<Node>> regular_nodes_;
220 : // Contains all nodes holding young objects. Note: when the list
221 : // is accessed, some of the objects may have been promoted already.
222 : std::vector<Node*> young_nodes_;
223 :
224 : std::unique_ptr<NodeSpace<TracedNode>> traced_nodes_;
225 : std::vector<TracedNode*> traced_young_nodes_;
226 :
227 : // Field always containing the number of handles to global objects.
228 : size_t handles_count_ = 0;
229 : size_t number_of_phantom_handle_resets_ = 0;
230 :
231 : std::vector<std::pair<Node*, PendingPhantomCallback>>
232 : regular_pending_phantom_callbacks_;
233 : std::vector<std::pair<TracedNode*, PendingPhantomCallback>>
234 : traced_pending_phantom_callbacks_;
235 : std::vector<PendingPhantomCallback> second_pass_callbacks_;
236 : bool second_pass_callbacks_task_posted_ = false;
237 :
238 : // Counter for recursive garbage collections during callback processing.
239 : unsigned post_gc_processing_count_ = 0;
240 :
241 : DISALLOW_COPY_AND_ASSIGN(GlobalHandles);
242 : };
243 :
244 : class GlobalHandles::PendingPhantomCallback final {
245 : public:
246 : typedef v8::WeakCallbackInfo<void> Data;
247 :
248 : enum InvocationType { kFirstPass, kSecondPass };
249 :
250 : PendingPhantomCallback(
251 : Data::Callback callback, void* parameter,
252 : void* embedder_fields[v8::kEmbedderFieldsInWeakCallback])
253 : : callback_(callback), parameter_(parameter) {
254 5970630 : for (int i = 0; i < v8::kEmbedderFieldsInWeakCallback; ++i) {
255 5970630 : embedder_fields_[i] = embedder_fields[i];
256 : }
257 : }
258 :
259 : void Invoke(Isolate* isolate, InvocationType type);
260 :
261 : Data::Callback callback() const { return callback_; }
262 :
263 : private:
264 : Data::Callback callback_;
265 : void* parameter_;
266 : void* embedder_fields_[v8::kEmbedderFieldsInWeakCallback];
267 : };
268 :
269 : class EternalHandles final {
270 : public:
271 : EternalHandles() = default;
272 : ~EternalHandles();
273 :
274 : // Create an EternalHandle, overwriting the index.
275 : void Create(Isolate* isolate, Object object, int* index);
276 :
277 : // Grab the handle for an existing EternalHandle.
278 : inline Handle<Object> Get(int index) {
279 : return Handle<Object>(GetLocation(index));
280 : }
281 :
282 : // Iterates over all handles.
283 : void IterateAllRoots(RootVisitor* visitor);
284 : // Iterates over all handles which might be in the young generation.
285 : void IterateYoungRoots(RootVisitor* visitor);
286 : // Rebuilds new space list.
287 : void PostGarbageCollectionProcessing();
288 :
289 : size_t handles_count() const { return size_; }
290 :
291 : private:
292 : static const int kInvalidIndex = -1;
293 : static const int kShift = 8;
294 : static const int kSize = 1 << kShift;
295 : static const int kMask = 0xff;
296 :
297 : // Gets the slot for an index. This returns an Address* rather than an
298 : // ObjectSlot in order to avoid #including slots.h in this header file.
299 : inline Address* GetLocation(int index) {
300 : DCHECK(index >= 0 && index < size_);
301 152836 : return &blocks_[index >> kShift][index & kMask];
302 : }
303 :
304 : int size_ = 0;
305 : std::vector<Address*> blocks_;
306 : std::vector<int> young_node_indices_;
307 :
308 : DISALLOW_COPY_AND_ASSIGN(EternalHandles);
309 : };
310 :
311 : } // namespace internal
312 : } // namespace v8
313 :
314 : #endif // V8_GLOBAL_HANDLES_H_
|