ca36b6c58bcf0cdc762f2aa01a259cc67334a986
[platform/upstream/nodejs.git] / deps / v8 / include / v8-util.h
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 template <typename K, typename V>
109 class DefaultPhantomPersistentValueMapTraits : public StdMapTraits<K, V> {
110  private:
111   template <typename T>
112   struct RemovePointer;
113
114  public:
115   // Weak callback & friends:
116   static const PersistentContainerCallbackType kCallbackType = kNotWeak;
117   typedef PersistentValueMap<
118       K, V, DefaultPhantomPersistentValueMapTraits<K, V> > MapType;
119   typedef void PhantomCallbackDataType;
120
121   static PhantomCallbackDataType* PhantomCallbackParameter(MapType* map,
122                                                            const K& key,
123                                                            Local<V> value) {
124     return NULL;
125   }
126   static MapType* MapFromPhantomCallbackData(
127       const PhantomCallbackData<PhantomCallbackDataType>& data) {
128     return NULL;
129   }
130   static K KeyFromPhantomCallbackData(
131       const PhantomCallbackData<PhantomCallbackDataType>& data) {
132     return K();
133   }
134   static void DisposeCallbackData(PhantomCallbackDataType* data) {}
135   static void Dispose(Isolate* isolate, UniquePersistent<V> value, K key) {}
136
137  private:
138   template <typename T>
139   struct RemovePointer<T*> {
140     typedef T Type;
141   };
142 };
143
144
145 /**
146  * A map wrapper that allows using UniquePersistent as a mapped value.
147  * C++11 embedders don't need this class, as they can use UniquePersistent
148  * directly in std containers.
149  *
150  * The map relies on a backing map, whose type and accessors are described
151  * by the Traits class. The backing map will handle values of type
152  * PersistentContainerValue, with all conversion into and out of V8
153  * handles being transparently handled by this class.
154  */
155 template <typename K, typename V, typename Traits>
156 class PersistentValueMapBase {
157  public:
158   Isolate* GetIsolate() { return isolate_; }
159
160   /**
161    * Return size of the map.
162    */
163   size_t Size() { return Traits::Size(&impl_); }
164
165   /**
166    * Return whether the map holds weak persistents.
167    */
168   bool IsWeak() { return Traits::kCallbackType != kNotWeak; }
169
170   /**
171    * Get value stored in map.
172    */
173   Local<V> Get(const K& key) {
174     return Local<V>::New(isolate_, FromVal(Traits::Get(&impl_, key)));
175   }
176
177   /**
178    * Check whether a value is contained in the map.
179    */
180   bool Contains(const K& key) {
181     return Traits::Get(&impl_, key) != kPersistentContainerNotFound;
182   }
183
184   /**
185    * Get value stored in map and set it in returnValue.
186    * Return true if a value was found.
187    */
188   bool SetReturnValue(const K& key,
189       ReturnValue<Value> returnValue) {
190     return SetReturnValueFromVal(&returnValue, Traits::Get(&impl_, key));
191   }
192
193   /**
194    * Call Isolate::SetReference with the given parent and the map value.
195    */
196   void SetReference(const K& key,
197       const Persistent<Object>& parent) {
198     GetIsolate()->SetReference(
199       reinterpret_cast<internal::Object**>(parent.val_),
200       reinterpret_cast<internal::Object**>(FromVal(Traits::Get(&impl_, key))));
201   }
202
203   /**
204    * Return value for key and remove it from the map.
205    */
206   UniquePersistent<V> Remove(const K& key) {
207     return Release(Traits::Remove(&impl_, key)).Pass();
208   }
209
210   /**
211   * Traverses the map repeatedly,
212   * in case side effects of disposal cause insertions.
213   **/
214   void Clear() {
215     typedef typename Traits::Iterator It;
216     HandleScope handle_scope(isolate_);
217     // TODO(dcarney): figure out if this swap and loop is necessary.
218     while (!Traits::Empty(&impl_)) {
219       typename Traits::Impl impl;
220       Traits::Swap(impl_, impl);
221       for (It i = Traits::Begin(&impl); i != Traits::End(&impl); ++i) {
222         Traits::Dispose(isolate_, Release(Traits::Value(i)).Pass(),
223                         Traits::Key(i));
224       }
225     }
226   }
227
228   /**
229    * Helper class for GetReference/SetWithReference. Do not use outside
230    * that context.
231    */
232   class PersistentValueReference {
233    public:
234     PersistentValueReference() : value_(kPersistentContainerNotFound) { }
235     PersistentValueReference(const PersistentValueReference& other)
236         : value_(other.value_) { }
237
238     Local<V> NewLocal(Isolate* isolate) const {
239       return Local<V>::New(isolate, FromVal(value_));
240     }
241     bool IsEmpty() const {
242       return value_ == kPersistentContainerNotFound;
243     }
244     template<typename T>
245     bool SetReturnValue(ReturnValue<T> returnValue) {
246       return SetReturnValueFromVal(&returnValue, value_);
247     }
248     void Reset() {
249       value_ = kPersistentContainerNotFound;
250     }
251     void operator=(const PersistentValueReference& other) {
252       value_ = other.value_;
253     }
254
255    private:
256     friend class PersistentValueMapBase;
257     friend class PersistentValueMap<K, V, Traits>;
258     friend class PhantomPersistentValueMap<K, V, Traits>;
259
260     explicit PersistentValueReference(PersistentContainerValue value)
261         : value_(value) { }
262
263     void operator=(PersistentContainerValue value) {
264       value_ = value;
265     }
266
267     PersistentContainerValue value_;
268   };
269
270   /**
271    * Get a reference to a map value. This enables fast, repeated access
272    * to a value stored in the map while the map remains unchanged.
273    *
274    * Careful: This is potentially unsafe, so please use with care.
275    * The value will become invalid if the value for this key changes
276    * in the underlying map, as a result of Set or Remove for the same
277    * key; as a result of the weak callback for the same key; or as a
278    * result of calling Clear() or destruction of the map.
279    */
280   PersistentValueReference GetReference(const K& key) {
281     return PersistentValueReference(Traits::Get(&impl_, key));
282   }
283
284  protected:
285   explicit PersistentValueMapBase(Isolate* isolate) : isolate_(isolate) {}
286
287   ~PersistentValueMapBase() { Clear(); }
288
289   Isolate* isolate() { return isolate_; }
290   typename Traits::Impl* impl() { return &impl_; }
291
292   static V* FromVal(PersistentContainerValue v) {
293     return reinterpret_cast<V*>(v);
294   }
295
296   static PersistentContainerValue ClearAndLeak(
297       UniquePersistent<V>* persistent) {
298     V* v = persistent->val_;
299     persistent->val_ = 0;
300     return reinterpret_cast<PersistentContainerValue>(v);
301   }
302
303   static PersistentContainerValue Leak(UniquePersistent<V>* persistent) {
304     return reinterpret_cast<PersistentContainerValue>(persistent->val_);
305   }
306
307   /**
308    * Return a container value as UniquePersistent and make sure the weak
309    * callback is properly disposed of. All remove functionality should go
310    * through this.
311    */
312   static UniquePersistent<V> Release(PersistentContainerValue v) {
313     UniquePersistent<V> p;
314     p.val_ = FromVal(v);
315     if (Traits::kCallbackType != kNotWeak && p.IsWeak()) {
316       Traits::DisposeCallbackData(
317           p.template ClearWeak<typename Traits::WeakCallbackDataType>());
318     }
319     return p.Pass();
320   }
321
322  private:
323   PersistentValueMapBase(PersistentValueMapBase&);
324   void operator=(PersistentValueMapBase&);
325
326   static bool SetReturnValueFromVal(ReturnValue<Value>* returnValue,
327                                     PersistentContainerValue value) {
328     bool hasValue = value != kPersistentContainerNotFound;
329     if (hasValue) {
330       returnValue->SetInternal(
331           *reinterpret_cast<internal::Object**>(FromVal(value)));
332     }
333     return hasValue;
334   }
335
336   Isolate* isolate_;
337   typename Traits::Impl impl_;
338 };
339
340
341 template <typename K, typename V, typename Traits>
342 class PersistentValueMap : public PersistentValueMapBase<K, V, Traits> {
343  public:
344   explicit PersistentValueMap(Isolate* isolate)
345       : PersistentValueMapBase<K, V, Traits>(isolate) {}
346
347   typedef
348       typename PersistentValueMapBase<K, V, Traits>::PersistentValueReference
349           PersistentValueReference;
350
351   /**
352    * Put value into map. Depending on Traits::kIsWeak, the value will be held
353    * by the map strongly or weakly.
354    * Returns old value as UniquePersistent.
355    */
356   UniquePersistent<V> Set(const K& key, Local<V> value) {
357     UniquePersistent<V> persistent(this->isolate(), value);
358     return SetUnique(key, &persistent);
359   }
360
361   /**
362    * Put value into map, like Set(const K&, Local<V>).
363    */
364   UniquePersistent<V> Set(const K& key, UniquePersistent<V> value) {
365     return SetUnique(key, &value);
366   }
367
368   /**
369    * Put the value into the map, and set the 'weak' callback when demanded
370    * by the Traits class.
371    */
372   UniquePersistent<V> SetUnique(const K& key, UniquePersistent<V>* persistent) {
373     if (Traits::kCallbackType != kNotWeak) {
374       Local<V> value(Local<V>::New(this->isolate(), *persistent));
375       persistent->template SetWeak<typename Traits::WeakCallbackDataType>(
376         Traits::WeakCallbackParameter(this, key, value), WeakCallback);
377     }
378     PersistentContainerValue old_value =
379         Traits::Set(this->impl(), key, this->ClearAndLeak(persistent));
380     return this->Release(old_value).Pass();
381   }
382
383   /**
384    * Put a value into the map and update the reference.
385    * Restrictions of GetReference apply here as well.
386    */
387   UniquePersistent<V> Set(const K& key, UniquePersistent<V> value,
388                           PersistentValueReference* reference) {
389     *reference = this->Leak(&value);
390     return SetUnique(key, &value);
391   }
392
393  private:
394   static void WeakCallback(
395       const WeakCallbackData<V, typename Traits::WeakCallbackDataType>& data) {
396     if (Traits::kCallbackType != kNotWeak) {
397       PersistentValueMap<K, V, Traits>* persistentValueMap =
398           Traits::MapFromWeakCallbackData(data);
399       K key = Traits::KeyFromWeakCallbackData(data);
400       Traits::Dispose(data.GetIsolate(),
401                       persistentValueMap->Remove(key).Pass(), key);
402       Traits::DisposeCallbackData(data.GetParameter());
403     }
404   }
405 };
406
407
408 template <typename K, typename V, typename Traits>
409 class PhantomPersistentValueMap : public PersistentValueMapBase<K, V, Traits> {
410  public:
411   explicit PhantomPersistentValueMap(Isolate* isolate)
412       : PersistentValueMapBase<K, V, Traits>(isolate) {}
413
414   typedef
415       typename PersistentValueMapBase<K, V, Traits>::PersistentValueReference
416           PersistentValueReference;
417
418   /**
419    * Put value into map. Depending on Traits::kIsWeak, the value will be held
420    * by the map strongly or weakly.
421    * Returns old value as UniquePersistent.
422    */
423   UniquePersistent<V> Set(const K& key, Local<V> value) {
424     UniquePersistent<V> persistent(this->isolate(), value);
425     return SetUnique(key, &persistent);
426   }
427
428   /**
429    * Put value into map, like Set(const K&, Local<V>).
430    */
431   UniquePersistent<V> Set(const K& key, UniquePersistent<V> value) {
432     return SetUnique(key, &value);
433   }
434
435   /**
436    * Put the value into the map, and set the 'weak' callback when demanded
437    * by the Traits class.
438    */
439   UniquePersistent<V> SetUnique(const K& key, UniquePersistent<V>* persistent) {
440     if (Traits::kCallbackType != kNotWeak) {
441       Local<V> value(Local<V>::New(this->isolate(), *persistent));
442       persistent->template SetPhantom<typename Traits::WeakCallbackDataType>(
443           Traits::WeakCallbackParameter(this, key, value), WeakCallback, 0, 1);
444     }
445     PersistentContainerValue old_value =
446         Traits::Set(this->impl(), key, this->ClearAndLeak(persistent));
447     return this->Release(old_value).Pass();
448   }
449
450   /**
451    * Put a value into the map and update the reference.
452    * Restrictions of GetReference apply here as well.
453    */
454   UniquePersistent<V> Set(const K& key, UniquePersistent<V> value,
455                           PersistentValueReference* reference) {
456     *reference = this->Leak(&value);
457     return SetUnique(key, &value);
458   }
459
460  private:
461   static void WeakCallback(
462       const PhantomCallbackData<typename Traits::WeakCallbackDataType>& data) {
463     if (Traits::kCallbackType != kNotWeak) {
464       PhantomPersistentValueMap<K, V, Traits>* persistentValueMap =
465           Traits::MapFromPhantomCallbackData(data);
466       K key = Traits::KeyFromPhantomCallbackData(data);
467       Traits::Dispose(data.GetIsolate(), persistentValueMap->Remove(key).Pass(),
468                       key);
469       Traits::DisposeCallbackData(data.GetParameter());
470     }
471   }
472 };
473
474
475 /**
476  * A map that uses UniquePersistent as value and std::map as the backing
477  * implementation. Persistents are held non-weak.
478  *
479  * C++11 embedders don't need this class, as they can use
480  * UniquePersistent directly in std containers.
481  */
482 template<typename K, typename V,
483     typename Traits = DefaultPersistentValueMapTraits<K, V> >
484 class StdPersistentValueMap : public PersistentValueMap<K, V, Traits> {
485  public:
486   explicit StdPersistentValueMap(Isolate* isolate)
487       : PersistentValueMap<K, V, Traits>(isolate) {}
488 };
489
490
491 class DefaultPersistentValueVectorTraits {
492  public:
493   typedef std::vector<PersistentContainerValue> Impl;
494
495   static void Append(Impl* impl, PersistentContainerValue value) {
496     impl->push_back(value);
497   }
498   static bool IsEmpty(const Impl* impl) {
499     return impl->empty();
500   }
501   static size_t Size(const Impl* impl) {
502     return impl->size();
503   }
504   static PersistentContainerValue Get(const Impl* impl, size_t i) {
505     return (i < impl->size()) ? impl->at(i) : kPersistentContainerNotFound;
506   }
507   static void ReserveCapacity(Impl* impl, size_t capacity) {
508     impl->reserve(capacity);
509   }
510   static void Clear(Impl* impl) {
511     impl->clear();
512   }
513 };
514
515
516 /**
517  * A vector wrapper that safely stores UniquePersistent values.
518  * C++11 embedders don't need this class, as they can use UniquePersistent
519  * directly in std containers.
520  *
521  * This class relies on a backing vector implementation, whose type and methods
522  * are described by the Traits class. The backing map will handle values of type
523  * PersistentContainerValue, with all conversion into and out of V8
524  * handles being transparently handled by this class.
525  */
526 template<typename V, typename Traits = DefaultPersistentValueVectorTraits>
527 class PersistentValueVector {
528  public:
529   explicit PersistentValueVector(Isolate* isolate) : isolate_(isolate) { }
530
531   ~PersistentValueVector() {
532     Clear();
533   }
534
535   /**
536    * Append a value to the vector.
537    */
538   void Append(Local<V> value) {
539     UniquePersistent<V> persistent(isolate_, value);
540     Traits::Append(&impl_, ClearAndLeak(&persistent));
541   }
542
543   /**
544    * Append a persistent's value to the vector.
545    */
546   void Append(UniquePersistent<V> persistent) {
547     Traits::Append(&impl_, ClearAndLeak(&persistent));
548   }
549
550   /**
551    * Are there any values in the vector?
552    */
553   bool IsEmpty() const {
554     return Traits::IsEmpty(&impl_);
555   }
556
557   /**
558    * How many elements are in the vector?
559    */
560   size_t Size() const {
561     return Traits::Size(&impl_);
562   }
563
564   /**
565    * Retrieve the i-th value in the vector.
566    */
567   Local<V> Get(size_t index) const {
568     return Local<V>::New(isolate_, FromVal(Traits::Get(&impl_, index)));
569   }
570
571   /**
572    * Remove all elements from the vector.
573    */
574   void Clear() {
575     size_t length = Traits::Size(&impl_);
576     for (size_t i = 0; i < length; i++) {
577       UniquePersistent<V> p;
578       p.val_ = FromVal(Traits::Get(&impl_, i));
579     }
580     Traits::Clear(&impl_);
581   }
582
583   /**
584    * Reserve capacity in the vector.
585    * (Efficiency gains depend on the backing implementation.)
586    */
587   void ReserveCapacity(size_t capacity) {
588     Traits::ReserveCapacity(&impl_, capacity);
589   }
590
591  private:
592   static PersistentContainerValue ClearAndLeak(
593       UniquePersistent<V>* persistent) {
594     V* v = persistent->val_;
595     persistent->val_ = 0;
596     return reinterpret_cast<PersistentContainerValue>(v);
597   }
598
599   static V* FromVal(PersistentContainerValue v) {
600     return reinterpret_cast<V*>(v);
601   }
602
603   Isolate* isolate_;
604   typename Traits::Impl impl_;
605 };
606
607 }  // namespace v8
608
609 #endif  // V8_UTIL_H_