LCOV - code coverage report
Current view: top level - include - v8-util.h (source / functions) Hit Total Coverage
Test: app.info Lines: 80 80 100.0 %
Date: 2019-04-17 Functions: 39 39 100.0 %

          Line data    Source code
       1             : // Copyright 2014 the V8 project authors. All rights reserved.
       2             : // Use of this source code is governed by a BSD-style license that can be
       3             : // found in the LICENSE file.
       4             : 
       5             : #ifndef V8_UTIL_H_
       6             : #define V8_UTIL_H_
       7             : 
       8             : #include "v8.h"  // NOLINT(build/include)
       9             : #include <assert.h>
      10             : #include <map>
      11             : #include <vector>
      12             : 
      13             : /**
      14             :  * Support for Persistent containers.
      15             :  *
      16             :  * C++11 embedders can use STL containers with Global values,
      17             :  * but pre-C++11 does not support the required move semantic and hence
      18             :  * may want these container classes.
      19             :  */
      20             : namespace v8 {
      21             : 
      22             : typedef uintptr_t PersistentContainerValue;
      23             : static const uintptr_t kPersistentContainerNotFound = 0;
      24             : enum PersistentContainerCallbackType {
      25             :   kNotWeak,
      26             :   // These correspond to v8::WeakCallbackType
      27             :   kWeakWithParameter,
      28             :   kWeakWithInternalFields
      29             : };
      30             : 
      31             : /**
      32             :  * A default trait implementation for PersistentValueMap which uses std::map
      33             :  * as a backing map.
      34             :  *
      35             :  * Users will have to implement their own weak callbacks & dispose traits.
      36             :  */
      37             : template<typename K, typename V>
      38             : class StdMapTraits {
      39             :  public:
      40             :   // STL map & related:
      41             :   typedef std::map<K, PersistentContainerValue> Impl;
      42             :   typedef typename Impl::iterator Iterator;
      43             : 
      44             :   static bool Empty(Impl* impl) { return impl->empty(); }
      45             :   static size_t Size(Impl* impl) { return impl->size(); }
      46             :   static void Swap(Impl& a, Impl& b) { std::swap(a, b); }  // NOLINT
      47             :   static Iterator Begin(Impl* impl) { return impl->begin(); }
      48             :   static Iterator End(Impl* impl) { return impl->end(); }
      49           5 :   static K Key(Iterator it) { return it->first; }
      50          20 :   static PersistentContainerValue Value(Iterator it) { return it->second; }
      51          55 :   static PersistentContainerValue Set(Impl* impl, K key,
      52             :       PersistentContainerValue value) {
      53         105 :     std::pair<Iterator, bool> res = impl->insert(std::make_pair(key, value));
      54             :     PersistentContainerValue old_value = kPersistentContainerNotFound;
      55          55 :     if (!res.second) {
      56          20 :       old_value = res.first->second;
      57          20 :       res.first->second = value;
      58             :     }
      59          55 :     return old_value;
      60             :   }
      61             :   static PersistentContainerValue Get(Impl* impl, K key) {
      62             :     Iterator it = impl->find(key);
      63          30 :     if (it == impl->end()) return kPersistentContainerNotFound;
      64          20 :     return it->second;
      65             :   }
      66          25 :   static PersistentContainerValue Remove(Impl* impl, K key) {
      67             :     Iterator it = impl->find(key);
      68          25 :     if (it == impl->end()) return kPersistentContainerNotFound;
      69          15 :     PersistentContainerValue value = it->second;
      70             :     impl->erase(it);
      71          15 :     return value;
      72             :   }
      73             : };
      74             : 
      75             : 
      76             : /**
      77             :  * A default trait implementation for PersistentValueMap, which inherits
      78             :  * a std:map backing map from StdMapTraits and holds non-weak persistent
      79             :  * objects and has no special Dispose handling.
      80             :  *
      81             :  * You should not derive from this class, since MapType depends on the
      82             :  * surrounding class, and hence a subclass cannot simply inherit the methods.
      83             :  */
      84             : template<typename K, typename V>
      85             : class DefaultPersistentValueMapTraits : public StdMapTraits<K, V> {
      86             :  public:
      87             :   // Weak callback & friends:
      88             :   static const PersistentContainerCallbackType kCallbackType = kNotWeak;
      89             :   typedef PersistentValueMap<K, V, DefaultPersistentValueMapTraits<K, V> >
      90             :       MapType;
      91             :   typedef void WeakCallbackDataType;
      92             : 
      93             :   static WeakCallbackDataType* WeakCallbackParameter(
      94             :       MapType* map, const K& key, Local<V> value) {
      95             :     return nullptr;
      96             :   }
      97             :   static MapType* MapFromWeakCallbackInfo(
      98             :       const WeakCallbackInfo<WeakCallbackDataType>& data) {
      99             :     return nullptr;
     100             :   }
     101             :   static K KeyFromWeakCallbackInfo(
     102             :       const WeakCallbackInfo<WeakCallbackDataType>& data) {
     103             :     return K();
     104             :   }
     105             :   static void DisposeCallbackData(WeakCallbackDataType* data) { }
     106             :   static void Dispose(Isolate* isolate, Global<V> value, K key) {}
     107             : };
     108             : 
     109             : 
     110             : template <typename K, typename V>
     111             : class DefaultGlobalMapTraits : public StdMapTraits<K, V> {
     112             :  private:
     113             :   template <typename T>
     114             :   struct RemovePointer;
     115             : 
     116             :  public:
     117             :   // Weak callback & friends:
     118             :   static const PersistentContainerCallbackType kCallbackType = kNotWeak;
     119             :   typedef GlobalValueMap<K, V, DefaultGlobalMapTraits<K, V> > MapType;
     120             :   typedef void WeakCallbackDataType;
     121             : 
     122             :   static WeakCallbackDataType* WeakCallbackParameter(MapType* map, const K& key,
     123             :                                                      Local<V> value) {
     124             :     return nullptr;
     125             :   }
     126             :   static MapType* MapFromWeakCallbackInfo(
     127             :       const WeakCallbackInfo<WeakCallbackDataType>& data) {
     128             :     return nullptr;
     129             :   }
     130             :   static K KeyFromWeakCallbackInfo(
     131             :       const WeakCallbackInfo<WeakCallbackDataType>& data) {
     132             :     return K();
     133             :   }
     134             :   static void DisposeCallbackData(WeakCallbackDataType* data) {}
     135             :   static void OnWeakCallback(
     136             :       const WeakCallbackInfo<WeakCallbackDataType>& data) {}
     137             :   static void Dispose(Isolate* isolate, Global<V> value, K key) {}
     138             :   // This is a second pass callback, so SetSecondPassCallback cannot be called.
     139             :   static void DisposeWeak(const WeakCallbackInfo<WeakCallbackDataType>& data) {}
     140             : 
     141             :  private:
     142             :   template <typename T>
     143             :   struct RemovePointer<T*> {
     144             :     typedef T Type;
     145             :   };
     146             : };
     147             : 
     148             : 
     149             : /**
     150             :  * A map wrapper that allows using Global as a mapped value.
     151             :  * C++11 embedders don't need this class, as they can use Global
     152             :  * directly in std containers.
     153             :  *
     154             :  * The map relies on a backing map, whose type and accessors are described
     155             :  * by the Traits class. The backing map will handle values of type
     156             :  * PersistentContainerValue, with all conversion into and out of V8
     157             :  * handles being transparently handled by this class.
     158             :  */
     159             : template <typename K, typename V, typename Traits>
     160             : class PersistentValueMapBase {
     161             :  public:
     162             :   Isolate* GetIsolate() { return isolate_; }
     163             : 
     164             :   /**
     165             :    * Return size of the map.
     166             :    */
     167             :   size_t Size() { return Traits::Size(&impl_); }
     168             : 
     169             :   /**
     170             :    * Return whether the map holds weak persistents.
     171             :    */
     172             :   bool IsWeak() { return Traits::kCallbackType != kNotWeak; }
     173             : 
     174             :   /**
     175             :    * Get value stored in map.
     176             :    */
     177          20 :   Local<V> Get(const K& key) {
     178          60 :     return Local<V>::New(isolate_, FromVal(Traits::Get(&impl_, key)));
     179             :   }
     180             : 
     181             :   /**
     182             :    * Check whether a value is contained in the map.
     183             :    */
     184             :   bool Contains(const K& key) {
     185             :     return Traits::Get(&impl_, key) != kPersistentContainerNotFound;
     186             :   }
     187             : 
     188             :   /**
     189             :    * Get value stored in map and set it in returnValue.
     190             :    * Return true if a value was found.
     191             :    */
     192             :   bool SetReturnValue(const K& key,
     193             :       ReturnValue<Value> returnValue) {
     194             :     return SetReturnValueFromVal(&returnValue, Traits::Get(&impl_, key));
     195             :   }
     196             : 
     197             :   /**
     198             :    * Call V8::RegisterExternallyReferencedObject with the map value for given
     199             :    * key.
     200             :    */
     201             :   V8_DEPRECATED(
     202             :       "Used TracedGlobal and EmbedderHeapTracer::RegisterEmbedderReference",
     203             :       inline void RegisterExternallyReferencedObject(K& key));
     204             : 
     205             :   /**
     206             :    * Return value for key and remove it from the map.
     207             :    */
     208          20 :   Global<V> Remove(const K& key) {
     209          40 :     return Release(Traits::Remove(&impl_, key)).Pass();
     210             :   }
     211             : 
     212             :   /**
     213             :   * Traverses the map repeatedly,
     214             :   * in case side effects of disposal cause insertions.
     215             :   **/
     216          30 :   void Clear() {
     217             :     typedef typename Traits::Iterator It;
     218          60 :     HandleScope handle_scope(isolate_);
     219             :     // TODO(dcarney): figure out if this swap and loop is necessary.
     220          70 :     while (!Traits::Empty(&impl_)) {
     221             :       typename Traits::Impl impl;
     222             :       Traits::Swap(impl_, impl);
     223          40 :       for (It i = Traits::Begin(&impl); i != Traits::End(&impl); ++i) {
     224          70 :         Traits::Dispose(isolate_, Release(Traits::Value(i)).Pass(),
     225             :                         Traits::Key(i));
     226             :       }
     227             :     }
     228          30 :   }
     229             : 
     230             :   /**
     231             :    * Helper class for GetReference/SetWithReference. Do not use outside
     232             :    * that context.
     233             :    */
     234             :   class PersistentValueReference {
     235             :    public:
     236             :     PersistentValueReference() : value_(kPersistentContainerNotFound) { }
     237             :     PersistentValueReference(const PersistentValueReference& other)
     238             :         : value_(other.value_) { }
     239             : 
     240             :     Local<V> NewLocal(Isolate* isolate) const {
     241             :       return Local<V>::New(isolate, FromVal(value_));
     242             :     }
     243             :     bool IsEmpty() const {
     244             :       return value_ == kPersistentContainerNotFound;
     245             :     }
     246             :     template<typename T>
     247             :     bool SetReturnValue(ReturnValue<T> returnValue) {
     248             :       return SetReturnValueFromVal(&returnValue, value_);
     249             :     }
     250             :     void Reset() {
     251             :       value_ = kPersistentContainerNotFound;
     252             :     }
     253             :     void operator=(const PersistentValueReference& other) {
     254             :       value_ = other.value_;
     255             :     }
     256             : 
     257             :    private:
     258             :     friend class PersistentValueMapBase;
     259             :     friend class PersistentValueMap<K, V, Traits>;
     260             :     friend class GlobalValueMap<K, V, Traits>;
     261             : 
     262             :     explicit PersistentValueReference(PersistentContainerValue value)
     263             :         : value_(value) { }
     264             : 
     265             :     void operator=(PersistentContainerValue value) {
     266             :       value_ = value;
     267             :     }
     268             : 
     269             :     PersistentContainerValue value_;
     270             :   };
     271             : 
     272             :   /**
     273             :    * Get a reference to a map value. This enables fast, repeated access
     274             :    * to a value stored in the map while the map remains unchanged.
     275             :    *
     276             :    * Careful: This is potentially unsafe, so please use with care.
     277             :    * The value will become invalid if the value for this key changes
     278             :    * in the underlying map, as a result of Set or Remove for the same
     279             :    * key; as a result of the weak callback for the same key; or as a
     280             :    * result of calling Clear() or destruction of the map.
     281             :    */
     282             :   PersistentValueReference GetReference(const K& key) {
     283             :     return PersistentValueReference(Traits::Get(&impl_, key));
     284             :   }
     285             : 
     286             :  protected:
     287             :   explicit PersistentValueMapBase(Isolate* isolate)
     288          30 :       : isolate_(isolate), label_(nullptr) {}
     289             :   PersistentValueMapBase(Isolate* isolate, const char* label)
     290             :       : isolate_(isolate), label_(label) {}
     291             : 
     292          30 :   ~PersistentValueMapBase() { Clear(); }
     293             : 
     294             :   Isolate* isolate() { return isolate_; }
     295          55 :   typename Traits::Impl* impl() { return &impl_; }
     296             : 
     297             :   static V* FromVal(PersistentContainerValue v) {
     298         130 :     return reinterpret_cast<V*>(v);
     299             :   }
     300             : 
     301             :   static PersistentContainerValue ClearAndLeak(Global<V>* persistent) {
     302          55 :     V* v = persistent->val_;
     303          55 :     persistent->val_ = nullptr;
     304          55 :     return reinterpret_cast<PersistentContainerValue>(v);
     305             :   }
     306             : 
     307             :   static PersistentContainerValue Leak(Global<V>* persistent) {
     308             :     return reinterpret_cast<PersistentContainerValue>(persistent->val_);
     309             :   }
     310             : 
     311             :   /**
     312             :    * Return a container value as Global and make sure the weak
     313             :    * callback is properly disposed of. All remove functionality should go
     314             :    * through this.
     315             :    */
     316          95 :   static Global<V> Release(PersistentContainerValue v) {
     317             :     Global<V> p;
     318          95 :     p.val_ = FromVal(v);
     319          40 :     if (Traits::kCallbackType != kNotWeak && p.IsWeak()) {
     320             :       Traits::DisposeCallbackData(
     321             :           p.template ClearWeak<typename Traits::WeakCallbackDataType>());
     322             :     }
     323          95 :     return p.Pass();
     324             :   }
     325             : 
     326           5 :   void RemoveWeak(const K& key) {
     327             :     Global<V> p;
     328           5 :     p.val_ = FromVal(Traits::Remove(&impl_, key));
     329             :     p.Reset();
     330           5 :   }
     331             : 
     332             :   void AnnotateStrongRetainer(Global<V>* persistent) {
     333             :     persistent->AnnotateStrongRetainer(label_);
     334             :   }
     335             : 
     336             :  private:
     337             :   PersistentValueMapBase(PersistentValueMapBase&);
     338             :   void operator=(PersistentValueMapBase&);
     339             : 
     340             :   static bool SetReturnValueFromVal(ReturnValue<Value>* returnValue,
     341             :                                     PersistentContainerValue value) {
     342             :     bool hasValue = value != kPersistentContainerNotFound;
     343             :     if (hasValue) {
     344             :       returnValue->SetInternal(
     345             :           *reinterpret_cast<internal::Address*>(FromVal(value)));
     346             :     }
     347             :     return hasValue;
     348             :   }
     349             : 
     350             :   Isolate* isolate_;
     351             :   typename Traits::Impl impl_;
     352             :   const char* label_;
     353             : };
     354             : 
     355             : template <typename K, typename V, typename Traits>
     356             : inline void
     357             : PersistentValueMapBase<K, V, Traits>::RegisterExternallyReferencedObject(
     358             :     K& key) {
     359             :   assert(Contains(key));
     360             :   V8::RegisterExternallyReferencedObject(
     361             :       reinterpret_cast<internal::Address*>(FromVal(Traits::Get(&impl_, key))),
     362             :       reinterpret_cast<internal::Isolate*>(GetIsolate()));
     363             : }
     364             : 
     365             : template <typename K, typename V, typename Traits>
     366           5 : class PersistentValueMap : public PersistentValueMapBase<K, V, Traits> {
     367             :  public:
     368             :   explicit PersistentValueMap(Isolate* isolate)
     369             :       : PersistentValueMapBase<K, V, Traits>(isolate) {}
     370             :   PersistentValueMap(Isolate* isolate, const char* label)
     371             :       : PersistentValueMapBase<K, V, Traits>(isolate, label) {}
     372             : 
     373             :   typedef
     374             :       typename PersistentValueMapBase<K, V, Traits>::PersistentValueReference
     375             :           PersistentValueReference;
     376             : 
     377             :   /**
     378             :    * Put value into map. Depending on Traits::kIsWeak, the value will be held
     379             :    * by the map strongly or weakly.
     380             :    * Returns old value as Global.
     381             :    */
     382           5 :   Global<V> Set(const K& key, Local<V> value) {
     383             :     Global<V> persistent(this->isolate(), value);
     384          10 :     return SetUnique(key, &persistent);
     385             :   }
     386             : 
     387             :   /**
     388             :    * Put value into map, like Set(const K&, Local<V>).
     389             :    */
     390             :   Global<V> Set(const K& key, Global<V> value) {
     391             :     return SetUnique(key, &value);
     392             :   }
     393             : 
     394             :   /**
     395             :    * Put the value into the map, and set the 'weak' callback when demanded
     396             :    * by the Traits class.
     397             :    */
     398           5 :   Global<V> SetUnique(const K& key, Global<V>* persistent) {
     399             :     if (Traits::kCallbackType == kNotWeak) {
     400             :       this->AnnotateStrongRetainer(persistent);
     401             :     } else {
     402             :       WeakCallbackType callback_type =
     403             :           Traits::kCallbackType == kWeakWithInternalFields
     404             :               ? WeakCallbackType::kInternalFields
     405             :               : WeakCallbackType::kParameter;
     406             :       Local<V> value(Local<V>::New(this->isolate(), *persistent));
     407             :       persistent->template SetWeak<typename Traits::WeakCallbackDataType>(
     408             :           Traits::WeakCallbackParameter(this, key, value), WeakCallback,
     409             :           callback_type);
     410             :     }
     411             :     PersistentContainerValue old_value =
     412          10 :         Traits::Set(this->impl(), key, this->ClearAndLeak(persistent));
     413          10 :     return this->Release(old_value).Pass();
     414             :   }
     415             : 
     416             :   /**
     417             :    * Put a value into the map and update the reference.
     418             :    * Restrictions of GetReference apply here as well.
     419             :    */
     420             :   Global<V> Set(const K& key, Global<V> value,
     421             :                 PersistentValueReference* reference) {
     422             :     *reference = this->Leak(&value);
     423             :     return SetUnique(key, &value);
     424             :   }
     425             : 
     426             :  private:
     427             :   static void WeakCallback(
     428             :       const WeakCallbackInfo<typename Traits::WeakCallbackDataType>& data) {
     429             :     if (Traits::kCallbackType != kNotWeak) {
     430             :       PersistentValueMap<K, V, Traits>* persistentValueMap =
     431             :           Traits::MapFromWeakCallbackInfo(data);
     432             :       K key = Traits::KeyFromWeakCallbackInfo(data);
     433             :       Traits::Dispose(data.GetIsolate(),
     434             :                       persistentValueMap->Remove(key).Pass(), key);
     435             :       Traits::DisposeCallbackData(data.GetParameter());
     436             :     }
     437             :   }
     438             : };
     439             : 
     440             : 
     441             : template <typename K, typename V, typename Traits>
     442          10 : class GlobalValueMap : public PersistentValueMapBase<K, V, Traits> {
     443             :  public:
     444             :   explicit GlobalValueMap(Isolate* isolate)
     445             :       : PersistentValueMapBase<K, V, Traits>(isolate) {}
     446             :   GlobalValueMap(Isolate* isolate, const char* label)
     447             :       : PersistentValueMapBase<K, V, Traits>(isolate, label) {}
     448             : 
     449             :   typedef
     450             :       typename PersistentValueMapBase<K, V, Traits>::PersistentValueReference
     451             :           PersistentValueReference;
     452             : 
     453             :   /**
     454             :    * Put value into map. Depending on Traits::kIsWeak, the value will be held
     455             :    * by the map strongly or weakly.
     456             :    * Returns old value as Global.
     457             :    */
     458          40 :   Global<V> Set(const K& key, Local<V> value) {
     459             :     Global<V> persistent(this->isolate(), value);
     460          80 :     return SetUnique(key, &persistent);
     461             :   }
     462             : 
     463             :   /**
     464             :    * Put value into map, like Set(const K&, Local<V>).
     465             :    */
     466             :   Global<V> Set(const K& key, Global<V> value) {
     467             :     return SetUnique(key, &value);
     468             :   }
     469             : 
     470             :   /**
     471             :    * Put the value into the map, and set the 'weak' callback when demanded
     472             :    * by the Traits class.
     473             :    */
     474          50 :   Global<V> SetUnique(const K& key, Global<V>* persistent) {
     475             :     if (Traits::kCallbackType == kNotWeak) {
     476             :       this->AnnotateStrongRetainer(persistent);
     477             :     } else {
     478             :       WeakCallbackType callback_type =
     479             :           Traits::kCallbackType == kWeakWithInternalFields
     480             :               ? WeakCallbackType::kInternalFields
     481             :               : WeakCallbackType::kParameter;
     482             :       Local<V> value(Local<V>::New(this->isolate(), *persistent));
     483             :       persistent->template SetWeak<typename Traits::WeakCallbackDataType>(
     484             :           Traits::WeakCallbackParameter(this, key, value), OnWeakCallback,
     485             :           callback_type);
     486             :     }
     487             :     PersistentContainerValue old_value =
     488         100 :         Traits::Set(this->impl(), key, this->ClearAndLeak(persistent));
     489         100 :     return this->Release(old_value).Pass();
     490             :   }
     491             : 
     492             :   /**
     493             :    * Put a value into the map and update the reference.
     494             :    * Restrictions of GetReference apply here as well.
     495             :    */
     496             :   Global<V> Set(const K& key, Global<V> value,
     497             :                 PersistentValueReference* reference) {
     498             :     *reference = this->Leak(&value);
     499          10 :     return SetUnique(key, &value);
     500             :   }
     501             : 
     502             :  private:
     503           5 :   static void OnWeakCallback(
     504             :       const WeakCallbackInfo<typename Traits::WeakCallbackDataType>& data) {
     505             :     if (Traits::kCallbackType != kNotWeak) {
     506             :       auto map = Traits::MapFromWeakCallbackInfo(data);
     507             :       K key = Traits::KeyFromWeakCallbackInfo(data);
     508           5 :       map->RemoveWeak(key);
     509             :       Traits::OnWeakCallback(data);
     510             :       data.SetSecondPassCallback(SecondWeakCallback);
     511             :     }
     512           5 :   }
     513             : 
     514           5 :   static void SecondWeakCallback(
     515             :       const WeakCallbackInfo<typename Traits::WeakCallbackDataType>& data) {
     516           5 :     Traits::DisposeWeak(data);
     517           5 :   }
     518             : };
     519             : 
     520             : 
     521             : /**
     522             :  * A map that uses Global as value and std::map as the backing
     523             :  * implementation. Persistents are held non-weak.
     524             :  *
     525             :  * C++11 embedders don't need this class, as they can use
     526             :  * Global directly in std containers.
     527             :  */
     528             : template<typename K, typename V,
     529             :     typename Traits = DefaultPersistentValueMapTraits<K, V> >
     530             : class StdPersistentValueMap : public PersistentValueMap<K, V, Traits> {
     531             :  public:
     532             :   explicit StdPersistentValueMap(Isolate* isolate)
     533             :       : PersistentValueMap<K, V, Traits>(isolate) {}
     534             : };
     535             : 
     536             : 
     537             : /**
     538             :  * A map that uses Global as value and std::map as the backing
     539             :  * implementation. Globals are held non-weak.
     540             :  *
     541             :  * C++11 embedders don't need this class, as they can use
     542             :  * Global directly in std containers.
     543             :  */
     544             : template <typename K, typename V,
     545             :           typename Traits = DefaultGlobalMapTraits<K, V> >
     546           5 : class StdGlobalValueMap : public GlobalValueMap<K, V, Traits> {
     547             :  public:
     548             :   explicit StdGlobalValueMap(Isolate* isolate)
     549             :       : GlobalValueMap<K, V, Traits>(isolate) {}
     550             : };
     551             : 
     552             : 
     553             : class DefaultPersistentValueVectorTraits {
     554             :  public:
     555             :   typedef std::vector<PersistentContainerValue> Impl;
     556             : 
     557             :   static void Append(Impl* impl, PersistentContainerValue value) {
     558       34187 :     impl->push_back(value);
     559             :   }
     560             :   static bool IsEmpty(const Impl* impl) {
     561             :     return impl->empty();
     562             :   }
     563             :   static size_t Size(const Impl* impl) {
     564             :     return impl->size();
     565             :   }
     566       68439 :   static PersistentContainerValue Get(const Impl* impl, size_t i) {
     567      136878 :     return (i < impl->size()) ? impl->at(i) : kPersistentContainerNotFound;
     568             :   }
     569             :   static void ReserveCapacity(Impl* impl, size_t capacity) {
     570           5 :     impl->reserve(capacity);
     571             :   }
     572             :   static void Clear(Impl* impl) {
     573             :     impl->clear();
     574             :   }
     575             : };
     576             : 
     577             : 
     578             : /**
     579             :  * A vector wrapper that safely stores Global values.
     580             :  * C++11 embedders don't need this class, as they can use Global
     581             :  * directly in std containers.
     582             :  *
     583             :  * This class relies on a backing vector implementation, whose type and methods
     584             :  * are described by the Traits class. The backing map will handle values of type
     585             :  * PersistentContainerValue, with all conversion into and out of V8
     586             :  * handles being transparently handled by this class.
     587             :  */
     588             : template<typename V, typename Traits = DefaultPersistentValueVectorTraits>
     589             : class PersistentValueVector {
     590             :  public:
     591        3826 :   explicit PersistentValueVector(Isolate* isolate) : isolate_(isolate) { }
     592             : 
     593        3826 :   ~PersistentValueVector() {
     594        3826 :     Clear();
     595        3826 :   }
     596             : 
     597             :   /**
     598             :    * Append a value to the vector.
     599             :    */
     600       34182 :   void Append(Local<V> value) {
     601       34182 :     Global<V> persistent(isolate_, value);
     602       34182 :     Traits::Append(&impl_, ClearAndLeak(&persistent));
     603       34182 :   }
     604             : 
     605             :   /**
     606             :    * Append a persistent's value to the vector.
     607             :    */
     608             :   void Append(Global<V> persistent) {
     609             :     Traits::Append(&impl_, ClearAndLeak(&persistent));
     610             :   }
     611             : 
     612             :   /**
     613             :    * Are there any values in the vector?
     614             :    */
     615             :   bool IsEmpty() const {
     616             :     return Traits::IsEmpty(&impl_);
     617             :   }
     618             : 
     619             :   /**
     620             :    * How many elements are in the vector?
     621             :    */
     622             :   size_t Size() const {
     623             :     return Traits::Size(&impl_);
     624             :   }
     625             : 
     626             :   /**
     627             :    * Retrieve the i-th value in the vector.
     628             :    */
     629       34252 :   Local<V> Get(size_t index) const {
     630      102756 :     return Local<V>::New(isolate_, FromVal(Traits::Get(&impl_, index)));
     631             :   }
     632             : 
     633             :   /**
     634             :    * Remove all elements from the vector.
     635             :    */
     636        4027 :   void Clear() {
     637             :     size_t length = Traits::Size(&impl_);
     638       72401 :     for (size_t i = 0; i < length; i++) {
     639             :       Global<V> p;
     640       34187 :       p.val_ = FromVal(Traits::Get(&impl_, i));
     641             :     }
     642             :     Traits::Clear(&impl_);
     643        4027 :   }
     644             : 
     645             :   /**
     646             :    * Reserve capacity in the vector.
     647             :    * (Efficiency gains depend on the backing implementation.)
     648             :    */
     649             :   void ReserveCapacity(size_t capacity) {
     650             :     Traits::ReserveCapacity(&impl_, capacity);
     651             :   }
     652             : 
     653             :  private:
     654             :   static PersistentContainerValue ClearAndLeak(Global<V>* persistent) {
     655           5 :     V* v = persistent->val_;
     656           5 :     persistent->val_ = nullptr;
     657       34187 :     return reinterpret_cast<PersistentContainerValue>(v);
     658             :   }
     659             : 
     660             :   static V* FromVal(PersistentContainerValue v) {
     661       68439 :     return reinterpret_cast<V*>(v);
     662             :   }
     663             : 
     664             :   Isolate* isolate_;
     665             :   typename Traits::Impl impl_;
     666             : };
     667             : 
     668             : }  // namespace v8
     669             : 
     670             : #endif  // V8_UTIL_H

Generated by: LCOV version 1.10