Team Fortress 2 Source Code as on 22/4/2020
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

487 lines
14 KiB

  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 "v8.h"
  7. #include <map>
  8. #include <vector>
  9. /**
  10. * Support for Persistent containers.
  11. *
  12. * C++11 embedders can use STL containers with UniquePersistent values,
  13. * but pre-C++11 does not support the required move semantic and hence
  14. * may want these container classes.
  15. */
  16. namespace v8 {
  17. typedef uintptr_t PersistentContainerValue;
  18. static const uintptr_t kPersistentContainerNotFound = 0;
  19. enum PersistentContainerCallbackType {
  20. kNotWeak,
  21. kWeak
  22. };
  23. /**
  24. * A default trait implemenation for PersistentValueMap which uses std::map
  25. * as a backing map.
  26. *
  27. * Users will have to implement their own weak callbacks & dispose traits.
  28. */
  29. template<typename K, typename V>
  30. class StdMapTraits {
  31. public:
  32. // STL map & related:
  33. typedef std::map<K, PersistentContainerValue> Impl;
  34. typedef typename Impl::iterator Iterator;
  35. static bool Empty(Impl* impl) { return impl->empty(); }
  36. static size_t Size(Impl* impl) { return impl->size(); }
  37. static void Swap(Impl& a, Impl& b) { std::swap(a, b); } // NOLINT
  38. static Iterator Begin(Impl* impl) { return impl->begin(); }
  39. static Iterator End(Impl* impl) { return impl->end(); }
  40. static K Key(Iterator it) { return it->first; }
  41. static PersistentContainerValue Value(Iterator it) { return it->second; }
  42. static PersistentContainerValue Set(Impl* impl, K key,
  43. PersistentContainerValue value) {
  44. std::pair<Iterator, bool> res = impl->insert(std::make_pair(key, value));
  45. PersistentContainerValue old_value = kPersistentContainerNotFound;
  46. if (!res.second) {
  47. old_value = res.first->second;
  48. res.first->second = value;
  49. }
  50. return old_value;
  51. }
  52. static PersistentContainerValue Get(Impl* impl, K key) {
  53. Iterator it = impl->find(key);
  54. if (it == impl->end()) return kPersistentContainerNotFound;
  55. return it->second;
  56. }
  57. static PersistentContainerValue Remove(Impl* impl, K key) {
  58. Iterator it = impl->find(key);
  59. if (it == impl->end()) return kPersistentContainerNotFound;
  60. PersistentContainerValue value = it->second;
  61. impl->erase(it);
  62. return value;
  63. }
  64. };
  65. /**
  66. * A default trait implementation for PersistentValueMap, which inherits
  67. * a std:map backing map from StdMapTraits and holds non-weak persistent
  68. * objects and has no special Dispose handling.
  69. *
  70. * You should not derive from this class, since MapType depends on the
  71. * surrounding class, and hence a subclass cannot simply inherit the methods.
  72. */
  73. template<typename K, typename V>
  74. class DefaultPersistentValueMapTraits : public StdMapTraits<K, V> {
  75. public:
  76. // Weak callback & friends:
  77. static const PersistentContainerCallbackType kCallbackType = kNotWeak;
  78. typedef PersistentValueMap<K, V, DefaultPersistentValueMapTraits<K, V> >
  79. MapType;
  80. typedef void WeakCallbackDataType;
  81. static WeakCallbackDataType* WeakCallbackParameter(
  82. MapType* map, const K& key, Local<V> value) {
  83. return NULL;
  84. }
  85. static MapType* MapFromWeakCallbackData(
  86. const WeakCallbackData<V, WeakCallbackDataType>& data) {
  87. return NULL;
  88. }
  89. static K KeyFromWeakCallbackData(
  90. const WeakCallbackData<V, WeakCallbackDataType>& data) {
  91. return K();
  92. }
  93. static void DisposeCallbackData(WeakCallbackDataType* data) { }
  94. static void Dispose(Isolate* isolate, UniquePersistent<V> value, K key) { }
  95. };
  96. /**
  97. * A map wrapper that allows using UniquePersistent as a mapped value.
  98. * C++11 embedders don't need this class, as they can use UniquePersistent
  99. * directly in std containers.
  100. *
  101. * The map relies on a backing map, whose type and accessors are described
  102. * by the Traits class. The backing map will handle values of type
  103. * PersistentContainerValue, with all conversion into and out of V8
  104. * handles being transparently handled by this class.
  105. */
  106. template<typename K, typename V, typename Traits>
  107. class PersistentValueMap {
  108. public:
  109. explicit PersistentValueMap(Isolate* isolate) : isolate_(isolate) {}
  110. ~PersistentValueMap() { Clear(); }
  111. Isolate* GetIsolate() { return isolate_; }
  112. /**
  113. * Return size of the map.
  114. */
  115. size_t Size() { return Traits::Size(&impl_); }
  116. /**
  117. * Return whether the map holds weak persistents.
  118. */
  119. bool IsWeak() { return Traits::kCallbackType != kNotWeak; }
  120. /**
  121. * Get value stored in map.
  122. */
  123. Local<V> Get(const K& key) {
  124. return Local<V>::New(isolate_, FromVal(Traits::Get(&impl_, key)));
  125. }
  126. /**
  127. * Check whether a value is contained in the map.
  128. */
  129. bool Contains(const K& key) {
  130. return Traits::Get(&impl_, key) != kPersistentContainerNotFound;
  131. }
  132. /**
  133. * Get value stored in map and set it in returnValue.
  134. * Return true if a value was found.
  135. */
  136. bool SetReturnValue(const K& key,
  137. ReturnValue<Value> returnValue) {
  138. return SetReturnValueFromVal(&returnValue, Traits::Get(&impl_, key));
  139. }
  140. /**
  141. * Call Isolate::SetReference with the given parent and the map value.
  142. */
  143. void SetReference(const K& key,
  144. const Persistent<Object>& parent) {
  145. GetIsolate()->SetReference(
  146. reinterpret_cast<internal::Object**>(parent.val_),
  147. reinterpret_cast<internal::Object**>(FromVal(Traits::Get(&impl_, key))));
  148. }
  149. /**
  150. * Put value into map. Depending on Traits::kIsWeak, the value will be held
  151. * by the map strongly or weakly.
  152. * Returns old value as UniquePersistent.
  153. */
  154. UniquePersistent<V> Set(const K& key, Local<V> value) {
  155. UniquePersistent<V> persistent(isolate_, value);
  156. return SetUnique(key, &persistent);
  157. }
  158. /**
  159. * Put value into map, like Set(const K&, Local<V>).
  160. */
  161. UniquePersistent<V> Set(const K& key, UniquePersistent<V> value) {
  162. return SetUnique(key, &value);
  163. }
  164. /**
  165. * Return value for key and remove it from the map.
  166. */
  167. UniquePersistent<V> Remove(const K& key) {
  168. return Release(Traits::Remove(&impl_, key)).Pass();
  169. }
  170. /**
  171. * Traverses the map repeatedly,
  172. * in case side effects of disposal cause insertions.
  173. **/
  174. void Clear() {
  175. typedef typename Traits::Iterator It;
  176. HandleScope handle_scope(isolate_);
  177. // TODO(dcarney): figure out if this swap and loop is necessary.
  178. while (!Traits::Empty(&impl_)) {
  179. typename Traits::Impl impl;
  180. Traits::Swap(impl_, impl);
  181. for (It i = Traits::Begin(&impl); i != Traits::End(&impl); ++i) {
  182. Traits::Dispose(isolate_, Release(Traits::Value(i)).Pass(),
  183. Traits::Key(i));
  184. }
  185. }
  186. }
  187. /**
  188. * Helper class for GetReference/SetWithReference. Do not use outside
  189. * that context.
  190. */
  191. class PersistentValueReference {
  192. public:
  193. PersistentValueReference() : value_(kPersistentContainerNotFound) { }
  194. PersistentValueReference(const PersistentValueReference& other)
  195. : value_(other.value_) { }
  196. Local<V> NewLocal(Isolate* isolate) const {
  197. return Local<V>::New(isolate, FromVal(value_));
  198. }
  199. bool IsEmpty() const {
  200. return value_ == kPersistentContainerNotFound;
  201. }
  202. template<typename T>
  203. bool SetReturnValue(ReturnValue<T> returnValue) {
  204. return SetReturnValueFromVal(&returnValue, value_);
  205. }
  206. void Reset() {
  207. value_ = kPersistentContainerNotFound;
  208. }
  209. void operator=(const PersistentValueReference& other) {
  210. value_ = other.value_;
  211. }
  212. private:
  213. friend class PersistentValueMap;
  214. explicit PersistentValueReference(PersistentContainerValue value)
  215. : value_(value) { }
  216. void operator=(PersistentContainerValue value) {
  217. value_ = value;
  218. }
  219. PersistentContainerValue value_;
  220. };
  221. /**
  222. * Get a reference to a map value. This enables fast, repeated access
  223. * to a value stored in the map while the map remains unchanged.
  224. *
  225. * Careful: This is potentially unsafe, so please use with care.
  226. * The value will become invalid if the value for this key changes
  227. * in the underlying map, as a result of Set or Remove for the same
  228. * key; as a result of the weak callback for the same key; or as a
  229. * result of calling Clear() or destruction of the map.
  230. */
  231. PersistentValueReference GetReference(const K& key) {
  232. return PersistentValueReference(Traits::Get(&impl_, key));
  233. }
  234. /**
  235. * Put a value into the map and update the reference.
  236. * Restrictions of GetReference apply here as well.
  237. */
  238. UniquePersistent<V> Set(const K& key, UniquePersistent<V> value,
  239. PersistentValueReference* reference) {
  240. *reference = Leak(&value);
  241. return SetUnique(key, &value);
  242. }
  243. private:
  244. PersistentValueMap(PersistentValueMap&);
  245. void operator=(PersistentValueMap&);
  246. /**
  247. * Put the value into the map, and set the 'weak' callback when demanded
  248. * by the Traits class.
  249. */
  250. UniquePersistent<V> SetUnique(const K& key, UniquePersistent<V>* persistent) {
  251. if (Traits::kCallbackType != kNotWeak) {
  252. Local<V> value(Local<V>::New(isolate_, *persistent));
  253. persistent->template SetWeak<typename Traits::WeakCallbackDataType>(
  254. Traits::WeakCallbackParameter(this, key, value), WeakCallback);
  255. }
  256. PersistentContainerValue old_value =
  257. Traits::Set(&impl_, key, ClearAndLeak(persistent));
  258. return Release(old_value).Pass();
  259. }
  260. static void WeakCallback(
  261. const WeakCallbackData<V, typename Traits::WeakCallbackDataType>& data) {
  262. if (Traits::kCallbackType != kNotWeak) {
  263. PersistentValueMap<K, V, Traits>* persistentValueMap =
  264. Traits::MapFromWeakCallbackData(data);
  265. K key = Traits::KeyFromWeakCallbackData(data);
  266. Traits::Dispose(data.GetIsolate(),
  267. persistentValueMap->Remove(key).Pass(), key);
  268. Traits::DisposeCallbackData(data.GetParameter());
  269. }
  270. }
  271. static V* FromVal(PersistentContainerValue v) {
  272. return reinterpret_cast<V*>(v);
  273. }
  274. static bool SetReturnValueFromVal(
  275. ReturnValue<Value>* returnValue, PersistentContainerValue value) {
  276. bool hasValue = value != kPersistentContainerNotFound;
  277. if (hasValue) {
  278. returnValue->SetInternal(
  279. *reinterpret_cast<internal::Object**>(FromVal(value)));
  280. }
  281. return hasValue;
  282. }
  283. static PersistentContainerValue ClearAndLeak(
  284. UniquePersistent<V>* persistent) {
  285. V* v = persistent->val_;
  286. persistent->val_ = 0;
  287. return reinterpret_cast<PersistentContainerValue>(v);
  288. }
  289. static PersistentContainerValue Leak(
  290. UniquePersistent<V>* persistent) {
  291. return reinterpret_cast<PersistentContainerValue>(persistent->val_);
  292. }
  293. /**
  294. * Return a container value as UniquePersistent and make sure the weak
  295. * callback is properly disposed of. All remove functionality should go
  296. * through this.
  297. */
  298. static UniquePersistent<V> Release(PersistentContainerValue v) {
  299. UniquePersistent<V> p;
  300. p.val_ = FromVal(v);
  301. if (Traits::kCallbackType != kNotWeak && p.IsWeak()) {
  302. Traits::DisposeCallbackData(
  303. p.template ClearWeak<typename Traits::WeakCallbackDataType>());
  304. }
  305. return p.Pass();
  306. }
  307. Isolate* isolate_;
  308. typename Traits::Impl impl_;
  309. };
  310. /**
  311. * A map that uses UniquePersistent as value and std::map as the backing
  312. * implementation. Persistents are held non-weak.
  313. *
  314. * C++11 embedders don't need this class, as they can use
  315. * UniquePersistent directly in std containers.
  316. */
  317. template<typename K, typename V,
  318. typename Traits = DefaultPersistentValueMapTraits<K, V> >
  319. class StdPersistentValueMap : public PersistentValueMap<K, V, Traits> {
  320. public:
  321. explicit StdPersistentValueMap(Isolate* isolate)
  322. : PersistentValueMap<K, V, Traits>(isolate) {}
  323. };
  324. class DefaultPersistentValueVectorTraits {
  325. public:
  326. typedef std::vector<PersistentContainerValue> Impl;
  327. static void Append(Impl* impl, PersistentContainerValue value) {
  328. impl->push_back(value);
  329. }
  330. static bool IsEmpty(const Impl* impl) {
  331. return impl->empty();
  332. }
  333. static size_t Size(const Impl* impl) {
  334. return impl->size();
  335. }
  336. static PersistentContainerValue Get(const Impl* impl, size_t i) {
  337. return (i < impl->size()) ? impl->at(i) : kPersistentContainerNotFound;
  338. }
  339. static void ReserveCapacity(Impl* impl, size_t capacity) {
  340. impl->reserve(capacity);
  341. }
  342. static void Clear(Impl* impl) {
  343. impl->clear();
  344. }
  345. };
  346. /**
  347. * A vector wrapper that safely stores UniquePersistent values.
  348. * C++11 embedders don't need this class, as they can use UniquePersistent
  349. * directly in std containers.
  350. *
  351. * This class relies on a backing vector implementation, whose type and methods
  352. * are described by the Traits class. The backing map will handle values of type
  353. * PersistentContainerValue, with all conversion into and out of V8
  354. * handles being transparently handled by this class.
  355. */
  356. template<typename V, typename Traits = DefaultPersistentValueVectorTraits>
  357. class PersistentValueVector {
  358. public:
  359. explicit PersistentValueVector(Isolate* isolate) : isolate_(isolate) { }
  360. ~PersistentValueVector() {
  361. Clear();
  362. }
  363. /**
  364. * Append a value to the vector.
  365. */
  366. void Append(Local<V> value) {
  367. UniquePersistent<V> persistent(isolate_, value);
  368. Traits::Append(&impl_, ClearAndLeak(&persistent));
  369. }
  370. /**
  371. * Append a persistent's value to the vector.
  372. */
  373. void Append(UniquePersistent<V> persistent) {
  374. Traits::Append(&impl_, ClearAndLeak(&persistent));
  375. }
  376. /**
  377. * Are there any values in the vector?
  378. */
  379. bool IsEmpty() const {
  380. return Traits::IsEmpty(&impl_);
  381. }
  382. /**
  383. * How many elements are in the vector?
  384. */
  385. size_t Size() const {
  386. return Traits::Size(&impl_);
  387. }
  388. /**
  389. * Retrieve the i-th value in the vector.
  390. */
  391. Local<V> Get(size_t index) const {
  392. return Local<V>::New(isolate_, FromVal(Traits::Get(&impl_, index)));
  393. }
  394. /**
  395. * Remove all elements from the vector.
  396. */
  397. void Clear() {
  398. size_t length = Traits::Size(&impl_);
  399. for (size_t i = 0; i < length; i++) {
  400. UniquePersistent<V> p;
  401. p.val_ = FromVal(Traits::Get(&impl_, i));
  402. }
  403. Traits::Clear(&impl_);
  404. }
  405. /**
  406. * Reserve capacity in the vector.
  407. * (Efficiency gains depend on the backing implementation.)
  408. */
  409. void ReserveCapacity(size_t capacity) {
  410. Traits::ReserveCapacity(&impl_, capacity);
  411. }
  412. private:
  413. static PersistentContainerValue ClearAndLeak(
  414. UniquePersistent<V>* persistent) {
  415. V* v = persistent->val_;
  416. persistent->val_ = 0;
  417. return reinterpret_cast<PersistentContainerValue>(v);
  418. }
  419. static V* FromVal(PersistentContainerValue v) {
  420. return reinterpret_cast<V*>(v);
  421. }
  422. Isolate* isolate_;
  423. typename Traits::Impl impl_;
  424. };
  425. } // namespace v8
  426. #endif // V8_UTIL_H_