v8-util.h 20 KB

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