• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
InitializeAsUsedNode(void * owner,TraceCallback trace)32   void InitializeAsUsedNode(void* owner, TraceCallback trace) {
33     owner_ = owner;
34     trace_ = trace;
35   }
36 
InitializeAsFreeNode(PersistentNode * next)37   void InitializeAsFreeNode(PersistentNode* next) {
38     next_ = next;
39     trace_ = nullptr;
40   }
41 
UpdateOwner(void * owner)42   void UpdateOwner(void* owner) {
43     CPPGC_DCHECK(IsUsed());
44     owner_ = owner;
45   }
46 
FreeListNext()47   PersistentNode* FreeListNext() const {
48     CPPGC_DCHECK(!IsUsed());
49     return next_;
50   }
51 
Trace(Visitor * visitor)52   void Trace(Visitor* visitor) const {
53     CPPGC_DCHECK(IsUsed());
54     trace_(visitor, owner_);
55   }
56 
IsUsed()57   bool IsUsed() const { return trace_; }
58 
owner()59   void* owner() const {
60     CPPGC_DCHECK(IsUsed());
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.
81   ~PersistentRegion();
82 
83   PersistentRegion(const PersistentRegion&) = delete;
84   PersistentRegion& operator=(const PersistentRegion&) = delete;
85 
AllocateNode(void * owner,TraceCallback trace)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     return node;
94   }
95 
FreeNode(PersistentNode * node)96   void FreeNode(PersistentNode* node) {
97     node->InitializeAsFreeNode(free_list_head_);
98     free_list_head_ = node;
99   }
100 
101   void Trace(Visitor*);
102 
103   size_t NodesInUse() const;
104 
105  private:
106   void EnsureNodeSlots();
107 
108   std::vector<std::unique_ptr<PersistentNodeSlots>> nodes_;
109   PersistentNode* free_list_head_ = nullptr;
110 };
111 
112 // CrossThreadPersistent uses PersistentRegion but protects it using this lock
113 // when needed.
114 class V8_EXPORT PersistentRegionLock final {
115  public:
116   PersistentRegionLock();
117   ~PersistentRegionLock();
118 };
119 
120 }  // namespace internal
121 
122 }  // namespace cppgc
123 
124 #endif  // INCLUDE_CPPGC_INTERNAL_PERSISTENT_NODE_H_
125