OLD | NEW |
1 /* | 1 /* |
2 * Copyright (C) 2014 Google Inc. All rights reserved. | 2 * Copyright (C) 2014 Google Inc. All rights reserved. |
3 * | 3 * |
4 * Redistribution and use in source and binary forms, with or without | 4 * Redistribution and use in source and binary forms, with or without |
5 * modification, are permitted provided that the following conditions are | 5 * modification, are permitted provided that the following conditions are |
6 * met: | 6 * met: |
7 * | 7 * |
8 * * Redistributions of source code must retain the above copyright | 8 * * Redistributions of source code must retain the above copyright |
9 * notice, this list of conditions and the following disclaimer. | 9 * notice, this list of conditions and the following disclaimer. |
10 * * Redistributions in binary form must reproduce the above | 10 * * Redistributions in binary form must reproduce the above |
(...skipping 16 matching lines...) Expand all Loading... |
27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | 27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
29 */ | 29 */ |
30 | 30 |
31 #ifndef Handle_h | 31 #ifndef Handle_h |
32 #define Handle_h | 32 #define Handle_h |
33 | 33 |
34 #include "platform/heap/Heap.h" | 34 #include "platform/heap/Heap.h" |
35 #include "platform/heap/HeapAllocator.h" | 35 #include "platform/heap/HeapAllocator.h" |
36 #include "platform/heap/InlinedGlobalMarkingVisitor.h" | 36 #include "platform/heap/InlinedGlobalMarkingVisitor.h" |
37 #include "platform/heap/PersistentNode.h" | 37 #include "platform/heap/Persistent.h" |
| 38 #include "platform/heap/Member.h" |
38 #include "platform/heap/ThreadState.h" | 39 #include "platform/heap/ThreadState.h" |
39 #include "platform/heap/TraceTraits.h" | 40 #include "platform/heap/TraceTraits.h" |
40 #include "platform/heap/Visitor.h" | 41 #include "platform/heap/Visitor.h" |
41 #include "wtf/Allocator.h" | 42 #include "wtf/Allocator.h" |
42 #include "wtf/Atomics.h" | |
43 #include "wtf/HashFunctions.h" | |
44 #include "wtf/TypeTraits.h" | |
45 | 43 |
46 #if defined(LEAK_SANITIZER) | 44 #if defined(LEAK_SANITIZER) |
47 #include "wtf/LeakAnnotations.h" | 45 #include "wtf/LeakAnnotations.h" |
48 #endif | 46 #endif |
49 | 47 |
50 namespace blink { | 48 namespace blink { |
51 | 49 |
52 // Marker used to annotate persistent objects and collections with, | |
53 // so as to enable reliable testing for persistent references via | |
54 // a type trait (see TypeTraits.h's IsPersistentReferenceType<>.) | |
55 #define IS_PERSISTENT_REFERENCE_TYPE() \ | |
56 public: \ | |
57 using IsPersistentReferenceTypeMarker = int; \ | |
58 private: | |
59 | |
60 enum WeaknessPersistentConfiguration { | |
61 NonWeakPersistentConfiguration, | |
62 WeakPersistentConfiguration | |
63 }; | |
64 | |
65 enum CrossThreadnessPersistentConfiguration { | |
66 SingleThreadPersistentConfiguration, | |
67 CrossThreadPersistentConfiguration | |
68 }; | |
69 | |
70 template<typename T, WeaknessPersistentConfiguration weaknessConfiguration, Cros
sThreadnessPersistentConfiguration crossThreadnessConfiguration> | |
71 class PersistentBase { | |
72 USING_FAST_MALLOC(PersistentBase); | |
73 IS_PERSISTENT_REFERENCE_TYPE(); | |
74 public: | |
75 PersistentBase() : m_raw(nullptr) | |
76 { | |
77 initialize(); | |
78 } | |
79 | |
80 PersistentBase(std::nullptr_t) : m_raw(nullptr) | |
81 { | |
82 initialize(); | |
83 } | |
84 | |
85 PersistentBase(T* raw) : m_raw(raw) | |
86 { | |
87 initialize(); | |
88 checkPointer(); | |
89 } | |
90 | |
91 PersistentBase(T& raw) : m_raw(&raw) | |
92 { | |
93 initialize(); | |
94 checkPointer(); | |
95 } | |
96 | |
97 PersistentBase(const PersistentBase& other) : m_raw(other) | |
98 { | |
99 initialize(); | |
100 checkPointer(); | |
101 } | |
102 | |
103 template<typename U> | |
104 PersistentBase(const PersistentBase<U, weaknessConfiguration, crossThreadnes
sConfiguration>& other) : m_raw(other) | |
105 { | |
106 initialize(); | |
107 checkPointer(); | |
108 } | |
109 | |
110 template<typename U> | |
111 PersistentBase(const Member<U>& other) : m_raw(other) | |
112 { | |
113 initialize(); | |
114 checkPointer(); | |
115 } | |
116 | |
117 ~PersistentBase() | |
118 { | |
119 uninitialize(); | |
120 m_raw = nullptr; | |
121 } | |
122 | |
123 template<typename VisitorDispatcher> | |
124 void trace(VisitorDispatcher visitor) | |
125 { | |
126 static_assert(sizeof(T), "T must be fully defined"); | |
127 static_assert(IsGarbageCollectedType<T>::value, "T needs to be a garbage
collected object"); | |
128 if (weaknessConfiguration == WeakPersistentConfiguration) { | |
129 visitor->registerWeakCell(&m_raw); | |
130 } else { | |
131 visitor->mark(m_raw); | |
132 } | |
133 } | |
134 | |
135 T* release() | |
136 { | |
137 T* result = m_raw; | |
138 assign(nullptr); | |
139 return result; | |
140 } | |
141 | |
142 void clear() { assign(nullptr); } | |
143 T& operator*() const { return *m_raw; } | |
144 explicit operator bool() const { return m_raw; } | |
145 operator T*() const { return m_raw; } | |
146 T* operator->() const { return *this; } | |
147 T* get() const { return m_raw; } | |
148 | |
149 template<typename U> | |
150 PersistentBase& operator=(U* other) | |
151 { | |
152 assign(other); | |
153 return *this; | |
154 } | |
155 | |
156 PersistentBase& operator=(std::nullptr_t) | |
157 { | |
158 assign(nullptr); | |
159 return *this; | |
160 } | |
161 | |
162 PersistentBase& operator=(const PersistentBase& other) | |
163 { | |
164 assign(other); | |
165 return *this; | |
166 } | |
167 | |
168 template<typename U> | |
169 PersistentBase& operator=(const PersistentBase<U, weaknessConfiguration, cro
ssThreadnessConfiguration>& other) | |
170 { | |
171 assign(other); | |
172 return *this; | |
173 } | |
174 | |
175 template<typename U> | |
176 PersistentBase& operator=(const Member<U>& other) | |
177 { | |
178 assign(other); | |
179 return *this; | |
180 } | |
181 | |
182 // Register the persistent node as a 'static reference', | |
183 // belonging to the current thread and a persistent that must | |
184 // be cleared when the ThreadState itself is cleared out and | |
185 // destructed. | |
186 // | |
187 // Static singletons arrange for this to happen, either to ensure | |
188 // clean LSan leak reports or to register a thread-local persistent | |
189 // needing to be cleared out before the thread is terminated. | |
190 PersistentBase* registerAsStaticReference() | |
191 { | |
192 if (m_persistentNode) { | |
193 ASSERT(ThreadState::current()); | |
194 ThreadState::current()->registerStaticPersistentNode(m_persistentNod
e, nullptr); | |
195 LEAK_SANITIZER_IGNORE_OBJECT(this); | |
196 } | |
197 return this; | |
198 } | |
199 | |
200 protected: | |
201 T* atomicGet() { return reinterpret_cast<T*>(acquireLoad(reinterpret_cast<vo
id* volatile*>(&m_raw))); } | |
202 | |
203 private: | |
204 NO_LAZY_SWEEP_SANITIZE_ADDRESS | |
205 void assign(T* ptr) | |
206 { | |
207 if (crossThreadnessConfiguration == CrossThreadPersistentConfiguration) | |
208 releaseStore(reinterpret_cast<void* volatile*>(&m_raw), ptr); | |
209 else | |
210 m_raw = ptr; | |
211 checkPointer(); | |
212 if (m_raw) { | |
213 if (!m_persistentNode) | |
214 initialize(); | |
215 return; | |
216 } | |
217 uninitialize(); | |
218 } | |
219 | |
220 NO_LAZY_SWEEP_SANITIZE_ADDRESS | |
221 void initialize() | |
222 { | |
223 ASSERT(!m_persistentNode); | |
224 if (!m_raw) | |
225 return; | |
226 | |
227 TraceCallback traceCallback = TraceMethodDelegate<PersistentBase<T, weak
nessConfiguration, crossThreadnessConfiguration>, &PersistentBase<T, weaknessCon
figuration, crossThreadnessConfiguration>::trace>::trampoline; | |
228 if (crossThreadnessConfiguration == CrossThreadPersistentConfiguration)
{ | |
229 ProcessHeap::crossThreadPersistentRegion().allocatePersistentNode(m_
persistentNode, this, traceCallback); | |
230 return; | |
231 } | |
232 ThreadState* state = ThreadStateFor<ThreadingTrait<T>::Affinity>::state(
); | |
233 ASSERT(state->checkThread()); | |
234 m_persistentNode = state->getPersistentRegion()->allocatePersistentNode(
this, traceCallback); | |
235 #if ENABLE(ASSERT) | |
236 m_state = state; | |
237 #endif | |
238 } | |
239 | |
240 void uninitialize() | |
241 { | |
242 if (crossThreadnessConfiguration == CrossThreadPersistentConfiguration)
{ | |
243 if (acquireLoad(reinterpret_cast<void* volatile*>(&m_persistentNode)
)) | |
244 ProcessHeap::crossThreadPersistentRegion().freePersistentNode(m_
persistentNode); | |
245 return; | |
246 } | |
247 | |
248 if (!m_persistentNode) | |
249 return; | |
250 ThreadState* state = ThreadStateFor<ThreadingTrait<T>::Affinity>::state(
); | |
251 ASSERT(state->checkThread()); | |
252 // Persistent handle must be created and destructed in the same thread. | |
253 ASSERT(m_state == state); | |
254 state->freePersistentNode(m_persistentNode); | |
255 m_persistentNode = nullptr; | |
256 } | |
257 | |
258 void checkPointer() | |
259 { | |
260 #if ENABLE(ASSERT) && defined(ADDRESS_SANITIZER) | |
261 if (!m_raw) | |
262 return; | |
263 | |
264 // ThreadHeap::isHeapObjectAlive(m_raw) checks that m_raw is a traceable | |
265 // object. In other words, it checks that the pointer is either of: | |
266 // | |
267 // (a) a pointer to the head of an on-heap object. | |
268 // (b) a pointer to the head of an on-heap mixin object. | |
269 // | |
270 // Otherwise, ThreadHeap::isHeapObjectAlive will crash when it calls | |
271 // header->checkHeader(). | |
272 ThreadHeap::isHeapObjectAlive(m_raw); | |
273 #endif | |
274 } | |
275 | |
276 // m_raw is accessed most, so put it at the first field. | |
277 T* m_raw; | |
278 PersistentNode* m_persistentNode = nullptr; | |
279 #if ENABLE(ASSERT) | |
280 ThreadState* m_state = nullptr; | |
281 #endif | |
282 }; | |
283 | |
284 // Persistent is a way to create a strong pointer from an off-heap object | |
285 // to another on-heap object. As long as the Persistent handle is alive | |
286 // the GC will keep the object pointed to alive. The Persistent handle is | |
287 // always a GC root from the point of view of the GC. | |
288 // | |
289 // We have to construct and destruct Persistent in the same thread. | |
290 template<typename T> | |
291 class Persistent : public PersistentBase<T, NonWeakPersistentConfiguration, Sing
leThreadPersistentConfiguration> { | |
292 typedef PersistentBase<T, NonWeakPersistentConfiguration, SingleThreadPersis
tentConfiguration> Parent; | |
293 public: | |
294 Persistent() : Parent() { } | |
295 Persistent(std::nullptr_t) : Parent(nullptr) { } | |
296 Persistent(T* raw) : Parent(raw) { } | |
297 Persistent(T& raw) : Parent(raw) { } | |
298 Persistent(const Persistent& other) : Parent(other) { } | |
299 template<typename U> | |
300 Persistent(const Persistent<U>& other) : Parent(other) { } | |
301 template<typename U> | |
302 Persistent(const Member<U>& other) : Parent(other) { } | |
303 | |
304 template<typename U> | |
305 Persistent& operator=(U* other) | |
306 { | |
307 Parent::operator=(other); | |
308 return *this; | |
309 } | |
310 | |
311 Persistent& operator=(std::nullptr_t) | |
312 { | |
313 Parent::operator=(nullptr); | |
314 return *this; | |
315 } | |
316 | |
317 Persistent& operator=(const Persistent& other) | |
318 { | |
319 Parent::operator=(other); | |
320 return *this; | |
321 } | |
322 | |
323 template<typename U> | |
324 Persistent& operator=(const Persistent<U>& other) | |
325 { | |
326 Parent::operator=(other); | |
327 return *this; | |
328 } | |
329 | |
330 template<typename U> | |
331 Persistent& operator=(const Member<U>& other) | |
332 { | |
333 Parent::operator=(other); | |
334 return *this; | |
335 } | |
336 }; | |
337 | |
338 // WeakPersistent is a way to create a weak pointer from an off-heap object | |
339 // to an on-heap object. The m_raw is automatically cleared when the pointee | |
340 // gets collected. | |
341 // | |
342 // We have to construct and destruct WeakPersistent in the same thread. | |
343 // | |
344 // Note that collections of WeakPersistents are not supported. Use a persistent | |
345 // collection of WeakMembers instead. | |
346 // | |
347 // HashSet<WeakPersistent<T>> m_set; // wrong | |
348 // PersistentHeapHashSet<WeakMember<T>> m_set; // correct | |
349 template<typename T> | |
350 class WeakPersistent : public PersistentBase<T, WeakPersistentConfiguration, Sin
gleThreadPersistentConfiguration> { | |
351 typedef PersistentBase<T, WeakPersistentConfiguration, SingleThreadPersisten
tConfiguration> Parent; | |
352 public: | |
353 WeakPersistent() : Parent() { } | |
354 WeakPersistent(std::nullptr_t) : Parent(nullptr) { } | |
355 WeakPersistent(T* raw) : Parent(raw) { } | |
356 WeakPersistent(T& raw) : Parent(raw) { } | |
357 WeakPersistent(const WeakPersistent& other) : Parent(other) { } | |
358 template<typename U> | |
359 WeakPersistent(const WeakPersistent<U>& other) : Parent(other) { } | |
360 template<typename U> | |
361 WeakPersistent(const Member<U>& other) : Parent(other) { } | |
362 | |
363 template<typename U> | |
364 WeakPersistent& operator=(U* other) | |
365 { | |
366 Parent::operator=(other); | |
367 return *this; | |
368 } | |
369 | |
370 WeakPersistent& operator=(std::nullptr_t) | |
371 { | |
372 Parent::operator=(nullptr); | |
373 return *this; | |
374 } | |
375 | |
376 WeakPersistent& operator=(const WeakPersistent& other) | |
377 { | |
378 Parent::operator=(other); | |
379 return *this; | |
380 } | |
381 | |
382 template<typename U> | |
383 WeakPersistent& operator=(const WeakPersistent<U>& other) | |
384 { | |
385 Parent::operator=(other); | |
386 return *this; | |
387 } | |
388 | |
389 template<typename U> | |
390 WeakPersistent& operator=(const Member<U>& other) | |
391 { | |
392 Parent::operator=(other); | |
393 return *this; | |
394 } | |
395 }; | |
396 | |
397 // Unlike Persistent, we can destruct a CrossThreadPersistent in a thread | |
398 // different from the construction thread. | |
399 template<typename T> | |
400 class CrossThreadPersistent : public PersistentBase<T, NonWeakPersistentConfigur
ation, CrossThreadPersistentConfiguration> { | |
401 typedef PersistentBase<T, NonWeakPersistentConfiguration, CrossThreadPersist
entConfiguration> Parent; | |
402 public: | |
403 CrossThreadPersistent() : Parent() { } | |
404 CrossThreadPersistent(std::nullptr_t) : Parent(nullptr) { } | |
405 CrossThreadPersistent(T* raw) : Parent(raw) { } | |
406 CrossThreadPersistent(T& raw) : Parent(raw) { } | |
407 CrossThreadPersistent(const CrossThreadPersistent& other) : Parent(other) {
} | |
408 template<typename U> | |
409 CrossThreadPersistent(const CrossThreadPersistent<U>& other) : Parent(other)
{ } | |
410 template<typename U> | |
411 CrossThreadPersistent(const Member<U>& other) : Parent(other) { } | |
412 | |
413 T* atomicGet() { return Parent::atomicGet(); } | |
414 | |
415 template<typename U> | |
416 CrossThreadPersistent& operator=(U* other) | |
417 { | |
418 Parent::operator=(other); | |
419 return *this; | |
420 } | |
421 | |
422 CrossThreadPersistent& operator=(std::nullptr_t) | |
423 { | |
424 Parent::operator=(nullptr); | |
425 return *this; | |
426 } | |
427 | |
428 CrossThreadPersistent& operator=(const CrossThreadPersistent& other) | |
429 { | |
430 Parent::operator=(other); | |
431 return *this; | |
432 } | |
433 | |
434 template<typename U> | |
435 CrossThreadPersistent& operator=(const CrossThreadPersistent<U>& other) | |
436 { | |
437 Parent::operator=(other); | |
438 return *this; | |
439 } | |
440 | |
441 template<typename U> | |
442 CrossThreadPersistent& operator=(const Member<U>& other) | |
443 { | |
444 Parent::operator=(other); | |
445 return *this; | |
446 } | |
447 }; | |
448 | |
449 // Combines the behavior of CrossThreadPersistent and WeakPersistent. | |
450 template<typename T> | |
451 class CrossThreadWeakPersistent : public PersistentBase<T, WeakPersistentConfigu
ration, CrossThreadPersistentConfiguration> { | |
452 typedef PersistentBase<T, WeakPersistentConfiguration, CrossThreadPersistent
Configuration> Parent; | |
453 public: | |
454 CrossThreadWeakPersistent() : Parent() { } | |
455 CrossThreadWeakPersistent(std::nullptr_t) : Parent(nullptr) { } | |
456 CrossThreadWeakPersistent(T* raw) : Parent(raw) { } | |
457 CrossThreadWeakPersistent(T& raw) : Parent(raw) { } | |
458 CrossThreadWeakPersistent(const CrossThreadWeakPersistent& other) : Parent(o
ther) { } | |
459 template<typename U> | |
460 CrossThreadWeakPersistent(const CrossThreadWeakPersistent<U>& other) : Paren
t(other) { } | |
461 template<typename U> | |
462 CrossThreadWeakPersistent(const Member<U>& other) : Parent(other) { } | |
463 | |
464 template<typename U> | |
465 CrossThreadWeakPersistent& operator=(U* other) | |
466 { | |
467 Parent::operator=(other); | |
468 return *this; | |
469 } | |
470 | |
471 CrossThreadWeakPersistent& operator=(std::nullptr_t) | |
472 { | |
473 Parent::operator=(nullptr); | |
474 return *this; | |
475 } | |
476 | |
477 CrossThreadWeakPersistent& operator=(const CrossThreadWeakPersistent& other) | |
478 { | |
479 Parent::operator=(other); | |
480 return *this; | |
481 } | |
482 | |
483 template<typename U> | |
484 CrossThreadWeakPersistent& operator=(const CrossThreadWeakPersistent<U>& oth
er) | |
485 { | |
486 Parent::operator=(other); | |
487 return *this; | |
488 } | |
489 | |
490 template<typename U> | |
491 CrossThreadWeakPersistent& operator=(const Member<U>& other) | |
492 { | |
493 Parent::operator=(other); | |
494 return *this; | |
495 } | |
496 }; | |
497 | |
498 template<typename Collection> | |
499 class PersistentHeapCollectionBase : public Collection { | |
500 // We overload the various new and delete operators with using the WTF Parti
tionAllocator to ensure persistent | |
501 // heap collections are always allocated off-heap. This allows persistent co
llections to be used in | |
502 // DEFINE_STATIC_LOCAL et. al. | |
503 WTF_USE_ALLOCATOR(PersistentHeapCollectionBase, WTF::PartitionAllocator); | |
504 IS_PERSISTENT_REFERENCE_TYPE(); | |
505 public: | |
506 PersistentHeapCollectionBase() | |
507 { | |
508 initialize(); | |
509 } | |
510 | |
511 PersistentHeapCollectionBase(const PersistentHeapCollectionBase& other) : Co
llection(other) | |
512 { | |
513 initialize(); | |
514 } | |
515 | |
516 template<typename OtherCollection> | |
517 PersistentHeapCollectionBase(const OtherCollection& other) : Collection(othe
r) | |
518 { | |
519 initialize(); | |
520 } | |
521 | |
522 ~PersistentHeapCollectionBase() | |
523 { | |
524 uninitialize(); | |
525 } | |
526 | |
527 template<typename VisitorDispatcher> | |
528 void trace(VisitorDispatcher visitor) | |
529 { | |
530 static_assert(sizeof(Collection), "Collection must be fully defined"); | |
531 visitor->trace(*static_cast<Collection*>(this)); | |
532 } | |
533 | |
534 // See PersistentBase::registerAsStaticReference() comment. | |
535 PersistentHeapCollectionBase* registerAsStaticReference() | |
536 { | |
537 if (m_persistentNode) { | |
538 ASSERT(ThreadState::current()); | |
539 ThreadState::current()->registerStaticPersistentNode(m_persistentNod
e, &PersistentHeapCollectionBase<Collection>::clearPersistentNode); | |
540 LEAK_SANITIZER_IGNORE_OBJECT(this); | |
541 } | |
542 return this; | |
543 } | |
544 | |
545 private: | |
546 | |
547 // Used when the registered PersistentNode of this object is | |
548 // released during ThreadState shutdown, clearing the association. | |
549 static void clearPersistentNode(void *self) | |
550 { | |
551 PersistentHeapCollectionBase<Collection>* collection = (reinterpret_cast
<PersistentHeapCollectionBase<Collection>*>(self)); | |
552 collection->uninitialize(); | |
553 collection->clear(); | |
554 } | |
555 | |
556 NO_LAZY_SWEEP_SANITIZE_ADDRESS | |
557 void initialize() | |
558 { | |
559 // FIXME: Derive affinity based on the collection. | |
560 ThreadState* state = ThreadState::current(); | |
561 ASSERT(state->checkThread()); | |
562 m_persistentNode = state->getPersistentRegion()->allocatePersistentNode(
this, TraceMethodDelegate<PersistentHeapCollectionBase<Collection>, &PersistentH
eapCollectionBase<Collection>::trace>::trampoline); | |
563 #if ENABLE(ASSERT) | |
564 m_state = state; | |
565 #endif | |
566 } | |
567 | |
568 void uninitialize() | |
569 { | |
570 if (!m_persistentNode) | |
571 return; | |
572 ThreadState* state = ThreadState::current(); | |
573 ASSERT(state->checkThread()); | |
574 // Persistent handle must be created and destructed in the same thread. | |
575 ASSERT(m_state == state); | |
576 state->freePersistentNode(m_persistentNode); | |
577 m_persistentNode = nullptr; | |
578 } | |
579 | |
580 PersistentNode* m_persistentNode; | |
581 #if ENABLE(ASSERT) | |
582 ThreadState* m_state; | |
583 #endif | |
584 }; | |
585 | |
586 template< | |
587 typename KeyArg, | |
588 typename MappedArg, | |
589 typename HashArg = typename DefaultHash<KeyArg>::Hash, | |
590 typename KeyTraitsArg = HashTraits<KeyArg>, | |
591 typename MappedTraitsArg = HashTraits<MappedArg>> | |
592 class PersistentHeapHashMap : public PersistentHeapCollectionBase<HeapHashMap<Ke
yArg, MappedArg, HashArg, KeyTraitsArg, MappedTraitsArg>> { }; | |
593 | |
594 template< | |
595 typename ValueArg, | |
596 typename HashArg = typename DefaultHash<ValueArg>::Hash, | |
597 typename TraitsArg = HashTraits<ValueArg>> | |
598 class PersistentHeapHashSet : public PersistentHeapCollectionBase<HeapHashSet<Va
lueArg, HashArg, TraitsArg>> { }; | |
599 | |
600 template< | |
601 typename ValueArg, | |
602 typename HashArg = typename DefaultHash<ValueArg>::Hash, | |
603 typename TraitsArg = HashTraits<ValueArg>> | |
604 class PersistentHeapLinkedHashSet : public PersistentHeapCollectionBase<HeapLink
edHashSet<ValueArg, HashArg, TraitsArg>> { }; | |
605 | |
606 template< | |
607 typename ValueArg, | |
608 size_t inlineCapacity = 0, | |
609 typename HashArg = typename DefaultHash<ValueArg>::Hash> | |
610 class PersistentHeapListHashSet : public PersistentHeapCollectionBase<HeapListHa
shSet<ValueArg, inlineCapacity, HashArg>> { }; | |
611 | |
612 template< | |
613 typename ValueArg, | |
614 typename HashFunctions = typename DefaultHash<ValueArg>::Hash, | |
615 typename Traits = HashTraits<ValueArg>> | |
616 class PersistentHeapHashCountedSet : public PersistentHeapCollectionBase<HeapHas
hCountedSet<ValueArg, HashFunctions, Traits>> { }; | |
617 | |
618 template<typename T, size_t inlineCapacity = 0> | |
619 class PersistentHeapVector : public PersistentHeapCollectionBase<HeapVector<T, i
nlineCapacity>> { | |
620 public: | |
621 PersistentHeapVector() | |
622 { | |
623 initializeUnusedSlots(); | |
624 } | |
625 | |
626 explicit PersistentHeapVector(size_t size) | |
627 : PersistentHeapCollectionBase<HeapVector<T, inlineCapacity>>(size) | |
628 { | |
629 initializeUnusedSlots(); | |
630 } | |
631 | |
632 PersistentHeapVector(const PersistentHeapVector& other) | |
633 : PersistentHeapCollectionBase<HeapVector<T, inlineCapacity>>(other) | |
634 { | |
635 initializeUnusedSlots(); | |
636 } | |
637 | |
638 template<size_t otherCapacity> | |
639 PersistentHeapVector(const HeapVector<T, otherCapacity>& other) | |
640 : PersistentHeapCollectionBase<HeapVector<T, inlineCapacity>>(other) | |
641 { | |
642 initializeUnusedSlots(); | |
643 } | |
644 | |
645 private: | |
646 void initializeUnusedSlots() | |
647 { | |
648 // The PersistentHeapVector is allocated off heap along with its | |
649 // inline buffer (if any.) Maintain the invariant that unused | |
650 // slots are cleared for the off-heap inline buffer also. | |
651 size_t unusedSlots = this->capacity() - this->size(); | |
652 if (unusedSlots) | |
653 this->clearUnusedSlots(this->end(), this->end() + unusedSlots); | |
654 } | |
655 }; | |
656 | |
657 template<typename T, size_t inlineCapacity = 0> | |
658 class PersistentHeapDeque : public PersistentHeapCollectionBase<HeapDeque<T, inl
ineCapacity>> { | |
659 public: | |
660 PersistentHeapDeque() { } | |
661 | |
662 template<size_t otherCapacity> | |
663 PersistentHeapDeque(const HeapDeque<T, otherCapacity>& other) | |
664 : PersistentHeapCollectionBase<HeapDeque<T, inlineCapacity>>(other) | |
665 { | |
666 } | |
667 }; | |
668 | |
669 // Members are used in classes to contain strong pointers to other oilpan heap | |
670 // allocated objects. | |
671 // All Member fields of a class must be traced in the class' trace method. | |
672 // During the mark phase of the GC all live objects are marked as live and | |
673 // all Member fields of a live object will be traced marked as live as well. | |
674 template<typename T> | |
675 class Member { | |
676 DISALLOW_NEW_EXCEPT_PLACEMENT_NEW(); | |
677 public: | |
678 Member() : m_raw(nullptr) | |
679 { | |
680 } | |
681 | |
682 Member(std::nullptr_t) : m_raw(nullptr) | |
683 { | |
684 } | |
685 | |
686 Member(T* raw) : m_raw(raw) | |
687 { | |
688 checkPointer(); | |
689 } | |
690 | |
691 explicit Member(T& raw) : m_raw(&raw) | |
692 { | |
693 checkPointer(); | |
694 } | |
695 | |
696 Member(WTF::HashTableDeletedValueType) : m_raw(reinterpret_cast<T*>(-1)) | |
697 { | |
698 } | |
699 | |
700 bool isHashTableDeletedValue() const { return m_raw == reinterpret_cast<T*>(
-1); } | |
701 | |
702 template<typename U> | |
703 Member(const Persistent<U>& other) : m_raw(other) | |
704 { | |
705 checkPointer(); | |
706 } | |
707 | |
708 Member(const Member& other) : m_raw(other) | |
709 { | |
710 checkPointer(); | |
711 } | |
712 | |
713 template<typename U> | |
714 Member(const Member<U>& other) : m_raw(other) | |
715 { | |
716 checkPointer(); | |
717 } | |
718 | |
719 T* release() | |
720 { | |
721 T* result = m_raw; | |
722 m_raw = nullptr; | |
723 return result; | |
724 } | |
725 | |
726 explicit operator bool() const { return m_raw; } | |
727 | |
728 operator T*() const { return m_raw; } | |
729 | |
730 T* operator->() const { return m_raw; } | |
731 T& operator*() const { return *m_raw; } | |
732 | |
733 template<typename U> | |
734 Member& operator=(const Persistent<U>& other) | |
735 { | |
736 m_raw = other; | |
737 checkPointer(); | |
738 return *this; | |
739 } | |
740 | |
741 template<typename U> | |
742 Member& operator=(const Member<U>& other) | |
743 { | |
744 m_raw = other; | |
745 checkPointer(); | |
746 return *this; | |
747 } | |
748 | |
749 template<typename U> | |
750 Member& operator=(U* other) | |
751 { | |
752 m_raw = other; | |
753 checkPointer(); | |
754 return *this; | |
755 } | |
756 | |
757 Member& operator=(std::nullptr_t) | |
758 { | |
759 m_raw = nullptr; | |
760 return *this; | |
761 } | |
762 | |
763 void swap(Member<T>& other) | |
764 { | |
765 std::swap(m_raw, other.m_raw); | |
766 checkPointer(); | |
767 } | |
768 | |
769 T* get() const { return m_raw; } | |
770 | |
771 void clear() { m_raw = nullptr; } | |
772 | |
773 | |
774 protected: | |
775 void checkPointer() | |
776 { | |
777 #if ENABLE(ASSERT) && defined(ADDRESS_SANITIZER) | |
778 if (!m_raw) | |
779 return; | |
780 // HashTable can store a special value (which is not aligned to the | |
781 // allocation granularity) to Member<> to represent a deleted entry. | |
782 // Thus we treat a pointer that is not aligned to the granularity | |
783 // as a valid pointer. | |
784 if (reinterpret_cast<intptr_t>(m_raw) % allocationGranularity) | |
785 return; | |
786 | |
787 // TODO(haraken): What we really want to check here is that the pointer | |
788 // is a traceable object. In other words, the pointer is either of: | |
789 // | |
790 // (a) a pointer to the head of an on-heap object. | |
791 // (b) a pointer to the head of an on-heap mixin object. | |
792 // | |
793 // We can check it by calling ThreadHeap::isHeapObjectAlive(m_raw), | |
794 // but we cannot call it here because it requires to include T.h. | |
795 // So we currently only try to implement the check for (a), but do | |
796 // not insist that T's definition is in scope. | |
797 if (IsFullyDefined<T>::value && !IsGarbageCollectedMixin<T>::value) | |
798 ASSERT(HeapObjectHeader::fromPayload(m_raw)->checkHeader()); | |
799 #endif | |
800 } | |
801 | |
802 T* m_raw; | |
803 | |
804 template<bool x, WTF::WeakHandlingFlag y, WTF::ShouldWeakPointersBeMarkedStr
ongly z, typename U, typename V> friend struct CollectionBackingTraceTrait; | |
805 friend class Visitor; | |
806 | |
807 }; | |
808 | |
809 // WeakMember is similar to Member in that it is used to point to other oilpan | |
810 // heap allocated objects. | |
811 // However instead of creating a strong pointer to the object, the WeakMember cr
eates | |
812 // a weak pointer, which does not keep the pointee alive. Hence if all pointers
to | |
813 // to a heap allocated object are weak the object will be garbage collected. At
the | |
814 // time of GC the weak pointers will automatically be set to null. | |
815 template<typename T> | |
816 class WeakMember : public Member<T> { | |
817 public: | |
818 WeakMember() : Member<T>() { } | |
819 | |
820 WeakMember(std::nullptr_t) : Member<T>(nullptr) { } | |
821 | |
822 WeakMember(T* raw) : Member<T>(raw) { } | |
823 | |
824 WeakMember(WTF::HashTableDeletedValueType x) : Member<T>(x) { } | |
825 | |
826 template<typename U> | |
827 WeakMember(const Persistent<U>& other) : Member<T>(other) { } | |
828 | |
829 template<typename U> | |
830 WeakMember(const Member<U>& other) : Member<T>(other) { } | |
831 | |
832 template<typename U> | |
833 WeakMember& operator=(const Persistent<U>& other) | |
834 { | |
835 this->m_raw = other; | |
836 this->checkPointer(); | |
837 return *this; | |
838 } | |
839 | |
840 template<typename U> | |
841 WeakMember& operator=(const Member<U>& other) | |
842 { | |
843 this->m_raw = other; | |
844 this->checkPointer(); | |
845 return *this; | |
846 } | |
847 | |
848 template<typename U> | |
849 WeakMember& operator=(U* other) | |
850 { | |
851 this->m_raw = other; | |
852 this->checkPointer(); | |
853 return *this; | |
854 } | |
855 | |
856 WeakMember& operator=(std::nullptr_t) | |
857 { | |
858 this->m_raw = nullptr; | |
859 return *this; | |
860 } | |
861 | |
862 private: | |
863 T** cell() const { return const_cast<T**>(&this->m_raw); } | |
864 | |
865 template<typename Derived> friend class VisitorHelper; | |
866 }; | |
867 | |
868 // UntracedMember is a pointer to an on-heap object that is not traced for some | |
869 // reason. Please don't use this unless you understand what you're doing. | |
870 // Basically, all pointers to on-heap objects must be stored in either of | |
871 // Persistent, Member or WeakMember. It is not allowed to leave raw pointers to | |
872 // on-heap objects. However, there can be scenarios where you have to use raw | |
873 // pointers for some reason, and in that case you can use UntracedMember. Of | |
874 // course, it must be guaranteed that the pointing on-heap object is kept alive | |
875 // while the raw pointer is pointing to the object. | |
876 template<typename T> | |
877 class UntracedMember final : public Member<T> { | |
878 public: | |
879 UntracedMember() : Member<T>() { } | |
880 | |
881 UntracedMember(std::nullptr_t) : Member<T>(nullptr) { } | |
882 | |
883 UntracedMember(T* raw) : Member<T>(raw) { } | |
884 | |
885 template<typename U> | |
886 UntracedMember(const Persistent<U>& other) : Member<T>(other) { } | |
887 | |
888 template<typename U> | |
889 UntracedMember(const Member<U>& other) : Member<T>(other) { } | |
890 | |
891 UntracedMember(WTF::HashTableDeletedValueType x) : Member<T>(x) { } | |
892 | |
893 template<typename U> | |
894 UntracedMember& operator=(const Persistent<U>& other) | |
895 { | |
896 this->m_raw = other; | |
897 this->checkPointer(); | |
898 return *this; | |
899 } | |
900 | |
901 template<typename U> | |
902 UntracedMember& operator=(const Member<U>& other) | |
903 { | |
904 this->m_raw = other; | |
905 this->checkPointer(); | |
906 return *this; | |
907 } | |
908 | |
909 template<typename U> | |
910 UntracedMember& operator=(U* other) | |
911 { | |
912 this->m_raw = other; | |
913 this->checkPointer(); | |
914 return *this; | |
915 } | |
916 | |
917 UntracedMember& operator=(std::nullptr_t) | |
918 { | |
919 this->m_raw = nullptr; | |
920 return *this; | |
921 } | |
922 }; | |
923 | |
924 // Comparison operators between (Weak)Members, Persistents, and UntracedMembers. | |
925 template<typename T, typename U> inline bool operator==(const Member<T>& a, cons
t Member<U>& b) { return a.get() == b.get(); } | |
926 template<typename T, typename U> inline bool operator!=(const Member<T>& a, cons
t Member<U>& b) { return a.get() != b.get(); } | |
927 template<typename T, typename U> inline bool operator==(const Persistent<T>& a,
const Persistent<U>& b) { return a.get() == b.get(); } | |
928 template<typename T, typename U> inline bool operator!=(const Persistent<T>& a,
const Persistent<U>& b) { return a.get() != b.get(); } | |
929 | |
930 template<typename T, typename U> inline bool operator==(const Member<T>& a, cons
t Persistent<U>& b) { return a.get() == b.get(); } | |
931 template<typename T, typename U> inline bool operator!=(const Member<T>& a, cons
t Persistent<U>& b) { return a.get() != b.get(); } | |
932 template<typename T, typename U> inline bool operator==(const Persistent<T>& a,
const Member<U>& b) { return a.get() == b.get(); } | |
933 template<typename T, typename U> inline bool operator!=(const Persistent<T>& a,
const Member<U>& b) { return a.get() != b.get(); } | |
934 | |
935 template<typename T, bool = IsGarbageCollectedType<T>::value> | 50 template<typename T, bool = IsGarbageCollectedType<T>::value> |
936 class RawPtrOrMemberTrait { | 51 class RawPtrOrMemberTrait { |
937 STATIC_ONLY(RawPtrOrMemberTrait) | 52 STATIC_ONLY(RawPtrOrMemberTrait) |
938 public: | 53 public: |
939 using Type = T*; | 54 using Type = T*; |
940 }; | 55 }; |
941 | 56 |
942 template<typename T> | 57 template<typename T> |
943 class RawPtrOrMemberTrait<T, true> { | 58 class RawPtrOrMemberTrait<T, true> { |
944 STATIC_ONLY(RawPtrOrMemberTrait) | 59 STATIC_ONLY(RawPtrOrMemberTrait) |
(...skipping 18 matching lines...) Expand all Loading... |
963 if (m_object) | 78 if (m_object) |
964 (m_object->*Disposer)(); | 79 (m_object->*Disposer)(); |
965 } | 80 } |
966 | 81 |
967 void clear() { m_object.clear(); } | 82 void clear() { m_object.clear(); } |
968 | 83 |
969 private: | 84 private: |
970 typename RawPtrOrMemberTrait<T>::Type m_object; | 85 typename RawPtrOrMemberTrait<T>::Type m_object; |
971 }; | 86 }; |
972 | 87 |
973 // SelfKeepAlive<Object> is the idiom to use for objects that have to keep | |
974 // themselves temporarily alive and cannot rely on there being some | |
975 // external reference in that interval: | |
976 // | |
977 // class Opener { | |
978 // public: | |
979 // ... | |
980 // void open() | |
981 // { | |
982 // // Retain a self-reference while in an open()ed state: | |
983 // m_keepAlive = this; | |
984 // .... | |
985 // } | |
986 // | |
987 // void close() | |
988 // { | |
989 // // Clear self-reference that ensured we were kept alive while opened. | |
990 // m_keepAlive.clear(); | |
991 // .... | |
992 // } | |
993 // | |
994 // private: | |
995 // ... | |
996 // SelfKeepAlive m_keepAlive; | |
997 // }; | |
998 // | |
999 // The responsibility to call clear() in a timely fashion resides with the imple
mentation | |
1000 // of the object. | |
1001 // | |
1002 // | |
1003 template<typename Self> | |
1004 class SelfKeepAlive final { | |
1005 DISALLOW_NEW(); | |
1006 public: | |
1007 SelfKeepAlive() | |
1008 { | |
1009 } | |
1010 | |
1011 explicit SelfKeepAlive(Self* self) | |
1012 { | |
1013 assign(self); | |
1014 } | |
1015 | |
1016 SelfKeepAlive& operator=(Self* self) | |
1017 { | |
1018 assign(self); | |
1019 return *this; | |
1020 } | |
1021 | |
1022 void clear() | |
1023 { | |
1024 m_keepAlive.clear(); | |
1025 } | |
1026 | |
1027 typedef Persistent<Self> (SelfKeepAlive::*UnspecifiedBoolType); | |
1028 operator UnspecifiedBoolType() const { return m_keepAlive ? &SelfKeepAlive::
m_keepAlive : 0; } | |
1029 | |
1030 private: | |
1031 void assign(Self* self) | |
1032 { | |
1033 ASSERT(!m_keepAlive || m_keepAlive.get() == self); | |
1034 m_keepAlive = self; | |
1035 } | |
1036 | |
1037 GC_PLUGIN_IGNORE("420515") | |
1038 Persistent<Self> m_keepAlive; | |
1039 }; | |
1040 | |
1041 // Only a very reduced form of weak heap object references can currently be held | |
1042 // by WTF::Closure<>s. i.e., bound as a 'this' pointer only. | |
1043 // | |
1044 // TODO(sof): once wtf/Functional.h is able to work over platform/heap/ types | |
1045 // (like CrossThreadWeakPersistent<>), drop the restriction on weak persistent | |
1046 // use by function closures (and rename this ad-hoc type.) | |
1047 template<typename T> | |
1048 class WeakPersistentThisPointer { | |
1049 STACK_ALLOCATED(); | |
1050 public: | |
1051 explicit WeakPersistentThisPointer(T* value) : m_value(value) { } | |
1052 WeakPersistent<T> value() const { return m_value; } | |
1053 private: | |
1054 WeakPersistent<T> m_value; | |
1055 }; | |
1056 | |
1057 template<typename T> | |
1058 class CrossThreadWeakPersistentThisPointer { | |
1059 STACK_ALLOCATED(); | |
1060 public: | |
1061 explicit CrossThreadWeakPersistentThisPointer(T* value) : m_value(value) { } | |
1062 CrossThreadWeakPersistent<T> value() const { return m_value; } | |
1063 private: | |
1064 CrossThreadWeakPersistent<T> m_value; | |
1065 }; | |
1066 | |
1067 template <typename T> | |
1068 Persistent<T> wrapPersistent(T* value) | |
1069 { | |
1070 return Persistent<T>(value); | |
1071 } | |
1072 | |
1073 template <typename T> | |
1074 CrossThreadPersistent<T> wrapCrossThreadPersistent(T* value) | |
1075 { | |
1076 return CrossThreadPersistent<T>(value); | |
1077 } | |
1078 | |
1079 // LEAK_SANITIZER_DISABLED_SCOPE: all allocations made in the current scope | 88 // LEAK_SANITIZER_DISABLED_SCOPE: all allocations made in the current scope |
1080 // will be exempted from LSan consideration. | 89 // will be exempted from LSan consideration. |
1081 // | 90 // |
1082 // TODO(sof): move this to wtf/LeakAnnotations.h (LeakSanitizer.h?) once | 91 // TODO(sof): move this to wtf/LeakAnnotations.h (LeakSanitizer.h?) once |
1083 // wtf/ can freely call upon Oilpan functionality. | 92 // wtf/ can freely call upon Oilpan functionality. |
1084 #if defined(LEAK_SANITIZER) | 93 #if defined(LEAK_SANITIZER) |
1085 class LeakSanitizerDisableScope { | 94 class LeakSanitizerDisableScope { |
1086 STACK_ALLOCATED(); | 95 STACK_ALLOCATED(); |
1087 WTF_MAKE_NONCOPYABLE(LeakSanitizerDisableScope); | 96 WTF_MAKE_NONCOPYABLE(LeakSanitizerDisableScope); |
1088 public: | 97 public: |
(...skipping 11 matching lines...) Expand all Loading... |
1100 ThreadState::current()->leaveStaticReferenceRegistrationDisabledScop
e(); | 109 ThreadState::current()->leaveStaticReferenceRegistrationDisabledScop
e(); |
1101 } | 110 } |
1102 }; | 111 }; |
1103 #define LEAK_SANITIZER_DISABLED_SCOPE LeakSanitizerDisableScope lsanDisabledScop
e | 112 #define LEAK_SANITIZER_DISABLED_SCOPE LeakSanitizerDisableScope lsanDisabledScop
e |
1104 #else | 113 #else |
1105 #define LEAK_SANITIZER_DISABLED_SCOPE | 114 #define LEAK_SANITIZER_DISABLED_SCOPE |
1106 #endif | 115 #endif |
1107 | 116 |
1108 } // namespace blink | 117 } // namespace blink |
1109 | 118 |
1110 namespace WTF { | |
1111 | |
1112 template <typename T> | |
1113 struct MemberHash : PtrHash<T> { | |
1114 STATIC_ONLY(MemberHash); | |
1115 template <typename U> | |
1116 static unsigned hash(const U& key) { return PtrHash<T>::hash(key); } | |
1117 template <typename U, typename V> | |
1118 static bool equal(const U& a, const V& b) { return a == b; } | |
1119 }; | |
1120 | |
1121 template <typename T> | |
1122 struct WeakMemberHash : MemberHash<T> { | |
1123 STATIC_ONLY(WeakMemberHash); | |
1124 }; | |
1125 | |
1126 template <typename T> | |
1127 struct UntracedMemberHash : MemberHash<T> { | |
1128 STATIC_ONLY(UntracedMemberHash); | |
1129 }; | |
1130 | |
1131 // PtrHash is the default hash for hash tables with members. | |
1132 template <typename T> | |
1133 struct DefaultHash<blink::Member<T>> { | |
1134 STATIC_ONLY(DefaultHash); | |
1135 using Hash = MemberHash<T>; | |
1136 }; | |
1137 | |
1138 template <typename T> | |
1139 struct DefaultHash<blink::WeakMember<T>> { | |
1140 STATIC_ONLY(DefaultHash); | |
1141 using Hash = WeakMemberHash<T>; | |
1142 }; | |
1143 | |
1144 template <typename T> | |
1145 struct DefaultHash<blink::UntracedMember<T>> { | |
1146 STATIC_ONLY(DefaultHash); | |
1147 using Hash = UntracedMemberHash<T>; | |
1148 }; | |
1149 | |
1150 template<typename T> | |
1151 struct NeedsTracing<blink::Member<T>> { | |
1152 STATIC_ONLY(NeedsTracing); | |
1153 static const bool value = true; | |
1154 }; | |
1155 | |
1156 template<typename T> | |
1157 struct IsWeak<blink::WeakMember<T>> { | |
1158 STATIC_ONLY(IsWeak); | |
1159 static const bool value = true; | |
1160 }; | |
1161 | |
1162 // For wtf/Functional.h | |
1163 template<typename T, bool isGarbageCollected> struct PointerParamStorageTraits; | |
1164 | |
1165 // The condition of 'T must be fully defined' (except for void) is checked in | |
1166 // blink::IsGarbageCollectedType<T>::value. | |
1167 template<typename T> | |
1168 struct PointerParamStorageTraits<T*, false> { | |
1169 STATIC_ONLY(PointerParamStorageTraits); | |
1170 using StorageType = T*; | |
1171 | |
1172 static StorageType wrap(T* value) { return value; } | |
1173 static T* unwrap(const StorageType& value) { return value; } | |
1174 }; | |
1175 | |
1176 template<typename T> | |
1177 struct PointerParamStorageTraits<T*, true> { | |
1178 STATIC_ONLY(PointerParamStorageTraits); | |
1179 using StorageType = blink::CrossThreadPersistent<T>; | |
1180 | |
1181 static StorageType wrap(T* value) { return value; } | |
1182 static T* unwrap(const StorageType& value) { return value.get(); } | |
1183 }; | |
1184 | |
1185 template<typename T> | |
1186 struct ParamStorageTraits<T*> : public PointerParamStorageTraits<T*, blink::IsGa
rbageCollectedType<T>::value> { | |
1187 STATIC_ONLY(ParamStorageTraits); | |
1188 }; | |
1189 | |
1190 template<typename T> | |
1191 struct ParamStorageTraits<blink::WeakPersistentThisPointer<T>> { | |
1192 STATIC_ONLY(ParamStorageTraits); | |
1193 static_assert(sizeof(T), "T must be fully defined"); | |
1194 using StorageType = blink::WeakPersistent<T>; | |
1195 | |
1196 static StorageType wrap(const blink::WeakPersistentThisPointer<T>& value) {
return value.value(); } | |
1197 | |
1198 // WTF::FunctionWrapper<> handles WeakPtr<>, so recast this weak persistent | |
1199 // into it. | |
1200 // | |
1201 // TODO(sof): remove this hack once wtf/Functional.h can also work with a ty
pe like | |
1202 // WeakPersistent<>. | |
1203 static WeakPtr<T> unwrap(const StorageType& value) { return WeakPtr<T>(WeakR
eference<T>::create(value.get())); } | |
1204 }; | |
1205 | |
1206 template<typename T> | |
1207 struct ParamStorageTraits<blink::CrossThreadWeakPersistentThisPointer<T>> { | |
1208 STATIC_ONLY(ParamStorageTraits); | |
1209 static_assert(sizeof(T), "T must be fully defined"); | |
1210 using StorageType = blink::CrossThreadWeakPersistent<T>; | |
1211 | |
1212 static StorageType wrap(const blink::CrossThreadWeakPersistentThisPointer<T>
& value) { return value.value(); } | |
1213 | |
1214 // WTF::FunctionWrapper<> handles WeakPtr<>, so recast this weak persistent | |
1215 // into it. | |
1216 // | |
1217 // TODO(sof): remove this hack once wtf/Functional.h can also work with a ty
pe like | |
1218 // CrossThreadWeakPersistent<>. | |
1219 static WeakPtr<T> unwrap(const StorageType& value) { return WeakPtr<T>(WeakR
eference<T>::create(value.get())); } | |
1220 }; | |
1221 | |
1222 } // namespace WTF | |
1223 | |
1224 #endif | 119 #endif |
OLD | NEW |