v8
V8 is Google’s open source high-performance JavaScript and WebAssembly engine, written in C++.
Loading...
Searching...
No Matches
global-handles.h
Go to the documentation of this file.
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_HANDLES_GLOBAL_HANDLES_H_
6#define V8_HANDLES_GLOBAL_HANDLES_H_
7
8#include <memory>
9#include <type_traits>
10#include <utility>
11#include <vector>
12
15#include "include/v8-profiler.h"
16#include "src/handles/handles.h"
17#include "src/heap/heap.h"
19#include "src/objects/objects.h"
20#include "src/utils/utils.h"
21
22namespace v8 {
23namespace internal {
24
25class HeapStats;
26class RootVisitor;
27
28// Global handles hold handles that are independent of stack-state and can have
29// callbacks and finalizers attached to them.
31 public:
32 GlobalHandles(const GlobalHandles&) = delete;
34
35 template <class NodeType>
36 class NodeBlock;
37
38 //
39 // API for regular handles.
40 //
41
42 static void MoveGlobal(Address** from, Address** to);
43
44 static IndirectHandle<Object> CopyGlobal(Address* location);
45
46 static void Destroy(Address* location);
47
48 // Make the global handle weak and set the callback parameter for the
49 // handle. When the garbage collector recognizes that only weak global
50 // handles point to an object the callback function is invoked (for each
51 // handle) with the handle and corresponding parameter as arguments. By
52 // default the handle still contains a pointer to the object that is being
53 // collected. For this reason the object is not collected until the next
54 // GC. For a phantom weak handle the handle is cleared (set to a Smi)
55 // before the callback is invoked, but the handle can still be identified
56 // in the callback by using the location() of the handle.
57 static void MakeWeak(Address* location, void* parameter,
60 static void MakeWeak(Address** location_addr);
61
62 static void AnnotateStrongRetainer(Address* location, const char* label);
63
64 // Clear the weakness of a global handle.
65 static void* ClearWeakness(Address* location);
66
67 // Tells whether global handle is weak.
68 static bool IsWeak(Address* location);
69
70 explicit GlobalHandles(Isolate* isolate);
72
73 // Creates a new global handle that is alive until Destroy is called.
75 IndirectHandle<Object> Create(Address value);
76
77 template <typename T>
78 inline IndirectHandle<T> Create(Tagged<T> value);
79
80 void RecordStats(HeapStats* stats);
81
82 size_t InvokeFirstPassWeakCallbacks();
83 void InvokeSecondPassPhantomCallbacks();
84
85 // Schedule or invoke second pass weak callbacks.
86 void PostGarbageCollectionProcessing(v8::GCCallbackFlags gc_callback_flags);
87
88 void IterateStrongRoots(RootVisitor* v);
89 void IterateWeakRoots(RootVisitor* v);
90 void IterateAllRoots(RootVisitor* v);
91 void IterateAllYoungRoots(RootVisitor* v);
92
93 // Marks handles that are phantom or have callbacks based on the predicate
94 // |should_reset_handle| as pending.
95 void IterateWeakRootsForPhantomHandles(
96 WeakSlotCallbackWithHeap should_reset_handle);
97
98 // Note: The following *Young* methods are used for the Scavenger to
99 // identify and process handles in the young generation. The set of young
100 // handles is complete but the methods may encounter handles that are
101 // already in old space.
102
103 // Iterates over strong and dependent handles. See the note above.
104 void IterateYoungStrongAndDependentRoots(RootVisitor* v);
105
106 // Processes all young weak objects:
107 // - Weak objects for which `should_reset_handle()` returns true are reset;
108 // - Others are passed to `v` iff `v` is not null.
109 void ProcessWeakYoungObjects(RootVisitor* v,
110 WeakSlotCallbackWithHeap should_reset_handle);
111
112 // Updates the list of young nodes that is maintained separately.
113 void UpdateListOfYoungNodes();
114 // Clears the list of young nodes, assuming that the young generation is
115 // empty.
116 void ClearListOfYoungNodes();
117
118 Isolate* isolate() const { return isolate_; }
119
120 size_t TotalSize() const;
121 size_t UsedSize() const;
122 // Number of global handles.
123 size_t handles_count() const;
124 size_t last_gc_custom_callbacks() const { return last_gc_custom_callbacks_; }
125
126 void IterateAllRootsForTesting(v8::PersistentHandleVisitor* v);
127
128#ifdef DEBUG
129 void PrintStats();
130 void Print();
131#endif // DEBUG
132
133 bool HasYoung() const { return !young_nodes_.empty(); }
134
135 private:
136 // Internal node structures.
137 class Node;
138 template <class BlockType>
140 template <class NodeType>
143
144 void ApplyPersistentHandleVisitor(v8::PersistentHandleVisitor* visitor,
145 Node* node);
146
147 // Clears a weak `node` for which `should_reset_node()` returns true.
148 //
149 // Returns false if a node is weak and alive which requires further
150 // processing, and true in all other cases (e.g. also strong nodes).
151 bool ResetWeakNodeIfDead(Node* node,
152 WeakSlotCallbackWithHeap should_reset_node);
153
155
156 std::unique_ptr<NodeSpace<Node>> regular_nodes_;
157 // Contains all nodes holding young objects. Note: when the list
158 // is accessed, some of the objects may have been promoted already.
159 std::vector<Node*> young_nodes_;
160 std::vector<std::pair<Node*, PendingPhantomCallback>>
162 std::vector<PendingPhantomCallback> second_pass_callbacks_;
163 bool second_pass_callbacks_task_posted_ = false;
164 size_t last_gc_custom_callbacks_ = 0;
165};
166
168 public:
170
172
174 Data::Callback callback, void* parameter,
175 void* embedder_fields[v8::kEmbedderFieldsInWeakCallback])
176 : callback_(callback), parameter_(parameter) {
177 for (int i = 0; i < v8::kEmbedderFieldsInWeakCallback; ++i) {
178 embedder_fields_[i] = embedder_fields[i];
179 }
180 }
181
182 void Invoke(Isolate* isolate, InvocationType type);
183
185
186 private:
190};
191
192class EternalHandles final {
193 public:
194 EternalHandles() = default;
198
199 // Create an EternalHandle, overwriting the index.
200 V8_EXPORT_PRIVATE void Create(Isolate* isolate, Tagged<Object> object,
201 int* index);
202
203 // Grab the handle for an existing EternalHandle.
204 inline IndirectHandle<Object> Get(int index) {
205 return IndirectHandle<Object>(GetLocation(index));
206 }
207
208 // Iterates over all handles.
209 void IterateAllRoots(RootVisitor* visitor);
210 // Iterates over all handles which might be in the young generation.
211 void IterateYoungRoots(RootVisitor* visitor);
212 // Rebuilds new space list.
214
215 size_t handles_count() const { return size_; }
216
217 private:
218 static const int kInvalidIndex = -1;
219 static const int kShift = 8;
220 static const int kSize = 1 << kShift;
221 static const int kMask = 0xff;
222
223 // Gets the slot for an index. This returns an Address* rather than an
224 // ObjectSlot in order to avoid #including slots.h in this header file.
225 inline Address* GetLocation(int index) {
226 DCHECK(index >= 0 && index < size_);
227 return &blocks_[index >> kShift][index & kMask];
228 }
229
230 int size_ = 0;
231 std::vector<Address*> blocks_;
232 std::vector<int> young_node_indices_;
233};
234
235// A vector of global Handles which automatically manages the backing of those
236// Handles as a vector of strong-rooted addresses. Handles returned by the
237// vector are valid as long as they are present in the vector.
238template <typename T>
239class GlobalHandleVector {
240 public:
241 class Iterator {
242 public:
243 explicit Iterator(
244 std::vector<Address, StrongRootAllocator<Address>>::iterator it)
245 : it_(it) {}
247 ++it_;
248 return *this;
249 }
251 bool operator==(const Iterator& that) const { return it_ == that.it_; }
252 bool operator!=(const Iterator& that) const { return it_ != that.it_; }
253
255
256 private:
257 std::vector<Address, StrongRootAllocator<Address>>::iterator it_;
258 };
259
260 explicit inline GlobalHandleVector(Heap* heap);
261 // Usage with LocalHeap is safe.
262 explicit inline GlobalHandleVector(LocalHeap* local_heap);
263
267
268 size_t size() const { return locations_.size(); }
269 bool empty() const { return locations_.empty(); }
270
271 void Reserve(size_t size) { locations_.reserve(size); }
272 void Push(Tagged<T> val) { locations_.push_back(val.ptr()); }
273 // Handles into the GlobalHandleVector become invalid when they are removed,
274 // so "pop" returns a raw object rather than a handle.
275 inline Tagged<T> Pop();
276
277 Iterator begin() { return Iterator(locations_.begin()); }
278 Iterator end() { return Iterator(locations_.end()); }
279
280 private:
281 std::vector<Address, StrongRootAllocator<Address>> locations_;
282};
283
284} // namespace internal
285} // namespace v8
286
287#endif // V8_HANDLES_GLOBAL_HANDLES_H_
Isolate * isolate_
void(*)(const WeakCallbackInfo< T > &data) Callback
std::vector< Address * > blocks_
IndirectHandle< Object > Get(int index)
EternalHandles & operator=(const EternalHandles &)=delete
EternalHandles(const EternalHandles &)=delete
V8_EXPORT_PRIVATE void Create(Isolate *isolate, Tagged< Object > object, int *index)
std::vector< int > young_node_indices_
void IterateAllRoots(RootVisitor *visitor)
void IterateYoungRoots(RootVisitor *visitor)
Address * GetLocation(int index)
bool operator!=(const Iterator &that) const
Iterator(std::vector< Address, StrongRootAllocator< Address > >::iterator it)
bool operator==(const Iterator &that) const
std::vector< Address, StrongRootAllocator< Address > >::iterator it_
std::vector< Address, StrongRootAllocator< Address > > locations_
IndirectHandle< T > operator[](size_t i)
void * embedder_fields_[v8::kEmbedderFieldsInWeakCallback]
void Invoke(Isolate *isolate, InvocationType type)
PendingPhantomCallback(Data::Callback callback, void *parameter, void *embedder_fields[v8::kEmbedderFieldsInWeakCallback])
static void MakeWeak(Address *location, void *parameter, WeakCallbackInfo< void >::Callback weak_callback, v8::WeakCallbackType type)
std::unique_ptr< NodeSpace< Node > > regular_nodes_
std::vector< std::pair< Node *, PendingPhantomCallback > > pending_phantom_callbacks_
std::vector< PendingPhantomCallback > second_pass_callbacks_
std::vector< Node * > young_nodes_
GlobalHandles & operator=(const GlobalHandles &)=delete
GlobalHandles(const GlobalHandles &)=delete
size_t last_gc_custom_callbacks() const
V8_INLINE constexpr StorageType ptr() const
Label label
V8_INLINE constexpr bool IsWeak(TaggedImpl< HeapObjectReferenceType::WEAK, StorageType > obj)
Definition objects.h:673
Handle< T > IndirectHandle
Definition globals.h:1086
bool(*)(Heap *heap, FullObjectSlot pointer) WeakSlotCallbackWithHeap
Definition globals.h:1278
Tagged< To > Cast(Tagged< From > value, const v8::SourceLocation &loc=INIT_SOURCE_LOCATION_IN_DEBUG)
Definition casting.h:150
static constexpr int kEmbedderFieldsInWeakCallback
GCCallbackFlags
#define DCHECK(condition)
Definition logging.h:482
#define V8_EXPORT_PRIVATE
Definition macros.h:460