v8  8.4.371 (node 14.19.3)
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 represesents 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  private:
60  // PersistentNode acts as a designated union:
61  // If trace_ != nullptr, owner_ points to the corresponding Persistent handle.
62  // Otherwise, next_ points to the next freed PersistentNode.
63  union {
64  void* owner_ = nullptr;
65  PersistentNode* next_;
66  };
67  TraceCallback trace_ = nullptr;
68 };
69 
71  using PersistentNodeSlots = std::array<PersistentNode, 256u>;
72 
73  public:
74  PersistentRegion() = default;
75 
78 
79  PersistentNode* AllocateNode(void* owner, TraceCallback trace) {
80  if (!free_list_head_) {
81  EnsureNodeSlots();
82  }
83  PersistentNode* node = free_list_head_;
84  free_list_head_ = free_list_head_->FreeListNext();
85  node->InitializeAsUsedNode(owner, trace);
86  return node;
87  }
88 
89  void FreeNode(PersistentNode* node) {
90  node->InitializeAsFreeNode(free_list_head_);
91  free_list_head_ = node;
92  }
93 
94  void Trace(Visitor*);
95 
96  size_t NodesInUse() const;
97 
98  private:
99  void EnsureNodeSlots();
100 
101  std::vector<std::unique_ptr<PersistentNodeSlots>> nodes_;
102  PersistentNode* free_list_head_ = nullptr;
103 };
104 
105 } // namespace internal
106 
107 } // namespace cppgc
108 
109 #endif // INCLUDE_CPPGC_INTERNAL_PERSISTENT_NODE_H_