v8 10.2.154 (node 18.16.0)
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 {
17
18class Visitor;
19
20namespace internal {
21
22class CrossThreadPersistentRegion;
23class FatalOutOfMemoryHandler;
24
25// PersistentNode represents a variant of two states:
26// 1) traceable node with a back pointer to the Persistent object;
27// 2) freelist entry.
28class PersistentNode final {
29 public:
30 PersistentNode() = default;
31
34
36 CPPGC_DCHECK(trace);
37 owner_ = owner;
38 trace_ = trace;
39 }
40
42 next_ = next;
43 trace_ = nullptr;
44 }
45
46 void UpdateOwner(void* owner) {
48 owner_ = owner;
49 }
50
53 return next_;
54 }
55
56 void Trace(Visitor* visitor) const {
58 trace_(visitor, owner_);
59 }
60
61 bool IsUsed() const { return trace_; }
62
63 void* owner() const {
65 return owner_;
66 }
67
68 private:
69 // PersistentNode acts as a designated union:
70 // If trace_ != nullptr, owner_ points to the corresponding Persistent handle.
71 // Otherwise, next_ points to the next freed PersistentNode.
72 union {
73 void* owner_ = nullptr;
75 };
76 TraceCallback trace_ = nullptr;
77};
78
80 using PersistentNodeSlots = std::array<PersistentNode, 256u>;
81
82 public:
83 // Clears Persistent fields to avoid stale pointers after heap teardown.
85
88
89 void Trace(Visitor*);
90
91 size_t NodesInUse() const;
92
94
95 protected:
96 explicit PersistentRegionBase(const FatalOutOfMemoryHandler& oom_handler);
97
99 TraceCallback trace) {
100 PersistentNode* node = nullptr;
101 if (V8_LIKELY(free_list_head_)) {
102 node = free_list_head_;
103 free_list_head_ = free_list_head_->FreeListNext();
104 CPPGC_DCHECK(!node->IsUsed());
105 node->InitializeAsUsedNode(owner, trace);
106 nodes_in_use_++;
107 }
108 return node;
109 }
110
112 CPPGC_DCHECK(node);
113 CPPGC_DCHECK(node->IsUsed());
114 node->InitializeAsFreeNode(free_list_head_);
115 free_list_head_ = node;
116 CPPGC_DCHECK(nodes_in_use_ > 0);
117 nodes_in_use_--;
118 }
119
121 TraceCallback trace);
122
123 private:
124 template <typename PersistentBaseClass>
125 void ClearAllUsedNodes();
126
127 void RefillFreeList();
128
129 std::vector<std::unique_ptr<PersistentNodeSlots>> nodes_;
130 PersistentNode* free_list_head_ = nullptr;
131 size_t nodes_in_use_ = 0;
132 const FatalOutOfMemoryHandler& oom_handler_;
133
135};
136
137// Variant of PersistentRegionBase that checks whether the allocation and
138// freeing happens only on the thread that created the region.
140 public:
141 explicit PersistentRegion(const FatalOutOfMemoryHandler&);
142 // Clears Persistent fields to avoid stale pointers after heap teardown.
143 ~PersistentRegion() = default;
144
147
149 CPPGC_DCHECK(IsCreationThread());
150 auto* node = TryAllocateNodeFromFreeList(owner, trace);
151 if (V8_LIKELY(node)) return node;
152
153 // Slow path allocation allows for checking thread correspondence.
154 CPPGC_CHECK(IsCreationThread());
155 return RefillFreeListAndAllocateNode(owner, trace);
156 }
157
159 CPPGC_DCHECK(IsCreationThread());
160 PersistentRegionBase::FreeNode(node);
161 }
162
163 private:
164 bool IsCreationThread();
165
166 int creation_thread_id_;
167};
168
169// CrossThreadPersistent uses PersistentRegionBase but protects it using this
170// lock when needed.
172 public:
175
176 static void AssertLocked();
177};
178
179// Variant of PersistentRegionBase that checks whether the PersistentRegionLock
180// is locked.
182 : protected PersistentRegionBase {
183 public:
184 explicit CrossThreadPersistentRegion(const FatalOutOfMemoryHandler&);
185 // Clears Persistent fields to avoid stale pointers after heap teardown.
187
190 delete;
191
193 PersistentRegionLock::AssertLocked();
194 auto* node = TryAllocateNodeFromFreeList(owner, trace);
195 if (V8_LIKELY(node)) return node;
196
197 return RefillFreeListAndAllocateNode(owner, trace);
198 }
199
201 PersistentRegionLock::AssertLocked();
202 PersistentRegionBase::FreeNode(node);
203 }
204
206
207 size_t NodesInUse() const;
208
210};
211
212} // namespace internal
213
214} // namespace cppgc
215
216#endif // INCLUDE_CPPGC_INTERNAL_PERSISTENT_NODE_H_
CrossThreadPersistentRegion(const CrossThreadPersistentRegion &)=delete
V8_INLINE PersistentNode * AllocateNode(void *owner, TraceCallback trace)
CrossThreadPersistentRegion(const FatalOutOfMemoryHandler &)
CrossThreadPersistentRegion & operator=(const CrossThreadPersistentRegion &)=delete
V8_INLINE void FreeNode(PersistentNode *node)
PersistentNode(const PersistentNode &)=delete
PersistentNode * FreeListNext() const
void InitializeAsUsedNode(void *owner, TraceCallback trace)
void InitializeAsFreeNode(PersistentNode *next)
PersistentNode & operator=(const PersistentNode &)=delete
void Trace(Visitor *visitor) const
PersistentNode * TryAllocateNodeFromFreeList(void *owner, TraceCallback trace)
PersistentRegionBase(const FatalOutOfMemoryHandler &oom_handler)
PersistentRegionBase & operator=(const PersistentRegionBase &)=delete
PersistentRegionBase(const PersistentRegionBase &)=delete
void FreeNode(PersistentNode *node)
PersistentNode * RefillFreeListAndAllocateNode(void *owner, TraceCallback trace)
PersistentRegion & operator=(const PersistentRegion &)=delete
V8_INLINE PersistentNode * AllocateNode(void *owner, TraceCallback 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(*)(Visitor *visitor, const void *object) TraceCallback
Definition trace-trait.h:34
#define V8_EXPORT
Definition v8config.h:578
#define V8_INLINE
Definition v8config.h:425
#define V8_LIKELY(condition)
Definition v8config.h:489