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