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

Generated by: LCOV version 1.10