libv8-node 16.20.0.0-arm64-darwin → 17.9.1.0-arm64-darwin
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/ext/libv8-node/location.rb +1 -1
- data/ext/libv8-node/paths.rb +1 -1
- data/lib/libv8/node/version.rb +3 -3
- data/vendor/v8/arm64-darwin/libv8/obj/libv8_monolith.a +0 -0
- data/vendor/v8/include/cppgc/allocation.h +11 -5
- data/vendor/v8/include/cppgc/cross-thread-persistent.h +78 -26
- data/vendor/v8/include/cppgc/internal/caged-heap-local-data.h +2 -2
- data/vendor/v8/include/cppgc/internal/finalizer-trait.h +2 -0
- data/vendor/v8/include/cppgc/internal/gc-info.h +90 -10
- data/vendor/v8/include/cppgc/internal/name-trait.h +11 -0
- data/vendor/v8/include/cppgc/internal/persistent-node.h +44 -12
- data/vendor/v8/include/cppgc/internal/pointer-policies.h +22 -11
- data/vendor/v8/include/cppgc/internal/write-barrier.h +9 -1
- data/vendor/v8/include/cppgc/persistent.h +1 -1
- data/vendor/v8/include/cppgc/prefinalizer.h +1 -1
- data/vendor/v8/include/v8-array-buffer.h +433 -0
- data/vendor/v8/include/v8-callbacks.h +377 -0
- data/vendor/v8/include/v8-container.h +129 -0
- data/vendor/v8/include/v8-context.h +418 -0
- data/vendor/v8/include/v8-cppgc.h +5 -2
- data/vendor/v8/include/v8-data.h +65 -0
- data/vendor/v8/include/v8-date.h +43 -0
- data/vendor/v8/include/v8-debug.h +151 -0
- data/vendor/v8/include/v8-embedder-heap.h +238 -0
- data/vendor/v8/include/v8-exception.h +224 -0
- data/vendor/v8/include/v8-extension.h +62 -0
- data/vendor/v8/include/v8-external.h +37 -0
- data/vendor/v8/include/v8-fast-api-calls.h +63 -11
- data/vendor/v8/include/v8-forward.h +81 -0
- data/vendor/v8/include/v8-function-callback.h +475 -0
- data/vendor/v8/include/v8-function.h +122 -0
- data/vendor/v8/include/v8-initialization.h +282 -0
- data/vendor/v8/include/v8-inspector.h +11 -21
- data/vendor/v8/include/v8-internal.h +85 -22
- data/vendor/v8/include/v8-isolate.h +1662 -0
- data/vendor/v8/include/v8-json.h +47 -0
- data/vendor/v8/include/v8-local-handle.h +459 -0
- data/vendor/v8/include/v8-locker.h +148 -0
- data/vendor/v8/include/v8-maybe.h +137 -0
- data/vendor/v8/include/v8-memory-span.h +43 -0
- data/vendor/v8/include/v8-message.h +241 -0
- data/vendor/v8/include/v8-metrics.h +37 -1
- data/vendor/v8/include/v8-microtask-queue.h +152 -0
- data/vendor/v8/include/v8-microtask.h +28 -0
- data/vendor/v8/include/v8-object.h +770 -0
- data/vendor/v8/include/v8-persistent-handle.h +590 -0
- data/vendor/v8/include/v8-platform.h +41 -17
- data/vendor/v8/include/v8-primitive-object.h +118 -0
- data/vendor/v8/include/v8-primitive.h +858 -0
- data/vendor/v8/include/v8-profiler.h +10 -11
- data/vendor/v8/include/v8-promise.h +174 -0
- data/vendor/v8/include/v8-proxy.h +50 -0
- data/vendor/v8/include/v8-regexp.h +105 -0
- data/vendor/v8/include/v8-script.h +771 -0
- data/vendor/v8/include/v8-snapshot.h +198 -0
- data/vendor/v8/include/v8-statistics.h +215 -0
- data/vendor/v8/include/v8-template.h +1052 -0
- data/vendor/v8/include/v8-traced-handle.h +605 -0
- data/vendor/v8/include/v8-typed-array.h +282 -0
- data/vendor/v8/include/v8-unwinder-state.h +4 -3
- data/vendor/v8/include/v8-unwinder.h +129 -0
- data/vendor/v8/include/v8-util.h +7 -1
- data/vendor/v8/include/v8-value-serializer.h +249 -0
- data/vendor/v8/include/v8-value.h +526 -0
- data/vendor/v8/include/v8-version.h +3 -3
- data/vendor/v8/include/v8-wasm.h +245 -0
- data/vendor/v8/include/v8-weak-callback-info.h +73 -0
- data/vendor/v8/include/v8.h +41 -12604
- metadata +47 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 6d904e10b6d367f165c2a0ddc2c3b98f9b95c7c60bd16c96342dc5cdedd3c479
|
4
|
+
data.tar.gz: 0bae2e779e697fbdebd6cd82bb4a5dd26cf30cf91f0ab453cfa38f70a2b02cd7
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 7c1ecbaf741776f86034ee0ecd99aaa2bd534e975c14b6fd7ac98f53a1062410e83ae165c1f3b70897a4311bbfb2d23fd20604d8b27c0457e4fde05cf5d9fe1d
|
7
|
+
data.tar.gz: 6d024a28b3d40a702da7c7577847a202a8200bbad4f0dae61e256349522b1209cc4c787490f53969408ea9e72d74e0edc085d38bc8a8efff838f3b1498c05145
|
data/ext/libv8-node/location.rb
CHANGED
@@ -45,7 +45,7 @@ module Libv8::Node
|
|
45
45
|
def verify_installation!
|
46
46
|
include_paths = Libv8::Node::Paths.include_paths
|
47
47
|
|
48
|
-
unless include_paths.detect { |p| Pathname(p).join('v8.h').exist? }
|
48
|
+
unless include_paths.detect { |p| Pathname(p).join('v8.h').exist? }
|
49
49
|
raise(HeaderNotFound, "Unable to locate 'v8.h' in the libv8 header paths: #{include_paths.inspect}")
|
50
50
|
end
|
51
51
|
|
data/ext/libv8-node/paths.rb
CHANGED
@@ -20,7 +20,7 @@ module Libv8::Node
|
|
20
20
|
end
|
21
21
|
|
22
22
|
def platform
|
23
|
-
Gem::Platform.local.tap { |p| RUBY_PLATFORM =~ /musl/ && p.version.nil?
|
23
|
+
Gem::Platform.local.tap { |p| RUBY_PLATFORM =~ /musl/ && p.version.nil? and p.instance_eval { @version = "musl" } }.to_s.gsub(/-darwin-?\d+/, '-darwin')
|
24
24
|
end
|
25
25
|
|
26
26
|
def config
|
data/lib/libv8/node/version.rb
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
module Libv8; end
|
2
2
|
|
3
3
|
module Libv8::Node
|
4
|
-
VERSION = '
|
5
|
-
NODE_VERSION = '
|
6
|
-
LIBV8_VERSION = '9.
|
4
|
+
VERSION = '17.9.1.0'.freeze
|
5
|
+
NODE_VERSION = '17.9.1'.freeze
|
6
|
+
LIBV8_VERSION = '9.6.180.15'.freeze # from v8/include/v8-version.h
|
7
7
|
end
|
Binary file
|
@@ -36,8 +36,13 @@ class V8_EXPORT MakeGarbageCollectedTraitInternal {
|
|
36
36
|
const_cast<uint16_t*>(reinterpret_cast<const uint16_t*>(
|
37
37
|
reinterpret_cast<const uint8_t*>(payload) -
|
38
38
|
api_constants::kFullyConstructedBitFieldOffsetFromPayload)));
|
39
|
-
|
40
|
-
|
39
|
+
// It's safe to split use load+store here (instead of a read-modify-write
|
40
|
+
// operation), since it's guaranteed that this 16-bit bitfield is only
|
41
|
+
// modified by a single thread. This is cheaper in terms of code bloat (on
|
42
|
+
// ARM) and performance.
|
43
|
+
uint16_t value = atomic_mutable_bitfield->load(std::memory_order_relaxed);
|
44
|
+
value |= api_constants::kFullyConstructedBitMask;
|
45
|
+
atomic_mutable_bitfield->store(value, std::memory_order_release);
|
41
46
|
}
|
42
47
|
|
43
48
|
template <typename U, typename CustomSpace>
|
@@ -202,7 +207,7 @@ struct PostConstructionCallbackTrait {
|
|
202
207
|
* \returns an instance of type T.
|
203
208
|
*/
|
204
209
|
template <typename T, typename... Args>
|
205
|
-
T* MakeGarbageCollected(AllocationHandle& handle, Args&&... args) {
|
210
|
+
V8_INLINE T* MakeGarbageCollected(AllocationHandle& handle, Args&&... args) {
|
206
211
|
T* object =
|
207
212
|
MakeGarbageCollectedTrait<T>::Call(handle, std::forward<Args>(args)...);
|
208
213
|
PostConstructionCallbackTrait<T>::Call(object);
|
@@ -220,8 +225,9 @@ T* MakeGarbageCollected(AllocationHandle& handle, Args&&... args) {
|
|
220
225
|
* \returns an instance of type T.
|
221
226
|
*/
|
222
227
|
template <typename T, typename... Args>
|
223
|
-
T* MakeGarbageCollected(AllocationHandle& handle,
|
224
|
-
|
228
|
+
V8_INLINE T* MakeGarbageCollected(AllocationHandle& handle,
|
229
|
+
AdditionalBytes additional_bytes,
|
230
|
+
Args&&... args) {
|
225
231
|
T* object = MakeGarbageCollectedTrait<T>::Call(handle, additional_bytes,
|
226
232
|
std::forward<Args>(args)...);
|
227
233
|
PostConstructionCallbackTrait<T>::Call(object);
|
@@ -34,7 +34,35 @@ class CrossThreadPersistentBase : public PersistentBase {
|
|
34
34
|
V8_CLANG_NO_SANITIZE("address")
|
35
35
|
void ClearFromGC() const {
|
36
36
|
raw_ = nullptr;
|
37
|
-
|
37
|
+
SetNodeSafe(nullptr);
|
38
|
+
}
|
39
|
+
|
40
|
+
// GetNodeSafe() can be used for a thread-safe IsValid() check in a
|
41
|
+
// double-checked locking pattern. See ~BasicCrossThreadPersistent.
|
42
|
+
PersistentNode* GetNodeSafe() const {
|
43
|
+
return reinterpret_cast<std::atomic<PersistentNode*>*>(&node_)->load(
|
44
|
+
std::memory_order_acquire);
|
45
|
+
}
|
46
|
+
|
47
|
+
// The GC writes using SetNodeSafe() while holding the lock.
|
48
|
+
V8_CLANG_NO_SANITIZE("address")
|
49
|
+
void SetNodeSafe(PersistentNode* value) const {
|
50
|
+
#if defined(__has_feature)
|
51
|
+
#if __has_feature(address_sanitizer)
|
52
|
+
#define V8_IS_ASAN 1
|
53
|
+
#endif
|
54
|
+
#endif
|
55
|
+
|
56
|
+
#ifdef V8_IS_ASAN
|
57
|
+
__atomic_store(&node_, &value, __ATOMIC_RELEASE);
|
58
|
+
#else // !V8_IS_ASAN
|
59
|
+
// Non-ASAN builds can use atomics. This also covers MSVC which does not
|
60
|
+
// have the __atomic_store intrinsic.
|
61
|
+
reinterpret_cast<std::atomic<PersistentNode*>*>(&node_)->store(
|
62
|
+
value, std::memory_order_release);
|
63
|
+
#endif // !V8_IS_ASAN
|
64
|
+
|
65
|
+
#undef V8_IS_ASAN
|
38
66
|
}
|
39
67
|
};
|
40
68
|
|
@@ -48,7 +76,31 @@ class BasicCrossThreadPersistent final : public CrossThreadPersistentBase,
|
|
48
76
|
using typename WeaknessPolicy::IsStrongPersistent;
|
49
77
|
using PointeeType = T;
|
50
78
|
|
51
|
-
~BasicCrossThreadPersistent() {
|
79
|
+
~BasicCrossThreadPersistent() {
|
80
|
+
// This implements fast path for destroying empty/sentinel.
|
81
|
+
//
|
82
|
+
// Simplified version of `AssignUnsafe()` to allow calling without a
|
83
|
+
// complete type `T`. Uses double-checked locking with a simple thread-safe
|
84
|
+
// check for a valid handle based on a node.
|
85
|
+
if (GetNodeSafe()) {
|
86
|
+
PersistentRegionLock guard;
|
87
|
+
const void* old_value = GetValue();
|
88
|
+
// The fast path check (GetNodeSafe()) does not acquire the lock. Recheck
|
89
|
+
// validity while holding the lock to ensure the reference has not been
|
90
|
+
// cleared.
|
91
|
+
if (IsValid(old_value)) {
|
92
|
+
CrossThreadPersistentRegion& region =
|
93
|
+
this->GetPersistentRegion(old_value);
|
94
|
+
region.FreeNode(GetNode());
|
95
|
+
SetNode(nullptr);
|
96
|
+
} else {
|
97
|
+
CPPGC_DCHECK(!GetNode());
|
98
|
+
}
|
99
|
+
}
|
100
|
+
// No need to call SetValue() as the handle is not used anymore. This can
|
101
|
+
// leave behind stale sentinel values but will always destroy the underlying
|
102
|
+
// node.
|
103
|
+
}
|
52
104
|
|
53
105
|
BasicCrossThreadPersistent(
|
54
106
|
const SourceLocation& loc = SourceLocation::Current())
|
@@ -135,7 +187,7 @@ class BasicCrossThreadPersistent final : public CrossThreadPersistentBase,
|
|
135
187
|
BasicCrossThreadPersistent& operator=(
|
136
188
|
const BasicCrossThreadPersistent& other) {
|
137
189
|
PersistentRegionLock guard;
|
138
|
-
|
190
|
+
AssignSafe(guard, other.Get());
|
139
191
|
return *this;
|
140
192
|
}
|
141
193
|
|
@@ -147,7 +199,7 @@ class BasicCrossThreadPersistent final : public CrossThreadPersistentBase,
|
|
147
199
|
OtherLocationPolicy,
|
148
200
|
OtherCheckingPolicy>& other) {
|
149
201
|
PersistentRegionLock guard;
|
150
|
-
|
202
|
+
AssignSafe(guard, other.Get());
|
151
203
|
return *this;
|
152
204
|
}
|
153
205
|
|
@@ -165,8 +217,13 @@ class BasicCrossThreadPersistent final : public CrossThreadPersistentBase,
|
|
165
217
|
return *this;
|
166
218
|
}
|
167
219
|
|
220
|
+
/**
|
221
|
+
* Assigns a raw pointer.
|
222
|
+
*
|
223
|
+
* Note: **Not thread-safe.**
|
224
|
+
*/
|
168
225
|
BasicCrossThreadPersistent& operator=(T* other) {
|
169
|
-
|
226
|
+
AssignUnsafe(other);
|
170
227
|
return *this;
|
171
228
|
}
|
172
229
|
|
@@ -181,13 +238,24 @@ class BasicCrossThreadPersistent final : public CrossThreadPersistentBase,
|
|
181
238
|
return operator=(member.Get());
|
182
239
|
}
|
183
240
|
|
241
|
+
/**
|
242
|
+
* Assigns a nullptr.
|
243
|
+
*
|
244
|
+
* \returns the handle.
|
245
|
+
*/
|
184
246
|
BasicCrossThreadPersistent& operator=(std::nullptr_t) {
|
185
247
|
Clear();
|
186
248
|
return *this;
|
187
249
|
}
|
188
250
|
|
251
|
+
/**
|
252
|
+
* Assigns the sentinel pointer.
|
253
|
+
*
|
254
|
+
* \returns the handle.
|
255
|
+
*/
|
189
256
|
BasicCrossThreadPersistent& operator=(SentinelPointer s) {
|
190
|
-
|
257
|
+
PersistentRegionLock guard;
|
258
|
+
AssignSafe(guard, s);
|
191
259
|
return *this;
|
192
260
|
}
|
193
261
|
|
@@ -209,24 +277,8 @@ class BasicCrossThreadPersistent final : public CrossThreadPersistentBase,
|
|
209
277
|
* Clears the stored object.
|
210
278
|
*/
|
211
279
|
void Clear() {
|
212
|
-
|
213
|
-
|
214
|
-
const void* old_value = GetValue();
|
215
|
-
if (IsValid(old_value)) {
|
216
|
-
PersistentRegionLock guard;
|
217
|
-
old_value = GetValue();
|
218
|
-
// The fast path check (IsValid()) does not acquire the lock. Reload
|
219
|
-
// the value to ensure the reference has not been cleared.
|
220
|
-
if (IsValid(old_value)) {
|
221
|
-
CrossThreadPersistentRegion& region =
|
222
|
-
this->GetPersistentRegion(old_value);
|
223
|
-
region.FreeNode(GetNode());
|
224
|
-
SetNode(nullptr);
|
225
|
-
} else {
|
226
|
-
CPPGC_DCHECK(!GetNode());
|
227
|
-
}
|
228
|
-
}
|
229
|
-
SetValue(nullptr);
|
280
|
+
PersistentRegionLock guard;
|
281
|
+
AssignSafe(guard, nullptr);
|
230
282
|
}
|
231
283
|
|
232
284
|
/**
|
@@ -302,7 +354,7 @@ class BasicCrossThreadPersistent final : public CrossThreadPersistentBase,
|
|
302
354
|
v->TraceRoot(*handle, handle->Location());
|
303
355
|
}
|
304
356
|
|
305
|
-
void
|
357
|
+
void AssignUnsafe(T* ptr) {
|
306
358
|
const void* old_value = GetValue();
|
307
359
|
if (IsValid(old_value)) {
|
308
360
|
PersistentRegionLock guard;
|
@@ -330,7 +382,7 @@ class BasicCrossThreadPersistent final : public CrossThreadPersistentBase,
|
|
330
382
|
this->CheckPointer(ptr);
|
331
383
|
}
|
332
384
|
|
333
|
-
void
|
385
|
+
void AssignSafe(PersistentRegionLock&, T* ptr) {
|
334
386
|
PersistentRegionLock::AssertLocked();
|
335
387
|
const void* old_value = GetValue();
|
336
388
|
if (IsValid(old_value)) {
|
@@ -53,10 +53,10 @@ static_assert(sizeof(AgeTable) == 1 * api_constants::kMB,
|
|
53
53
|
#endif // CPPGC_YOUNG_GENERATION
|
54
54
|
|
55
55
|
struct CagedHeapLocalData final {
|
56
|
-
|
56
|
+
CagedHeapLocalData(HeapBase&, PageAllocator&);
|
57
57
|
|
58
58
|
bool is_incremental_marking_in_progress = false;
|
59
|
-
HeapBase
|
59
|
+
HeapBase& heap_base;
|
60
60
|
#if defined(CPPGC_YOUNG_GENERATION)
|
61
61
|
AgeTable age_table;
|
62
62
|
#endif
|
@@ -76,6 +76,8 @@ struct FinalizerTrait {
|
|
76
76
|
}
|
77
77
|
|
78
78
|
public:
|
79
|
+
static constexpr bool HasFinalizer() { return kNonTrivialFinalizer; }
|
80
|
+
|
79
81
|
// The callback used to finalize an object of type T.
|
80
82
|
static constexpr FinalizationCallback kCallback =
|
81
83
|
kNonTrivialFinalizer ? Finalize : nullptr;
|
@@ -19,11 +19,94 @@ namespace internal {
|
|
19
19
|
|
20
20
|
using GCInfoIndex = uint16_t;
|
21
21
|
|
22
|
-
|
23
|
-
//
|
24
|
-
|
25
|
-
|
26
|
-
|
22
|
+
struct V8_EXPORT EnsureGCInfoIndexTrait final {
|
23
|
+
// Acquires a new GC info object and returns the index. In addition, also
|
24
|
+
// updates `registered_index` atomically.
|
25
|
+
template <typename T>
|
26
|
+
V8_INLINE static GCInfoIndex EnsureIndex(
|
27
|
+
std::atomic<GCInfoIndex>& registered_index) {
|
28
|
+
return EnsureGCInfoIndexTraitDispatch<T>{}(registered_index);
|
29
|
+
}
|
30
|
+
|
31
|
+
private:
|
32
|
+
template <typename T, bool = std::is_polymorphic<T>::value,
|
33
|
+
bool = FinalizerTrait<T>::HasFinalizer(),
|
34
|
+
bool = NameTrait<T>::HasNonHiddenName()>
|
35
|
+
struct EnsureGCInfoIndexTraitDispatch;
|
36
|
+
|
37
|
+
static GCInfoIndex EnsureGCInfoIndexPolymorphic(std::atomic<GCInfoIndex>&,
|
38
|
+
TraceCallback,
|
39
|
+
FinalizationCallback,
|
40
|
+
NameCallback);
|
41
|
+
static GCInfoIndex EnsureGCInfoIndexPolymorphic(std::atomic<GCInfoIndex>&,
|
42
|
+
TraceCallback,
|
43
|
+
FinalizationCallback);
|
44
|
+
static GCInfoIndex EnsureGCInfoIndexPolymorphic(std::atomic<GCInfoIndex>&,
|
45
|
+
TraceCallback, NameCallback);
|
46
|
+
static GCInfoIndex EnsureGCInfoIndexPolymorphic(std::atomic<GCInfoIndex>&,
|
47
|
+
TraceCallback);
|
48
|
+
static GCInfoIndex EnsureGCInfoIndexNonPolymorphic(std::atomic<GCInfoIndex>&,
|
49
|
+
TraceCallback,
|
50
|
+
FinalizationCallback,
|
51
|
+
|
52
|
+
NameCallback);
|
53
|
+
static GCInfoIndex EnsureGCInfoIndexNonPolymorphic(std::atomic<GCInfoIndex>&,
|
54
|
+
TraceCallback,
|
55
|
+
FinalizationCallback);
|
56
|
+
static GCInfoIndex EnsureGCInfoIndexNonPolymorphic(std::atomic<GCInfoIndex>&,
|
57
|
+
TraceCallback,
|
58
|
+
NameCallback);
|
59
|
+
static GCInfoIndex EnsureGCInfoIndexNonPolymorphic(std::atomic<GCInfoIndex>&,
|
60
|
+
TraceCallback);
|
61
|
+
};
|
62
|
+
|
63
|
+
#define DISPATCH(is_polymorphic, has_finalizer, has_non_hidden_name, function) \
|
64
|
+
template <typename T> \
|
65
|
+
struct EnsureGCInfoIndexTrait::EnsureGCInfoIndexTraitDispatch< \
|
66
|
+
T, is_polymorphic, has_finalizer, has_non_hidden_name> { \
|
67
|
+
V8_INLINE GCInfoIndex \
|
68
|
+
operator()(std::atomic<GCInfoIndex>& registered_index) { \
|
69
|
+
return function; \
|
70
|
+
} \
|
71
|
+
};
|
72
|
+
|
73
|
+
// --------------------------------------------------------------------- //
|
74
|
+
// DISPATCH(is_polymorphic, has_finalizer, has_non_hidden_name, function)
|
75
|
+
// --------------------------------------------------------------------- //
|
76
|
+
DISPATCH(true, true, true, //
|
77
|
+
EnsureGCInfoIndexPolymorphic(registered_index, //
|
78
|
+
TraceTrait<T>::Trace, //
|
79
|
+
FinalizerTrait<T>::kCallback, //
|
80
|
+
NameTrait<T>::GetName)) //
|
81
|
+
DISPATCH(true, true, false, //
|
82
|
+
EnsureGCInfoIndexPolymorphic(registered_index, //
|
83
|
+
TraceTrait<T>::Trace, //
|
84
|
+
FinalizerTrait<T>::kCallback)) //
|
85
|
+
DISPATCH(true, false, true, //
|
86
|
+
EnsureGCInfoIndexPolymorphic(registered_index, //
|
87
|
+
TraceTrait<T>::Trace, //
|
88
|
+
NameTrait<T>::GetName)) //
|
89
|
+
DISPATCH(true, false, false, //
|
90
|
+
EnsureGCInfoIndexPolymorphic(registered_index, //
|
91
|
+
TraceTrait<T>::Trace)) //
|
92
|
+
DISPATCH(false, true, true, //
|
93
|
+
EnsureGCInfoIndexNonPolymorphic(registered_index, //
|
94
|
+
TraceTrait<T>::Trace, //
|
95
|
+
FinalizerTrait<T>::kCallback, //
|
96
|
+
NameTrait<T>::GetName)) //
|
97
|
+
DISPATCH(false, true, false, //
|
98
|
+
EnsureGCInfoIndexNonPolymorphic(registered_index, //
|
99
|
+
TraceTrait<T>::Trace, //
|
100
|
+
FinalizerTrait<T>::kCallback)) //
|
101
|
+
DISPATCH(false, false, true, //
|
102
|
+
EnsureGCInfoIndexNonPolymorphic(registered_index, //
|
103
|
+
TraceTrait<T>::Trace, //
|
104
|
+
NameTrait<T>::GetName)) //
|
105
|
+
DISPATCH(false, false, false, //
|
106
|
+
EnsureGCInfoIndexNonPolymorphic(registered_index, //
|
107
|
+
TraceTrait<T>::Trace)) //
|
108
|
+
|
109
|
+
#undef DISPATCH
|
27
110
|
|
28
111
|
// Fold types based on finalizer behavior. Note that finalizer characteristics
|
29
112
|
// align with trace behavior, i.e., destructors are virtual when trace methods
|
@@ -57,16 +140,13 @@ struct GCInfoFolding {
|
|
57
140
|
// finalization, and naming.
|
58
141
|
template <typename T>
|
59
142
|
struct GCInfoTrait final {
|
60
|
-
static GCInfoIndex Index() {
|
143
|
+
V8_INLINE static GCInfoIndex Index() {
|
61
144
|
static_assert(sizeof(T), "T must be fully defined");
|
62
145
|
static std::atomic<GCInfoIndex>
|
63
146
|
registered_index; // Uses zero initialization.
|
64
147
|
const GCInfoIndex index = registered_index.load(std::memory_order_acquire);
|
65
148
|
return index ? index
|
66
|
-
:
|
67
|
-
registered_index, FinalizerTrait<T>::kCallback,
|
68
|
-
TraceTrait<T>::Trace, NameTrait<T>::GetName,
|
69
|
-
std::is_polymorphic<T>::value);
|
149
|
+
: EnsureGCInfoIndexTrait::EnsureIndex<T>(registered_index);
|
70
150
|
}
|
71
151
|
};
|
72
152
|
|
@@ -6,6 +6,7 @@
|
|
6
6
|
#define INCLUDE_CPPGC_INTERNAL_NAME_TRAIT_H_
|
7
7
|
|
8
8
|
#include <cstddef>
|
9
|
+
#include <type_traits>
|
9
10
|
|
10
11
|
#include "cppgc/name-provider.h"
|
11
12
|
#include "v8config.h" // NOLINT(build/include_directory)
|
@@ -67,6 +68,16 @@ class V8_EXPORT NameTraitBase {
|
|
67
68
|
template <typename T>
|
68
69
|
class NameTrait final : public NameTraitBase {
|
69
70
|
public:
|
71
|
+
static constexpr bool HasNonHiddenName() {
|
72
|
+
#if CPPGC_SUPPORTS_COMPILE_TIME_TYPENAME
|
73
|
+
return true;
|
74
|
+
#elif CPPGC_SUPPORTS_OBJECT_NAMES
|
75
|
+
return true;
|
76
|
+
#else // !CPPGC_SUPPORTS_OBJECT_NAMES
|
77
|
+
return std::is_base_of<NameProvider, T>::value;
|
78
|
+
#endif // !CPPGC_SUPPORTS_OBJECT_NAMES
|
79
|
+
}
|
80
|
+
|
70
81
|
static HeapObjectName GetName(const void* obj) {
|
71
82
|
return GetNameFor(static_cast<const T*>(obj));
|
72
83
|
}
|
@@ -75,16 +75,16 @@ class PersistentNode final {
|
|
75
75
|
TraceCallback trace_ = nullptr;
|
76
76
|
};
|
77
77
|
|
78
|
-
class V8_EXPORT
|
78
|
+
class V8_EXPORT PersistentRegionBase {
|
79
79
|
using PersistentNodeSlots = std::array<PersistentNode, 256u>;
|
80
80
|
|
81
81
|
public:
|
82
|
-
|
82
|
+
PersistentRegionBase() = default;
|
83
83
|
// Clears Persistent fields to avoid stale pointers after heap teardown.
|
84
|
-
~
|
84
|
+
~PersistentRegionBase();
|
85
85
|
|
86
|
-
|
87
|
-
|
86
|
+
PersistentRegionBase(const PersistentRegionBase&) = delete;
|
87
|
+
PersistentRegionBase& operator=(const PersistentRegionBase&) = delete;
|
88
88
|
|
89
89
|
PersistentNode* AllocateNode(void* owner, TraceCallback trace) {
|
90
90
|
if (!free_list_head_) {
|
@@ -126,8 +126,39 @@ class V8_EXPORT PersistentRegion {
|
|
126
126
|
friend class CrossThreadPersistentRegion;
|
127
127
|
};
|
128
128
|
|
129
|
-
//
|
130
|
-
//
|
129
|
+
// Variant of PersistentRegionBase that checks whether the allocation and
|
130
|
+
// freeing happens only on the thread that created the region.
|
131
|
+
class V8_EXPORT PersistentRegion final : public PersistentRegionBase {
|
132
|
+
public:
|
133
|
+
PersistentRegion();
|
134
|
+
// Clears Persistent fields to avoid stale pointers after heap teardown.
|
135
|
+
~PersistentRegion() = default;
|
136
|
+
|
137
|
+
PersistentRegion(const PersistentRegion&) = delete;
|
138
|
+
PersistentRegion& operator=(const PersistentRegion&) = delete;
|
139
|
+
|
140
|
+
V8_INLINE PersistentNode* AllocateNode(void* owner, TraceCallback trace) {
|
141
|
+
#if V8_ENABLE_CHECKS
|
142
|
+
CheckIsCreationThread();
|
143
|
+
#endif // V8_ENABLE_CHECKS
|
144
|
+
return PersistentRegionBase::AllocateNode(owner, trace);
|
145
|
+
}
|
146
|
+
|
147
|
+
V8_INLINE void FreeNode(PersistentNode* node) {
|
148
|
+
#if V8_ENABLE_CHECKS
|
149
|
+
CheckIsCreationThread();
|
150
|
+
#endif // V8_ENABLE_CHECKS
|
151
|
+
PersistentRegionBase::FreeNode(node);
|
152
|
+
}
|
153
|
+
|
154
|
+
private:
|
155
|
+
void CheckIsCreationThread();
|
156
|
+
|
157
|
+
int creation_thread_id_;
|
158
|
+
};
|
159
|
+
|
160
|
+
// CrossThreadPersistent uses PersistentRegionBase but protects it using this
|
161
|
+
// lock when needed.
|
131
162
|
class V8_EXPORT PersistentRegionLock final {
|
132
163
|
public:
|
133
164
|
PersistentRegionLock();
|
@@ -136,9 +167,10 @@ class V8_EXPORT PersistentRegionLock final {
|
|
136
167
|
static void AssertLocked();
|
137
168
|
};
|
138
169
|
|
139
|
-
// Variant of
|
140
|
-
// locked.
|
141
|
-
class V8_EXPORT CrossThreadPersistentRegion final
|
170
|
+
// Variant of PersistentRegionBase that checks whether the PersistentRegionLock
|
171
|
+
// is locked.
|
172
|
+
class V8_EXPORT CrossThreadPersistentRegion final
|
173
|
+
: protected PersistentRegionBase {
|
142
174
|
public:
|
143
175
|
CrossThreadPersistentRegion() = default;
|
144
176
|
// Clears Persistent fields to avoid stale pointers after heap teardown.
|
@@ -150,12 +182,12 @@ class V8_EXPORT CrossThreadPersistentRegion final : protected PersistentRegion {
|
|
150
182
|
|
151
183
|
V8_INLINE PersistentNode* AllocateNode(void* owner, TraceCallback trace) {
|
152
184
|
PersistentRegionLock::AssertLocked();
|
153
|
-
return
|
185
|
+
return PersistentRegionBase::AllocateNode(owner, trace);
|
154
186
|
}
|
155
187
|
|
156
188
|
V8_INLINE void FreeNode(PersistentNode* node) {
|
157
189
|
PersistentRegionLock::AssertLocked();
|
158
|
-
|
190
|
+
PersistentRegionBase::FreeNode(node);
|
159
191
|
}
|
160
192
|
|
161
193
|
void Trace(Visitor*);
|
@@ -51,7 +51,17 @@ struct NoWriteBarrierPolicy {
|
|
51
51
|
static void AssigningBarrier(const void*, const void*) {}
|
52
52
|
};
|
53
53
|
|
54
|
-
class V8_EXPORT
|
54
|
+
class V8_EXPORT SameThreadEnabledCheckingPolicyBase {
|
55
|
+
protected:
|
56
|
+
void CheckPointerImpl(const void* ptr, bool points_to_payload,
|
57
|
+
bool check_off_heap_assignments);
|
58
|
+
|
59
|
+
const HeapBase* heap_ = nullptr;
|
60
|
+
};
|
61
|
+
|
62
|
+
template <bool kCheckOffHeapAssignments>
|
63
|
+
class V8_EXPORT SameThreadEnabledCheckingPolicy
|
64
|
+
: private SameThreadEnabledCheckingPolicyBase {
|
55
65
|
protected:
|
56
66
|
template <typename T>
|
57
67
|
void CheckPointer(const T* ptr) {
|
@@ -61,23 +71,20 @@ class V8_EXPORT EnabledCheckingPolicy {
|
|
61
71
|
}
|
62
72
|
|
63
73
|
private:
|
64
|
-
void CheckPointerImpl(const void* ptr, bool points_to_payload);
|
65
|
-
|
66
74
|
template <typename T, bool = IsCompleteV<T>>
|
67
75
|
struct CheckPointersImplTrampoline {
|
68
|
-
static void Call(
|
69
|
-
policy->CheckPointerImpl(ptr, false);
|
76
|
+
static void Call(SameThreadEnabledCheckingPolicy* policy, const T* ptr) {
|
77
|
+
policy->CheckPointerImpl(ptr, false, kCheckOffHeapAssignments);
|
70
78
|
}
|
71
79
|
};
|
72
80
|
|
73
81
|
template <typename T>
|
74
82
|
struct CheckPointersImplTrampoline<T, true> {
|
75
|
-
static void Call(
|
76
|
-
policy->CheckPointerImpl(ptr, IsGarbageCollectedTypeV<T
|
83
|
+
static void Call(SameThreadEnabledCheckingPolicy* policy, const T* ptr) {
|
84
|
+
policy->CheckPointerImpl(ptr, IsGarbageCollectedTypeV<T>,
|
85
|
+
kCheckOffHeapAssignments);
|
77
86
|
}
|
78
87
|
};
|
79
|
-
|
80
|
-
const HeapBase* heap_ = nullptr;
|
81
88
|
};
|
82
89
|
|
83
90
|
class DisabledCheckingPolicy {
|
@@ -86,8 +93,12 @@ class DisabledCheckingPolicy {
|
|
86
93
|
};
|
87
94
|
|
88
95
|
#if V8_ENABLE_CHECKS
|
89
|
-
|
90
|
-
|
96
|
+
// Off heap members are not connected to object graph and thus cannot ressurect
|
97
|
+
// dead objects.
|
98
|
+
using DefaultMemberCheckingPolicy =
|
99
|
+
SameThreadEnabledCheckingPolicy<false /* kCheckOffHeapAssignments*/>;
|
100
|
+
using DefaultPersistentCheckingPolicy =
|
101
|
+
SameThreadEnabledCheckingPolicy<true /* kCheckOffHeapAssignments*/>;
|
91
102
|
#else
|
92
103
|
using DefaultMemberCheckingPolicy = DisabledCheckingPolicy;
|
93
104
|
using DefaultPersistentCheckingPolicy = DisabledCheckingPolicy;
|
@@ -214,6 +214,11 @@ struct WriteBarrierTypeForCagedHeapPolicy::ValueModeDispatch<
|
|
214
214
|
static V8_INLINE WriteBarrier::Type Get(const void* slot, const void* value,
|
215
215
|
WriteBarrier::Params& params,
|
216
216
|
HeapHandleCallback) {
|
217
|
+
#if !defined(CPPGC_YOUNG_GENERATION)
|
218
|
+
if (V8_LIKELY(!WriteBarrier::IsAnyIncrementalOrConcurrentMarking())) {
|
219
|
+
return SetAndReturnType<WriteBarrier::Type::kNone>(params);
|
220
|
+
}
|
221
|
+
#endif // !CPPGC_YOUNG_GENERATION
|
217
222
|
bool within_cage = TryGetCagedHeap(slot, value, params);
|
218
223
|
if (!within_cage) {
|
219
224
|
return WriteBarrier::Type::kNone;
|
@@ -317,7 +322,10 @@ struct WriteBarrierTypeForNonCagedHeapPolicy::ValueModeDispatch<
|
|
317
322
|
HeapHandleCallback callback) {
|
318
323
|
// The following check covers nullptr as well as sentinel pointer.
|
319
324
|
if (object <= static_cast<void*>(kSentinelPointer)) {
|
320
|
-
return WriteBarrier::Type::kNone;
|
325
|
+
return SetAndReturnType<WriteBarrier::Type::kNone>(params);
|
326
|
+
}
|
327
|
+
if (V8_LIKELY(!WriteBarrier::IsAnyIncrementalOrConcurrentMarking())) {
|
328
|
+
return SetAndReturnType<WriteBarrier::Type::kNone>(params);
|
321
329
|
}
|
322
330
|
if (IsMarking(object, ¶ms.heap)) {
|
323
331
|
return SetAndReturnType<WriteBarrier::Type::kMarking>(params);
|
@@ -45,7 +45,7 @@ class PersistentBase {
|
|
45
45
|
mutable const void* raw_ = nullptr;
|
46
46
|
mutable PersistentNode* node_ = nullptr;
|
47
47
|
|
48
|
-
friend class
|
48
|
+
friend class PersistentRegionBase;
|
49
49
|
};
|
50
50
|
|
51
51
|
// The basic class from which all Persistent classes are generated.
|
@@ -38,7 +38,7 @@ class PrefinalizerRegistration final {
|
|
38
38
|
"Only garbage collected objects can have prefinalizers"); \
|
39
39
|
Class* self = static_cast<Class*>(object); \
|
40
40
|
if (liveness_broker.IsHeapObjectAlive(self)) return false; \
|
41
|
-
self->
|
41
|
+
self->PreFinalizer(); \
|
42
42
|
return true; \
|
43
43
|
} \
|
44
44
|
\
|