v8 12.4.254 (node 22.4.1)
V8 is Google's open source JavaScript engine
Loading...
Searching...
No Matches
persistent-node.h
Go to the documentation of this file.
1// Copyright 2020 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 INCLUDE_CPPGC_INTERNAL_PERSISTENT_NODE_H_
6#define INCLUDE_CPPGC_INTERNAL_PERSISTENT_NODE_H_
7
8#include <array>
9#include <memory>
10#include <vector>
11
13#include "cppgc/trace-trait.h"
14#include "v8config.h" // NOLINT(build/include_directory)
15
16namespace cppgc {
17namespace internal {
18
19class CrossThreadPersistentRegion;
20class FatalOutOfMemoryHandler;
21class RootVisitor;
22
23// PersistentNode represents a variant of two states:
24// 1) traceable node with a back pointer to the Persistent object;
25// 2) freelist entry.
26class PersistentNode final {
27 public:
28 PersistentNode() = default;
29
32
34 CPPGC_DCHECK(trace);
35 owner_ = owner;
36 trace_ = trace;
37 }
38
40 next_ = next;
41 trace_ = nullptr;
42 }
43
44 void UpdateOwner(void* owner) {
46 owner_ = owner;
47 }
48
51 return next_;
52 }
53
54 void Trace(RootVisitor& root_visitor) const {
56 trace_(root_visitor, owner_);
57 }
58
59 bool IsUsed() const { return trace_; }
60
61 void* owner() const {
63 return owner_;
64 }
65
66 private:
67 // PersistentNode acts as a designated union:
68 // If trace_ != nullptr, owner_ points to the corresponding Persistent handle.
69 // Otherwise, next_ points to the next freed PersistentNode.
70 union {
71 void* owner_ = nullptr;
73 };
74 TraceRootCallback trace_ = nullptr;
75};
76
78 using PersistentNodeSlots = std::array<PersistentNode, 256u>;
79
80 public:
81 // Clears Persistent fields to avoid stale pointers after heap teardown.
83
86
88
89 size_t NodesInUse() const;
90
92
93 protected:
94 explicit PersistentRegionBase(const FatalOutOfMemoryHandler& oom_handler);
95
97 TraceRootCallback trace) {
98 PersistentNode* node = nullptr;
99 if (V8_LIKELY(free_list_head_)) {
100 node = free_list_head_;
101 free_list_head_ = free_list_head_->FreeListNext();
102 CPPGC_DCHECK(!node->IsUsed());
103 node->InitializeAsUsedNode(owner, trace);
104 nodes_in_use_++;
105 }
106 return node;
107 }
108
110 CPPGC_DCHECK(node);
111 CPPGC_DCHECK(node->IsUsed());
112 node->InitializeAsFreeNode(free_list_head_);
113 free_list_head_ = node;
114 CPPGC_DCHECK(nodes_in_use_ > 0);
115 nodes_in_use_--;
116 }
117
119 TraceRootCallback trace);
120
121 private:
122 template <typename PersistentBaseClass>
123 void ClearAllUsedNodes();
124
125 void RefillFreeList();
126
127 std::vector<std::unique_ptr<PersistentNodeSlots>> nodes_;
128 PersistentNode* free_list_head_ = nullptr;
129 size_t nodes_in_use_ = 0;
130 const FatalOutOfMemoryHandler& oom_handler_;
131
133};
134
135// Variant of PersistentRegionBase that checks whether the allocation and
136// freeing happens only on the thread that created the region.
138 public:
139 explicit PersistentRegion(const FatalOutOfMemoryHandler&);
140 // Clears Persistent fields to avoid stale pointers after heap teardown.
141 ~PersistentRegion() = default;
142
145
147 CPPGC_DCHECK(IsCreationThread());
148 auto* node = TryAllocateNodeFromFreeList(owner, trace);
149 if (V8_LIKELY(node)) return node;
150
151 // Slow path allocation allows for checking thread correspondence.
152 CPPGC_CHECK(IsCreationThread());
153 return RefillFreeListAndAllocateNode(owner, trace);
154 }
155
157 CPPGC_DCHECK(IsCreationThread());
158 PersistentRegionBase::FreeNode(node);
159 }
160
161 private:
162 bool IsCreationThread();
163
164 int creation_thread_id_;
165};
166
167// CrossThreadPersistent uses PersistentRegionBase but protects it using this
168// lock when needed.
170 public:
173
174 static void AssertLocked();
175};
176
177// Variant of PersistentRegionBase that checks whether the PersistentRegionLock
178// is locked.
180 : protected PersistentRegionBase {
181 public:
182 explicit CrossThreadPersistentRegion(const FatalOutOfMemoryHandler&);
183 // Clears Persistent fields to avoid stale pointers after heap teardown.
185
188 delete;
189
191 PersistentRegionLock::AssertLocked();
192 auto* node = TryAllocateNodeFromFreeList(owner, trace);
193 if (V8_LIKELY(node)) return node;
194
195 return RefillFreeListAndAllocateNode(owner, trace);
196 }
197
199 PersistentRegionLock::AssertLocked();
200 PersistentRegionBase::FreeNode(node);
201 }
202
204
205 size_t NodesInUse() const;
206
208};
209
210} // namespace internal
211
212} // namespace cppgc
213
214#endif // INCLUDE_CPPGC_INTERNAL_PERSISTENT_NODE_H_
CrossThreadPersistentRegion(const CrossThreadPersistentRegion &)=delete
V8_INLINE PersistentNode * AllocateNode(void *owner, TraceRootCallback trace)
CrossThreadPersistentRegion(const FatalOutOfMemoryHandler &)
CrossThreadPersistentRegion & operator=(const CrossThreadPersistentRegion &)=delete
V8_INLINE void FreeNode(PersistentNode *node)
PersistentNode(const PersistentNode &)=delete
void Trace(RootVisitor &root_visitor) const
PersistentNode * FreeListNext() const
void InitializeAsUsedNode(void *owner, TraceRootCallback trace)
void InitializeAsFreeNode(PersistentNode *next)
PersistentNode & operator=(const PersistentNode &)=delete
PersistentRegionBase(const FatalOutOfMemoryHandler &oom_handler)
PersistentNode * RefillFreeListAndAllocateNode(void *owner, TraceRootCallback trace)
PersistentRegionBase & operator=(const PersistentRegionBase &)=delete
PersistentRegionBase(const PersistentRegionBase &)=delete
void FreeNode(PersistentNode *node)
PersistentNode * TryAllocateNodeFromFreeList(void *owner, TraceRootCallback trace)
PersistentRegion & operator=(const PersistentRegion &)=delete
V8_INLINE PersistentNode * AllocateNode(void *owner, TraceRootCallback trace)
PersistentRegion(const FatalOutOfMemoryHandler &)
PersistentRegion(const PersistentRegion &)=delete
V8_INLINE void FreeNode(PersistentNode *node)
#define CPPGC_DCHECK(condition)
Definition logging.h:36
#define CPPGC_CHECK(condition)
Definition logging.h:45
void(*)(RootVisitor &, const void *object) TraceRootCallback
Definition trace-trait.h:21
#define V8_EXPORT
Definition v8config.h:753
#define V8_INLINE
Definition v8config.h:477
#define V8_LIKELY(condition)
Definition v8config.h:618