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