Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-02-21 10:05:27

0001 // Copyright 2021 the V8 project authors. All rights reserved.
0002 // Use of this source code is governed by a BSD-style license that can be
0003 // found in the LICENSE file.
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,  // See EmbedderRootsHandler::IsRoot().
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 }  // namespace internal
0051 
0052 /**
0053  * An indirect handle, where the indirect pointer points to a GlobalHandles
0054  * node.
0055  */
0056 class TracedReferenceBase : public api_internal::IndirectHandleBase {
0057  public:
0058   /**
0059    * If non-empty, destroy the underlying storage cell. |IsEmpty| will return
0060    * true after this call.
0061    */
0062   V8_INLINE void Reset();
0063 
0064   /**
0065    * Construct a Local<Value> from this handle.
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    * Returns true if this TracedReference is empty, i.e., has not been
0074    * assigned an object. This version of IsEmpty is thread-safe.
0075    */
0076   bool IsEmptyThreadSafe() const {
0077     return this->GetSlotThreadSafe() == nullptr;
0078   }
0079 
0080  protected:
0081   V8_INLINE TracedReferenceBase() = default;
0082 
0083   /**
0084    * Update this reference in a thread-safe way.
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    * Get this reference in a thread-safe way
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  * A traced handle with copy and move semantics. The handle is to be used
0112  * together as part of GarbageCollected objects (see v8-cppgc.h) or from stack
0113  * and specifies edges from C++ objects to JavaScript.
0114  *
0115  * The exact semantics are:
0116  * - Tracing garbage collections using CppHeap.
0117  * - Non-tracing garbage collections refer to
0118  *   |v8::EmbedderRootsHandler::IsRoot()| whether the handle should
0119  * be treated as root or not.
0120  *
0121  * Note that the base class cannot be instantiated itself, use |TracedReference|
0122  * instead.
0123  */
0124 template <typename T>
0125 class BasicTracedReference : public TracedReferenceBase {
0126  public:
0127   /**
0128    * Construct a Local<T> from this handle.
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  // V8_ENABLE_CHECKS
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    * An empty BasicTracedReference without storage cell.
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  * A traced handle without destructor that clears the handle. The embedder needs
0173  * to ensure that the handle is not accessed once the V8 object has been
0174  * reclaimed. For more details see BasicTracedReference.
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    * An empty TracedReference without storage cell.
0185    */
0186   V8_INLINE TracedReference() = default;
0187 
0188   /**
0189    * Construct a TracedReference from a Local.
0190    *
0191    * When the Local is non-empty, a new storage cell is created
0192    * pointing to the same object.
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    * Construct a droppable TracedReference from a Local. Droppable means that V8
0208    * is free to reclaim the pointee if it is unmodified and otherwise
0209    * unreachable
0210    *
0211    * When the Local is non-empty, a new storage cell is created
0212    * pointing to the same object.
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    * Move constructor initializing TracedReference from an
0229    * existing one.
0230    */
0231   V8_INLINE TracedReference(TracedReference&& other) noexcept {
0232     // Forward to operator=.
0233     *this = std::move(other);
0234   }
0235 
0236   /**
0237    * Move constructor initializing TracedReference from an
0238    * existing one.
0239    */
0240   template <typename S>
0241   V8_INLINE TracedReference(TracedReference<S>&& other) noexcept {
0242     // Forward to operator=.
0243     *this = std::move(other);
0244   }
0245 
0246   /**
0247    * Copy constructor initializing TracedReference from an
0248    * existing one.
0249    */
0250   V8_INLINE TracedReference(const TracedReference& other) {
0251     // Forward to operator=;
0252     *this = other;
0253   }
0254 
0255   /**
0256    * Copy constructor initializing TracedReference from an
0257    * existing one.
0258    */
0259   template <typename S>
0260   V8_INLINE TracedReference(const TracedReference<S>& other) {
0261     // Forward to operator=;
0262     *this = other;
0263   }
0264 
0265   /**
0266    * Move assignment operator initializing TracedReference from an existing one.
0267    */
0268   V8_INLINE TracedReference& operator=(TracedReference&& rhs) noexcept;
0269 
0270   /**
0271    * Move assignment operator initializing TracedReference from an existing one.
0272    */
0273   template <class S>
0274   V8_INLINE TracedReference& operator=(TracedReference<S>&& rhs) noexcept;
0275 
0276   /**
0277    * Copy assignment operator initializing TracedReference from an existing one.
0278    */
0279   V8_INLINE TracedReference& operator=(const TracedReference& rhs);
0280 
0281   /**
0282    * Copy assignment operator initializing TracedReference from an existing one.
0283    */
0284   template <class S>
0285   V8_INLINE TracedReference& operator=(const TracedReference<S>& rhs);
0286 
0287   /**
0288    * Always resets the reference. Creates a new reference from `other` if it is
0289    * non-empty.
0290    */
0291   template <class S>
0292   V8_INLINE void Reset(Isolate* isolate, const Local<S>& other);
0293 
0294   /**
0295    * Always resets the reference. Creates a new reference from `other` if it is
0296    * non-empty. The new reference is droppable, see constructor.
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 // --- Implementation ---
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 }  // namespace v8
0431 
0432 #endif  // INCLUDE_V8_TRACED_HANDLE_H_