v8  9.0.257(node16.0.0)
V8 is Google's open source JavaScript engine
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 
12 #include "cppgc/internal/logging.h"
13 #include "cppgc/trace-trait.h"
14 #include "v8config.h" // NOLINT(build/include_directory)
15 
16 namespace cppgc {
17 
18 class Visitor;
19 
20 namespace internal {
21 
22 // PersistentNode represents a variant of two states:
23 // 1) traceable node with a back pointer to the Persistent object;
24 // 2) freelist entry.
25 class PersistentNode final {
26  public:
27  PersistentNode() = default;
28 
29  PersistentNode(const PersistentNode&) = delete;
30  PersistentNode& operator=(const PersistentNode&) = delete;
31 
32  void InitializeAsUsedNode(void* owner, TraceCallback trace) {
33  owner_ = owner;
34  trace_ = trace;
35  }
36 
37  void InitializeAsFreeNode(PersistentNode* next) {
38  next_ = next;
39  trace_ = nullptr;
40  }
41 
42  void UpdateOwner(void* owner) {
44  owner_ = owner;
45  }
46 
47  PersistentNode* FreeListNext() const {
49  return next_;
50  }
51 
52  void Trace(Visitor* visitor) const {
54  trace_(visitor, owner_);
55  }
56 
57  bool IsUsed() const { return trace_; }
58 
59  void* owner() const {
61  return owner_;
62  }
63 
64  private:
65  // PersistentNode acts as a designated union:
66  // If trace_ != nullptr, owner_ points to the corresponding Persistent handle.
67  // Otherwise, next_ points to the next freed PersistentNode.
68  union {
69  void* owner_ = nullptr;
70  PersistentNode* next_;
71  };
72  TraceCallback trace_ = nullptr;
73 };
74 
75 class V8_EXPORT PersistentRegion final {
76  using PersistentNodeSlots = std::array<PersistentNode, 256u>;
77 
78  public:
79  PersistentRegion() = default;
80  // Clears Persistent fields to avoid stale pointers after heap teardown.
82 
83  PersistentRegion(const PersistentRegion&) = delete;
84  PersistentRegion& operator=(const PersistentRegion&) = delete;
85 
86  PersistentNode* AllocateNode(void* owner, TraceCallback trace) {
87  if (!free_list_head_) {
88  EnsureNodeSlots();
89  }
90  PersistentNode* node = free_list_head_;
91  free_list_head_ = free_list_head_->FreeListNext();
92  node->InitializeAsUsedNode(owner, trace);
93  nodes_in_use_++;
94  return node;
95  }
96 
97  void FreeNode(PersistentNode* node) {
98  node->InitializeAsFreeNode(free_list_head_);
99  free_list_head_ = node;
100  CPPGC_DCHECK(nodes_in_use_ > 0);
101  nodes_in_use_--;
102  }
103 
104  void Trace(Visitor*);
105 
106  size_t NodesInUse() const;
107 
108  void ClearAllUsedNodes();
109 
110  private:
111  void EnsureNodeSlots();
112 
113  std::vector<std::unique_ptr<PersistentNodeSlots>> nodes_;
114  PersistentNode* free_list_head_ = nullptr;
115  size_t nodes_in_use_ = 0;
116 };
117 
118 // CrossThreadPersistent uses PersistentRegion but protects it using this lock
119 // when needed.
120 class V8_EXPORT PersistentRegionLock final {
121  public:
124 
125  static void AssertLocked();
126 };
127 
128 } // namespace internal
129 
130 } // namespace cppgc
131 
132 #endif // INCLUDE_CPPGC_INTERNAL_PERSISTENT_NODE_H_
cppgc::internal::PersistentNode::Trace
void Trace(Visitor *visitor) const
Definition: persistent-node.h:52
cppgc::internal::PersistentNode::PersistentNode
PersistentNode(const PersistentNode &)=delete
cppgc::internal::PersistentRegion::NodesInUse
size_t NodesInUse() const
cppgc::internal::PersistentRegion::AllocateNode
PersistentNode * AllocateNode(void *owner, TraceCallback trace)
Definition: persistent-node.h:86
cppgc::internal::PersistentNode::UpdateOwner
void UpdateOwner(void *owner)
Definition: persistent-node.h:42
cppgc::internal::PersistentNode::FreeListNext
PersistentNode * FreeListNext() const
Definition: persistent-node.h:47
cppgc::internal::PersistentRegion::Trace
void Trace(Visitor *)
cppgc::internal::PersistentRegionLock::~PersistentRegionLock
~PersistentRegionLock()
cppgc::internal::PersistentRegion::FreeNode
void FreeNode(PersistentNode *node)
Definition: persistent-node.h:97
cppgc::internal::PersistentRegion::PersistentRegion
PersistentRegion(const PersistentRegion &)=delete
cppgc::internal::PersistentRegion::operator=
PersistentRegion & operator=(const PersistentRegion &)=delete
cppgc::internal::PersistentRegion::ClearAllUsedNodes
void ClearAllUsedNodes()
cppgc::internal::PersistentRegion::PersistentRegion
PersistentRegion()=default
cppgc
Definition: allocation.h:17
cppgc::internal::PersistentNode::PersistentNode
PersistentNode()=default
V8_EXPORT
#define V8_EXPORT
Definition: v8config.h:512
cppgc::internal::PersistentRegionLock::AssertLocked
static void AssertLocked()
cppgc::internal::PersistentRegionLock::PersistentRegionLock
PersistentRegionLock()
cppgc::Visitor
Definition: visitor.h:52
cppgc::internal::PersistentNode::owner
void * owner() const
Definition: persistent-node.h:59
cppgc::internal::PersistentNode::InitializeAsUsedNode
void InitializeAsUsedNode(void *owner, TraceCallback trace)
Definition: persistent-node.h:32
CPPGC_DCHECK
#define CPPGC_DCHECK(condition)
Definition: logging.h:36
cppgc::internal::PersistentNode::operator=
PersistentNode & operator=(const PersistentNode &)=delete
cppgc::internal
Definition: allocation.h:22
cppgc::internal::PersistentNode::IsUsed
bool IsUsed() const
Definition: persistent-node.h:57
cppgc::internal::PersistentRegion::~PersistentRegion
~PersistentRegion()
cppgc::internal::PersistentNode::InitializeAsFreeNode
void InitializeAsFreeNode(PersistentNode *next)
Definition: persistent-node.h:37