v8
V8 is Google’s open source high-performance JavaScript and WebAssembly engine, written in C++.
Loading...
Searching...
No Matches
managed.h
Go to the documentation of this file.
1// Copyright 2016 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 V8_OBJECTS_MANAGED_H_
6#define V8_OBJECTS_MANAGED_H_
7
8#include <memory>
9
11#include "src/api/api.h"
13#include "src/handles/handles.h"
14#include "src/heap/factory.h"
15#include "src/objects/foreign.h"
17
18namespace v8::internal {
19
20// Mechanism for associating an ExternalPointerTag with a C++ type that is
21// referenced via a Managed. Every such C++ type must have a unique
22// ExternalPointerTag to ensure type-safe access to the external object.
23//
24// This mechanism supports two ways of associating tags with types:
25//
26// 1. By adding a 'static constexpr ExternalPointerTag kManagedTag` field to
27// the C++ class (preferred for C++ types defined in V8 code):
28//
29// class MyCppClass {
30// public:
31// static constexpr ExternalPointerTag kManagedTag = kMyCppClassTag;
32// ...;
33//
34// 2. Through the ASSIGN_EXTERNAL_POINTER_TAG_FOR_MANAGED macro, which uses
35// template specialization (necessary for C++ types defined outside of V8):
36//
37// ASSIGN_EXTERNAL_POINTER_TAG_FOR_MANAGED(MyCppClass, kMyCppClassTag)
38//
39// Note that the struct created by this macro must be visible when the
40// Managed<CppType> is used. In particular, there may be issues if the
41// CppType is only forward declared and the respective header isn't included.
42// Note also that this macro must be used inside the v8::internal namespace.
43//
44template <typename CppType>
46 static constexpr ExternalPointerTag value = CppType::kManagedTag;
47};
48
49#define ASSIGN_EXTERNAL_POINTER_TAG_FOR_MANAGED(CppType, Tag) \
50 template <> \
51 struct TagForManaged<CppType> { \
52 static constexpr ExternalPointerTag value = Tag; \
53 };
54
55// Implements a doubly-linked lists of destructors for the isolate.
57#ifdef V8_ENABLE_SANDBOX
58 : public ExternalPointerTable::ManagedResource {
59#else
60 : public Malloced {
61#endif // V8_ENABLE_SANDBOX
62
63 // Estimated size of external memory associated with the managed object.
64 // This is used to adjust the garbage collector's heuristics upon
65 // allocation and deallocation of a managed object.
66 size_t estimated_size_ = 0;
69 void* shared_ptr_ptr_ = nullptr;
70 void (*destructor_)(void* shared_ptr) = nullptr;
73
74 ManagedPtrDestructor(size_t estimated_size, void* shared_ptr_ptr,
75 void (*destructor)(void*))
76 : estimated_size_(estimated_size),
77 shared_ptr_ptr_(shared_ptr_ptr),
78 destructor_(destructor) {}
79};
80
81// The GC finalizer of a managed object, which does not depend on
82// the template parameter.
84 const v8::WeakCallbackInfo<void>& data);
85
86// {Managed<T>} is essentially a {std::shared_ptr<T>} allocated on the heap
87// that can be used to manage the lifetime of C++ objects that are shared
88// across multiple isolates.
89// When a {Managed<T>} object is garbage collected (or an isolate which
90// contains {Managed<T>} is torn down), the {Managed<T>} deletes its underlying
91// {std::shared_ptr<T>}, thereby decrementing its internal reference count,
92// which will delete the C++ object when the reference count drops to 0.
93template <class CppType>
94class Managed : public Foreign {
95 public:
97 explicit Managed(Address ptr) : Foreign(ptr) {}
98 V8_INLINE constexpr Managed(Address ptr, SkipTypeCheckTag)
99 : Foreign(ptr, SkipTypeCheckTag{}) {}
100
101 // For every object, add a `->` operator which returns a pointer to this
102 // object. This will allow smoother transition between T and Tagged<T>.
103 Managed* operator->() { return this; }
104 const Managed* operator->() const { return this; }
105
106 // Get a raw pointer to the C++ object.
107 V8_INLINE CppType* raw() { return GetSharedPtrPtr()->get(); }
108
109 // Get a reference to the shared pointer to the C++ object.
110 V8_INLINE const std::shared_ptr<CppType>& get() { return *GetSharedPtrPtr(); }
111
112 // Read back the memory estimate that was provided when creating this Managed.
113 size_t estimated_size() const { return GetDestructor()->estimated_size_; }
114
115 // Create a {Managed>} from an existing {std::shared_ptr} or {std::unique_ptr}
116 // (which will automatically convert to a {std::shared_ptr}).
118 Isolate* isolate, size_t estimated_size,
119 std::shared_ptr<CppType> shared_ptr,
120 AllocationType allocation_type = AllocationType::kYoung);
121
122 private:
123 friend class Tagged<Managed>;
124
125 // Internally this {Foreign} object stores a pointer to a
126 // ManagedPtrDestructor, which again stores the std::shared_ptr.
129 return reinterpret_cast<ManagedPtrDestructor*>(foreign_address<kTag>());
130 }
131
132 std::shared_ptr<CppType>* GetSharedPtrPtr() {
133 return reinterpret_cast<std::shared_ptr<CppType>*>(
134 GetDestructor()->shared_ptr_ptr_);
135 }
136};
137
138// {TrustedManaged<T>} is semantically equivalent to {Managed<T>}, but lives in
139// the trusted space. It is thus based on {TrustedForeign} instead of {Foreign}
140// and does not need any tagging.
141template <class CppType>
142class TrustedManaged : public TrustedForeign {
143 public:
145 explicit TrustedManaged(Address ptr) : TrustedForeign(ptr) {}
146 V8_INLINE constexpr TrustedManaged(Address ptr, SkipTypeCheckTag)
147 : TrustedForeign(ptr, SkipTypeCheckTag{}) {}
148
149 // For every object, add a `->` operator which returns a pointer to this
150 // object. This will allow smoother transition between T and Tagged<T>.
151 TrustedManaged* operator->() { return this; }
152 const TrustedManaged* operator->() const { return this; }
153
154 // Get a raw pointer to the C++ object.
155 V8_INLINE CppType* raw() { return GetSharedPtrPtr()->get(); }
156
157 // Get a reference to the shared pointer to the C++ object.
158 V8_INLINE const std::shared_ptr<CppType>& get() { return *GetSharedPtrPtr(); }
159
160 // Create a {Managed<CppType>} from an existing {std::shared_ptr} or
161 // {std::unique_ptr} (which will implicitly convert to {std::shared_ptr}).
163 Isolate* isolate, size_t estimated_size,
164 std::shared_ptr<CppType> shared_ptr);
165
166 private:
167 friend class Tagged<TrustedManaged>;
168
169 // Internally the {TrustedForeign} stores a pointer to the
170 // {std::shared_ptr<CppType>}.
171 std::shared_ptr<CppType>* GetSharedPtrPtr() {
172 auto destructor =
173 reinterpret_cast<ManagedPtrDestructor*>(foreign_address());
174 return reinterpret_cast<std::shared_ptr<CppType>*>(
175 destructor->shared_ptr_ptr_);
176 }
177};
178
179} // namespace v8::internal
180
181#endif // V8_OBJECTS_MANAGED_H_
std::shared_ptr< CppType > * GetSharedPtrPtr()
Definition managed.h:132
const Managed * operator->() const
Definition managed.h:104
V8_INLINE const std::shared_ptr< CppType > & get()
Definition managed.h:110
Managed(Address ptr)
Definition managed.h:97
Managed * operator->()
Definition managed.h:103
ManagedPtrDestructor * GetDestructor() const
Definition managed.h:127
V8_INLINE CppType * raw()
Definition managed.h:107
V8_INLINE constexpr Managed(Address ptr, SkipTypeCheckTag)
Definition managed.h:98
size_t estimated_size() const
Definition managed.h:113
TrustedManaged(Address ptr)
Definition managed.h:145
V8_INLINE const std::shared_ptr< CppType > & get()
Definition managed.h:158
std::shared_ptr< CppType > * GetSharedPtrPtr()
Definition managed.h:171
V8_INLINE constexpr TrustedManaged(Address ptr, SkipTypeCheckTag)
Definition managed.h:146
V8_INLINE CppType * raw()
Definition managed.h:155
const TrustedManaged * operator->() const
Definition managed.h:152
TrustedManaged * operator->()
Definition managed.h:151
void ManagedObjectFinalizer(const v8::WeakCallbackInfo< void > &data)
Definition managed.cc:33
#define V8_EXPORT_PRIVATE
Definition macros.h:460
ManagedPtrDestructor * prev_
Definition managed.h:67
void(* destructor_)(void *shared_ptr)
Definition managed.h:70
ManagedPtrDestructor * next_
Definition managed.h:68
ManagedPtrDestructor(size_t estimated_size, void *shared_ptr_ptr, void(*destructor)(void *))
Definition managed.h:74
V8_NO_UNIQUE_ADDRESS ExternalMemoryAccounter external_memory_accounter_
Definition managed.h:72
#define V8_NO_UNIQUE_ADDRESS
Definition v8config.h:722
#define V8_INLINE
Definition v8config.h:500