OLD | NEW |
1 // Copyright 2014 the V8 project authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #ifndef V8_UTIL_H_ | 5 #ifndef V8_UTIL_H_ |
6 #define V8_UTIL_H_ | 6 #define V8_UTIL_H_ |
7 | 7 |
8 #include "v8.h" | 8 #include "v8.h" |
9 #include <map> | 9 #include <map> |
10 #include <vector> | 10 #include <vector> |
(...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
98 } | 98 } |
99 static K KeyFromWeakCallbackData( | 99 static K KeyFromWeakCallbackData( |
100 const WeakCallbackData<V, WeakCallbackDataType>& data) { | 100 const WeakCallbackData<V, WeakCallbackDataType>& data) { |
101 return K(); | 101 return K(); |
102 } | 102 } |
103 static void DisposeCallbackData(WeakCallbackDataType* data) { } | 103 static void DisposeCallbackData(WeakCallbackDataType* data) { } |
104 static void Dispose(Isolate* isolate, UniquePersistent<V> value, K key) { } | 104 static void Dispose(Isolate* isolate, UniquePersistent<V> value, K key) { } |
105 }; | 105 }; |
106 | 106 |
107 | 107 |
| 108 template <typename K, typename V> |
| 109 class DefaultPhantomPersistentValueMapTraits : public StdMapTraits<K, V> { |
| 110 private: |
| 111 template <typename T> |
| 112 struct RemovePointer; |
| 113 |
| 114 public: |
| 115 // Weak callback & friends: |
| 116 static const PersistentContainerCallbackType kCallbackType = kNotWeak; |
| 117 typedef PersistentValueMap< |
| 118 K, V, DefaultPhantomPersistentValueMapTraits<K, V> > MapType; |
| 119 typedef void PhantomCallbackDataType; |
| 120 |
| 121 static PhantomCallbackDataType* PhantomCallbackParameter(MapType* map, |
| 122 const K& key, |
| 123 Local<V> value) { |
| 124 return NULL; |
| 125 } |
| 126 static MapType* MapFromPhantomCallbackData( |
| 127 const PhantomCallbackData<PhantomCallbackDataType>& data) { |
| 128 return NULL; |
| 129 } |
| 130 static K KeyFromPhantomCallbackData( |
| 131 const PhantomCallbackData<PhantomCallbackDataType>& data) { |
| 132 return K(); |
| 133 } |
| 134 static void DisposeCallbackData(PhantomCallbackDataType* data) {} |
| 135 static void Dispose(Isolate* isolate, UniquePersistent<V> value, K key) {} |
| 136 |
| 137 private: |
| 138 template <typename T> |
| 139 struct RemovePointer<T*> { |
| 140 typedef T Type; |
| 141 }; |
| 142 }; |
| 143 |
| 144 |
108 /** | 145 /** |
109 * A map wrapper that allows using UniquePersistent as a mapped value. | 146 * A map wrapper that allows using UniquePersistent as a mapped value. |
110 * C++11 embedders don't need this class, as they can use UniquePersistent | 147 * C++11 embedders don't need this class, as they can use UniquePersistent |
111 * directly in std containers. | 148 * directly in std containers. |
112 * | 149 * |
113 * The map relies on a backing map, whose type and accessors are described | 150 * The map relies on a backing map, whose type and accessors are described |
114 * by the Traits class. The backing map will handle values of type | 151 * by the Traits class. The backing map will handle values of type |
115 * PersistentContainerValue, with all conversion into and out of V8 | 152 * PersistentContainerValue, with all conversion into and out of V8 |
116 * handles being transparently handled by this class. | 153 * handles being transparently handled by this class. |
117 */ | 154 */ |
118 template<typename K, typename V, typename Traits> | 155 template <typename K, typename V, typename Traits> |
119 class PersistentValueMap { | 156 class PersistentValueMapBase { |
120 public: | 157 public: |
121 explicit PersistentValueMap(Isolate* isolate) : isolate_(isolate) {} | |
122 | |
123 ~PersistentValueMap() { Clear(); } | |
124 | |
125 Isolate* GetIsolate() { return isolate_; } | 158 Isolate* GetIsolate() { return isolate_; } |
126 | 159 |
127 /** | 160 /** |
128 * Return size of the map. | 161 * Return size of the map. |
129 */ | 162 */ |
130 size_t Size() { return Traits::Size(&impl_); } | 163 size_t Size() { return Traits::Size(&impl_); } |
131 | 164 |
132 /** | 165 /** |
133 * Return whether the map holds weak persistents. | 166 * Return whether the map holds weak persistents. |
134 */ | 167 */ |
(...skipping 26 matching lines...) Expand all Loading... |
161 * Call Isolate::SetReference with the given parent and the map value. | 194 * Call Isolate::SetReference with the given parent and the map value. |
162 */ | 195 */ |
163 void SetReference(const K& key, | 196 void SetReference(const K& key, |
164 const Persistent<Object>& parent) { | 197 const Persistent<Object>& parent) { |
165 GetIsolate()->SetReference( | 198 GetIsolate()->SetReference( |
166 reinterpret_cast<internal::Object**>(parent.val_), | 199 reinterpret_cast<internal::Object**>(parent.val_), |
167 reinterpret_cast<internal::Object**>(FromVal(Traits::Get(&impl_, key)))); | 200 reinterpret_cast<internal::Object**>(FromVal(Traits::Get(&impl_, key)))); |
168 } | 201 } |
169 | 202 |
170 /** | 203 /** |
171 * Put value into map. Depending on Traits::kIsWeak, the value will be held | |
172 * by the map strongly or weakly. | |
173 * Returns old value as UniquePersistent. | |
174 */ | |
175 UniquePersistent<V> Set(const K& key, Local<V> value) { | |
176 UniquePersistent<V> persistent(isolate_, value); | |
177 return SetUnique(key, &persistent); | |
178 } | |
179 | |
180 /** | |
181 * Put value into map, like Set(const K&, Local<V>). | |
182 */ | |
183 UniquePersistent<V> Set(const K& key, UniquePersistent<V> value) { | |
184 return SetUnique(key, &value); | |
185 } | |
186 | |
187 /** | |
188 * Return value for key and remove it from the map. | 204 * Return value for key and remove it from the map. |
189 */ | 205 */ |
190 UniquePersistent<V> Remove(const K& key) { | 206 UniquePersistent<V> Remove(const K& key) { |
191 return Release(Traits::Remove(&impl_, key)).Pass(); | 207 return Release(Traits::Remove(&impl_, key)).Pass(); |
192 } | 208 } |
193 | 209 |
194 /** | 210 /** |
195 * Traverses the map repeatedly, | 211 * Traverses the map repeatedly, |
196 * in case side effects of disposal cause insertions. | 212 * in case side effects of disposal cause insertions. |
197 **/ | 213 **/ |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
230 return SetReturnValueFromVal(&returnValue, value_); | 246 return SetReturnValueFromVal(&returnValue, value_); |
231 } | 247 } |
232 void Reset() { | 248 void Reset() { |
233 value_ = kPersistentContainerNotFound; | 249 value_ = kPersistentContainerNotFound; |
234 } | 250 } |
235 void operator=(const PersistentValueReference& other) { | 251 void operator=(const PersistentValueReference& other) { |
236 value_ = other.value_; | 252 value_ = other.value_; |
237 } | 253 } |
238 | 254 |
239 private: | 255 private: |
240 friend class PersistentValueMap; | 256 friend class PersistentValueMapBase; |
| 257 friend class PersistentValueMap<K, V, Traits>; |
| 258 friend class PhantomPersistentValueMap<K, V, Traits>; |
241 | 259 |
242 explicit PersistentValueReference(PersistentContainerValue value) | 260 explicit PersistentValueReference(PersistentContainerValue value) |
243 : value_(value) { } | 261 : value_(value) { } |
244 | 262 |
245 void operator=(PersistentContainerValue value) { | 263 void operator=(PersistentContainerValue value) { |
246 value_ = value; | 264 value_ = value; |
247 } | 265 } |
248 | 266 |
249 PersistentContainerValue value_; | 267 PersistentContainerValue value_; |
250 }; | 268 }; |
251 | 269 |
252 /** | 270 /** |
253 * Get a reference to a map value. This enables fast, repeated access | 271 * Get a reference to a map value. This enables fast, repeated access |
254 * to a value stored in the map while the map remains unchanged. | 272 * to a value stored in the map while the map remains unchanged. |
255 * | 273 * |
256 * Careful: This is potentially unsafe, so please use with care. | 274 * Careful: This is potentially unsafe, so please use with care. |
257 * The value will become invalid if the value for this key changes | 275 * The value will become invalid if the value for this key changes |
258 * in the underlying map, as a result of Set or Remove for the same | 276 * in the underlying map, as a result of Set or Remove for the same |
259 * key; as a result of the weak callback for the same key; or as a | 277 * key; as a result of the weak callback for the same key; or as a |
260 * result of calling Clear() or destruction of the map. | 278 * result of calling Clear() or destruction of the map. |
261 */ | 279 */ |
262 PersistentValueReference GetReference(const K& key) { | 280 PersistentValueReference GetReference(const K& key) { |
263 return PersistentValueReference(Traits::Get(&impl_, key)); | 281 return PersistentValueReference(Traits::Get(&impl_, key)); |
264 } | 282 } |
265 | 283 |
| 284 protected: |
| 285 explicit PersistentValueMapBase(Isolate* isolate) : isolate_(isolate) {} |
| 286 |
| 287 ~PersistentValueMapBase() { Clear(); } |
| 288 |
| 289 Isolate* isolate() { return isolate_; } |
| 290 typename Traits::Impl* impl() { return &impl_; } |
| 291 |
| 292 static V* FromVal(PersistentContainerValue v) { |
| 293 return reinterpret_cast<V*>(v); |
| 294 } |
| 295 |
| 296 static PersistentContainerValue ClearAndLeak( |
| 297 UniquePersistent<V>* persistent) { |
| 298 V* v = persistent->val_; |
| 299 persistent->val_ = 0; |
| 300 return reinterpret_cast<PersistentContainerValue>(v); |
| 301 } |
| 302 |
| 303 static PersistentContainerValue Leak(UniquePersistent<V>* persistent) { |
| 304 return reinterpret_cast<PersistentContainerValue>(persistent->val_); |
| 305 } |
| 306 |
266 /** | 307 /** |
267 * Put a value into the map and update the reference. | 308 * Return a container value as UniquePersistent and make sure the weak |
268 * Restrictions of GetReference apply here as well. | 309 * callback is properly disposed of. All remove functionality should go |
| 310 * through this. |
269 */ | 311 */ |
270 UniquePersistent<V> Set(const K& key, UniquePersistent<V> value, | 312 static UniquePersistent<V> Release(PersistentContainerValue v) { |
271 PersistentValueReference* reference) { | 313 UniquePersistent<V> p; |
272 *reference = Leak(&value); | 314 p.val_ = FromVal(v); |
| 315 if (Traits::kCallbackType != kNotWeak && p.IsWeak()) { |
| 316 Traits::DisposeCallbackData( |
| 317 p.template ClearWeak<typename Traits::WeakCallbackDataType>()); |
| 318 } |
| 319 return p.Pass(); |
| 320 } |
| 321 |
| 322 private: |
| 323 PersistentValueMapBase(PersistentValueMapBase&); |
| 324 void operator=(PersistentValueMapBase&); |
| 325 |
| 326 static bool SetReturnValueFromVal(ReturnValue<Value>* returnValue, |
| 327 PersistentContainerValue value) { |
| 328 bool hasValue = value != kPersistentContainerNotFound; |
| 329 if (hasValue) { |
| 330 returnValue->SetInternal( |
| 331 *reinterpret_cast<internal::Object**>(FromVal(value))); |
| 332 } |
| 333 return hasValue; |
| 334 } |
| 335 |
| 336 Isolate* isolate_; |
| 337 typename Traits::Impl impl_; |
| 338 }; |
| 339 |
| 340 |
| 341 template <typename K, typename V, typename Traits> |
| 342 class PersistentValueMap : public PersistentValueMapBase<K, V, Traits> { |
| 343 public: |
| 344 explicit PersistentValueMap(Isolate* isolate) |
| 345 : PersistentValueMapBase<K, V, Traits>(isolate) {} |
| 346 |
| 347 typedef |
| 348 typename PersistentValueMapBase<K, V, Traits>::PersistentValueReference |
| 349 PersistentValueReference; |
| 350 |
| 351 /** |
| 352 * Put value into map. Depending on Traits::kIsWeak, the value will be held |
| 353 * by the map strongly or weakly. |
| 354 * Returns old value as UniquePersistent. |
| 355 */ |
| 356 UniquePersistent<V> Set(const K& key, Local<V> value) { |
| 357 UniquePersistent<V> persistent(this->isolate(), value); |
| 358 return SetUnique(key, &persistent); |
| 359 } |
| 360 |
| 361 /** |
| 362 * Put value into map, like Set(const K&, Local<V>). |
| 363 */ |
| 364 UniquePersistent<V> Set(const K& key, UniquePersistent<V> value) { |
273 return SetUnique(key, &value); | 365 return SetUnique(key, &value); |
274 } | 366 } |
275 | 367 |
276 private: | |
277 PersistentValueMap(PersistentValueMap&); | |
278 void operator=(PersistentValueMap&); | |
279 | |
280 /** | 368 /** |
281 * Put the value into the map, and set the 'weak' callback when demanded | 369 * Put the value into the map, and set the 'weak' callback when demanded |
282 * by the Traits class. | 370 * by the Traits class. |
283 */ | 371 */ |
284 UniquePersistent<V> SetUnique(const K& key, UniquePersistent<V>* persistent) { | 372 UniquePersistent<V> SetUnique(const K& key, UniquePersistent<V>* persistent) { |
285 if (Traits::kCallbackType != kNotWeak) { | 373 if (Traits::kCallbackType != kNotWeak) { |
286 Local<V> value(Local<V>::New(isolate_, *persistent)); | 374 Local<V> value(Local<V>::New(this->isolate(), *persistent)); |
287 persistent->template SetWeak<typename Traits::WeakCallbackDataType>( | 375 persistent->template SetWeak<typename Traits::WeakCallbackDataType>( |
288 Traits::WeakCallbackParameter(this, key, value), WeakCallback); | 376 Traits::WeakCallbackParameter(this, key, value), WeakCallback); |
289 } | 377 } |
290 PersistentContainerValue old_value = | 378 PersistentContainerValue old_value = |
291 Traits::Set(&impl_, key, ClearAndLeak(persistent)); | 379 Traits::Set(this->impl(), key, this->ClearAndLeak(persistent)); |
292 return Release(old_value).Pass(); | 380 return this->Release(old_value).Pass(); |
293 } | 381 } |
294 | 382 |
| 383 /** |
| 384 * Put a value into the map and update the reference. |
| 385 * Restrictions of GetReference apply here as well. |
| 386 */ |
| 387 UniquePersistent<V> Set(const K& key, UniquePersistent<V> value, |
| 388 PersistentValueReference* reference) { |
| 389 *reference = this->Leak(&value); |
| 390 return SetUnique(key, &value); |
| 391 } |
| 392 |
| 393 private: |
295 static void WeakCallback( | 394 static void WeakCallback( |
296 const WeakCallbackData<V, typename Traits::WeakCallbackDataType>& data) { | 395 const WeakCallbackData<V, typename Traits::WeakCallbackDataType>& data) { |
297 if (Traits::kCallbackType != kNotWeak) { | 396 if (Traits::kCallbackType != kNotWeak) { |
298 PersistentValueMap<K, V, Traits>* persistentValueMap = | 397 PersistentValueMap<K, V, Traits>* persistentValueMap = |
299 Traits::MapFromWeakCallbackData(data); | 398 Traits::MapFromWeakCallbackData(data); |
300 K key = Traits::KeyFromWeakCallbackData(data); | 399 K key = Traits::KeyFromWeakCallbackData(data); |
301 Traits::Dispose(data.GetIsolate(), | 400 Traits::Dispose(data.GetIsolate(), |
302 persistentValueMap->Remove(key).Pass(), key); | 401 persistentValueMap->Remove(key).Pass(), key); |
303 Traits::DisposeCallbackData(data.GetParameter()); | 402 Traits::DisposeCallbackData(data.GetParameter()); |
304 } | 403 } |
305 } | 404 } |
| 405 }; |
306 | 406 |
307 static V* FromVal(PersistentContainerValue v) { | |
308 return reinterpret_cast<V*>(v); | |
309 } | |
310 | 407 |
311 static bool SetReturnValueFromVal( | 408 template <typename K, typename V, typename Traits> |
312 ReturnValue<Value>* returnValue, PersistentContainerValue value) { | 409 class PhantomPersistentValueMap : public PersistentValueMapBase<K, V, Traits> { |
313 bool hasValue = value != kPersistentContainerNotFound; | 410 public: |
314 if (hasValue) { | 411 explicit PhantomPersistentValueMap(Isolate* isolate) |
315 returnValue->SetInternal( | 412 : PersistentValueMapBase<K, V, Traits>(isolate) {} |
316 *reinterpret_cast<internal::Object**>(FromVal(value))); | |
317 } | |
318 return hasValue; | |
319 } | |
320 | 413 |
321 static PersistentContainerValue ClearAndLeak( | 414 typedef |
322 UniquePersistent<V>* persistent) { | 415 typename PersistentValueMapBase<K, V, Traits>::PersistentValueReference |
323 V* v = persistent->val_; | 416 PersistentValueReference; |
324 persistent->val_ = 0; | |
325 return reinterpret_cast<PersistentContainerValue>(v); | |
326 } | |
327 | 417 |
328 static PersistentContainerValue Leak( | 418 /** |
329 UniquePersistent<V>* persistent) { | 419 * Put value into map. Depending on Traits::kIsWeak, the value will be held |
330 return reinterpret_cast<PersistentContainerValue>(persistent->val_); | 420 * by the map strongly or weakly. |
| 421 * Returns old value as UniquePersistent. |
| 422 */ |
| 423 UniquePersistent<V> Set(const K& key, Local<V> value) { |
| 424 UniquePersistent<V> persistent(this->isolate(), value); |
| 425 return SetUnique(key, &persistent); |
331 } | 426 } |
332 | 427 |
333 /** | 428 /** |
334 * Return a container value as UniquePersistent and make sure the weak | 429 * Put value into map, like Set(const K&, Local<V>). |
335 * callback is properly disposed of. All remove functionality should go | |
336 * through this. | |
337 */ | 430 */ |
338 static UniquePersistent<V> Release(PersistentContainerValue v) { | 431 UniquePersistent<V> Set(const K& key, UniquePersistent<V> value) { |
339 UniquePersistent<V> p; | 432 return SetUnique(key, &value); |
340 p.val_ = FromVal(v); | |
341 if (Traits::kCallbackType != kNotWeak && p.IsWeak()) { | |
342 Traits::DisposeCallbackData( | |
343 p.template ClearWeak<typename Traits::WeakCallbackDataType>()); | |
344 } | |
345 return p.Pass(); | |
346 } | 433 } |
347 | 434 |
348 Isolate* isolate_; | 435 /** |
349 typename Traits::Impl impl_; | 436 * Put the value into the map, and set the 'weak' callback when demanded |
| 437 * by the Traits class. |
| 438 */ |
| 439 UniquePersistent<V> SetUnique(const K& key, UniquePersistent<V>* persistent) { |
| 440 if (Traits::kCallbackType != kNotWeak) { |
| 441 Local<V> value(Local<V>::New(this->isolate(), *persistent)); |
| 442 persistent->template SetPhantom<typename Traits::WeakCallbackDataType>( |
| 443 Traits::WeakCallbackParameter(this, key, value), WeakCallback, 0, 1); |
| 444 } |
| 445 PersistentContainerValue old_value = |
| 446 Traits::Set(this->impl(), key, this->ClearAndLeak(persistent)); |
| 447 return this->Release(old_value).Pass(); |
| 448 } |
| 449 |
| 450 /** |
| 451 * Put a value into the map and update the reference. |
| 452 * Restrictions of GetReference apply here as well. |
| 453 */ |
| 454 UniquePersistent<V> Set(const K& key, UniquePersistent<V> value, |
| 455 PersistentValueReference* reference) { |
| 456 *reference = this->Leak(&value); |
| 457 return SetUnique(key, &value); |
| 458 } |
| 459 |
| 460 private: |
| 461 static void WeakCallback( |
| 462 const PhantomCallbackData<typename Traits::WeakCallbackDataType>& data) { |
| 463 if (Traits::kCallbackType != kNotWeak) { |
| 464 PhantomPersistentValueMap<K, V, Traits>* persistentValueMap = |
| 465 Traits::MapFromPhantomCallbackData(data); |
| 466 K key = Traits::KeyFromPhantomCallbackData(data); |
| 467 Traits::Dispose(data.GetIsolate(), persistentValueMap->Remove(key).Pass(), |
| 468 key); |
| 469 Traits::DisposeCallbackData(data.GetParameter()); |
| 470 } |
| 471 } |
350 }; | 472 }; |
351 | 473 |
352 | 474 |
353 /** | 475 /** |
354 * A map that uses UniquePersistent as value and std::map as the backing | 476 * A map that uses UniquePersistent as value and std::map as the backing |
355 * implementation. Persistents are held non-weak. | 477 * implementation. Persistents are held non-weak. |
356 * | 478 * |
357 * C++11 embedders don't need this class, as they can use | 479 * C++11 embedders don't need this class, as they can use |
358 * UniquePersistent directly in std containers. | 480 * UniquePersistent directly in std containers. |
359 */ | 481 */ |
(...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
478 return reinterpret_cast<V*>(v); | 600 return reinterpret_cast<V*>(v); |
479 } | 601 } |
480 | 602 |
481 Isolate* isolate_; | 603 Isolate* isolate_; |
482 typename Traits::Impl impl_; | 604 typename Traits::Impl impl_; |
483 }; | 605 }; |
484 | 606 |
485 } // namespace v8 | 607 } // namespace v8 |
486 | 608 |
487 #endif // V8_UTIL_H_ | 609 #endif // V8_UTIL_H_ |
OLD | NEW |