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 23 matching lines...) Expand all Loading... |
34 #include "heap/Heap.h" | 34 #include "heap/Heap.h" |
35 #include "heap/ThreadState.h" | 35 #include "heap/ThreadState.h" |
36 #include "heap/Visitor.h" | 36 #include "heap/Visitor.h" |
37 | 37 |
38 #include "wtf/Ptr.h" | 38 #include "wtf/Ptr.h" |
39 #include "wtf/RefCounted.h" | 39 #include "wtf/RefCounted.h" |
40 | 40 |
41 namespace WebCore { | 41 namespace WebCore { |
42 | 42 |
43 template<typename T> class Member; | 43 template<typename T> class Member; |
| 44 template<typename T> struct OffHeapCollectionTraceTrait; |
44 | 45 |
45 class PersistentNode { | 46 class PersistentNode { |
46 public: | 47 public: |
47 explicit PersistentNode(TraceCallback trace) : m_trace(trace) { } | 48 explicit PersistentNode(TraceCallback trace) |
| 49 : m_trace(trace) |
| 50 { |
| 51 } |
48 | 52 |
49 virtual ~PersistentNode() { } | 53 bool isAlive() { return m_trace; } |
| 54 |
| 55 virtual ~PersistentNode() |
| 56 { |
| 57 ASSERT(isAlive()); |
| 58 m_trace = 0; |
| 59 } |
50 | 60 |
51 // Ideally the trace method should be virtual and automatically dispatch | 61 // Ideally the trace method should be virtual and automatically dispatch |
52 // to the most specific implementation. However having a virtual method | 62 // to the most specific implementation. However having a virtual method |
53 // on PersistentNode leads to too eager template instantiation with MSVC | 63 // on PersistentNode leads to too eager template instantiation with MSVC |
54 // which leads to include cycles. | 64 // which leads to include cycles. |
55 // Instead we call the constructor with a TraceCallback which knows the | 65 // Instead we call the constructor with a TraceCallback which knows the |
56 // type of the most specific child and calls trace directly. See | 66 // type of the most specific child and calls trace directly. See |
57 // TraceMethodDelegate in Visitor.h for how this is done. | 67 // TraceMethodDelegate in Visitor.h for how this is done. |
58 void trace(Visitor* visitor) | 68 void trace(Visitor* visitor) |
59 { | 69 { |
(...skipping 11 matching lines...) Expand all Loading... |
71 friend class PersistentAnchor; | 81 friend class PersistentAnchor; |
72 friend class ThreadState; | 82 friend class ThreadState; |
73 }; | 83 }; |
74 | 84 |
75 template<ThreadAffinity Affinity, typename Owner> | 85 template<ThreadAffinity Affinity, typename Owner> |
76 class PersistentBase : public PersistentNode { | 86 class PersistentBase : public PersistentNode { |
77 public: | 87 public: |
78 ~PersistentBase() | 88 ~PersistentBase() |
79 { | 89 { |
80 #ifndef NDEBUG | 90 #ifndef NDEBUG |
| 91 ASSERT(isAlive()); |
| 92 ASSERT(m_next->isAlive()); |
| 93 ASSERT(m_prev->isAlive()); |
81 m_threadState->checkThread(); | 94 m_threadState->checkThread(); |
82 #endif | 95 #endif |
83 m_next->m_prev = m_prev; | 96 m_next->m_prev = m_prev; |
84 m_prev->m_next = m_next; | 97 m_prev->m_next = m_next; |
85 } | 98 } |
86 | 99 |
87 protected: | 100 protected: |
88 inline PersistentBase() | 101 inline PersistentBase() |
89 : PersistentNode(TraceMethodDelegate<Owner, &Owner::trace>::trampoline) | 102 : PersistentNode(TraceMethodDelegate<Owner, &Owner::trace>::trampoline) |
90 #ifndef NDEBUG | 103 #ifndef NDEBUG |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
131 #endif | 144 #endif |
132 }; | 145 }; |
133 | 146 |
134 // A dummy Persistent handle that ensures the list of persistents is never null. | 147 // A dummy Persistent handle that ensures the list of persistents is never null. |
135 // This removes a test from a hot path. | 148 // This removes a test from a hot path. |
136 class PersistentAnchor : public PersistentNode { | 149 class PersistentAnchor : public PersistentNode { |
137 public: | 150 public: |
138 void trace(Visitor*) { } | 151 void trace(Visitor*) { } |
139 | 152 |
140 private: | 153 private: |
141 virtual ~PersistentAnchor() { } | 154 virtual ~PersistentAnchor() |
| 155 { |
| 156 ASSERT(m_next == this); |
| 157 ASSERT(m_prev == this); |
| 158 } |
142 PersistentAnchor() : PersistentNode(TraceMethodDelegate<PersistentAnchor, &P
ersistentAnchor::trace>::trampoline) | 159 PersistentAnchor() : PersistentNode(TraceMethodDelegate<PersistentAnchor, &P
ersistentAnchor::trace>::trampoline) |
143 { | 160 { |
144 m_next = this; | 161 m_next = this; |
145 m_prev = this; | 162 m_prev = this; |
146 } | 163 } |
147 | 164 |
148 friend class ThreadState; | 165 friend class ThreadState; |
149 }; | 166 }; |
150 | 167 |
151 // Persistent handles are used to store pointers into the | 168 // Persistent handles are used to store pointers into the |
(...skipping 252 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
404 // Comparison operators between (Weak)Members and Persistents | 421 // Comparison operators between (Weak)Members and Persistents |
405 template<typename T, typename U> inline bool operator==(const Member<T>& a, cons
t Member<U>& b) { return a.get() == b.get(); } | 422 template<typename T, typename U> inline bool operator==(const Member<T>& a, cons
t Member<U>& b) { return a.get() == b.get(); } |
406 template<typename T, typename U> inline bool operator!=(const Member<T>& a, cons
t Member<U>& b) { return a.get() != b.get(); } | 423 template<typename T, typename U> inline bool operator!=(const Member<T>& a, cons
t Member<U>& b) { return a.get() != b.get(); } |
407 template<typename T, typename U> inline bool operator==(const Member<T>& a, cons
t Persistent<U>& b) { return a.get() == b.get(); } | 424 template<typename T, typename U> inline bool operator==(const Member<T>& a, cons
t Persistent<U>& b) { return a.get() == b.get(); } |
408 template<typename T, typename U> inline bool operator!=(const Member<T>& a, cons
t Persistent<U>& b) { return a.get() != b.get(); } | 425 template<typename T, typename U> inline bool operator!=(const Member<T>& a, cons
t Persistent<U>& b) { return a.get() != b.get(); } |
409 template<typename T, typename U> inline bool operator==(const Persistent<T>& a,
const Member<U>& b) { return a.get() == b.get(); } | 426 template<typename T, typename U> inline bool operator==(const Persistent<T>& a,
const Member<U>& b) { return a.get() == b.get(); } |
410 template<typename T, typename U> inline bool operator!=(const Persistent<T>& a,
const Member<U>& b) { return a.get() != b.get(); } | 427 template<typename T, typename U> inline bool operator!=(const Persistent<T>& a,
const Member<U>& b) { return a.get() != b.get(); } |
411 template<typename T, typename U> inline bool operator==(const Persistent<T>& a,
const Persistent<U>& b) { return a.get() == b.get(); } | 428 template<typename T, typename U> inline bool operator==(const Persistent<T>& a,
const Persistent<U>& b) { return a.get() == b.get(); } |
412 template<typename T, typename U> inline bool operator!=(const Persistent<T>& a,
const Persistent<U>& b) { return a.get() != b.get(); } | 429 template<typename T, typename U> inline bool operator!=(const Persistent<T>& a,
const Persistent<U>& b) { return a.get() != b.get(); } |
413 | 430 |
| 431 template<typename Collection, ThreadAffinity Affinity = MainThreadOnly> class Co
llectionPersistent; |
| 432 |
| 433 // Used to inject correctly typed operator[] into CollectionPersistent when we a
re wrapping Vector. |
| 434 template<typename T> class IndexingBehavior { }; |
| 435 |
| 436 template<typename T, size_t inlineCapacity> |
| 437 class IndexingBehavior<CollectionPersistent<Vector<T, inlineCapacity, WTF::Defau
ltAllocator> > > { |
| 438 typedef CollectionPersistent<Vector<T, inlineCapacity, WTF::DefaultAllocator
> > CollectionPersistentType; |
| 439 public: |
| 440 T& operator[] (size_t i) { return (**static_cast<CollectionPersistentType*>(
this))[i]; } |
| 441 const T& operator[] (size_t i) const { return (**static_cast<const Collectio
nPersistentType*>(this))[i]; } |
| 442 }; |
| 443 |
| 444 template<typename Collection, ThreadAffinity Affinity> |
| 445 class CollectionPersistent |
| 446 : public PersistentBase<Affinity, CollectionPersistent<Collection, Affinity>
> |
| 447 , public IndexingBehavior<CollectionPersistent<Collection, Affinity> > { |
| 448 public: |
| 449 typedef Collection CollectionType; |
| 450 typedef typename Collection::iterator iterator; |
| 451 typedef typename Collection::const_iterator const_iterator; |
| 452 |
| 453 CollectionPersistent() { } |
| 454 explicit CollectionPersistent(size_t size) : m_collection(Collection(size))
{ } |
| 455 explicit CollectionPersistent(const Collection& collection) : m_collection(c
ollection) { } |
| 456 CollectionPersistent& operator=(const Collection& collection) { m_collection
= collection; return *this; } |
| 457 Collection* operator->() { return &m_collection; } |
| 458 const Collection* operator->() const { return &m_collection; } |
| 459 Collection& operator*() { return m_collection; } |
| 460 const Collection& operator*() const { return m_collection; } |
| 461 |
| 462 void trace(Visitor* visitor) |
| 463 { |
| 464 OffHeapCollectionTraceTrait<Collection>::trace(visitor, m_collection); |
| 465 } |
| 466 |
| 467 #if defined(TRACE_GC_MARKING) && TRACE_GC_MARKING |
| 468 virtual const char* name() OVERRIDE |
| 469 { |
| 470 ASSERT(this == static_cast<PersistentNode*>(this)); |
| 471 const char* n = FieldAnnotationBase::fromAddress(this); |
| 472 return n ? n : "CollectionPersistent"; |
| 473 } |
| 474 #endif |
| 475 |
| 476 private: |
| 477 Collection m_collection; |
| 478 }; |
| 479 |
414 // Template aliases for the transition period where we want to support | 480 // Template aliases for the transition period where we want to support |
415 // both reference counting and garbage collection based on a | 481 // both reference counting and garbage collection based on a |
416 // compile-time flag. | 482 // compile-time flag. |
417 // | 483 // |
418 // With clang we can use c++11 template aliases which is really what | 484 // With clang we can use c++11 template aliases which is really what |
419 // we want. For GCC and MSVC we simulate the template aliases with | 485 // we want. For GCC and MSVC we simulate the template aliases with |
420 // stylized macros until we can use template aliases. | 486 // stylized macros until we can use template aliases. |
421 #if ENABLE(OILPAN) | 487 #if ENABLE(OILPAN) |
422 | 488 |
423 #if COMPILER(CLANG) | 489 #if COMPILER(CLANG) |
(...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
511 | 577 |
512 template<typename T> struct HashTraits<WebCore::Member<T> > : SimpleClassHashTra
its<WebCore::Member<T> > { | 578 template<typename T> struct HashTraits<WebCore::Member<T> > : SimpleClassHashTra
its<WebCore::Member<T> > { |
513 static const bool needsDestruction = false; | 579 static const bool needsDestruction = false; |
514 // FIXME: The distinction between PeekInType and PassInType is there for | 580 // FIXME: The distinction between PeekInType and PassInType is there for |
515 // the sake of the reference counting handles. When they are gone the two | 581 // the sake of the reference counting handles. When they are gone the two |
516 // types can be merged into PassInType. | 582 // types can be merged into PassInType. |
517 // FIXME: Implement proper const'ness for iterator types. Requires support | 583 // FIXME: Implement proper const'ness for iterator types. Requires support |
518 // in the marking Visitor. | 584 // in the marking Visitor. |
519 typedef T* PeekInType; | 585 typedef T* PeekInType; |
520 typedef T* PassInType; | 586 typedef T* PassInType; |
521 typedef T* IteratorGetType; | 587 typedef WebCore::Member<T>* IteratorGetType; |
522 typedef T* IteratorConstGetType; | 588 typedef const WebCore::Member<T>* IteratorConstGetType; |
523 typedef T* IteratorReferenceType; | 589 typedef T* IteratorReferenceType; |
524 typedef T* IteratorConstReferenceType; | 590 typedef T* IteratorConstReferenceType; |
525 static IteratorConstGetType getToConstGetConversion(const WebCore::Member<T>
* x) { return x->get(); } | 591 static IteratorConstGetType getToConstGetConversion(const WebCore::Member<T>
* x) { return x->get(); } |
526 static IteratorReferenceType getToReferenceConversion(IteratorGetType x) { r
eturn x; } | 592 static IteratorReferenceType getToReferenceConversion(IteratorGetType x) { r
eturn x->get(); } |
527 static IteratorConstReferenceType getToReferenceConstConversion(IteratorCons
tGetType x) { return x; } | 593 static IteratorConstReferenceType getToReferenceConstConversion(IteratorCons
tGetType x) { return x->get(); } |
528 // FIXME: Similarly, there is no need for a distinction between PeekOutType | 594 // FIXME: Similarly, there is no need for a distinction between PeekOutType |
529 // and PassOutType without reference counting. | 595 // and PassOutType without reference counting. |
530 typedef T* PeekOutType; | 596 typedef T* PeekOutType; |
531 typedef T* PassOutType; | 597 typedef T* PassOutType; |
532 | 598 |
533 template<typename U> | 599 template<typename U> |
534 static void store(const U& value, WebCore::Member<T>& storage) { storage = v
alue; } | 600 static void store(const U& value, WebCore::Member<T>& storage) { storage = v
alue; } |
535 | 601 |
536 static PeekOutType peek(const WebCore::Member<T>& value) { return value; } | 602 static PeekOutType peek(const WebCore::Member<T>& value) { return value; } |
537 static PassOutType passOut(const WebCore::Member<T>& value) { return value;
} | 603 static PassOutType passOut(const WebCore::Member<T>& value) { return value;
} |
538 }; | 604 }; |
539 | 605 |
540 template<typename T> struct HashTraits<WebCore::WeakMember<T> > : SimpleClassHas
hTraits<WebCore::WeakMember<T> > { | 606 template<typename T> struct HashTraits<WebCore::WeakMember<T> > : SimpleClassHas
hTraits<WebCore::WeakMember<T> > { |
541 static const bool needsDestruction = false; | 607 static const bool needsDestruction = false; |
542 // FIXME: The distinction between PeekInType and PassInType is there for | 608 // FIXME: The distinction between PeekInType and PassInType is there for |
543 // the sake of the reference counting handles. When they are gone the two | 609 // the sake of the reference counting handles. When they are gone the two |
544 // types can be merged into PassInType. | 610 // types can be merged into PassInType. |
545 // FIXME: Implement proper const'ness for iterator types. Requires support | 611 // FIXME: Implement proper const'ness for iterator types. Requires support |
546 // in the marking Visitor. | 612 // in the marking Visitor. |
547 typedef T* PeekInType; | 613 typedef T* PeekInType; |
548 typedef T* PassInType; | 614 typedef T* PassInType; |
549 typedef T* IteratorGetType; | 615 typedef WebCore::WeakMember<T>* IteratorGetType; |
550 typedef T* IteratorConstGetType; | 616 typedef const WebCore::WeakMember<T>* IteratorConstGetType; |
551 typedef T* IteratorReferenceType; | 617 typedef T* IteratorReferenceType; |
552 typedef T* IteratorConstReferenceType; | 618 typedef T* IteratorConstReferenceType; |
553 static IteratorConstGetType getToConstGetConversion(const WebCore::WeakMembe
r<T>* x) { return x->get(); } | 619 static IteratorConstGetType getToConstGetConversion(const WebCore::WeakMembe
r<T>* x) { return x->get(); } |
554 static IteratorReferenceType getToReferenceConversion(IteratorGetType x) { r
eturn x; } | 620 static IteratorReferenceType getToReferenceConversion(IteratorGetType x) { r
eturn x->get(); } |
555 static IteratorConstReferenceType getToReferenceConstConversion(IteratorCons
tGetType x) { return x; } | 621 static IteratorConstReferenceType getToReferenceConstConversion(IteratorCons
tGetType x) { return x->get(); } |
556 // FIXME: Similarly, there is no need for a distinction between PeekOutType | 622 // FIXME: Similarly, there is no need for a distinction between PeekOutType |
557 // and PassOutType without reference counting. | 623 // and PassOutType without reference counting. |
558 typedef T* PeekOutType; | 624 typedef T* PeekOutType; |
559 typedef T* PassOutType; | 625 typedef T* PassOutType; |
560 | 626 |
561 template<typename U> | 627 template<typename U> |
562 static void store(const U& value, WebCore::WeakMember<T>& storage) { storage
= value; } | 628 static void store(const U& value, WebCore::WeakMember<T>& storage) { storage
= value; } |
563 | 629 |
564 static PeekOutType peek(const WebCore::WeakMember<T>& value) { return value;
} | 630 static PeekOutType peek(const WebCore::WeakMember<T>& value) { return value;
} |
565 static PassOutType passOut(const WebCore::WeakMember<T>& value) { return val
ue; } | 631 static PassOutType passOut(const WebCore::WeakMember<T>& value) { return val
ue; } |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
597 }; | 663 }; |
598 | 664 |
599 template<typename Key, typename Value, typename Extractor, typename Traits, type
name KeyTraits> | 665 template<typename Key, typename Value, typename Extractor, typename Traits, type
name KeyTraits> |
600 struct IsWeak<WebCore::HeapHashTableBacking<Key, Value, Extractor, Traits, KeyTr
aits> > { | 666 struct IsWeak<WebCore::HeapHashTableBacking<Key, Value, Extractor, Traits, KeyTr
aits> > { |
601 static const bool value = Traits::isWeak; | 667 static const bool value = Traits::isWeak; |
602 }; | 668 }; |
603 | 669 |
604 } // namespace WTF | 670 } // namespace WTF |
605 | 671 |
606 #endif | 672 #endif |
OLD | NEW |