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 5 : 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 : V8_DEPRECATED(
202 : "Used TracedGlobal and EmbedderHeapTracer::RegisterEmbedderReference",
203 : inline void RegisterExternallyReferencedObject(K& key));
204 :
205 : /**
206 : * Return value for key and remove it from the map.
207 : */
208 20 : Global<V> Remove(const K& key) {
209 40 : return Release(Traits::Remove(&impl_, key)).Pass();
210 : }
211 :
212 : /**
213 : * Traverses the map repeatedly,
214 : * in case side effects of disposal cause insertions.
215 : **/
216 30 : void Clear() {
217 : typedef typename Traits::Iterator It;
218 60 : HandleScope handle_scope(isolate_);
219 : // TODO(dcarney): figure out if this swap and loop is necessary.
220 70 : while (!Traits::Empty(&impl_)) {
221 : typename Traits::Impl impl;
222 : Traits::Swap(impl_, impl);
223 40 : for (It i = Traits::Begin(&impl); i != Traits::End(&impl); ++i) {
224 70 : Traits::Dispose(isolate_, Release(Traits::Value(i)).Pass(),
225 : Traits::Key(i));
226 : }
227 : }
228 30 : }
229 :
230 : /**
231 : * Helper class for GetReference/SetWithReference. Do not use outside
232 : * that context.
233 : */
234 : class PersistentValueReference {
235 : public:
236 : PersistentValueReference() : value_(kPersistentContainerNotFound) { }
237 : PersistentValueReference(const PersistentValueReference& other)
238 : : value_(other.value_) { }
239 :
240 : Local<V> NewLocal(Isolate* isolate) const {
241 : return Local<V>::New(isolate, FromVal(value_));
242 : }
243 : bool IsEmpty() const {
244 : return value_ == kPersistentContainerNotFound;
245 : }
246 : template<typename T>
247 : bool SetReturnValue(ReturnValue<T> returnValue) {
248 : return SetReturnValueFromVal(&returnValue, value_);
249 : }
250 : void Reset() {
251 : value_ = kPersistentContainerNotFound;
252 : }
253 : void operator=(const PersistentValueReference& other) {
254 : value_ = other.value_;
255 : }
256 :
257 : private:
258 : friend class PersistentValueMapBase;
259 : friend class PersistentValueMap<K, V, Traits>;
260 : friend class GlobalValueMap<K, V, Traits>;
261 :
262 : explicit PersistentValueReference(PersistentContainerValue value)
263 : : value_(value) { }
264 :
265 : void operator=(PersistentContainerValue value) {
266 : value_ = value;
267 : }
268 :
269 : PersistentContainerValue value_;
270 : };
271 :
272 : /**
273 : * Get a reference to a map value. This enables fast, repeated access
274 : * to a value stored in the map while the map remains unchanged.
275 : *
276 : * Careful: This is potentially unsafe, so please use with care.
277 : * The value will become invalid if the value for this key changes
278 : * in the underlying map, as a result of Set or Remove for the same
279 : * key; as a result of the weak callback for the same key; or as a
280 : * result of calling Clear() or destruction of the map.
281 : */
282 : PersistentValueReference GetReference(const K& key) {
283 : return PersistentValueReference(Traits::Get(&impl_, key));
284 : }
285 :
286 : protected:
287 : explicit PersistentValueMapBase(Isolate* isolate)
288 30 : : isolate_(isolate), label_(nullptr) {}
289 : PersistentValueMapBase(Isolate* isolate, const char* label)
290 : : isolate_(isolate), label_(label) {}
291 :
292 30 : ~PersistentValueMapBase() { Clear(); }
293 :
294 : Isolate* isolate() { return isolate_; }
295 55 : typename Traits::Impl* impl() { return &impl_; }
296 :
297 : static V* FromVal(PersistentContainerValue v) {
298 130 : return reinterpret_cast<V*>(v);
299 : }
300 :
301 : static PersistentContainerValue ClearAndLeak(Global<V>* persistent) {
302 55 : V* v = persistent->val_;
303 55 : persistent->val_ = nullptr;
304 55 : return reinterpret_cast<PersistentContainerValue>(v);
305 : }
306 :
307 : static PersistentContainerValue Leak(Global<V>* persistent) {
308 : return reinterpret_cast<PersistentContainerValue>(persistent->val_);
309 : }
310 :
311 : /**
312 : * Return a container value as Global and make sure the weak
313 : * callback is properly disposed of. All remove functionality should go
314 : * through this.
315 : */
316 95 : static Global<V> Release(PersistentContainerValue v) {
317 : Global<V> p;
318 95 : p.val_ = FromVal(v);
319 40 : if (Traits::kCallbackType != kNotWeak && p.IsWeak()) {
320 : Traits::DisposeCallbackData(
321 : p.template ClearWeak<typename Traits::WeakCallbackDataType>());
322 : }
323 95 : return p.Pass();
324 : }
325 :
326 5 : void RemoveWeak(const K& key) {
327 : Global<V> p;
328 5 : p.val_ = FromVal(Traits::Remove(&impl_, key));
329 : p.Reset();
330 5 : }
331 :
332 : void AnnotateStrongRetainer(Global<V>* persistent) {
333 : persistent->AnnotateStrongRetainer(label_);
334 : }
335 :
336 : private:
337 : PersistentValueMapBase(PersistentValueMapBase&);
338 : void operator=(PersistentValueMapBase&);
339 :
340 : static bool SetReturnValueFromVal(ReturnValue<Value>* returnValue,
341 : PersistentContainerValue value) {
342 : bool hasValue = value != kPersistentContainerNotFound;
343 : if (hasValue) {
344 : returnValue->SetInternal(
345 : *reinterpret_cast<internal::Address*>(FromVal(value)));
346 : }
347 : return hasValue;
348 : }
349 :
350 : Isolate* isolate_;
351 : typename Traits::Impl impl_;
352 : const char* label_;
353 : };
354 :
355 : template <typename K, typename V, typename Traits>
356 : inline void
357 : PersistentValueMapBase<K, V, Traits>::RegisterExternallyReferencedObject(
358 : K& key) {
359 : assert(Contains(key));
360 : V8::RegisterExternallyReferencedObject(
361 : reinterpret_cast<internal::Address*>(FromVal(Traits::Get(&impl_, key))),
362 : reinterpret_cast<internal::Isolate*>(GetIsolate()));
363 : }
364 :
365 : template <typename K, typename V, typename Traits>
366 5 : class PersistentValueMap : public PersistentValueMapBase<K, V, Traits> {
367 : public:
368 : explicit PersistentValueMap(Isolate* isolate)
369 : : PersistentValueMapBase<K, V, Traits>(isolate) {}
370 : PersistentValueMap(Isolate* isolate, const char* label)
371 : : PersistentValueMapBase<K, V, Traits>(isolate, label) {}
372 :
373 : typedef
374 : typename PersistentValueMapBase<K, V, Traits>::PersistentValueReference
375 : 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 5 : Global<V> Set(const K& key, Local<V> value) {
383 : Global<V> persistent(this->isolate(), value);
384 10 : 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 5 : Global<V> SetUnique(const K& key, Global<V>* persistent) {
399 : if (Traits::kCallbackType == kNotWeak) {
400 : this->AnnotateStrongRetainer(persistent);
401 : } else {
402 : WeakCallbackType callback_type =
403 : Traits::kCallbackType == kWeakWithInternalFields
404 : ? WeakCallbackType::kInternalFields
405 : : WeakCallbackType::kParameter;
406 : Local<V> value(Local<V>::New(this->isolate(), *persistent));
407 : persistent->template SetWeak<typename Traits::WeakCallbackDataType>(
408 : Traits::WeakCallbackParameter(this, key, value), WeakCallback,
409 : callback_type);
410 : }
411 : PersistentContainerValue old_value =
412 10 : Traits::Set(this->impl(), key, this->ClearAndLeak(persistent));
413 10 : return this->Release(old_value).Pass();
414 : }
415 :
416 : /**
417 : * Put a value into the map and update the reference.
418 : * Restrictions of GetReference apply here as well.
419 : */
420 : Global<V> Set(const K& key, Global<V> value,
421 : PersistentValueReference* reference) {
422 : *reference = this->Leak(&value);
423 : return SetUnique(key, &value);
424 : }
425 :
426 : private:
427 : static void WeakCallback(
428 : const WeakCallbackInfo<typename Traits::WeakCallbackDataType>& data) {
429 : if (Traits::kCallbackType != kNotWeak) {
430 : PersistentValueMap<K, V, Traits>* persistentValueMap =
431 : Traits::MapFromWeakCallbackInfo(data);
432 : K key = Traits::KeyFromWeakCallbackInfo(data);
433 : Traits::Dispose(data.GetIsolate(),
434 : persistentValueMap->Remove(key).Pass(), key);
435 : Traits::DisposeCallbackData(data.GetParameter());
436 : }
437 : }
438 : };
439 :
440 :
441 : template <typename K, typename V, typename Traits>
442 10 : class GlobalValueMap : public PersistentValueMapBase<K, V, Traits> {
443 : public:
444 : explicit GlobalValueMap(Isolate* isolate)
445 : : PersistentValueMapBase<K, V, Traits>(isolate) {}
446 : GlobalValueMap(Isolate* isolate, const char* label)
447 : : PersistentValueMapBase<K, V, Traits>(isolate, label) {}
448 :
449 : typedef
450 : typename PersistentValueMapBase<K, V, Traits>::PersistentValueReference
451 : PersistentValueReference;
452 :
453 : /**
454 : * Put value into map. Depending on Traits::kIsWeak, the value will be held
455 : * by the map strongly or weakly.
456 : * Returns old value as Global.
457 : */
458 40 : Global<V> Set(const K& key, Local<V> value) {
459 : Global<V> persistent(this->isolate(), value);
460 80 : return SetUnique(key, &persistent);
461 : }
462 :
463 : /**
464 : * Put value into map, like Set(const K&, Local<V>).
465 : */
466 : Global<V> Set(const K& key, Global<V> value) {
467 : return SetUnique(key, &value);
468 : }
469 :
470 : /**
471 : * Put the value into the map, and set the 'weak' callback when demanded
472 : * by the Traits class.
473 : */
474 50 : Global<V> SetUnique(const K& key, Global<V>* persistent) {
475 : if (Traits::kCallbackType == kNotWeak) {
476 : this->AnnotateStrongRetainer(persistent);
477 : } else {
478 : WeakCallbackType callback_type =
479 : Traits::kCallbackType == kWeakWithInternalFields
480 : ? WeakCallbackType::kInternalFields
481 : : WeakCallbackType::kParameter;
482 : Local<V> value(Local<V>::New(this->isolate(), *persistent));
483 : persistent->template SetWeak<typename Traits::WeakCallbackDataType>(
484 : Traits::WeakCallbackParameter(this, key, value), OnWeakCallback,
485 : callback_type);
486 : }
487 : PersistentContainerValue old_value =
488 100 : Traits::Set(this->impl(), key, this->ClearAndLeak(persistent));
489 100 : return this->Release(old_value).Pass();
490 : }
491 :
492 : /**
493 : * Put a value into the map and update the reference.
494 : * Restrictions of GetReference apply here as well.
495 : */
496 : Global<V> Set(const K& key, Global<V> value,
497 : PersistentValueReference* reference) {
498 : *reference = this->Leak(&value);
499 10 : return SetUnique(key, &value);
500 : }
501 :
502 : private:
503 5 : static void OnWeakCallback(
504 : const WeakCallbackInfo<typename Traits::WeakCallbackDataType>& data) {
505 : if (Traits::kCallbackType != kNotWeak) {
506 : auto map = Traits::MapFromWeakCallbackInfo(data);
507 : K key = Traits::KeyFromWeakCallbackInfo(data);
508 5 : map->RemoveWeak(key);
509 : Traits::OnWeakCallback(data);
510 : data.SetSecondPassCallback(SecondWeakCallback);
511 : }
512 5 : }
513 :
514 5 : static void SecondWeakCallback(
515 : const WeakCallbackInfo<typename Traits::WeakCallbackDataType>& data) {
516 5 : Traits::DisposeWeak(data);
517 5 : }
518 : };
519 :
520 :
521 : /**
522 : * A map that uses Global as value and std::map as the backing
523 : * implementation. Persistents are held non-weak.
524 : *
525 : * C++11 embedders don't need this class, as they can use
526 : * Global directly in std containers.
527 : */
528 : template<typename K, typename V,
529 : typename Traits = DefaultPersistentValueMapTraits<K, V> >
530 : class StdPersistentValueMap : public PersistentValueMap<K, V, Traits> {
531 : public:
532 : explicit StdPersistentValueMap(Isolate* isolate)
533 : : PersistentValueMap<K, V, Traits>(isolate) {}
534 : };
535 :
536 :
537 : /**
538 : * A map that uses Global as value and std::map as the backing
539 : * implementation. Globals are held non-weak.
540 : *
541 : * C++11 embedders don't need this class, as they can use
542 : * Global directly in std containers.
543 : */
544 : template <typename K, typename V,
545 : typename Traits = DefaultGlobalMapTraits<K, V> >
546 5 : class StdGlobalValueMap : public GlobalValueMap<K, V, Traits> {
547 : public:
548 : explicit StdGlobalValueMap(Isolate* isolate)
549 : : GlobalValueMap<K, V, Traits>(isolate) {}
550 : };
551 :
552 :
553 : class DefaultPersistentValueVectorTraits {
554 : public:
555 : typedef std::vector<PersistentContainerValue> Impl;
556 :
557 : static void Append(Impl* impl, PersistentContainerValue value) {
558 34187 : impl->push_back(value);
559 : }
560 : static bool IsEmpty(const Impl* impl) {
561 : return impl->empty();
562 : }
563 : static size_t Size(const Impl* impl) {
564 : return impl->size();
565 : }
566 68439 : static PersistentContainerValue Get(const Impl* impl, size_t i) {
567 136878 : return (i < impl->size()) ? impl->at(i) : kPersistentContainerNotFound;
568 : }
569 : static void ReserveCapacity(Impl* impl, size_t capacity) {
570 5 : impl->reserve(capacity);
571 : }
572 : static void Clear(Impl* impl) {
573 : impl->clear();
574 : }
575 : };
576 :
577 :
578 : /**
579 : * A vector wrapper that safely stores Global values.
580 : * C++11 embedders don't need this class, as they can use Global
581 : * directly in std containers.
582 : *
583 : * This class relies on a backing vector implementation, whose type and methods
584 : * are described by the Traits class. The backing map will handle values of type
585 : * PersistentContainerValue, with all conversion into and out of V8
586 : * handles being transparently handled by this class.
587 : */
588 : template<typename V, typename Traits = DefaultPersistentValueVectorTraits>
589 : class PersistentValueVector {
590 : public:
591 3826 : explicit PersistentValueVector(Isolate* isolate) : isolate_(isolate) { }
592 :
593 3826 : ~PersistentValueVector() {
594 3826 : Clear();
595 3826 : }
596 :
597 : /**
598 : * Append a value to the vector.
599 : */
600 34182 : void Append(Local<V> value) {
601 34182 : Global<V> persistent(isolate_, value);
602 34182 : Traits::Append(&impl_, ClearAndLeak(&persistent));
603 34182 : }
604 :
605 : /**
606 : * Append a persistent's value to the vector.
607 : */
608 : void Append(Global<V> persistent) {
609 : Traits::Append(&impl_, ClearAndLeak(&persistent));
610 : }
611 :
612 : /**
613 : * Are there any values in the vector?
614 : */
615 : bool IsEmpty() const {
616 : return Traits::IsEmpty(&impl_);
617 : }
618 :
619 : /**
620 : * How many elements are in the vector?
621 : */
622 : size_t Size() const {
623 : return Traits::Size(&impl_);
624 : }
625 :
626 : /**
627 : * Retrieve the i-th value in the vector.
628 : */
629 34252 : Local<V> Get(size_t index) const {
630 102756 : return Local<V>::New(isolate_, FromVal(Traits::Get(&impl_, index)));
631 : }
632 :
633 : /**
634 : * Remove all elements from the vector.
635 : */
636 4027 : void Clear() {
637 : size_t length = Traits::Size(&impl_);
638 72401 : for (size_t i = 0; i < length; i++) {
639 : Global<V> p;
640 34187 : p.val_ = FromVal(Traits::Get(&impl_, i));
641 : }
642 : Traits::Clear(&impl_);
643 4027 : }
644 :
645 : /**
646 : * Reserve capacity in the vector.
647 : * (Efficiency gains depend on the backing implementation.)
648 : */
649 : void ReserveCapacity(size_t capacity) {
650 : Traits::ReserveCapacity(&impl_, capacity);
651 : }
652 :
653 : private:
654 : static PersistentContainerValue ClearAndLeak(Global<V>* persistent) {
655 5 : V* v = persistent->val_;
656 5 : persistent->val_ = nullptr;
657 34187 : return reinterpret_cast<PersistentContainerValue>(v);
658 : }
659 :
660 : static V* FromVal(PersistentContainerValue v) {
661 68439 : return reinterpret_cast<V*>(v);
662 : }
663 :
664 : Isolate* isolate_;
665 : typename Traits::Impl impl_;
666 : };
667 :
668 : } // namespace v8
669 :
670 : #endif // V8_UTIL_H
|