Back to home page

EIC code displayed by LXR

 
 

    


Warning, file /include/node/v8-traced-handle.h was not indexed or was modified since last indexation (in which case cross-reference links may be missing, inaccurate or erroneous).

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 Address* GlobalizeTracedReference(
0041     Isolate* isolate, Address value, Address* slot,
0042     TracedReferenceStoreMode store_mode,
0043     TracedReferenceHandling reference_handling);
0044 V8_EXPORT void MoveTracedReference(Address** from, Address** to);
0045 V8_EXPORT void CopyTracedReference(const Address* const* from, Address** to);
0046 V8_EXPORT void DisposeTracedReference(Address* global_handle);
0047 
0048 }  // namespace internal
0049 
0050 /**
0051  * An indirect handle, where the indirect pointer points to a GlobalHandles
0052  * node.
0053  */
0054 class TracedReferenceBase : public api_internal::IndirectHandleBase {
0055  public:
0056   static_assert(sizeof(std::atomic<internal::Address*>) ==
0057                 sizeof(internal::Address*));
0058 
0059   /**
0060    * If non-empty, destroy the underlying storage cell. |IsEmpty| will return
0061    * true after this call.
0062    */
0063   V8_INLINE void Reset();
0064 
0065   /**
0066    * Construct a Local<Data> from this handle.
0067    */
0068   V8_INLINE Local<Data> Get(Isolate* isolate) const {
0069     if (IsEmpty()) return Local<Data>();
0070     return Local<Data>::New(isolate, this->value<Data>());
0071   }
0072 
0073   /**
0074    * Returns true if this TracedReference is empty, i.e., has not been
0075    * assigned an object. This version of IsEmpty is thread-safe.
0076    */
0077   bool IsEmptyThreadSafe() const { return GetSlotThreadSafe() == nullptr; }
0078 
0079  protected:
0080   V8_INLINE TracedReferenceBase() = default;
0081 
0082   /**
0083    * Update this reference in a thread-safe way.
0084    */
0085   void SetSlotThreadSafe(internal::Address* new_val) {
0086     reinterpret_cast<std::atomic<internal::Address*>*>(&slot())->store(
0087         new_val, std::memory_order_relaxed);
0088   }
0089 
0090   /**
0091    * Get this reference in a thread-safe way
0092    */
0093   const internal::Address* GetSlotThreadSafe() const {
0094     return reinterpret_cast<const std::atomic<internal::Address*>*>(&slot())
0095         ->load(std::memory_order_relaxed);
0096   }
0097 
0098   V8_EXPORT void CheckValue() const;
0099 
0100   friend class internal::BasicTracedReferenceExtractor;
0101   template <typename F>
0102   friend class Local;
0103   template <typename U>
0104   friend bool operator==(const TracedReferenceBase&, const Local<U>&);
0105   friend bool operator==(const TracedReferenceBase&,
0106                          const TracedReferenceBase&);
0107 };
0108 
0109 /**
0110  * A traced handle with copy and move semantics. The handle is to be used
0111  * together as part of GarbageCollected objects (see v8-cppgc.h) or from stack
0112  * and specifies edges from C++ objects to JavaScript.
0113  *
0114  * The exact semantics are:
0115  * - Tracing garbage collections using CppHeap.
0116  * - Non-tracing garbage collections refer to
0117  *   |v8::EmbedderRootsHandler::IsRoot()| whether the handle should
0118  * be treated as root or not.
0119  *
0120  * Note that the base class cannot be instantiated itself, use |TracedReference|
0121  * instead.
0122  */
0123 template <typename T>
0124 class BasicTracedReference : public TracedReferenceBase {
0125  public:
0126   /**
0127    * Construct a Local<T> from this handle.
0128    */
0129   Local<T> Get(Isolate* isolate) const { return Local<T>::New(isolate, *this); }
0130 
0131   template <class S>
0132   V8_INLINE BasicTracedReference<S>& As() const {
0133     return reinterpret_cast<BasicTracedReference<S>&>(
0134         const_cast<BasicTracedReference<T>&>(*this));
0135   }
0136 
0137  private:
0138   /**
0139    * An empty BasicTracedReference without storage cell.
0140    */
0141   BasicTracedReference() = default;
0142 
0143   V8_INLINE static internal::Address* NewFromNonEmptyValue(
0144       Isolate* isolate, T* that, internal::Address** slot,
0145       internal::TracedReferenceStoreMode store_mode,
0146       internal::TracedReferenceHandling reference_handling);
0147 
0148   template <typename F>
0149   friend class Local;
0150   friend class Object;
0151   template <typename F>
0152   friend class TracedReference;
0153   template <typename F>
0154   friend class BasicTracedReference;
0155   template <typename F>
0156   friend class ReturnValue;
0157 };
0158 
0159 /**
0160  * A traced handle without destructor that clears the handle. The embedder needs
0161  * to ensure that the handle is not accessed once the V8 object has been
0162  * reclaimed. For more details see BasicTracedReference.
0163  */
0164 template <typename T>
0165 class TracedReference : public BasicTracedReference<T> {
0166  public:
0167   struct IsDroppable {};
0168 
0169   using BasicTracedReference<T>::Reset;
0170 
0171   /**
0172    * An empty TracedReference without storage cell.
0173    */
0174   V8_INLINE TracedReference() = default;
0175 
0176   /**
0177    * Construct a TracedReference from a Local.
0178    *
0179    * When the Local is non-empty, a new storage cell is created
0180    * pointing to the same object.
0181    */
0182   template <class S>
0183   TracedReference(Isolate* isolate, Local<S> that) : BasicTracedReference<T>() {
0184     static_assert(std::is_base_of<T, S>::value, "type check");
0185     if (V8_UNLIKELY(that.IsEmpty())) {
0186       return;
0187     }
0188     this->slot() = this->NewFromNonEmptyValue(
0189         isolate, *that, &this->slot(),
0190         internal::TracedReferenceStoreMode::kInitializingStore,
0191         internal::TracedReferenceHandling::kDefault);
0192   }
0193 
0194   /**
0195    * Construct a droppable TracedReference from a Local. Droppable means that V8
0196    * is free to reclaim the pointee if it is unmodified and otherwise
0197    * unreachable
0198    *
0199    * When the Local is non-empty, a new storage cell is created
0200    * pointing to the same object.
0201    */
0202   template <class S>
0203   TracedReference(Isolate* isolate, Local<S> that, IsDroppable)
0204       : BasicTracedReference<T>() {
0205     static_assert(std::is_base_of<T, S>::value, "type check");
0206     if (V8_UNLIKELY(that.IsEmpty())) {
0207       return;
0208     }
0209     this->slot() = this->NewFromNonEmptyValue(
0210         isolate, *that, &this->slot(),
0211         internal::TracedReferenceStoreMode::kInitializingStore,
0212         internal::TracedReferenceHandling::kDroppable);
0213   }
0214 
0215   /**
0216    * Move constructor initializing TracedReference from an
0217    * existing one.
0218    */
0219   V8_INLINE TracedReference(TracedReference&& other) noexcept {
0220     // Forward to operator=.
0221     *this = std::move(other);
0222   }
0223 
0224   /**
0225    * Move constructor initializing TracedReference from an
0226    * existing one.
0227    */
0228   template <typename S>
0229   V8_INLINE TracedReference(TracedReference<S>&& other) noexcept {
0230     // Forward to operator=.
0231     *this = std::move(other);
0232   }
0233 
0234   /**
0235    * Copy constructor initializing TracedReference from an
0236    * existing one.
0237    */
0238   V8_INLINE TracedReference(const TracedReference& other) {
0239     // Forward to operator=;
0240     *this = other;
0241   }
0242 
0243   /**
0244    * Copy constructor initializing TracedReference from an
0245    * existing one.
0246    */
0247   template <typename S>
0248   V8_INLINE TracedReference(const TracedReference<S>& other) {
0249     // Forward to operator=;
0250     *this = other;
0251   }
0252 
0253   /**
0254    * Move assignment operator initializing TracedReference from an existing one.
0255    */
0256   V8_INLINE TracedReference& operator=(TracedReference&& rhs) noexcept;
0257 
0258   /**
0259    * Move assignment operator initializing TracedReference from an existing one.
0260    */
0261   template <class S>
0262   V8_INLINE TracedReference& operator=(TracedReference<S>&& rhs) noexcept;
0263 
0264   /**
0265    * Copy assignment operator initializing TracedReference from an existing one.
0266    */
0267   V8_INLINE TracedReference& operator=(const TracedReference& rhs);
0268 
0269   /**
0270    * Copy assignment operator initializing TracedReference from an existing one.
0271    */
0272   template <class S>
0273   V8_INLINE TracedReference& operator=(const TracedReference<S>& rhs);
0274 
0275   /**
0276    * Always resets the reference. Creates a new reference from `other` if it is
0277    * non-empty.
0278    */
0279   template <class S>
0280   V8_INLINE void Reset(Isolate* isolate, const Local<S>& other);
0281 
0282   /**
0283    * Always resets the reference. Creates a new reference from `other` if it is
0284    * non-empty. The new reference is droppable, see constructor.
0285    */
0286   template <class S>
0287   V8_INLINE void Reset(Isolate* isolate, const Local<S>& other, IsDroppable);
0288 
0289   template <class S>
0290   V8_INLINE TracedReference<S>& As() const {
0291     return reinterpret_cast<TracedReference<S>&>(
0292         const_cast<TracedReference<T>&>(*this));
0293   }
0294 };
0295 
0296 // --- Implementation ---
0297 template <class T>
0298 internal::Address* BasicTracedReference<T>::NewFromNonEmptyValue(
0299     Isolate* isolate, T* that, internal::Address** slot,
0300     internal::TracedReferenceStoreMode store_mode,
0301     internal::TracedReferenceHandling reference_handling) {
0302   return internal::GlobalizeTracedReference(
0303       reinterpret_cast<internal::Isolate*>(isolate),
0304       internal::ValueHelper::ValueAsAddress(that),
0305       reinterpret_cast<internal::Address*>(slot), store_mode,
0306       reference_handling);
0307 }
0308 
0309 void TracedReferenceBase::Reset() {
0310   if (V8_UNLIKELY(IsEmpty())) {
0311     return;
0312   }
0313   internal::DisposeTracedReference(slot());
0314   SetSlotThreadSafe(nullptr);
0315 }
0316 
0317 V8_INLINE bool operator==(const TracedReferenceBase& lhs,
0318                           const TracedReferenceBase& rhs) {
0319   return internal::HandleHelper::EqualHandles(lhs, rhs);
0320 }
0321 
0322 template <typename U>
0323 V8_INLINE bool operator==(const TracedReferenceBase& lhs,
0324                           const v8::Local<U>& rhs) {
0325   return internal::HandleHelper::EqualHandles(lhs, rhs);
0326 }
0327 
0328 template <typename U>
0329 V8_INLINE bool operator==(const v8::Local<U>& lhs,
0330                           const TracedReferenceBase& rhs) {
0331   return rhs == lhs;
0332 }
0333 
0334 V8_INLINE bool operator!=(const TracedReferenceBase& lhs,
0335                           const TracedReferenceBase& rhs) {
0336   return !(lhs == rhs);
0337 }
0338 
0339 template <typename U>
0340 V8_INLINE bool operator!=(const TracedReferenceBase& lhs,
0341                           const v8::Local<U>& rhs) {
0342   return !(lhs == rhs);
0343 }
0344 
0345 template <typename U>
0346 V8_INLINE bool operator!=(const v8::Local<U>& lhs,
0347                           const TracedReferenceBase& rhs) {
0348   return !(rhs == lhs);
0349 }
0350 
0351 template <class T>
0352 template <class S>
0353 void TracedReference<T>::Reset(Isolate* isolate, const Local<S>& other) {
0354   static_assert(std::is_base_of<T, S>::value, "type check");
0355   this->Reset();
0356   if (V8_UNLIKELY(other.IsEmpty())) {
0357     return;
0358   }
0359   this->SetSlotThreadSafe(this->NewFromNonEmptyValue(
0360       isolate, *other, &this->slot(),
0361       internal::TracedReferenceStoreMode::kAssigningStore,
0362       internal::TracedReferenceHandling::kDefault));
0363 }
0364 
0365 template <class T>
0366 template <class S>
0367 void TracedReference<T>::Reset(Isolate* isolate, const Local<S>& other,
0368                                IsDroppable) {
0369   static_assert(std::is_base_of<T, S>::value, "type check");
0370   this->Reset();
0371   if (V8_UNLIKELY(other.IsEmpty())) {
0372     return;
0373   }
0374   this->SetSlotThreadSafe(this->NewFromNonEmptyValue(
0375       isolate, *other, &this->slot(),
0376       internal::TracedReferenceStoreMode::kAssigningStore,
0377       internal::TracedReferenceHandling::kDroppable));
0378 }
0379 
0380 template <class T>
0381 template <class S>
0382 TracedReference<T>& TracedReference<T>::operator=(
0383     TracedReference<S>&& rhs) noexcept {
0384   static_assert(std::is_base_of<T, S>::value, "type check");
0385   *this = std::move(rhs.template As<T>());
0386   return *this;
0387 }
0388 
0389 template <class T>
0390 template <class S>
0391 TracedReference<T>& TracedReference<T>::operator=(
0392     const TracedReference<S>& rhs) {
0393   static_assert(std::is_base_of<T, S>::value, "type check");
0394   *this = rhs.template As<T>();
0395   return *this;
0396 }
0397 
0398 template <class T>
0399 TracedReference<T>& TracedReference<T>::operator=(
0400     TracedReference&& rhs) noexcept {
0401   if (this != &rhs) {
0402     internal::MoveTracedReference(&rhs.slot(), &this->slot());
0403   }
0404   return *this;
0405 }
0406 
0407 template <class T>
0408 TracedReference<T>& TracedReference<T>::operator=(const TracedReference& rhs) {
0409   if (this != &rhs) {
0410     this->Reset();
0411     if (!rhs.IsEmpty()) {
0412       internal::CopyTracedReference(&rhs.slot(), &this->slot());
0413     }
0414   }
0415   return *this;
0416 }
0417 
0418 }  // namespace v8
0419 
0420 #endif  // INCLUDE_V8_TRACED_HANDLE_H_