File indexing completed on 2025-02-21 10:05:27
0001
0002
0003
0004
0005 #ifndef INCLUDE_V8_TRACED_HANDLE_H_
0006 #define INCLUDE_V8_TRACED_HANDLE_H_
0007
0008 #include <stddef.h>
0009 #include <stdint.h>
0010 #include <stdio.h>
0011
0012 #include <atomic>
0013 #include <memory>
0014 #include <type_traits>
0015 #include <utility>
0016
0017 #include "v8-internal.h" // NOLINT(build/include_directory)
0018 #include "v8-local-handle.h" // NOLINT(build/include_directory)
0019 #include "v8-weak-callback-info.h" // NOLINT(build/include_directory)
0020 #include "v8config.h" // NOLINT(build/include_directory)
0021
0022 namespace v8 {
0023
0024 class Value;
0025
0026 namespace internal {
0027
0028 class BasicTracedReferenceExtractor;
0029
0030 enum class TracedReferenceStoreMode {
0031 kInitializingStore,
0032 kAssigningStore,
0033 };
0034
0035 enum class TracedReferenceHandling {
0036 kDefault,
0037 kDroppable
0038 };
0039
0040 V8_EXPORT internal::Address* GlobalizeTracedReference(
0041 internal::Isolate* isolate, internal::Address value,
0042 internal::Address* slot, TracedReferenceStoreMode store_mode,
0043 internal::TracedReferenceHandling reference_handling);
0044 V8_EXPORT void MoveTracedReference(internal::Address** from,
0045 internal::Address** to);
0046 V8_EXPORT void CopyTracedReference(const internal::Address* const* from,
0047 internal::Address** to);
0048 V8_EXPORT void DisposeTracedReference(internal::Address* global_handle);
0049
0050 }
0051
0052
0053
0054
0055
0056 class TracedReferenceBase : public api_internal::IndirectHandleBase {
0057 public:
0058
0059
0060
0061
0062 V8_INLINE void Reset();
0063
0064
0065
0066
0067 V8_INLINE Local<Value> Get(Isolate* isolate) const {
0068 if (IsEmpty()) return Local<Value>();
0069 return Local<Value>::New(isolate, this->value<Value>());
0070 }
0071
0072
0073
0074
0075
0076 bool IsEmptyThreadSafe() const {
0077 return this->GetSlotThreadSafe() == nullptr;
0078 }
0079
0080 protected:
0081 V8_INLINE TracedReferenceBase() = default;
0082
0083
0084
0085
0086 void SetSlotThreadSafe(void* new_val) {
0087 reinterpret_cast<std::atomic<void*>*>(&slot())->store(
0088 new_val, std::memory_order_relaxed);
0089 }
0090
0091
0092
0093
0094 const void* GetSlotThreadSafe() const {
0095 return reinterpret_cast<std::atomic<const void*> const*>(&slot())->load(
0096 std::memory_order_relaxed);
0097 }
0098
0099 V8_EXPORT void CheckValue() const;
0100
0101 friend class internal::BasicTracedReferenceExtractor;
0102 template <typename F>
0103 friend class Local;
0104 template <typename U>
0105 friend bool operator==(const TracedReferenceBase&, const Local<U>&);
0106 friend bool operator==(const TracedReferenceBase&,
0107 const TracedReferenceBase&);
0108 };
0109
0110
0111
0112
0113
0114
0115
0116
0117
0118
0119
0120
0121
0122
0123
0124 template <typename T>
0125 class BasicTracedReference : public TracedReferenceBase {
0126 public:
0127
0128
0129
0130 Local<T> Get(Isolate* isolate) const { return Local<T>::New(isolate, *this); }
0131
0132 template <class S>
0133 V8_INLINE BasicTracedReference<S>& As() const {
0134 return reinterpret_cast<BasicTracedReference<S>&>(
0135 const_cast<BasicTracedReference<T>&>(*this));
0136 }
0137
0138 V8_DEPRECATE_SOON("Use Get to convert to Local instead")
0139 V8_INLINE T* operator->() const {
0140 #ifdef V8_ENABLE_CHECKS
0141 CheckValue();
0142 #endif
0143 return this->template value<T>();
0144 }
0145
0146 V8_DEPRECATE_SOON("Use Get to convert to Local instead")
0147 V8_INLINE T* operator*() const { return this->operator->(); }
0148
0149 private:
0150
0151
0152
0153 BasicTracedReference() = default;
0154
0155 V8_INLINE static internal::Address* NewFromNonEmptyValue(
0156 Isolate* isolate, T* that, internal::Address** slot,
0157 internal::TracedReferenceStoreMode store_mode,
0158 internal::TracedReferenceHandling reference_handling);
0159
0160 template <typename F>
0161 friend class Local;
0162 friend class Object;
0163 template <typename F>
0164 friend class TracedReference;
0165 template <typename F>
0166 friend class BasicTracedReference;
0167 template <typename F>
0168 friend class ReturnValue;
0169 };
0170
0171
0172
0173
0174
0175
0176 template <typename T>
0177 class TracedReference : public BasicTracedReference<T> {
0178 public:
0179 struct IsDroppable {};
0180
0181 using BasicTracedReference<T>::Reset;
0182
0183
0184
0185
0186 V8_INLINE TracedReference() = default;
0187
0188
0189
0190
0191
0192
0193
0194 template <class S>
0195 TracedReference(Isolate* isolate, Local<S> that) : BasicTracedReference<T>() {
0196 static_assert(std::is_base_of<T, S>::value, "type check");
0197 if (V8_UNLIKELY(that.IsEmpty())) {
0198 return;
0199 }
0200 this->slot() = this->NewFromNonEmptyValue(
0201 isolate, *that, &this->slot(),
0202 internal::TracedReferenceStoreMode::kInitializingStore,
0203 internal::TracedReferenceHandling::kDefault);
0204 }
0205
0206
0207
0208
0209
0210
0211
0212
0213
0214 template <class S>
0215 TracedReference(Isolate* isolate, Local<S> that, IsDroppable)
0216 : BasicTracedReference<T>() {
0217 static_assert(std::is_base_of<T, S>::value, "type check");
0218 if (V8_UNLIKELY(that.IsEmpty())) {
0219 return;
0220 }
0221 this->slot() = this->NewFromNonEmptyValue(
0222 isolate, *that, &this->slot(),
0223 internal::TracedReferenceStoreMode::kInitializingStore,
0224 internal::TracedReferenceHandling::kDroppable);
0225 }
0226
0227
0228
0229
0230
0231 V8_INLINE TracedReference(TracedReference&& other) noexcept {
0232
0233 *this = std::move(other);
0234 }
0235
0236
0237
0238
0239
0240 template <typename S>
0241 V8_INLINE TracedReference(TracedReference<S>&& other) noexcept {
0242
0243 *this = std::move(other);
0244 }
0245
0246
0247
0248
0249
0250 V8_INLINE TracedReference(const TracedReference& other) {
0251
0252 *this = other;
0253 }
0254
0255
0256
0257
0258
0259 template <typename S>
0260 V8_INLINE TracedReference(const TracedReference<S>& other) {
0261
0262 *this = other;
0263 }
0264
0265
0266
0267
0268 V8_INLINE TracedReference& operator=(TracedReference&& rhs) noexcept;
0269
0270
0271
0272
0273 template <class S>
0274 V8_INLINE TracedReference& operator=(TracedReference<S>&& rhs) noexcept;
0275
0276
0277
0278
0279 V8_INLINE TracedReference& operator=(const TracedReference& rhs);
0280
0281
0282
0283
0284 template <class S>
0285 V8_INLINE TracedReference& operator=(const TracedReference<S>& rhs);
0286
0287
0288
0289
0290
0291 template <class S>
0292 V8_INLINE void Reset(Isolate* isolate, const Local<S>& other);
0293
0294
0295
0296
0297
0298 template <class S>
0299 V8_INLINE void Reset(Isolate* isolate, const Local<S>& other, IsDroppable);
0300
0301 template <class S>
0302 V8_INLINE TracedReference<S>& As() const {
0303 return reinterpret_cast<TracedReference<S>&>(
0304 const_cast<TracedReference<T>&>(*this));
0305 }
0306 };
0307
0308
0309 template <class T>
0310 internal::Address* BasicTracedReference<T>::NewFromNonEmptyValue(
0311 Isolate* isolate, T* that, internal::Address** slot,
0312 internal::TracedReferenceStoreMode store_mode,
0313 internal::TracedReferenceHandling reference_handling) {
0314 return internal::GlobalizeTracedReference(
0315 reinterpret_cast<internal::Isolate*>(isolate),
0316 internal::ValueHelper::ValueAsAddress(that),
0317 reinterpret_cast<internal::Address*>(slot), store_mode,
0318 reference_handling);
0319 }
0320
0321 void TracedReferenceBase::Reset() {
0322 if (V8_UNLIKELY(IsEmpty())) {
0323 return;
0324 }
0325 internal::DisposeTracedReference(slot());
0326 SetSlotThreadSafe(nullptr);
0327 }
0328
0329 V8_INLINE bool operator==(const TracedReferenceBase& lhs,
0330 const TracedReferenceBase& rhs) {
0331 return internal::HandleHelper::EqualHandles(lhs, rhs);
0332 }
0333
0334 template <typename U>
0335 V8_INLINE bool operator==(const TracedReferenceBase& lhs,
0336 const v8::Local<U>& rhs) {
0337 return internal::HandleHelper::EqualHandles(lhs, rhs);
0338 }
0339
0340 template <typename U>
0341 V8_INLINE bool operator==(const v8::Local<U>& lhs,
0342 const TracedReferenceBase& rhs) {
0343 return rhs == lhs;
0344 }
0345
0346 V8_INLINE bool operator!=(const TracedReferenceBase& lhs,
0347 const TracedReferenceBase& rhs) {
0348 return !(lhs == rhs);
0349 }
0350
0351 template <typename U>
0352 V8_INLINE bool operator!=(const TracedReferenceBase& lhs,
0353 const v8::Local<U>& rhs) {
0354 return !(lhs == rhs);
0355 }
0356
0357 template <typename U>
0358 V8_INLINE bool operator!=(const v8::Local<U>& lhs,
0359 const TracedReferenceBase& rhs) {
0360 return !(rhs == lhs);
0361 }
0362
0363 template <class T>
0364 template <class S>
0365 void TracedReference<T>::Reset(Isolate* isolate, const Local<S>& other) {
0366 static_assert(std::is_base_of<T, S>::value, "type check");
0367 this->Reset();
0368 if (V8_UNLIKELY(other.IsEmpty())) {
0369 return;
0370 }
0371 this->SetSlotThreadSafe(this->NewFromNonEmptyValue(
0372 isolate, *other, &this->slot(),
0373 internal::TracedReferenceStoreMode::kAssigningStore,
0374 internal::TracedReferenceHandling::kDefault));
0375 }
0376
0377 template <class T>
0378 template <class S>
0379 void TracedReference<T>::Reset(Isolate* isolate, const Local<S>& other,
0380 IsDroppable) {
0381 static_assert(std::is_base_of<T, S>::value, "type check");
0382 this->Reset();
0383 if (V8_UNLIKELY(other.IsEmpty())) {
0384 return;
0385 }
0386 this->SetSlotThreadSafe(this->NewFromNonEmptyValue(
0387 isolate, *other, &this->slot(),
0388 internal::TracedReferenceStoreMode::kAssigningStore,
0389 internal::TracedReferenceHandling::kDroppable));
0390 }
0391
0392 template <class T>
0393 template <class S>
0394 TracedReference<T>& TracedReference<T>::operator=(
0395 TracedReference<S>&& rhs) noexcept {
0396 static_assert(std::is_base_of<T, S>::value, "type check");
0397 *this = std::move(rhs.template As<T>());
0398 return *this;
0399 }
0400
0401 template <class T>
0402 template <class S>
0403 TracedReference<T>& TracedReference<T>::operator=(
0404 const TracedReference<S>& rhs) {
0405 static_assert(std::is_base_of<T, S>::value, "type check");
0406 *this = rhs.template As<T>();
0407 return *this;
0408 }
0409
0410 template <class T>
0411 TracedReference<T>& TracedReference<T>::operator=(
0412 TracedReference&& rhs) noexcept {
0413 if (this != &rhs) {
0414 internal::MoveTracedReference(&rhs.slot(), &this->slot());
0415 }
0416 return *this;
0417 }
0418
0419 template <class T>
0420 TracedReference<T>& TracedReference<T>::operator=(const TracedReference& rhs) {
0421 if (this != &rhs) {
0422 this->Reset();
0423 if (!rhs.IsEmpty()) {
0424 internal::CopyTracedReference(&rhs.slot(), &this->slot());
0425 }
0426 }
0427 return *this;
0428 }
0429
0430 }
0431
0432 #endif