LCOV - code coverage report
Current view: top level - include - v8-util.h (source / functions) Hit Total Coverage
Test: app.info Lines: 90 90 100.0 %
Date: 2019-02-19 Functions: 44 44 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          10 :   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             :   void RegisterExternallyReferencedObject(K& key) {
     202             :     assert(Contains(key));
     203             :     V8::RegisterExternallyReferencedObject(
     204             :         reinterpret_cast<internal::Address*>(FromVal(Traits::Get(&impl_, key))),
     205             :         reinterpret_cast<internal::Isolate*>(GetIsolate()));
     206             :   }
     207             : 
     208             :   /**
     209             :    * Return value for key and remove it from the map.
     210             :    */
     211          20 :   Global<V> Remove(const K& key) {
     212          40 :     return Release(Traits::Remove(&impl_, key)).Pass();
     213             :   }
     214             : 
     215             :   /**
     216             :   * Traverses the map repeatedly,
     217             :   * in case side effects of disposal cause insertions.
     218             :   **/
     219          30 :   void Clear() {
     220             :     typedef typename Traits::Iterator It;
     221          30 :     HandleScope handle_scope(isolate_);
     222             :     // TODO(dcarney): figure out if this swap and loop is necessary.
     223          80 :     while (!Traits::Empty(&impl_)) {
     224             :       typename Traits::Impl impl;
     225             :       Traits::Swap(impl_, impl);
     226          60 :       for (It i = Traits::Begin(&impl); i != Traits::End(&impl); ++i) {
     227           5 :         Traits::Dispose(isolate_, Release(Traits::Value(i)).Pass(),
     228          65 :                         Traits::Key(i));
     229             :       }
     230          30 :     }
     231          30 :   }
     232             : 
     233             :   /**
     234             :    * Helper class for GetReference/SetWithReference. Do not use outside
     235             :    * that context.
     236             :    */
     237             :   class PersistentValueReference {
     238             :    public:
     239             :     PersistentValueReference() : value_(kPersistentContainerNotFound) { }
     240             :     PersistentValueReference(const PersistentValueReference& other)
     241             :         : value_(other.value_) { }
     242             : 
     243             :     Local<V> NewLocal(Isolate* isolate) const {
     244          10 :       return Local<V>::New(isolate, FromVal(value_));
     245             :     }
     246             :     bool IsEmpty() const {
     247             :       return value_ == kPersistentContainerNotFound;
     248             :     }
     249             :     template<typename T>
     250             :     bool SetReturnValue(ReturnValue<T> returnValue) {
     251             :       return SetReturnValueFromVal(&returnValue, value_);
     252             :     }
     253             :     void Reset() {
     254             :       value_ = kPersistentContainerNotFound;
     255             :     }
     256             :     void operator=(const PersistentValueReference& other) {
     257             :       value_ = other.value_;
     258             :     }
     259             : 
     260             :    private:
     261             :     friend class PersistentValueMapBase;
     262             :     friend class PersistentValueMap<K, V, Traits>;
     263             :     friend class GlobalValueMap<K, V, Traits>;
     264             : 
     265             :     explicit PersistentValueReference(PersistentContainerValue value)
     266          10 :         : value_(value) { }
     267             : 
     268             :     void operator=(PersistentContainerValue value) {
     269             :       value_ = value;
     270             :     }
     271             : 
     272             :     PersistentContainerValue value_;
     273             :   };
     274             : 
     275             :   /**
     276             :    * Get a reference to a map value. This enables fast, repeated access
     277             :    * to a value stored in the map while the map remains unchanged.
     278             :    *
     279             :    * Careful: This is potentially unsafe, so please use with care.
     280             :    * The value will become invalid if the value for this key changes
     281             :    * in the underlying map, as a result of Set or Remove for the same
     282             :    * key; as a result of the weak callback for the same key; or as a
     283             :    * result of calling Clear() or destruction of the map.
     284             :    */
     285          10 :   PersistentValueReference GetReference(const K& key) {
     286          20 :     return PersistentValueReference(Traits::Get(&impl_, key));
     287             :   }
     288             : 
     289             :  protected:
     290             :   explicit PersistentValueMapBase(Isolate* isolate)
     291          30 :       : isolate_(isolate), label_(nullptr) {}
     292             :   PersistentValueMapBase(Isolate* isolate, const char* label)
     293             :       : isolate_(isolate), label_(label) {}
     294             : 
     295          30 :   ~PersistentValueMapBase() { Clear(); }
     296             : 
     297             :   Isolate* isolate() { return isolate_; }
     298             :   typename Traits::Impl* impl() { return &impl_; }
     299             : 
     300             :   static V* FromVal(PersistentContainerValue v) {
     301         130 :     return reinterpret_cast<V*>(v);
     302             :   }
     303             : 
     304             :   static PersistentContainerValue ClearAndLeak(Global<V>* persistent) {
     305          55 :     V* v = persistent->val_;
     306          55 :     persistent->val_ = nullptr;
     307          55 :     return reinterpret_cast<PersistentContainerValue>(v);
     308             :   }
     309             : 
     310             :   static PersistentContainerValue Leak(Global<V>* persistent) {
     311             :     return reinterpret_cast<PersistentContainerValue>(persistent->val_);
     312             :   }
     313             : 
     314             :   /**
     315             :    * Return a container value as Global and make sure the weak
     316             :    * callback is properly disposed of. All remove functionality should go
     317             :    * through this.
     318             :    */
     319          95 :   static Global<V> Release(PersistentContainerValue v) {
     320             :     Global<V> p;
     321          95 :     p.val_ = FromVal(v);
     322          40 :     if (Traits::kCallbackType != kNotWeak && p.IsWeak()) {
     323             :       Traits::DisposeCallbackData(
     324             :           p.template ClearWeak<typename Traits::WeakCallbackDataType>());
     325             :     }
     326          95 :     return p.Pass();
     327             :   }
     328             : 
     329           5 :   void RemoveWeak(const K& key) {
     330             :     Global<V> p;
     331           5 :     p.val_ = FromVal(Traits::Remove(&impl_, key));
     332             :     p.Reset();
     333           5 :   }
     334             : 
     335             :   void AnnotateStrongRetainer(Global<V>* persistent) {
     336             :     persistent->AnnotateStrongRetainer(label_);
     337             :   }
     338             : 
     339             :  private:
     340             :   PersistentValueMapBase(PersistentValueMapBase&);
     341             :   void operator=(PersistentValueMapBase&);
     342             : 
     343             :   static bool SetReturnValueFromVal(ReturnValue<Value>* returnValue,
     344             :                                     PersistentContainerValue value) {
     345             :     bool hasValue = value != kPersistentContainerNotFound;
     346             :     if (hasValue) {
     347             :       returnValue->SetInternal(
     348             :           *reinterpret_cast<internal::Address*>(FromVal(value)));
     349             :     }
     350             :     return hasValue;
     351             :   }
     352             : 
     353             :   Isolate* isolate_;
     354             :   typename Traits::Impl impl_;
     355             :   const char* label_;
     356             : };
     357             : 
     358             : 
     359             : template <typename K, typename V, typename Traits>
     360           5 : class PersistentValueMap : public PersistentValueMapBase<K, V, Traits> {
     361             :  public:
     362             :   explicit PersistentValueMap(Isolate* isolate)
     363             :       : PersistentValueMapBase<K, V, Traits>(isolate) {}
     364             :   PersistentValueMap(Isolate* isolate, const char* label)
     365             :       : PersistentValueMapBase<K, V, Traits>(isolate, label) {}
     366             : 
     367             :   typedef
     368             :       typename PersistentValueMapBase<K, V, Traits>::PersistentValueReference
     369             :           PersistentValueReference;
     370             : 
     371             :   /**
     372             :    * Put value into map. Depending on Traits::kIsWeak, the value will be held
     373             :    * by the map strongly or weakly.
     374             :    * Returns old value as Global.
     375             :    */
     376           5 :   Global<V> Set(const K& key, Local<V> value) {
     377           5 :     Global<V> persistent(this->isolate(), value);
     378          10 :     return SetUnique(key, &persistent);
     379             :   }
     380             : 
     381             :   /**
     382             :    * Put value into map, like Set(const K&, Local<V>).
     383             :    */
     384             :   Global<V> Set(const K& key, Global<V> value) {
     385             :     return SetUnique(key, &value);
     386             :   }
     387             : 
     388             :   /**
     389             :    * Put the value into the map, and set the 'weak' callback when demanded
     390             :    * by the Traits class.
     391             :    */
     392           5 :   Global<V> SetUnique(const K& key, Global<V>* persistent) {
     393             :     if (Traits::kCallbackType == kNotWeak) {
     394           5 :       this->AnnotateStrongRetainer(persistent);
     395             :     } else {
     396             :       WeakCallbackType callback_type =
     397             :           Traits::kCallbackType == kWeakWithInternalFields
     398             :               ? WeakCallbackType::kInternalFields
     399             :               : WeakCallbackType::kParameter;
     400             :       Local<V> value(Local<V>::New(this->isolate(), *persistent));
     401             :       persistent->template SetWeak<typename Traits::WeakCallbackDataType>(
     402             :           Traits::WeakCallbackParameter(this, key, value), WeakCallback,
     403             :           callback_type);
     404             :     }
     405             :     PersistentContainerValue old_value =
     406          10 :         Traits::Set(this->impl(), key, this->ClearAndLeak(persistent));
     407          10 :     return this->Release(old_value).Pass();
     408             :   }
     409             : 
     410             :   /**
     411             :    * Put a value into the map and update the reference.
     412             :    * Restrictions of GetReference apply here as well.
     413             :    */
     414             :   Global<V> Set(const K& key, Global<V> value,
     415             :                 PersistentValueReference* reference) {
     416             :     *reference = this->Leak(&value);
     417             :     return SetUnique(key, &value);
     418             :   }
     419             : 
     420             :  private:
     421             :   static void WeakCallback(
     422             :       const WeakCallbackInfo<typename Traits::WeakCallbackDataType>& data) {
     423             :     if (Traits::kCallbackType != kNotWeak) {
     424             :       PersistentValueMap<K, V, Traits>* persistentValueMap =
     425             :           Traits::MapFromWeakCallbackInfo(data);
     426             :       K key = Traits::KeyFromWeakCallbackInfo(data);
     427             :       Traits::Dispose(data.GetIsolate(),
     428             :                       persistentValueMap->Remove(key).Pass(), key);
     429             :       Traits::DisposeCallbackData(data.GetParameter());
     430             :     }
     431             :   }
     432             : };
     433             : 
     434             : 
     435             : template <typename K, typename V, typename Traits>
     436          10 : class GlobalValueMap : public PersistentValueMapBase<K, V, Traits> {
     437             :  public:
     438             :   explicit GlobalValueMap(Isolate* isolate)
     439             :       : PersistentValueMapBase<K, V, Traits>(isolate) {}
     440             :   GlobalValueMap(Isolate* isolate, const char* label)
     441             :       : PersistentValueMapBase<K, V, Traits>(isolate, label) {}
     442             : 
     443             :   typedef
     444             :       typename PersistentValueMapBase<K, V, Traits>::PersistentValueReference
     445             :           PersistentValueReference;
     446             : 
     447             :   /**
     448             :    * Put value into map. Depending on Traits::kIsWeak, the value will be held
     449             :    * by the map strongly or weakly.
     450             :    * Returns old value as Global.
     451             :    */
     452          40 :   Global<V> Set(const K& key, Local<V> value) {
     453          40 :     Global<V> persistent(this->isolate(), value);
     454          80 :     return SetUnique(key, &persistent);
     455             :   }
     456             : 
     457             :   /**
     458             :    * Put value into map, like Set(const K&, Local<V>).
     459             :    */
     460             :   Global<V> Set(const K& key, Global<V> value) {
     461             :     return SetUnique(key, &value);
     462             :   }
     463             : 
     464             :   /**
     465             :    * Put the value into the map, and set the 'weak' callback when demanded
     466             :    * by the Traits class.
     467             :    */
     468          50 :   Global<V> SetUnique(const K& key, Global<V>* persistent) {
     469             :     if (Traits::kCallbackType == kNotWeak) {
     470          50 :       this->AnnotateStrongRetainer(persistent);
     471             :     } else {
     472             :       WeakCallbackType callback_type =
     473             :           Traits::kCallbackType == kWeakWithInternalFields
     474             :               ? WeakCallbackType::kInternalFields
     475             :               : WeakCallbackType::kParameter;
     476             :       Local<V> value(Local<V>::New(this->isolate(), *persistent));
     477             :       persistent->template SetWeak<typename Traits::WeakCallbackDataType>(
     478             :           Traits::WeakCallbackParameter(this, key, value), OnWeakCallback,
     479             :           callback_type);
     480             :     }
     481             :     PersistentContainerValue old_value =
     482          50 :         Traits::Set(this->impl(), key, this->ClearAndLeak(persistent));
     483         100 :     return this->Release(old_value).Pass();
     484             :   }
     485             : 
     486             :   /**
     487             :    * Put a value into the map and update the reference.
     488             :    * Restrictions of GetReference apply here as well.
     489             :    */
     490             :   Global<V> Set(const K& key, Global<V> value,
     491             :                 PersistentValueReference* reference) {
     492             :     *reference = this->Leak(&value);
     493          10 :     return SetUnique(key, &value);
     494             :   }
     495             : 
     496             :  private:
     497           5 :   static void OnWeakCallback(
     498           5 :       const WeakCallbackInfo<typename Traits::WeakCallbackDataType>& data) {
     499             :     if (Traits::kCallbackType != kNotWeak) {
     500             :       auto map = Traits::MapFromWeakCallbackInfo(data);
     501             :       K key = Traits::KeyFromWeakCallbackInfo(data);
     502           5 :       map->RemoveWeak(key);
     503             :       Traits::OnWeakCallback(data);
     504             :       data.SetSecondPassCallback(SecondWeakCallback);
     505             :     }
     506           5 :   }
     507             : 
     508           5 :   static void SecondWeakCallback(
     509             :       const WeakCallbackInfo<typename Traits::WeakCallbackDataType>& data) {
     510           5 :     Traits::DisposeWeak(data);
     511           5 :   }
     512             : };
     513             : 
     514             : 
     515             : /**
     516             :  * A map that uses Global as value and std::map as the backing
     517             :  * implementation. Persistents are held non-weak.
     518             :  *
     519             :  * C++11 embedders don't need this class, as they can use
     520             :  * Global directly in std containers.
     521             :  */
     522             : template<typename K, typename V,
     523             :     typename Traits = DefaultPersistentValueMapTraits<K, V> >
     524             : class StdPersistentValueMap : public PersistentValueMap<K, V, Traits> {
     525             :  public:
     526             :   explicit StdPersistentValueMap(Isolate* isolate)
     527             :       : PersistentValueMap<K, V, Traits>(isolate) {}
     528             : };
     529             : 
     530             : 
     531             : /**
     532             :  * A map that uses Global as value and std::map as the backing
     533             :  * implementation. Globals are held non-weak.
     534             :  *
     535             :  * C++11 embedders don't need this class, as they can use
     536             :  * Global directly in std containers.
     537             :  */
     538             : template <typename K, typename V,
     539             :           typename Traits = DefaultGlobalMapTraits<K, V> >
     540             : class StdGlobalValueMap : public GlobalValueMap<K, V, Traits> {
     541             :  public:
     542             :   explicit StdGlobalValueMap(Isolate* isolate)
     543             :       : GlobalValueMap<K, V, Traits>(isolate) {}
     544             : };
     545             : 
     546             : 
     547             : class DefaultPersistentValueVectorTraits {
     548             :  public:
     549             :   typedef std::vector<PersistentContainerValue> Impl;
     550             : 
     551             :   static void Append(Impl* impl, PersistentContainerValue value) {
     552       34110 :     impl->push_back(value);
     553             :   }
     554             :   static bool IsEmpty(const Impl* impl) {
     555             :     return impl->empty();
     556             :   }
     557       41932 :   static size_t Size(const Impl* impl) {
     558             :     return impl->size();
     559             :   }
     560       68285 :   static PersistentContainerValue Get(const Impl* impl, size_t i) {
     561      136570 :     return (i < impl->size()) ? impl->at(i) : kPersistentContainerNotFound;
     562             :   }
     563             :   static void ReserveCapacity(Impl* impl, size_t capacity) {
     564           5 :     impl->reserve(capacity);
     565             :   }
     566             :   static void Clear(Impl* impl) {
     567             :     impl->clear();
     568             :   }
     569             : };
     570             : 
     571             : 
     572             : /**
     573             :  * A vector wrapper that safely stores Global values.
     574             :  * C++11 embedders don't need this class, as they can use Global
     575             :  * directly in std containers.
     576             :  *
     577             :  * This class relies on a backing vector implementation, whose type and methods
     578             :  * are described by the Traits class. The backing map will handle values of type
     579             :  * PersistentContainerValue, with all conversion into and out of V8
     580             :  * handles being transparently handled by this class.
     581             :  */
     582             : template<typename V, typename Traits = DefaultPersistentValueVectorTraits>
     583             : class PersistentValueVector {
     584             :  public:
     585        3788 :   explicit PersistentValueVector(Isolate* isolate) : isolate_(isolate) { }
     586             : 
     587        3788 :   ~PersistentValueVector() {
     588        3788 :     Clear();
     589        3788 :   }
     590             : 
     591             :   /**
     592             :    * Append a value to the vector.
     593             :    */
     594       34105 :   void Append(Local<V> value) {
     595       34105 :     Global<V> persistent(isolate_, value);
     596       34105 :     Traits::Append(&impl_, ClearAndLeak(&persistent));
     597       34105 :   }
     598             : 
     599             :   /**
     600             :    * Append a persistent's value to the vector.
     601             :    */
     602             :   void Append(Global<V> persistent) {
     603             :     Traits::Append(&impl_, ClearAndLeak(&persistent));
     604             :   }
     605             : 
     606             :   /**
     607             :    * Are there any values in the vector?
     608             :    */
     609             :   bool IsEmpty() const {
     610             :     return Traits::IsEmpty(&impl_);
     611             :   }
     612             : 
     613             :   /**
     614             :    * How many elements are in the vector?
     615             :    */
     616             :   size_t Size() const {
     617             :     return Traits::Size(&impl_);
     618             :   }
     619             : 
     620             :   /**
     621             :    * Retrieve the i-th value in the vector.
     622             :    */
     623       34175 :   Local<V> Get(size_t index) const {
     624      102525 :     return Local<V>::New(isolate_, FromVal(Traits::Get(&impl_, index)));
     625             :   }
     626             : 
     627             :   /**
     628             :    * Remove all elements from the vector.
     629             :    */
     630        3984 :   void Clear() {
     631             :     size_t length = Traits::Size(&impl_);
     632       38094 :     for (size_t i = 0; i < length; i++) {
     633             :       Global<V> p;
     634       34110 :       p.val_ = FromVal(Traits::Get(&impl_, i));
     635             :     }
     636             :     Traits::Clear(&impl_);
     637        3984 :   }
     638             : 
     639             :   /**
     640             :    * Reserve capacity in the vector.
     641             :    * (Efficiency gains depend on the backing implementation.)
     642             :    */
     643             :   void ReserveCapacity(size_t capacity) {
     644             :     Traits::ReserveCapacity(&impl_, capacity);
     645             :   }
     646             : 
     647             :  private:
     648             :   static PersistentContainerValue ClearAndLeak(Global<V>* persistent) {
     649           5 :     V* v = persistent->val_;
     650           5 :     persistent->val_ = nullptr;
     651       34110 :     return reinterpret_cast<PersistentContainerValue>(v);
     652             :   }
     653             : 
     654             :   static V* FromVal(PersistentContainerValue v) {
     655       68285 :     return reinterpret_cast<V*>(v);
     656             :   }
     657             : 
     658             :   Isolate* isolate_;
     659             :   typename Traits::Impl impl_;
     660             : };
     661             : 
     662             : }  // namespace v8
     663             : 
     664             : #endif  // V8_UTIL_H

Generated by: LCOV version 1.10