Home | History | Annotate | Download | only in include
      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"
      9 #include <map>
     10 #include <vector>
     11 
     12 /**
     13  * Support for Persistent containers.
     14  *
     15  * C++11 embedders can use STL containers with UniquePersistent values,
     16  * but pre-C++11 does not support the required move semantic and hence
     17  * may want these container classes.
     18  */
     19 namespace v8 {
     20 
     21 typedef uintptr_t PersistentContainerValue;
     22 static const uintptr_t kPersistentContainerNotFound = 0;
     23 enum PersistentContainerCallbackType {
     24   kNotWeak,
     25   kWeak
     26 };
     27 
     28 
     29 /**
     30  * A default trait implemenation for PersistentValueMap which uses std::map
     31  * as a backing map.
     32  *
     33  * Users will have to implement their own weak callbacks & dispose traits.
     34  */
     35 template<typename K, typename V>
     36 class StdMapTraits {
     37  public:
     38   // STL map & related:
     39   typedef std::map<K, PersistentContainerValue> Impl;
     40   typedef typename Impl::iterator Iterator;
     41 
     42   static bool Empty(Impl* impl) { return impl->empty(); }
     43   static size_t Size(Impl* impl) { return impl->size(); }
     44   static void Swap(Impl& a, Impl& b) { std::swap(a, b); }  // NOLINT
     45   static Iterator Begin(Impl* impl) { return impl->begin(); }
     46   static Iterator End(Impl* impl) { return impl->end(); }
     47   static K Key(Iterator it) { return it->first; }
     48   static PersistentContainerValue Value(Iterator it) { return it->second; }
     49   static PersistentContainerValue Set(Impl* impl, K key,
     50       PersistentContainerValue value) {
     51     std::pair<Iterator, bool> res = impl->insert(std::make_pair(key, value));
     52     PersistentContainerValue old_value = kPersistentContainerNotFound;
     53     if (!res.second) {
     54       old_value = res.first->second;
     55       res.first->second = value;
     56     }
     57     return old_value;
     58   }
     59   static PersistentContainerValue Get(Impl* impl, K key) {
     60     Iterator it = impl->find(key);
     61     if (it == impl->end()) return kPersistentContainerNotFound;
     62     return it->second;
     63   }
     64   static PersistentContainerValue Remove(Impl* impl, K key) {
     65     Iterator it = impl->find(key);
     66     if (it == impl->end()) return kPersistentContainerNotFound;
     67     PersistentContainerValue value = it->second;
     68     impl->erase(it);
     69     return value;
     70   }
     71 };
     72 
     73 
     74 /**
     75  * A default trait implementation for PersistentValueMap, which inherits
     76  * a std:map backing map from StdMapTraits and holds non-weak persistent
     77  * objects and has no special Dispose handling.
     78  *
     79  * You should not derive from this class, since MapType depends on the
     80  * surrounding class, and hence a subclass cannot simply inherit the methods.
     81  */
     82 template<typename K, typename V>
     83 class DefaultPersistentValueMapTraits : public StdMapTraits<K, V> {
     84  public:
     85   // Weak callback & friends:
     86   static const PersistentContainerCallbackType kCallbackType = kNotWeak;
     87   typedef PersistentValueMap<K, V, DefaultPersistentValueMapTraits<K, V> >
     88       MapType;
     89   typedef void WeakCallbackDataType;
     90 
     91   static WeakCallbackDataType* WeakCallbackParameter(
     92       MapType* map, const K& key, Local<V> value) {
     93     return NULL;
     94   }
     95   static MapType* MapFromWeakCallbackData(
     96           const WeakCallbackData<V, WeakCallbackDataType>& data) {
     97     return NULL;
     98   }
     99   static K KeyFromWeakCallbackData(
    100       const WeakCallbackData<V, WeakCallbackDataType>& data) {
    101     return K();
    102   }
    103   static void DisposeCallbackData(WeakCallbackDataType* data) { }
    104   static void Dispose(Isolate* isolate, UniquePersistent<V> value, K key) { }
    105 };
    106 
    107 
    108 /**
    109  * A map wrapper that allows using UniquePersistent as a mapped value.
    110  * C++11 embedders don't need this class, as they can use UniquePersistent
    111  * directly in std containers.
    112  *
    113  * The map relies on a backing map, whose type and accessors are described
    114  * by the Traits class. The backing map will handle values of type
    115  * PersistentContainerValue, with all conversion into and out of V8
    116  * handles being transparently handled by this class.
    117  */
    118 template<typename K, typename V, typename Traits>
    119 class PersistentValueMap {
    120  public:
    121   explicit PersistentValueMap(Isolate* isolate) : isolate_(isolate) {}
    122 
    123   ~PersistentValueMap() { Clear(); }
    124 
    125   Isolate* GetIsolate() { return isolate_; }
    126 
    127   /**
    128    * Return size of the map.
    129    */
    130   size_t Size() { return Traits::Size(&impl_); }
    131 
    132   /**
    133    * Return whether the map holds weak persistents.
    134    */
    135   bool IsWeak() { return Traits::kCallbackType != kNotWeak; }
    136 
    137   /**
    138    * Get value stored in map.
    139    */
    140   Local<V> Get(const K& key) {
    141     return Local<V>::New(isolate_, FromVal(Traits::Get(&impl_, key)));
    142   }
    143 
    144   /**
    145    * Check whether a value is contained in the map.
    146    */
    147   bool Contains(const K& key) {
    148     return Traits::Get(&impl_, key) != kPersistentContainerNotFound;
    149   }
    150 
    151   /**
    152    * Get value stored in map and set it in returnValue.
    153    * Return true if a value was found.
    154    */
    155   bool SetReturnValue(const K& key,
    156       ReturnValue<Value> returnValue) {
    157     return SetReturnValueFromVal(&returnValue, Traits::Get(&impl_, key));
    158   }
    159 
    160   /**
    161    * Call Isolate::SetReference with the given parent and the map value.
    162    */
    163   void SetReference(const K& key,
    164       const Persistent<Object>& parent) {
    165     GetIsolate()->SetReference(
    166       reinterpret_cast<internal::Object**>(parent.val_),
    167       reinterpret_cast<internal::Object**>(FromVal(Traits::Get(&impl_, key))));
    168   }
    169 
    170   /**
    171    * Put value into map. Depending on Traits::kIsWeak, the value will be held
    172    * by the map strongly or weakly.
    173    * Returns old value as UniquePersistent.
    174    */
    175   UniquePersistent<V> Set(const K& key, Local<V> value) {
    176     UniquePersistent<V> persistent(isolate_, value);
    177     return SetUnique(key, &persistent);
    178   }
    179 
    180   /**
    181    * Put value into map, like Set(const K&, Local<V>).
    182    */
    183   UniquePersistent<V> Set(const K& key, UniquePersistent<V> value) {
    184     return SetUnique(key, &value);
    185   }
    186 
    187   /**
    188    * Return value for key and remove it from the map.
    189    */
    190   UniquePersistent<V> Remove(const K& key) {
    191     return Release(Traits::Remove(&impl_, key)).Pass();
    192   }
    193 
    194   /**
    195   * Traverses the map repeatedly,
    196   * in case side effects of disposal cause insertions.
    197   **/
    198   void Clear() {
    199     typedef typename Traits::Iterator It;
    200     HandleScope handle_scope(isolate_);
    201     // TODO(dcarney): figure out if this swap and loop is necessary.
    202     while (!Traits::Empty(&impl_)) {
    203       typename Traits::Impl impl;
    204       Traits::Swap(impl_, impl);
    205       for (It i = Traits::Begin(&impl); i != Traits::End(&impl); ++i) {
    206         Traits::Dispose(isolate_, Release(Traits::Value(i)).Pass(),
    207                         Traits::Key(i));
    208       }
    209     }
    210   }
    211 
    212   /**
    213    * Helper class for GetReference/SetWithReference. Do not use outside
    214    * that context.
    215    */
    216   class PersistentValueReference {
    217    public:
    218     PersistentValueReference() : value_(kPersistentContainerNotFound) { }
    219     PersistentValueReference(const PersistentValueReference& other)
    220         : value_(other.value_) { }
    221 
    222     Local<V> NewLocal(Isolate* isolate) const {
    223       return Local<V>::New(isolate, FromVal(value_));
    224     }
    225     bool IsEmpty() const {
    226       return value_ == kPersistentContainerNotFound;
    227     }
    228     template<typename T>
    229     bool SetReturnValue(ReturnValue<T> returnValue) {
    230       return SetReturnValueFromVal(&returnValue, value_);
    231     }
    232     void Reset() {
    233       value_ = kPersistentContainerNotFound;
    234     }
    235     void operator=(const PersistentValueReference& other) {
    236       value_ = other.value_;
    237     }
    238 
    239    private:
    240     friend class PersistentValueMap;
    241 
    242     explicit PersistentValueReference(PersistentContainerValue value)
    243         : value_(value) { }
    244 
    245     void operator=(PersistentContainerValue value) {
    246       value_ = value;
    247     }
    248 
    249     PersistentContainerValue value_;
    250   };
    251 
    252   /**
    253    * Get a reference to a map value. This enables fast, repeated access
    254    * to a value stored in the map while the map remains unchanged.
    255    *
    256    * Careful: This is potentially unsafe, so please use with care.
    257    * The value will become invalid if the value for this key changes
    258    * in the underlying map, as a result of Set or Remove for the same
    259    * key; as a result of the weak callback for the same key; or as a
    260    * result of calling Clear() or destruction of the map.
    261    */
    262   PersistentValueReference GetReference(const K& key) {
    263     return PersistentValueReference(Traits::Get(&impl_, key));
    264   }
    265 
    266   /**
    267    * Put a value into the map and update the reference.
    268    * Restrictions of GetReference apply here as well.
    269    */
    270   UniquePersistent<V> Set(const K& key, UniquePersistent<V> value,
    271                           PersistentValueReference* reference) {
    272     *reference = Leak(&value);
    273     return SetUnique(key, &value);
    274   }
    275 
    276  private:
    277   PersistentValueMap(PersistentValueMap&);
    278   void operator=(PersistentValueMap&);
    279 
    280   /**
    281    * Put the value into the map, and set the 'weak' callback when demanded
    282    * by the Traits class.
    283    */
    284   UniquePersistent<V> SetUnique(const K& key, UniquePersistent<V>* persistent) {
    285     if (Traits::kCallbackType != kNotWeak) {
    286       Local<V> value(Local<V>::New(isolate_, *persistent));
    287       persistent->template SetWeak<typename Traits::WeakCallbackDataType>(
    288         Traits::WeakCallbackParameter(this, key, value), WeakCallback);
    289     }
    290     PersistentContainerValue old_value =
    291         Traits::Set(&impl_, key, ClearAndLeak(persistent));
    292     return Release(old_value).Pass();
    293   }
    294 
    295   static void WeakCallback(
    296       const WeakCallbackData<V, typename Traits::WeakCallbackDataType>& data) {
    297     if (Traits::kCallbackType != kNotWeak) {
    298       PersistentValueMap<K, V, Traits>* persistentValueMap =
    299           Traits::MapFromWeakCallbackData(data);
    300       K key = Traits::KeyFromWeakCallbackData(data);
    301       Traits::Dispose(data.GetIsolate(),
    302                       persistentValueMap->Remove(key).Pass(), key);
    303       Traits::DisposeCallbackData(data.GetParameter());
    304     }
    305   }
    306 
    307   static V* FromVal(PersistentContainerValue v) {
    308     return reinterpret_cast<V*>(v);
    309   }
    310 
    311   static bool SetReturnValueFromVal(
    312       ReturnValue<Value>* returnValue, PersistentContainerValue value) {
    313     bool hasValue = value != kPersistentContainerNotFound;
    314     if (hasValue) {
    315       returnValue->SetInternal(
    316           *reinterpret_cast<internal::Object**>(FromVal(value)));
    317     }
    318     return hasValue;
    319   }
    320 
    321   static PersistentContainerValue ClearAndLeak(
    322       UniquePersistent<V>* persistent) {
    323     V* v = persistent->val_;
    324     persistent->val_ = 0;
    325     return reinterpret_cast<PersistentContainerValue>(v);
    326   }
    327 
    328   static PersistentContainerValue Leak(
    329       UniquePersistent<V>* persistent) {
    330     return reinterpret_cast<PersistentContainerValue>(persistent->val_);
    331   }
    332 
    333   /**
    334    * Return a container value as UniquePersistent and make sure the weak
    335    * callback is properly disposed of. All remove functionality should go
    336    * through this.
    337    */
    338   static UniquePersistent<V> Release(PersistentContainerValue v) {
    339     UniquePersistent<V> p;
    340     p.val_ = FromVal(v);
    341     if (Traits::kCallbackType != kNotWeak && p.IsWeak()) {
    342       Traits::DisposeCallbackData(
    343           p.template ClearWeak<typename Traits::WeakCallbackDataType>());
    344     }
    345     return p.Pass();
    346   }
    347 
    348   Isolate* isolate_;
    349   typename Traits::Impl impl_;
    350 };
    351 
    352 
    353 /**
    354  * A map that uses UniquePersistent as value and std::map as the backing
    355  * implementation. Persistents are held non-weak.
    356  *
    357  * C++11 embedders don't need this class, as they can use
    358  * UniquePersistent directly in std containers.
    359  */
    360 template<typename K, typename V,
    361     typename Traits = DefaultPersistentValueMapTraits<K, V> >
    362 class StdPersistentValueMap : public PersistentValueMap<K, V, Traits> {
    363  public:
    364   explicit StdPersistentValueMap(Isolate* isolate)
    365       : PersistentValueMap<K, V, Traits>(isolate) {}
    366 };
    367 
    368 
    369 class DefaultPersistentValueVectorTraits {
    370  public:
    371   typedef std::vector<PersistentContainerValue> Impl;
    372 
    373   static void Append(Impl* impl, PersistentContainerValue value) {
    374     impl->push_back(value);
    375   }
    376   static bool IsEmpty(const Impl* impl) {
    377     return impl->empty();
    378   }
    379   static size_t Size(const Impl* impl) {
    380     return impl->size();
    381   }
    382   static PersistentContainerValue Get(const Impl* impl, size_t i) {
    383     return (i < impl->size()) ? impl->at(i) : kPersistentContainerNotFound;
    384   }
    385   static void ReserveCapacity(Impl* impl, size_t capacity) {
    386     impl->reserve(capacity);
    387   }
    388   static void Clear(Impl* impl) {
    389     impl->clear();
    390   }
    391 };
    392 
    393 
    394 /**
    395  * A vector wrapper that safely stores UniquePersistent values.
    396  * C++11 embedders don't need this class, as they can use UniquePersistent
    397  * directly in std containers.
    398  *
    399  * This class relies on a backing vector implementation, whose type and methods
    400  * are described by the Traits class. The backing map will handle values of type
    401  * PersistentContainerValue, with all conversion into and out of V8
    402  * handles being transparently handled by this class.
    403  */
    404 template<typename V, typename Traits = DefaultPersistentValueVectorTraits>
    405 class PersistentValueVector {
    406  public:
    407   explicit PersistentValueVector(Isolate* isolate) : isolate_(isolate) { }
    408 
    409   ~PersistentValueVector() {
    410     Clear();
    411   }
    412 
    413   /**
    414    * Append a value to the vector.
    415    */
    416   void Append(Local<V> value) {
    417     UniquePersistent<V> persistent(isolate_, value);
    418     Traits::Append(&impl_, ClearAndLeak(&persistent));
    419   }
    420 
    421   /**
    422    * Append a persistent's value to the vector.
    423    */
    424   void Append(UniquePersistent<V> persistent) {
    425     Traits::Append(&impl_, ClearAndLeak(&persistent));
    426   }
    427 
    428   /**
    429    * Are there any values in the vector?
    430    */
    431   bool IsEmpty() const {
    432     return Traits::IsEmpty(&impl_);
    433   }
    434 
    435   /**
    436    * How many elements are in the vector?
    437    */
    438   size_t Size() const {
    439     return Traits::Size(&impl_);
    440   }
    441 
    442   /**
    443    * Retrieve the i-th value in the vector.
    444    */
    445   Local<V> Get(size_t index) const {
    446     return Local<V>::New(isolate_, FromVal(Traits::Get(&impl_, index)));
    447   }
    448 
    449   /**
    450    * Remove all elements from the vector.
    451    */
    452   void Clear() {
    453     size_t length = Traits::Size(&impl_);
    454     for (size_t i = 0; i < length; i++) {
    455       UniquePersistent<V> p;
    456       p.val_ = FromVal(Traits::Get(&impl_, i));
    457     }
    458     Traits::Clear(&impl_);
    459   }
    460 
    461   /**
    462    * Reserve capacity in the vector.
    463    * (Efficiency gains depend on the backing implementation.)
    464    */
    465   void ReserveCapacity(size_t capacity) {
    466     Traits::ReserveCapacity(&impl_, capacity);
    467   }
    468 
    469  private:
    470   static PersistentContainerValue ClearAndLeak(
    471       UniquePersistent<V>* persistent) {
    472     V* v = persistent->val_;
    473     persistent->val_ = 0;
    474     return reinterpret_cast<PersistentContainerValue>(v);
    475   }
    476 
    477   static V* FromVal(PersistentContainerValue v) {
    478     return reinterpret_cast<V*>(v);
    479   }
    480 
    481   Isolate* isolate_;
    482   typename Traits::Impl impl_;
    483 };
    484 
    485 }  // namespace v8
    486 
    487 #endif  // V8_UTIL_H_
    488