Back to home page

EIC code displayed by LXR

 
 

    


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

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_PERSISTENT_HANDLE_H_
0006 #define INCLUDE_V8_PERSISTENT_HANDLE_H_
0007 
0008 #include "v8-internal.h"            // NOLINT(build/include_directory)
0009 #include "v8-local-handle.h"        // NOLINT(build/include_directory)
0010 #include "v8-weak-callback-info.h"  // NOLINT(build/include_directory)
0011 #include "v8config.h"               // NOLINT(build/include_directory)
0012 
0013 namespace v8 {
0014 
0015 class Isolate;
0016 template <class K, class V, class T>
0017 class PersistentValueMapBase;
0018 template <class V, class T>
0019 class PersistentValueVector;
0020 template <class T>
0021 class Global;
0022 template <class T>
0023 class PersistentBase;
0024 template <class K, class V, class T>
0025 class PersistentValueMap;
0026 class Value;
0027 
0028 namespace api_internal {
0029 V8_EXPORT internal::Address* Eternalize(v8::Isolate* isolate, Value* handle);
0030 V8_EXPORT internal::Address* CopyGlobalReference(internal::Address* from);
0031 V8_EXPORT void DisposeGlobal(internal::Address* global_handle);
0032 V8_EXPORT void MakeWeak(internal::Address** location_addr);
0033 V8_EXPORT void* ClearWeak(internal::Address* location);
0034 V8_EXPORT void AnnotateStrongRetainer(internal::Address* location,
0035                                       const char* label);
0036 V8_EXPORT internal::Address* GlobalizeReference(internal::Isolate* isolate,
0037                                                 internal::Address value);
0038 V8_EXPORT void MoveGlobalReference(internal::Address** from,
0039                                    internal::Address** to);
0040 }  // namespace api_internal
0041 
0042 /**
0043  * Eternal handles are set-once handles that live for the lifetime of the
0044  * isolate.
0045  */
0046 template <class T>
0047 class Eternal : public api_internal::IndirectHandleBase {
0048  public:
0049   V8_INLINE Eternal() = default;
0050 
0051   template <class S>
0052   V8_INLINE Eternal(Isolate* isolate, Local<S> handle) {
0053     Set(isolate, handle);
0054   }
0055 
0056   // Can only be safely called if already set.
0057   V8_INLINE Local<T> Get(Isolate* isolate) const {
0058     // The eternal handle will never go away, so as with the roots, we don't
0059     // even need to open a handle.
0060     return Local<T>::FromSlot(slot());
0061   }
0062 
0063   template <class S>
0064   void Set(Isolate* isolate, Local<S> handle) {
0065     static_assert(std::is_base_of<T, S>::value, "type check");
0066     slot() =
0067         api_internal::Eternalize(isolate, *handle.template UnsafeAs<Value>());
0068   }
0069 };
0070 
0071 namespace api_internal {
0072 V8_EXPORT void MakeWeak(internal::Address* location, void* data,
0073                         WeakCallbackInfo<void>::Callback weak_callback,
0074                         WeakCallbackType type);
0075 }  // namespace api_internal
0076 
0077 /**
0078  * An object reference that is independent of any handle scope.  Where
0079  * a Local handle only lives as long as the HandleScope in which it was
0080  * allocated, a PersistentBase handle remains valid until it is explicitly
0081  * disposed using Reset().
0082  *
0083  * A persistent handle contains a reference to a storage cell within
0084  * the V8 engine which holds an object value and which is updated by
0085  * the garbage collector whenever the object is moved.  A new storage
0086  * cell can be created using the constructor or PersistentBase::Reset and
0087  * existing handles can be disposed using PersistentBase::Reset.
0088  *
0089  */
0090 template <class T>
0091 class PersistentBase : public api_internal::IndirectHandleBase {
0092  public:
0093   /**
0094    * If non-empty, destroy the underlying storage cell
0095    * IsEmpty() will return true after this call.
0096    */
0097   V8_INLINE void Reset();
0098 
0099   /**
0100    * If non-empty, destroy the underlying storage cell
0101    * and create a new one with the contents of other if other is non empty
0102    */
0103   template <class S>
0104   V8_INLINE void Reset(Isolate* isolate, const Local<S>& other);
0105 
0106   /**
0107    * If non-empty, destroy the underlying storage cell
0108    * and create a new one with the contents of other if other is non empty
0109    */
0110   template <class S>
0111   V8_INLINE void Reset(Isolate* isolate, const PersistentBase<S>& other);
0112 
0113   V8_INLINE Local<T> Get(Isolate* isolate) const {
0114     return Local<T>::New(isolate, *this);
0115   }
0116 
0117   template <class S>
0118   V8_INLINE bool operator==(const PersistentBase<S>& that) const {
0119     return internal::HandleHelper::EqualHandles(*this, that);
0120   }
0121 
0122   template <class S>
0123   V8_INLINE bool operator==(const Local<S>& that) const {
0124     return internal::HandleHelper::EqualHandles(*this, that);
0125   }
0126 
0127   template <class S>
0128   V8_INLINE bool operator!=(const PersistentBase<S>& that) const {
0129     return !operator==(that);
0130   }
0131 
0132   template <class S>
0133   V8_INLINE bool operator!=(const Local<S>& that) const {
0134     return !operator==(that);
0135   }
0136 
0137   /**
0138    * Install a finalization callback on this object.
0139    * NOTE: There is no guarantee as to *when* or even *if* the callback is
0140    * invoked. The invocation is performed solely on a best effort basis.
0141    * As always, GC-based finalization should *not* be relied upon for any
0142    * critical form of resource management!
0143    *
0144    * The callback is supposed to reset the handle. No further V8 API may be
0145    * called in this callback. In case additional work involving V8 needs to be
0146    * done, a second callback can be scheduled using
0147    * WeakCallbackInfo<void>::SetSecondPassCallback.
0148    */
0149   template <typename P>
0150   V8_INLINE void SetWeak(P* parameter,
0151                          typename WeakCallbackInfo<P>::Callback callback,
0152                          WeakCallbackType type);
0153 
0154   /**
0155    * Turns this handle into a weak phantom handle without finalization callback.
0156    * The handle will be reset automatically when the garbage collector detects
0157    * that the object is no longer reachable.
0158    */
0159   V8_INLINE void SetWeak();
0160 
0161   template <typename P>
0162   V8_INLINE P* ClearWeak();
0163 
0164   // TODO(dcarney): remove this.
0165   V8_INLINE void ClearWeak() { ClearWeak<void>(); }
0166 
0167   /**
0168    * Annotates the strong handle with the given label, which is then used by the
0169    * heap snapshot generator as a name of the edge from the root to the handle.
0170    * The function does not take ownership of the label and assumes that the
0171    * label is valid as long as the handle is valid.
0172    */
0173   V8_INLINE void AnnotateStrongRetainer(const char* label);
0174 
0175   /** Returns true if the handle's reference is weak.  */
0176   V8_INLINE bool IsWeak() const;
0177 
0178   /**
0179    * Assigns a wrapper class ID to the handle.
0180    */
0181   V8_INLINE void SetWrapperClassId(uint16_t class_id);
0182 
0183   /**
0184    * Returns the class ID previously assigned to this handle or 0 if no class ID
0185    * was previously assigned.
0186    */
0187   V8_INLINE uint16_t WrapperClassId() const;
0188 
0189   PersistentBase(const PersistentBase& other) = delete;
0190   void operator=(const PersistentBase&) = delete;
0191 
0192  private:
0193   friend class Isolate;
0194   friend class Utils;
0195   template <class F>
0196   friend class Local;
0197   template <class F1, class F2>
0198   friend class Persistent;
0199   template <class F>
0200   friend class Global;
0201   template <class F>
0202   friend class PersistentBase;
0203   template <class F>
0204   friend class ReturnValue;
0205   template <class F1, class F2, class F3>
0206   friend class PersistentValueMapBase;
0207   template <class F1, class F2>
0208   friend class PersistentValueVector;
0209   friend class Object;
0210   friend class internal::ValueHelper;
0211 
0212   V8_INLINE PersistentBase() = default;
0213 
0214   V8_INLINE explicit PersistentBase(internal::Address* location)
0215       : IndirectHandleBase(location) {}
0216 
0217   V8_INLINE static internal::Address* New(Isolate* isolate, T* that);
0218 };
0219 
0220 /**
0221  * Default traits for Persistent. This class does not allow
0222  * use of the copy constructor or assignment operator.
0223  * At present kResetInDestructor is not set, but that will change in a future
0224  * version.
0225  */
0226 template <class T>
0227 class NonCopyablePersistentTraits {
0228  public:
0229   using NonCopyablePersistent = Persistent<T, NonCopyablePersistentTraits<T>>;
0230   static const bool kResetInDestructor = false;
0231   template <class S, class M>
0232   V8_INLINE static void Copy(const Persistent<S, M>& source,
0233                              NonCopyablePersistent* dest) {
0234     static_assert(sizeof(S) < 0,
0235                   "NonCopyablePersistentTraits::Copy is not instantiable");
0236   }
0237 };
0238 
0239 /**
0240  * Helper class traits to allow copying and assignment of Persistent.
0241  * This will clone the contents of storage cell, but not any of the flags, etc.
0242  */
0243 template <class T>
0244 struct CopyablePersistentTraits {
0245   using CopyablePersistent = Persistent<T, CopyablePersistentTraits<T>>;
0246   static const bool kResetInDestructor = true;
0247   template <class S, class M>
0248   static V8_INLINE void Copy(const Persistent<S, M>& source,
0249                              CopyablePersistent* dest) {
0250     // do nothing, just allow copy
0251   }
0252 };
0253 
0254 /**
0255  * A PersistentBase which allows copy and assignment.
0256  *
0257  * Copy, assignment and destructor behavior is controlled by the traits
0258  * class M.
0259  *
0260  * CAVEAT: Persistent objects do not have proper destruction behavior by default
0261  * and as such will leak the object without explicit clear. Consider using
0262  * `v8::Global` instead which has proper destruction and move semantics.
0263  */
0264 template <class T, class M>
0265 class Persistent : public PersistentBase<T> {
0266  public:
0267   /**
0268    * A Persistent with no storage cell.
0269    */
0270   V8_INLINE Persistent() = default;
0271 
0272   /**
0273    * Construct a Persistent from a Local.
0274    * When the Local is non-empty, a new storage cell is created
0275    * pointing to the same object, and no flags are set.
0276    */
0277   template <class S>
0278   V8_INLINE Persistent(Isolate* isolate, Local<S> that)
0279       : PersistentBase<T>(
0280             PersistentBase<T>::New(isolate, that.template value<S>())) {
0281     static_assert(std::is_base_of<T, S>::value, "type check");
0282   }
0283 
0284   /**
0285    * Construct a Persistent from a Persistent.
0286    * When the Persistent is non-empty, a new storage cell is created
0287    * pointing to the same object, and no flags are set.
0288    */
0289   template <class S, class M2>
0290   V8_INLINE Persistent(Isolate* isolate, const Persistent<S, M2>& that)
0291       : PersistentBase<T>(
0292             PersistentBase<T>::New(isolate, that.template value<S>())) {
0293     static_assert(std::is_base_of<T, S>::value, "type check");
0294   }
0295 
0296   /**
0297    * The copy constructors and assignment operator create a Persistent
0298    * exactly as the Persistent constructor, but the Copy function from the
0299    * traits class is called, allowing the setting of flags based on the
0300    * copied Persistent.
0301    */
0302   V8_INLINE Persistent(const Persistent& that) : PersistentBase<T>() {
0303     Copy(that);
0304   }
0305   template <class S, class M2>
0306   V8_INLINE Persistent(const Persistent<S, M2>& that) : PersistentBase<T>() {
0307     Copy(that);
0308   }
0309   V8_INLINE Persistent& operator=(const Persistent& that) {
0310     Copy(that);
0311     return *this;
0312   }
0313   template <class S, class M2>
0314   V8_INLINE Persistent& operator=(const Persistent<S, M2>& that) {
0315     Copy(that);
0316     return *this;
0317   }
0318 
0319   /**
0320    * The destructor will dispose the Persistent based on the
0321    * kResetInDestructor flags in the traits class.  Since not calling dispose
0322    * can result in a memory leak, it is recommended to always set this flag.
0323    */
0324   V8_INLINE ~Persistent() {
0325     if (M::kResetInDestructor) this->Reset();
0326   }
0327 
0328   // TODO(dcarney): this is pretty useless, fix or remove
0329   template <class S, class M2>
0330   V8_INLINE static Persistent<T, M>& Cast(const Persistent<S, M2>& that) {
0331 #ifdef V8_ENABLE_CHECKS
0332     // If we're going to perform the type check then we have to check
0333     // that the handle isn't empty before doing the checked cast.
0334     if (!that.IsEmpty()) T::Cast(that.template value<S>());
0335 #endif
0336     return reinterpret_cast<Persistent<T, M>&>(
0337         const_cast<Persistent<S, M2>&>(that));
0338   }
0339 
0340   // TODO(dcarney): this is pretty useless, fix or remove
0341   template <class S, class M2>
0342   V8_INLINE Persistent<S, M2>& As() const {
0343     return Persistent<S, M2>::Cast(*this);
0344   }
0345 
0346  private:
0347   friend class Isolate;
0348   friend class Utils;
0349   template <class F>
0350   friend class Local;
0351   template <class F1, class F2>
0352   friend class Persistent;
0353   template <class F>
0354   friend class ReturnValue;
0355 
0356   template <class S, class M2>
0357   V8_INLINE void Copy(const Persistent<S, M2>& that);
0358 };
0359 
0360 /**
0361  * A PersistentBase which has move semantics.
0362  *
0363  * Note: Persistent class hierarchy is subject to future changes.
0364  */
0365 template <class T>
0366 class Global : public PersistentBase<T> {
0367  public:
0368   /**
0369    * A Global with no storage cell.
0370    */
0371   V8_INLINE Global() = default;
0372 
0373   /**
0374    * Construct a Global from a Local.
0375    * When the Local is non-empty, a new storage cell is created
0376    * pointing to the same object, and no flags are set.
0377    */
0378   template <class S>
0379   V8_INLINE Global(Isolate* isolate, Local<S> that)
0380       : PersistentBase<T>(
0381             PersistentBase<T>::New(isolate, that.template value<S>())) {
0382     static_assert(std::is_base_of<T, S>::value, "type check");
0383   }
0384 
0385   /**
0386    * Construct a Global from a PersistentBase.
0387    * When the Persistent is non-empty, a new storage cell is created
0388    * pointing to the same object, and no flags are set.
0389    */
0390   template <class S>
0391   V8_INLINE Global(Isolate* isolate, const PersistentBase<S>& that)
0392       : PersistentBase<T>(
0393             PersistentBase<T>::New(isolate, that.template value<S>())) {
0394     static_assert(std::is_base_of<T, S>::value, "type check");
0395   }
0396 
0397   /**
0398    * Move constructor.
0399    */
0400   V8_INLINE Global(Global&& other);
0401 
0402   V8_INLINE ~Global() { this->Reset(); }
0403 
0404   /**
0405    * Move via assignment.
0406    */
0407   template <class S>
0408   V8_INLINE Global& operator=(Global<S>&& rhs);
0409 
0410   /**
0411    * Pass allows returning uniques from functions, etc.
0412    */
0413   Global Pass() { return static_cast<Global&&>(*this); }
0414 
0415   /*
0416    * For compatibility with Chromium's base::Bind (base::Passed).
0417    */
0418   using MoveOnlyTypeForCPP03 = void;
0419 
0420   Global(const Global&) = delete;
0421   void operator=(const Global&) = delete;
0422 
0423  private:
0424   template <class F>
0425   friend class ReturnValue;
0426 };
0427 
0428 // UniquePersistent is an alias for Global for historical reason.
0429 template <class T>
0430 using UniquePersistent = Global<T>;
0431 
0432 /**
0433  * Interface for iterating through all the persistent handles in the heap.
0434  */
0435 class V8_EXPORT PersistentHandleVisitor {
0436  public:
0437   virtual ~PersistentHandleVisitor() = default;
0438   virtual void VisitPersistentHandle(Persistent<Value>* value,
0439                                      uint16_t class_id) {}
0440 };
0441 
0442 template <class T>
0443 internal::Address* PersistentBase<T>::New(Isolate* isolate, T* that) {
0444   if (internal::ValueHelper::IsEmpty(that)) return nullptr;
0445   return api_internal::GlobalizeReference(
0446       reinterpret_cast<internal::Isolate*>(isolate),
0447       internal::ValueHelper::ValueAsAddress(that));
0448 }
0449 
0450 template <class T, class M>
0451 template <class S, class M2>
0452 void Persistent<T, M>::Copy(const Persistent<S, M2>& that) {
0453   static_assert(std::is_base_of<T, S>::value, "type check");
0454   this->Reset();
0455   if (that.IsEmpty()) return;
0456   this->slot() = api_internal::CopyGlobalReference(that.slot());
0457   M::Copy(that, this);
0458 }
0459 
0460 template <class T>
0461 bool PersistentBase<T>::IsWeak() const {
0462   using I = internal::Internals;
0463   if (this->IsEmpty()) return false;
0464   return I::GetNodeState(this->slot()) == I::kNodeStateIsWeakValue;
0465 }
0466 
0467 template <class T>
0468 void PersistentBase<T>::Reset() {
0469   if (this->IsEmpty()) return;
0470   api_internal::DisposeGlobal(this->slot());
0471   this->Clear();
0472 }
0473 
0474 /**
0475  * If non-empty, destroy the underlying storage cell
0476  * and create a new one with the contents of other if other is non empty
0477  */
0478 template <class T>
0479 template <class S>
0480 void PersistentBase<T>::Reset(Isolate* isolate, const Local<S>& other) {
0481   static_assert(std::is_base_of<T, S>::value, "type check");
0482   Reset();
0483   if (other.IsEmpty()) return;
0484   this->slot() = New(isolate, *other);
0485 }
0486 
0487 /**
0488  * If non-empty, destroy the underlying storage cell
0489  * and create a new one with the contents of other if other is non empty
0490  */
0491 template <class T>
0492 template <class S>
0493 void PersistentBase<T>::Reset(Isolate* isolate,
0494                               const PersistentBase<S>& other) {
0495   static_assert(std::is_base_of<T, S>::value, "type check");
0496   Reset();
0497   if (other.IsEmpty()) return;
0498   this->slot() = New(isolate, other.template value<S>());
0499 }
0500 
0501 template <class T>
0502 template <typename P>
0503 V8_INLINE void PersistentBase<T>::SetWeak(
0504     P* parameter, typename WeakCallbackInfo<P>::Callback callback,
0505     WeakCallbackType type) {
0506   using Callback = WeakCallbackInfo<void>::Callback;
0507 #if (__GNUC__ >= 8) && !defined(__clang__)
0508 #pragma GCC diagnostic push
0509 #pragma GCC diagnostic ignored "-Wcast-function-type"
0510 #endif
0511   api_internal::MakeWeak(this->slot(), parameter,
0512                          reinterpret_cast<Callback>(callback), type);
0513 #if (__GNUC__ >= 8) && !defined(__clang__)
0514 #pragma GCC diagnostic pop
0515 #endif
0516 }
0517 
0518 template <class T>
0519 void PersistentBase<T>::SetWeak() {
0520   api_internal::MakeWeak(&this->slot());
0521 }
0522 
0523 template <class T>
0524 template <typename P>
0525 P* PersistentBase<T>::ClearWeak() {
0526   return reinterpret_cast<P*>(api_internal::ClearWeak(this->slot()));
0527 }
0528 
0529 template <class T>
0530 void PersistentBase<T>::AnnotateStrongRetainer(const char* label) {
0531   api_internal::AnnotateStrongRetainer(this->slot(), label);
0532 }
0533 
0534 template <class T>
0535 void PersistentBase<T>::SetWrapperClassId(uint16_t class_id) {
0536   using I = internal::Internals;
0537   if (this->IsEmpty()) return;
0538   uint8_t* addr = reinterpret_cast<uint8_t*>(slot()) + I::kNodeClassIdOffset;
0539   *reinterpret_cast<uint16_t*>(addr) = class_id;
0540 }
0541 
0542 template <class T>
0543 uint16_t PersistentBase<T>::WrapperClassId() const {
0544   using I = internal::Internals;
0545   if (this->IsEmpty()) return 0;
0546   uint8_t* addr = reinterpret_cast<uint8_t*>(slot()) + I::kNodeClassIdOffset;
0547   return *reinterpret_cast<uint16_t*>(addr);
0548 }
0549 
0550 template <class T>
0551 Global<T>::Global(Global&& other) : PersistentBase<T>(other.slot()) {
0552   if (!other.IsEmpty()) {
0553     api_internal::MoveGlobalReference(&other.slot(), &this->slot());
0554     other.Clear();
0555   }
0556 }
0557 
0558 template <class T>
0559 template <class S>
0560 Global<T>& Global<T>::operator=(Global<S>&& rhs) {
0561   static_assert(std::is_base_of<T, S>::value, "type check");
0562   if (this != &rhs) {
0563     this->Reset();
0564     if (!rhs.IsEmpty()) {
0565       this->slot() = rhs.slot();
0566       api_internal::MoveGlobalReference(&rhs.slot(), &this->slot());
0567       rhs.Clear();
0568     }
0569   }
0570   return *this;
0571 }
0572 
0573 }  // namespace v8
0574 
0575 #endif  // INCLUDE_V8_PERSISTENT_HANDLE_H_