v8  9.4.146 (node 16.13.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 class CrossThreadPersistentRegion;
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.
27 class PersistentNode final {
28  public:
29  PersistentNode() = default;
30 
31  PersistentNode(const PersistentNode&) = delete;
32  PersistentNode& operator=(const PersistentNode&) = delete;
33 
34  void InitializeAsUsedNode(void* owner, TraceCallback trace) {
35  CPPGC_DCHECK(trace);
36  owner_ = owner;
37  trace_ = trace;
38  }
39 
40  void InitializeAsFreeNode(PersistentNode* next) {
41  next_ = next;
42  trace_ = nullptr;
43  }
44 
45  void UpdateOwner(void* owner) {
47  owner_ = owner;
48  }
49 
50  PersistentNode* FreeListNext() const {
52  return next_;
53  }
54 
55  void Trace(Visitor* visitor) const {
57  trace_(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;
73  PersistentNode* next_;
74  };
75  TraceCallback trace_ = nullptr;
76 };
77 
79  using PersistentNodeSlots = std::array<PersistentNode, 256u>;
80 
81  public:
82  PersistentRegion() = default;
83  // Clears Persistent fields to avoid stale pointers after heap teardown.
85 
88 
89  PersistentNode* AllocateNode(void* owner, TraceCallback trace) {
90  if (!free_list_head_) {
91  EnsureNodeSlots();
92  }
93  PersistentNode* node = free_list_head_;
94  free_list_head_ = free_list_head_->FreeListNext();
96  node->InitializeAsUsedNode(owner, trace);
97  nodes_in_use_++;
98  return node;
99  }
100 
101  void FreeNode(PersistentNode* node) {
102  CPPGC_DCHECK(node);
104  node->InitializeAsFreeNode(free_list_head_);
105  free_list_head_ = node;
106  CPPGC_DCHECK(nodes_in_use_ > 0);
107  nodes_in_use_--;
108  }
109 
110  void Trace(Visitor*);
111 
112  size_t NodesInUse() const;
113 
115 
116  private:
117  void EnsureNodeSlots();
118 
119  template <typename PersistentBaseClass>
120  void ClearAllUsedNodes();
121 
122  std::vector<std::unique_ptr<PersistentNodeSlots>> nodes_;
123  PersistentNode* free_list_head_ = nullptr;
124  size_t nodes_in_use_ = 0;
125 
126  friend class CrossThreadPersistentRegion;
127 };
128 
129 // CrossThreadPersistent uses PersistentRegion but protects it using this lock
130 // when needed.
131 class V8_EXPORT PersistentRegionLock final {
132  public:
135 
136  static void AssertLocked();
137 };
138 
139 // Variant of PersistentRegion that checks whether the PersistentRegionLock is
140 // locked.
141 class V8_EXPORT CrossThreadPersistentRegion final : protected PersistentRegion {
142  public:
144  // Clears Persistent fields to avoid stale pointers after heap teardown.
146 
147  CrossThreadPersistentRegion(const CrossThreadPersistentRegion&) = delete;
148  CrossThreadPersistentRegion& operator=(const CrossThreadPersistentRegion&) =
149  delete;
150 
151  V8_INLINE PersistentNode* AllocateNode(void* owner, TraceCallback trace) {
152  PersistentRegionLock::AssertLocked();
153  return PersistentRegion::AllocateNode(owner, trace);
154  }
155 
156  V8_INLINE void FreeNode(PersistentNode* node) {
157  PersistentRegionLock::AssertLocked();
159  }
160 
161  void Trace(Visitor*);
162 
163  size_t NodesInUse() const;
164 
166 };
167 
168 } // namespace internal
169 
170 } // namespace cppgc
171 
172 #endif // INCLUDE_CPPGC_INTERNAL_PERSISTENT_NODE_H_