OLD | NEW |
1 // Copyright 2014 the V8 project authors. All rights reserved. | 1 // Copyright 2014 the V8 project authors. All rights reserved. |
2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
4 // met: | 4 // met: |
5 // | 5 // |
6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
(...skipping 24 matching lines...) Expand all Loading... |
35 * Support for Persistent containers. | 35 * Support for Persistent containers. |
36 * | 36 * |
37 * C++11 embedders can use STL containers with UniquePersistent values, | 37 * C++11 embedders can use STL containers with UniquePersistent values, |
38 * but pre-C++11 does not support the required move semantic and hence | 38 * but pre-C++11 does not support the required move semantic and hence |
39 * may want these container classes. | 39 * may want these container classes. |
40 */ | 40 */ |
41 namespace v8 { | 41 namespace v8 { |
42 | 42 |
43 typedef uintptr_t PersistentContainerValue; | 43 typedef uintptr_t PersistentContainerValue; |
44 static const uintptr_t kPersistentContainerNotFound = 0; | 44 static const uintptr_t kPersistentContainerNotFound = 0; |
| 45 enum PersistentContainerCallbackType { |
| 46 kNotWeak, |
| 47 kWeak |
| 48 }; |
45 | 49 |
46 | 50 |
47 /** | 51 /** |
48 * A default trait implemenation for PersistentValueMap which uses std::map | 52 * A default trait implemenation for PersistentValueMap which uses std::map |
49 * as a backing map. | 53 * as a backing map. |
50 * | 54 * |
51 * Users will have to implement their own weak callbacks & dispose traits. | 55 * Users will have to implement their own weak callbacks & dispose traits. |
52 */ | 56 */ |
53 template<typename K, typename V> | 57 template<typename K, typename V> |
54 class StdMapTraits { | 58 class StdMapTraits { |
(...skipping 30 matching lines...) Expand all Loading... |
85 PersistentContainerValue value = it->second; | 89 PersistentContainerValue value = it->second; |
86 impl->erase(it); | 90 impl->erase(it); |
87 return value; | 91 return value; |
88 } | 92 } |
89 }; | 93 }; |
90 | 94 |
91 | 95 |
92 /** | 96 /** |
93 * A default trait implementation for PersistentValueMap, which inherits | 97 * A default trait implementation for PersistentValueMap, which inherits |
94 * a std:map backing map from StdMapTraits and holds non-weak persistent | 98 * a std:map backing map from StdMapTraits and holds non-weak persistent |
95 * objects. | 99 * objects and has no special Dispose handling. |
96 * | 100 * |
97 * Users have to implement their own dispose trait. | 101 * You should not derive from this class, since MapType depends on the |
| 102 * surrounding class, and hence a subclass cannot simply inherit the methods. |
98 */ | 103 */ |
99 template<typename K, typename V> | 104 template<typename K, typename V> |
100 class StrongMapTraits : public StdMapTraits<K, V> { | 105 class DefaultPersistentValueMapTraits : public StdMapTraits<K, V> { |
101 public: | 106 public: |
102 // Weak callback & friends: | 107 // Weak callback & friends: |
103 static const bool kIsWeak = false; | 108 static const PersistentContainerCallbackType kCallbackType = kNotWeak; |
104 typedef typename StdMapTraits<K, V>::Impl Impl; | 109 typedef PersistentValueMap<K, V, DefaultPersistentValueMapTraits<K, V> > |
| 110 MapType; |
105 typedef void WeakCallbackDataType; | 111 typedef void WeakCallbackDataType; |
| 112 |
106 static WeakCallbackDataType* WeakCallbackParameter( | 113 static WeakCallbackDataType* WeakCallbackParameter( |
107 Impl* impl, const K& key, Local<V> value); | 114 MapType* map, const K& key, Local<V> value) { |
108 static Impl* ImplFromWeakCallbackData( | 115 return NULL; |
109 const WeakCallbackData<V, WeakCallbackDataType>& data); | 116 } |
| 117 static MapType* MapFromWeakCallbackData( |
| 118 const WeakCallbackData<V, WeakCallbackDataType>& data) { |
| 119 return NULL; |
| 120 } |
110 static K KeyFromWeakCallbackData( | 121 static K KeyFromWeakCallbackData( |
111 const WeakCallbackData<V, WeakCallbackDataType>& data); | 122 const WeakCallbackData<V, WeakCallbackDataType>& data) { |
112 static void DisposeCallbackData(WeakCallbackDataType* data); | 123 return K(); |
| 124 } |
| 125 static void DisposeCallbackData(WeakCallbackDataType* data) { } |
| 126 static void Dispose(Isolate* isolate, UniquePersistent<V> value, K key) { } |
113 }; | 127 }; |
114 | 128 |
115 | 129 |
116 /** | |
117 * A default trait implementation for PersistentValueMap, with a std::map | |
118 * backing map, non-weak persistents as values, and no special dispose | |
119 * handling. Can be used as-is. | |
120 */ | |
121 template<typename K, typename V> | |
122 class DefaultPersistentValueMapTraits : public StrongMapTraits<K, V> { | |
123 public: | |
124 typedef typename StrongMapTraits<K, V>::Impl Impl; | |
125 static void Dispose(Isolate* isolate, UniquePersistent<V> value, | |
126 Impl* impl, K key) { } | |
127 }; | |
128 | |
129 | |
130 /** | 130 /** |
131 * A map wrapper that allows using UniquePersistent as a mapped value. | 131 * A map wrapper that allows using UniquePersistent as a mapped value. |
132 * C++11 embedders don't need this class, as they can use UniquePersistent | 132 * C++11 embedders don't need this class, as they can use UniquePersistent |
133 * directly in std containers. | 133 * directly in std containers. |
134 * | 134 * |
135 * The map relies on a backing map, whose type and accessors are described | 135 * The map relies on a backing map, whose type and accessors are described |
136 * by the Traits class. The backing map will handle values of type | 136 * by the Traits class. The backing map will handle values of type |
137 * PersistentContainerValue, with all conversion into and out of V8 | 137 * PersistentContainerValue, with all conversion into and out of V8 |
138 * handles being transparently handled by this class. | 138 * handles being transparently handled by this class. |
139 */ | 139 */ |
140 template<typename K, typename V, typename Traits> | 140 template<typename K, typename V, typename Traits> |
141 class PersistentValueMap { | 141 class PersistentValueMap { |
142 public: | 142 public: |
143 V8_INLINE explicit PersistentValueMap(Isolate* isolate) : isolate_(isolate) {} | 143 V8_INLINE explicit PersistentValueMap(Isolate* isolate) : isolate_(isolate) {} |
144 | 144 |
145 V8_INLINE ~PersistentValueMap() { Clear(); } | 145 V8_INLINE ~PersistentValueMap() { Clear(); } |
146 | 146 |
147 V8_INLINE Isolate* GetIsolate() { return isolate_; } | 147 V8_INLINE Isolate* GetIsolate() { return isolate_; } |
148 | 148 |
149 /** | 149 /** |
150 * Return size of the map. | 150 * Return size of the map. |
151 */ | 151 */ |
152 V8_INLINE size_t Size() { return Traits::Size(&impl_); } | 152 V8_INLINE size_t Size() { return Traits::Size(&impl_); } |
153 | 153 |
154 /** | 154 /** |
155 * Return whether the map holds weak persistents. | 155 * Return whether the map holds weak persistents. |
156 */ | 156 */ |
157 V8_INLINE bool IsWeak() { return Traits::kIsWeak; } | 157 V8_INLINE bool IsWeak() { return Traits::kCallbackType != kNotWeak; } |
158 | 158 |
159 /** | 159 /** |
160 * Get value stored in map. | 160 * Get value stored in map. |
161 */ | 161 */ |
162 V8_INLINE Local<V> Get(const K& key) { | 162 V8_INLINE Local<V> Get(const K& key) { |
163 return Local<V>::New(isolate_, FromVal(Traits::Get(&impl_, key))); | 163 return Local<V>::New(isolate_, FromVal(Traits::Get(&impl_, key))); |
164 } | 164 } |
165 | 165 |
166 /** | 166 /** |
167 * Check whether a value is contained in the map. | 167 * Check whether a value is contained in the map. |
168 */ | 168 */ |
169 V8_INLINE bool Contains(const K& key) { | 169 V8_INLINE bool Contains(const K& key) { |
170 return Traits::Get(&impl_, key) != 0; | 170 return Traits::Get(&impl_, key) != kPersistentContainerNotFound; |
171 } | 171 } |
172 | 172 |
173 /** | 173 /** |
174 * Get value stored in map and set it in returnValue. | 174 * Get value stored in map and set it in returnValue. |
175 * Return true if a value was found. | 175 * Return true if a value was found. |
176 */ | 176 */ |
177 V8_INLINE bool SetReturnValue(const K& key, | 177 V8_INLINE bool SetReturnValue(const K& key, |
178 ReturnValue<Value>& returnValue) { | 178 ReturnValue<Value> returnValue) { |
179 PersistentContainerValue value = Traits::Get(&impl_, key); | 179 return SetReturnValueFromVal(returnValue, Traits::Get(&impl_, key)); |
180 bool hasValue = value != 0; | |
181 if (hasValue) { | |
182 returnValue.SetInternal( | |
183 *reinterpret_cast<internal::Object**>(FromVal(value))); | |
184 } | |
185 return hasValue; | |
186 } | 180 } |
187 | 181 |
188 /** | 182 /** |
189 * Call Isolate::SetReference with the given parent and the map value. | 183 * Call Isolate::SetReference with the given parent and the map value. |
190 */ | 184 */ |
191 V8_INLINE void SetReference(const K& key, | 185 V8_INLINE void SetReference(const K& key, |
192 const Persistent<Object>& parent) { | 186 const Persistent<Object>& parent) { |
193 GetIsolate()->SetReference( | 187 GetIsolate()->SetReference( |
194 reinterpret_cast<internal::Object**>(parent.val_), | 188 reinterpret_cast<internal::Object**>(parent.val_), |
195 reinterpret_cast<internal::Object**>(FromVal(Traits::Get(&impl_, key)))); | 189 reinterpret_cast<internal::Object**>(FromVal(Traits::Get(&impl_, key)))); |
(...skipping 28 matching lines...) Expand all Loading... |
224 * in case side effects of disposal cause insertions. | 218 * in case side effects of disposal cause insertions. |
225 **/ | 219 **/ |
226 void Clear() { | 220 void Clear() { |
227 typedef typename Traits::Iterator It; | 221 typedef typename Traits::Iterator It; |
228 HandleScope handle_scope(isolate_); | 222 HandleScope handle_scope(isolate_); |
229 // TODO(dcarney): figure out if this swap and loop is necessary. | 223 // TODO(dcarney): figure out if this swap and loop is necessary. |
230 while (!Traits::Empty(&impl_)) { | 224 while (!Traits::Empty(&impl_)) { |
231 typename Traits::Impl impl; | 225 typename Traits::Impl impl; |
232 Traits::Swap(impl_, impl); | 226 Traits::Swap(impl_, impl); |
233 for (It i = Traits::Begin(&impl); i != Traits::End(&impl); ++i) { | 227 for (It i = Traits::Begin(&impl); i != Traits::End(&impl); ++i) { |
234 Traits::Dispose(isolate_, Release(Traits::Value(i)).Pass(), &impl, | 228 Traits::Dispose(isolate_, Release(Traits::Value(i)).Pass(), |
235 Traits::Key(i)); | 229 Traits::Key(i)); |
236 } | 230 } |
237 } | 231 } |
238 } | 232 } |
239 | 233 |
| 234 /** |
| 235 * Helper class for GetReference/SetWithReference. Do not use outside |
| 236 * that context. |
| 237 */ |
| 238 class PersistentValueReference { |
| 239 public: |
| 240 PersistentValueReference() : value_(kPersistentContainerNotFound) { } |
| 241 PersistentValueReference(const PersistentValueReference& other) |
| 242 : value_(other.value_) { } |
| 243 |
| 244 Local<V> NewLocal(Isolate* isolate) const { |
| 245 return Local<V>::New(isolate, FromVal(value_)); |
| 246 } |
| 247 bool IsEmpty() const { |
| 248 return value_ == kPersistentContainerNotFound; |
| 249 } |
| 250 template<typename T> |
| 251 bool SetReturnValue(ReturnValue<T> returnValue) { |
| 252 return SetReturnValueFromVal(returnValue, value_); |
| 253 } |
| 254 void Reset() { |
| 255 value_ = kPersistentContainerNotFound; |
| 256 } |
| 257 void operator=(const PersistentValueReference& other) { |
| 258 value_ = other.value_; |
| 259 } |
| 260 |
| 261 private: |
| 262 friend class PersistentValueMap; |
| 263 |
| 264 explicit PersistentValueReference(PersistentContainerValue value) |
| 265 : value_(value) { } |
| 266 |
| 267 void operator=(PersistentContainerValue value) { |
| 268 value_ = value; |
| 269 } |
| 270 |
| 271 PersistentContainerValue value_; |
| 272 }; |
| 273 |
| 274 /** |
| 275 * Get a reference to a map value. This enables fast, repeated access |
| 276 * to a value stored in the map while the map remains unchanged. |
| 277 * |
| 278 * Careful: This is potentially unsafe, so please use with care. |
| 279 * The value will become invalid if the value for this key changes |
| 280 * in the underlying map, as a result of Set or Remove for the same |
| 281 * key; as a result of the weak callback for the same key; or as a |
| 282 * result of calling Clear() or destruction of the map. |
| 283 */ |
| 284 V8_INLINE PersistentValueReference GetReference(const K& key) { |
| 285 return PersistentValueReference(Traits::Get(&impl_, key)); |
| 286 } |
| 287 |
| 288 /** |
| 289 * Put a value into the map and update the reference. |
| 290 * Restrictions of GetReference apply here as well. |
| 291 */ |
| 292 UniquePersistent<V> Set(const K& key, UniquePersistent<V> value, |
| 293 PersistentValueReference* reference) { |
| 294 *reference = Leak(&value); |
| 295 return SetUnique(key, &value); |
| 296 } |
| 297 |
240 private: | 298 private: |
241 PersistentValueMap(PersistentValueMap&); | 299 PersistentValueMap(PersistentValueMap&); |
242 void operator=(PersistentValueMap&); | 300 void operator=(PersistentValueMap&); |
243 | 301 |
244 /** | 302 /** |
245 * Put the value into the map, and set the 'weak' callback when demanded | 303 * Put the value into the map, and set the 'weak' callback when demanded |
246 * by the Traits class. | 304 * by the Traits class. |
247 */ | 305 */ |
248 UniquePersistent<V> SetUnique(const K& key, UniquePersistent<V>* persistent) { | 306 UniquePersistent<V> SetUnique(const K& key, UniquePersistent<V>* persistent) { |
249 if (Traits::kIsWeak) { | 307 if (Traits::kCallbackType != kNotWeak) { |
250 Local<V> value(Local<V>::New(isolate_, *persistent)); | 308 Local<V> value(Local<V>::New(isolate_, *persistent)); |
251 persistent->template SetWeak<typename Traits::WeakCallbackDataType>( | 309 persistent->template SetWeak<typename Traits::WeakCallbackDataType>( |
252 Traits::WeakCallbackParameter(&impl_, key, value), WeakCallback); | 310 Traits::WeakCallbackParameter(this, key, value), WeakCallback); |
253 } | 311 } |
254 PersistentContainerValue old_value = | 312 PersistentContainerValue old_value = |
255 Traits::Set(&impl_, key, ClearAndLeak(persistent)); | 313 Traits::Set(&impl_, key, ClearAndLeak(persistent)); |
256 return Release(old_value).Pass(); | 314 return Release(old_value).Pass(); |
257 } | 315 } |
258 | 316 |
259 static void WeakCallback( | 317 static void WeakCallback( |
260 const WeakCallbackData<V, typename Traits::WeakCallbackDataType>& data) { | 318 const WeakCallbackData<V, typename Traits::WeakCallbackDataType>& data) { |
261 if (Traits::kIsWeak) { | 319 if (Traits::kCallbackType != kNotWeak) { |
262 typename Traits::Impl* impl = Traits::ImplFromWeakCallbackData(data); | 320 PersistentValueMap<K, V, Traits>* persistentValueMap = |
| 321 Traits::MapFromWeakCallbackData(data); |
263 K key = Traits::KeyFromWeakCallbackData(data); | 322 K key = Traits::KeyFromWeakCallbackData(data); |
264 PersistentContainerValue value = Traits::Remove(impl, key); | 323 Traits::Dispose(data.GetIsolate(), |
265 Traits::Dispose(data.GetIsolate(), Release(value).Pass(), impl, key); | 324 persistentValueMap->Remove(key).Pass(), key); |
266 } | 325 } |
267 } | 326 } |
268 | 327 |
269 V8_INLINE static V* FromVal(PersistentContainerValue v) { | 328 V8_INLINE static V* FromVal(PersistentContainerValue v) { |
270 return reinterpret_cast<V*>(v); | 329 return reinterpret_cast<V*>(v); |
271 } | 330 } |
272 | 331 |
| 332 V8_INLINE static bool SetReturnValueFromVal( |
| 333 ReturnValue<Value>& returnValue, PersistentContainerValue value) { |
| 334 bool hasValue = value != kPersistentContainerNotFound; |
| 335 if (hasValue) { |
| 336 returnValue.SetInternal( |
| 337 *reinterpret_cast<internal::Object**>(FromVal(value))); |
| 338 } |
| 339 return hasValue; |
| 340 } |
| 341 |
273 V8_INLINE static PersistentContainerValue ClearAndLeak( | 342 V8_INLINE static PersistentContainerValue ClearAndLeak( |
274 UniquePersistent<V>* persistent) { | 343 UniquePersistent<V>* persistent) { |
275 V* v = persistent->val_; | 344 V* v = persistent->val_; |
276 persistent->val_ = 0; | 345 persistent->val_ = 0; |
277 return reinterpret_cast<PersistentContainerValue>(v); | 346 return reinterpret_cast<PersistentContainerValue>(v); |
278 } | 347 } |
279 | 348 |
| 349 V8_INLINE static PersistentContainerValue Leak( |
| 350 UniquePersistent<V>* persistent) { |
| 351 return reinterpret_cast<PersistentContainerValue>(persistent->val_); |
| 352 } |
| 353 |
280 /** | 354 /** |
281 * Return a container value as UniquePersistent and make sure the weak | 355 * Return a container value as UniquePersistent and make sure the weak |
282 * callback is properly disposed of. All remove functionality should go | 356 * callback is properly disposed of. All remove functionality should go |
283 * through this. | 357 * through this. |
284 */ | 358 */ |
285 V8_INLINE static UniquePersistent<V> Release(PersistentContainerValue v) { | 359 V8_INLINE static UniquePersistent<V> Release(PersistentContainerValue v) { |
286 UniquePersistent<V> p; | 360 UniquePersistent<V> p; |
287 p.val_ = FromVal(v); | 361 p.val_ = FromVal(v); |
288 if (Traits::kIsWeak && !p.IsEmpty()) { | 362 if (Traits::kCallbackType != kNotWeak && !p.IsEmpty()) { |
289 Traits::DisposeCallbackData( | 363 Traits::DisposeCallbackData( |
290 p.template ClearWeak<typename Traits::WeakCallbackDataType>()); | 364 p.template ClearWeak<typename Traits::WeakCallbackDataType>()); |
291 } | 365 } |
292 return p.Pass(); | 366 return p.Pass(); |
293 } | 367 } |
294 | 368 |
295 Isolate* isolate_; | 369 Isolate* isolate_; |
296 typename Traits::Impl impl_; | 370 typename Traits::Impl impl_; |
297 }; | 371 }; |
298 | 372 |
299 | 373 |
300 /** | 374 /** |
301 * A map that uses UniquePersistent as value and std::map as the backing | 375 * A map that uses UniquePersistent as value and std::map as the backing |
302 * implementation. Persistents are held non-weak. | 376 * implementation. Persistents are held non-weak. |
303 * | 377 * |
304 * C++11 embedders don't need this class, as they can use | 378 * C++11 embedders don't need this class, as they can use |
305 * UniquePersistent directly in std containers. | 379 * UniquePersistent directly in std containers. |
306 */ | 380 */ |
307 template<typename K, typename V, | 381 template<typename K, typename V, |
308 typename Traits = DefaultPersistentValueMapTraits<K, V> > | 382 typename Traits = DefaultPersistentValueMapTraits<K, V> > |
309 class StdPersistentValueMap : public PersistentValueMap<K, V, Traits> { | 383 class StdPersistentValueMap : public PersistentValueMap<K, V, Traits> { |
310 public: | 384 public: |
311 explicit StdPersistentValueMap(Isolate* isolate) | 385 explicit StdPersistentValueMap(Isolate* isolate) |
312 : PersistentValueMap<K, V, Traits>(isolate) {} | 386 : PersistentValueMap<K, V, Traits>(isolate) {} |
313 }; | 387 }; |
314 | 388 |
315 | |
316 /** | |
317 * Empty default implementations for StrongTraits methods. | |
318 * | |
319 * These should not be necessary, since they're only used in code that | |
320 * is surrounded by if(Traits::kIsWeak), which for StrongMapTraits is | |
321 * compile-time false. Most compilers can live without them; however | |
322 * the compiler we use from 64-bit Win differs. | |
323 * | |
324 * TODO(vogelheim): Remove these once they're no longer necessary. | |
325 */ | |
326 template<typename K, typename V> | |
327 typename StrongMapTraits<K, V>::WeakCallbackDataType* | |
328 StrongMapTraits<K, V>::WeakCallbackParameter( | |
329 Impl* impl, const K& key, Local<V> value) { | |
330 return NULL; | |
331 } | |
332 | |
333 | |
334 template<typename K, typename V> | |
335 typename StrongMapTraits<K, V>::Impl* | |
336 StrongMapTraits<K, V>::ImplFromWeakCallbackData( | |
337 const WeakCallbackData<V, WeakCallbackDataType>& data) { | |
338 return NULL; | |
339 } | |
340 | |
341 | |
342 template<typename K, typename V> | |
343 K StrongMapTraits<K, V>::KeyFromWeakCallbackData( | |
344 const WeakCallbackData<V, WeakCallbackDataType>& data) { | |
345 return K(); | |
346 } | |
347 | |
348 | |
349 template<typename K, typename V> | |
350 void StrongMapTraits<K, V>::DisposeCallbackData(WeakCallbackDataType* data) { | |
351 } | |
352 | |
353 } // namespace v8 | 389 } // namespace v8 |
354 | 390 |
355 #endif // V8_UTIL_H_ | 391 #endif // V8_UTIL_H_ |
OLD | NEW |