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