v8
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 
19 namespace v8 {
20 
21 typedef uintptr_t PersistentContainerValue;
22 static const uintptr_t kPersistentContainerNotFound = 0;
23 enum PersistentContainerCallbackType {
24  kNotWeak,
25  // These correspond to v8::WeakCallbackType
26  kWeakWithParameter,
27  kWeakWithInternalFields,
28  kWeak = kWeakWithParameter // For backwards compatibility. Deprecate.
29 };
30 
31 
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,
53  PersistentContainerValue value) {
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 
85 template<typename K, typename V>
87  public:
88  // Weak callback & friends:
89  static const PersistentContainerCallbackType kCallbackType = kNotWeak;
91  MapType;
92  typedef void WeakCallbackDataType;
93 
94  static WeakCallbackDataType* WeakCallbackParameter(
95  MapType* map, const K& key, Local<V> value) {
96  return NULL;
97  }
98  static MapType* MapFromWeakCallbackData(
100  return NULL;
101  }
102  static K KeyFromWeakCallbackData(
104  return K();
105  }
106  static void DisposeCallbackData(WeakCallbackDataType* data) { }
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:
119  static const PersistentContainerCallbackType kCallbackType = kNotWeak;
121  typedef void WeakCallbackDataType;
122 
123  static WeakCallbackDataType* WeakCallbackParameter(MapType* map, const K& key,
124  Local<V> value) {
125  return nullptr;
126  }
127  static MapType* MapFromWeakCallbackInfo(
129  return nullptr;
130  }
131  static K KeyFromWeakCallbackInfo(
133  return K();
134  }
135  static void DisposeCallbackData(WeakCallbackDataType* data) {}
136  static void Dispose(Isolate* isolate, Global<V> value, K key) {}
137  // This is a second pass callback, so SetSecondPassCallback cannot be called.
138  static void DisposeWeak(const WeakCallbackInfo<WeakCallbackDataType>& data) {}
139 
140  private:
141  template <typename T>
142  struct RemovePointer<T*> {
143  typedef T Type;
144  };
145 };
146 
147 
158 template <typename K, typename V, typename Traits>
160  public:
161  Isolate* GetIsolate() { return isolate_; }
162 
166  size_t Size() { return Traits::Size(&impl_); }
167 
171  bool IsWeak() { return Traits::kCallbackType != kNotWeak; }
172 
176  Local<V> Get(const K& key) {
177  return Local<V>::New(isolate_, FromVal(Traits::Get(&impl_, key)));
178  }
179 
183  bool Contains(const K& key) {
184  return Traits::Get(&impl_, key) != kPersistentContainerNotFound;
185  }
186 
191  bool SetReturnValue(const K& key,
192  ReturnValue<Value> returnValue) {
193  return SetReturnValueFromVal(&returnValue, Traits::Get(&impl_, key));
194  }
195 
199  void SetReference(const K& key,
200  const Persistent<Object>& parent) {
201  GetIsolate()->SetReference(
202  reinterpret_cast<internal::Object**>(parent.val_),
203  reinterpret_cast<internal::Object**>(FromVal(Traits::Get(&impl_, key))));
204  }
205 
209  Global<V> Remove(const K& key) {
210  return Release(Traits::Remove(&impl_, key)).Pass();
211  }
212 
217  void Clear() {
218  typedef typename Traits::Iterator It;
219  HandleScope handle_scope(isolate_);
220  // TODO(dcarney): figure out if this swap and loop is necessary.
221  while (!Traits::Empty(&impl_)) {
222  typename Traits::Impl impl;
223  Traits::Swap(impl_, impl);
224  for (It i = Traits::Begin(&impl); i != Traits::End(&impl); ++i) {
225  Traits::Dispose(isolate_, Release(Traits::Value(i)).Pass(),
226  Traits::Key(i));
227  }
228  }
229  }
230 
236  public:
237  PersistentValueReference() : value_(kPersistentContainerNotFound) { }
239  : value_(other.value_) { }
240 
241  Local<V> NewLocal(Isolate* isolate) const {
242  return Local<V>::New(isolate, FromVal(value_));
243  }
244  bool IsEmpty() const {
245  return value_ == kPersistentContainerNotFound;
246  }
247  template<typename T>
248  bool SetReturnValue(ReturnValue<T> returnValue) {
249  return SetReturnValueFromVal(&returnValue, value_);
250  }
251  void Reset() {
252  value_ = kPersistentContainerNotFound;
253  }
254  void operator=(const PersistentValueReference& other) {
255  value_ = other.value_;
256  }
257 
258  private:
259  friend class PersistentValueMapBase;
260  friend class PersistentValueMap<K, V, Traits>;
261  friend class GlobalValueMap<K, V, Traits>;
262 
263  explicit PersistentValueReference(PersistentContainerValue value)
264  : value_(value) { }
265 
266  void operator=(PersistentContainerValue value) {
267  value_ = value;
268  }
269 
270  PersistentContainerValue value_;
271  };
272 
284  return PersistentValueReference(Traits::Get(&impl_, key));
285  }
286 
287  protected:
288  explicit PersistentValueMapBase(Isolate* isolate) : isolate_(isolate) {}
289 
290  ~PersistentValueMapBase() { Clear(); }
291 
292  Isolate* isolate() { return isolate_; }
293  typename Traits::Impl* impl() { return &impl_; }
294 
295  static V* FromVal(PersistentContainerValue v) {
296  return reinterpret_cast<V*>(v);
297  }
298 
299  static PersistentContainerValue ClearAndLeak(Global<V>* persistent) {
300  V* v = persistent->val_;
301  persistent->val_ = 0;
302  return reinterpret_cast<PersistentContainerValue>(v);
303  }
304 
305  static PersistentContainerValue Leak(Global<V>* persistent) {
306  return reinterpret_cast<PersistentContainerValue>(persistent->val_);
307  }
308 
314  static Global<V> Release(PersistentContainerValue v) {
315  Global<V> p;
316  p.val_ = FromVal(v);
317  if (Traits::kCallbackType != kNotWeak && p.IsWeak()) {
318  Traits::DisposeCallbackData(
319  p.template ClearWeak<typename Traits::WeakCallbackDataType>());
320  }
321  return p.Pass();
322  }
323 
324  void RemoveWeak(const K& key) {
325  Global<V> p;
326  p.val_ = FromVal(Traits::Remove(&impl_, key));
327  p.Reset();
328  }
329 
330  private:
331  PersistentValueMapBase(PersistentValueMapBase&);
332  void operator=(PersistentValueMapBase&);
333 
334  static bool SetReturnValueFromVal(ReturnValue<Value>* returnValue,
335  PersistentContainerValue value) {
336  bool hasValue = value != kPersistentContainerNotFound;
337  if (hasValue) {
338  returnValue->SetInternal(
339  *reinterpret_cast<internal::Object**>(FromVal(value)));
340  }
341  return hasValue;
342  }
343 
344  Isolate* isolate_;
345  typename Traits::Impl impl_;
346 };
347 
348 
349 template <typename K, typename V, typename Traits>
350 class PersistentValueMap : public PersistentValueMapBase<K, V, Traits> {
351  public:
352  explicit PersistentValueMap(Isolate* isolate)
354 
355  typedef
358 
364  Global<V> Set(const K& key, Local<V> value) {
365  Global<V> persistent(this->isolate(), value);
366  return SetUnique(key, &persistent);
367  }
368 
372  Global<V> Set(const K& key, Global<V> value) {
373  return SetUnique(key, &value);
374  }
375 
380  Global<V> SetUnique(const K& key, Global<V>* persistent) {
381  if (Traits::kCallbackType != kNotWeak) {
382  Local<V> value(Local<V>::New(this->isolate(), *persistent));
383  persistent->template SetWeak<typename Traits::WeakCallbackDataType>(
384  Traits::WeakCallbackParameter(this, key, value), WeakCallback);
385  }
386  PersistentContainerValue old_value =
387  Traits::Set(this->impl(), key, this->ClearAndLeak(persistent));
388  return this->Release(old_value).Pass();
389  }
390 
395  Global<V> Set(const K& key, Global<V> value,
396  PersistentValueReference* reference) {
397  *reference = this->Leak(&value);
398  return SetUnique(key, &value);
399  }
400 
401  private:
402  static void WeakCallback(
404  if (Traits::kCallbackType != kNotWeak) {
405  PersistentValueMap<K, V, Traits>* persistentValueMap =
406  Traits::MapFromWeakCallbackData(data);
407  K key = Traits::KeyFromWeakCallbackData(data);
408  Traits::Dispose(data.GetIsolate(),
409  persistentValueMap->Remove(key).Pass(), key);
410  Traits::DisposeCallbackData(data.GetParameter());
411  }
412  }
413 };
414 
415 
416 template <typename K, typename V, typename Traits>
417 class GlobalValueMap : public PersistentValueMapBase<K, V, Traits> {
418  public:
419  explicit GlobalValueMap(Isolate* isolate)
421 
422  typedef
424  PersistentValueReference;
425 
431  Global<V> Set(const K& key, Local<V> value) {
432  Global<V> persistent(this->isolate(), value);
433  return SetUnique(key, &persistent);
434  }
435 
439  Global<V> Set(const K& key, Global<V> value) {
440  return SetUnique(key, &value);
441  }
442 
447  Global<V> SetUnique(const K& key, Global<V>* persistent) {
448  if (Traits::kCallbackType != kNotWeak) {
449  WeakCallbackType callback_type =
450  Traits::kCallbackType == kWeakWithInternalFields
451  ? WeakCallbackType::kInternalFields
452  : WeakCallbackType::kParameter;
453  Local<V> value(Local<V>::New(this->isolate(), *persistent));
454  persistent->template SetWeak<typename Traits::WeakCallbackDataType>(
455  Traits::WeakCallbackParameter(this, key, value), FirstWeakCallback,
456  callback_type);
457  }
458  PersistentContainerValue old_value =
459  Traits::Set(this->impl(), key, this->ClearAndLeak(persistent));
460  return this->Release(old_value).Pass();
461  }
462 
467  Global<V> Set(const K& key, Global<V> value,
468  PersistentValueReference* reference) {
469  *reference = this->Leak(&value);
470  return SetUnique(key, &value);
471  }
472 
473  private:
474  static void FirstWeakCallback(
476  if (Traits::kCallbackType != kNotWeak) {
477  auto map = Traits::MapFromWeakCallbackInfo(data);
478  K key = Traits::KeyFromWeakCallbackInfo(data);
479  map->RemoveWeak(key);
480  data.SetSecondPassCallback(SecondWeakCallback);
481  }
482  }
483 
484  static void SecondWeakCallback(
485  const WeakCallbackInfo<typename Traits::WeakCallbackDataType>& data) {
486  Traits::DisposeWeak(data);
487  }
488 };
489 
490 
498 template<typename K, typename V,
499  typename Traits = DefaultPersistentValueMapTraits<K, V> >
500 class StdPersistentValueMap : public PersistentValueMap<K, V, Traits> {
501  public:
502  explicit StdPersistentValueMap(Isolate* isolate)
504 };
505 
506 
514 template <typename K, typename V,
515  typename Traits = DefaultGlobalMapTraits<K, V> >
516 class StdGlobalValueMap : public GlobalValueMap<K, V, Traits> {
517  public:
518  explicit StdGlobalValueMap(Isolate* isolate)
519  : GlobalValueMap<K, V, Traits>(isolate) {}
520 };
521 
522 
524  public:
525  typedef std::vector<PersistentContainerValue> Impl;
526 
527  static void Append(Impl* impl, PersistentContainerValue value) {
528  impl->push_back(value);
529  }
530  static bool IsEmpty(const Impl* impl) {
531  return impl->empty();
532  }
533  static size_t Size(const Impl* impl) {
534  return impl->size();
535  }
536  static PersistentContainerValue Get(const Impl* impl, size_t i) {
537  return (i < impl->size()) ? impl->at(i) : kPersistentContainerNotFound;
538  }
539  static void ReserveCapacity(Impl* impl, size_t capacity) {
540  impl->reserve(capacity);
541  }
542  static void Clear(Impl* impl) {
543  impl->clear();
544  }
545 };
546 
547 
558 template<typename V, typename Traits = DefaultPersistentValueVectorTraits>
560  public:
561  explicit PersistentValueVector(Isolate* isolate) : isolate_(isolate) { }
562 
564  Clear();
565  }
566 
570  void Append(Local<V> value) {
571  Global<V> persistent(isolate_, value);
572  Traits::Append(&impl_, ClearAndLeak(&persistent));
573  }
574 
578  void Append(Global<V> persistent) {
579  Traits::Append(&impl_, ClearAndLeak(&persistent));
580  }
581 
585  bool IsEmpty() const {
586  return Traits::IsEmpty(&impl_);
587  }
588 
592  size_t Size() const {
593  return Traits::Size(&impl_);
594  }
595 
599  Local<V> Get(size_t index) const {
600  return Local<V>::New(isolate_, FromVal(Traits::Get(&impl_, index)));
601  }
602 
606  void Clear() {
607  size_t length = Traits::Size(&impl_);
608  for (size_t i = 0; i < length; i++) {
609  Global<V> p;
610  p.val_ = FromVal(Traits::Get(&impl_, i));
611  }
612  Traits::Clear(&impl_);
613  }
614 
619  void ReserveCapacity(size_t capacity) {
620  Traits::ReserveCapacity(&impl_, capacity);
621  }
622 
623  private:
624  static PersistentContainerValue ClearAndLeak(Global<V>* persistent) {
625  V* v = persistent->val_;
626  persistent->val_ = 0;
627  return reinterpret_cast<PersistentContainerValue>(v);
628  }
629 
630  static V* FromVal(PersistentContainerValue v) {
631  return reinterpret_cast<V*>(v);
632  }
633 
634  Isolate* isolate_;
635  typename Traits::Impl impl_;
636 };
637 
638 } // namespace v8
639 
640 #endif // V8_UTIL_H
bool IsWeak()
Definition: v8-util.h:171
Definition: v8.h:118
Definition: v8.h:862
V8_INLINE void Reset()
Definition: v8.h:6934
Definition: v8.h:1641
bool IsEmpty() const
Definition: v8-util.h:585
Global< V > Set(const K &key, Global< V > value)
Definition: v8-util.h:439
void Clear()
Definition: v8-util.h:606
Definition: v8-util.h:417
size_t Size()
Definition: v8-util.h:166
Local< V > Get(size_t index) const
Definition: v8-util.h:599
Definition: v8-util.h:516
Global< V > Set(const K &key, Local< V > value)
Definition: v8-util.h:364
Definition: v8-util.h:39
void ReserveCapacity(size_t capacity)
Definition: v8-util.h:619
void Append(Global< V > persistent)
Definition: v8-util.h:578
Global< V > Remove(const K &key)
Definition: v8-util.h:209
Global< V > SetUnique(const K &key, Global< V > *persistent)
Definition: v8-util.h:380
bool Contains(const K &key)
Definition: v8-util.h:183
size_t Size() const
Definition: v8-util.h:592
static Global< V > Release(PersistentContainerValue v)
Definition: v8-util.h:314
Definition: libplatform.h:10
Global< V > Set(const K &key, Global< V > value)
Definition: v8-util.h:372
void Append(Local< V > value)
Definition: v8-util.h:570
void SetReference(const Persistent< T > &parent, const Persistent< S > &child)
Definition: v8.h:7866
Definition: v8-util.h:112
Definition: v8-util.h:500
Global< V > Set(const K &key, Global< V > value, PersistentValueReference *reference)
Definition: v8-util.h:467
Global< V > SetUnique(const K &key, Global< V > *persistent)
Definition: v8-util.h:447
static V8_INLINE Local< T > New(Isolate *isolate, Local< T > that)
Definition: v8.h:6830
Global Pass()
Definition: v8.h:830
Definition: v8-util.h:159
Global< V > Set(const K &key, Global< V > value, PersistentValueReference *reference)
Definition: v8-util.h:395
void Clear()
Definition: v8-util.h:217
Definition: v8-util.h:86
Definition: v8.h:116
Definition: v8-util.h:559
Definition: v8.h:448
Definition: v8.h:4946
PersistentValueReference GetReference(const K &key)
Definition: v8-util.h:283
void SetReference(const K &key, const Persistent< Object > &parent)
Definition: v8-util.h:199
Local< V > Get(const K &key)
Definition: v8-util.h:176
Definition: v8.h:136
Global< V > Set(const K &key, Local< V > value)
Definition: v8-util.h:431
Definition: v8.h:403
Definition: v8-util.h:350
Definition: v8.h:109
V8_INLINE bool IsWeak() const
Definition: v8.h:6925
bool SetReturnValue(const K &key, ReturnValue< Value > returnValue)
Definition: v8-util.h:191