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 753 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
764 m_raw = nullptr; | 764 m_raw = nullptr; |
765 return *this; | 765 return *this; |
766 } | 766 } |
767 | 767 |
768 void swap(Member<T>& other) | 768 void swap(Member<T>& other) |
769 { | 769 { |
770 std::swap(m_raw, other.m_raw); | 770 std::swap(m_raw, other.m_raw); |
771 checkPointer(); | 771 checkPointer(); |
772 } | 772 } |
773 | 773 |
774 T* get() const { return m_raw; } | 774 T* get() const |
| 775 { |
| 776 #if ENABLE(ASSERT) && defined(ADDRESS_SANITIZER) |
| 777 // Verify that this handle points to a live on-heap object, if a pointer |
| 778 // has been assigned to this handle out of GarbageCollectedMixin constru
ctions. |
| 779 if (m_raw && m_gcGeneration != gcGenerationUnchecked && !ThreadState::cu
rrent()->isConstructingGCMixin()) { |
| 780 HeapObjectHeader* header = heapObjectHeader(); |
| 781 ASSERT(m_gcGeneration == header->gcGeneration()); |
| 782 } |
| 783 #endif |
| 784 return m_raw; |
| 785 } |
| 786 |
| 787 // This method is an accessor without any security checks, and it is |
| 788 // expected to be used under some limited condition. |
| 789 // So do NOT use it, if you do not know what it means. |
| 790 // TODO(peria): We should remove this method. |
| 791 T* unsafeGet() const |
| 792 { |
| 793 return m_raw; |
| 794 } |
775 | 795 |
776 void clear() { m_raw = nullptr; } | 796 void clear() { m_raw = nullptr; } |
777 | 797 |
| 798 protected: |
| 799 #if ENABLE(ASSERT) && defined(ADDRESS_SANITIZER) |
| 800 HeapObjectHeader* heapObjectHeader() const |
| 801 { |
| 802 BasePage* page = pageFromObject(m_raw); |
| 803 if (page->isLargeObjectPage()) { |
| 804 LargeObjectPage* large = static_cast<LargeObjectPage*>(page); |
| 805 return large->heapObjectHeader(); |
| 806 } |
| 807 NormalPage* normal = static_cast<NormalPage*>(page); |
| 808 return normal->findHeaderFromObject(m_raw); |
| 809 } |
| 810 #endif |
778 | 811 |
779 protected: | |
780 void checkPointer() | 812 void checkPointer() |
781 { | 813 { |
782 #if ENABLE(ASSERT) && defined(ADDRESS_SANITIZER) | 814 #if ENABLE(ASSERT) && defined(ADDRESS_SANITIZER) |
783 if (!m_raw) | 815 if (!m_raw) |
784 return; | 816 return; |
785 // HashTable can store a special value (which is not aligned to the | 817 // HashTable can store a special value (which is not aligned to the |
786 // allocation granularity) to Member<> to represent a deleted entry. | 818 // allocation granularity) to Member<> to represent a deleted entry. |
787 // Thus we treat a pointer that is not aligned to the granularity | 819 // Thus we treat a pointer that is not aligned to the granularity |
788 // as a valid pointer. | 820 // as a valid pointer. |
789 if (reinterpret_cast<intptr_t>(m_raw) % allocationGranularity) | 821 if (reinterpret_cast<intptr_t>(m_raw) % allocationGranularity) |
790 return; | 822 return; |
791 | 823 |
792 // TODO(haraken): What we really want to check here is that the pointer | 824 // m_gcGeneration verifies use-after-free of this Member handle. |
793 // is a traceable object. In other words, the pointer is either of: | 825 // If m_gcGeneration is gcGenerationUnchecked or m_raw is nullptr, |
794 // | 826 // the verification is skipped. |
795 // (a) a pointer to the head of an on-heap object. | 827 // We set gcGenerationUnchecked while constructing a GC mixin object |
796 // (b) a pointer to the head of an on-heap mixin object. | 828 // (and skip the verification unfortunately) because |
797 // | 829 // HeapObjectHeaderTrait<T>::heapObjectHeader doesn't work before |
798 // We can check it by calling Heap::isHeapObjectAlive(m_raw), | 830 // the vtable of the object is complete. |
799 // but we cannot call it here because it requires to include T.h. | 831 // FIXME(Oilpan): We want to check them, too. |
800 // So we currently only try to implement the check for (a), but do | 832 m_gcGeneration = gcGenerationUnchecked; |
801 // not insist that T's definition is in scope. | 833 if (!ThreadState::current()->isConstructingGCMixin()) { |
802 if (IsFullyDefined<T>::value && !IsGarbageCollectedMixin<T>::value) | 834 HeapObjectHeader* header = heapObjectHeader(); |
803 ASSERT(HeapObjectHeader::fromPayload(m_raw)->checkHeader()); | 835 m_gcGeneration = header->gcGeneration(); |
| 836 ASSERT(m_gcGeneration != gcGenerationForFreeListEntry); |
| 837 } |
804 #endif | 838 #endif |
805 } | 839 } |
806 | 840 |
807 T* m_raw; | 841 T* m_raw; |
808 | 842 |
| 843 #if ENABLE(ASSERT) && defined(ADDRESS_SANITIZER) |
| 844 uint32_t m_gcGeneration; |
| 845 #endif |
| 846 |
809 template<bool x, WTF::WeakHandlingFlag y, WTF::ShouldWeakPointersBeMarkedStr
ongly z, typename U, typename V> friend struct CollectionBackingTraceTrait; | 847 template<bool x, WTF::WeakHandlingFlag y, WTF::ShouldWeakPointersBeMarkedStr
ongly z, typename U, typename V> friend struct CollectionBackingTraceTrait; |
810 friend class Visitor; | 848 friend class Visitor; |
811 | |
812 }; | 849 }; |
813 | 850 |
814 // WeakMember is similar to Member in that it is used to point to other oilpan | 851 // WeakMember is similar to Member in that it is used to point to other oilpan |
815 // heap allocated objects. | 852 // heap allocated objects. |
816 // However instead of creating a strong pointer to the object, the WeakMember cr
eates | 853 // However instead of creating a strong pointer to the object, the WeakMember cr
eates |
817 // a weak pointer, which does not keep the pointee alive. Hence if all pointers
to | 854 // a weak pointer, which does not keep the pointee alive. Hence if all pointers
to |
818 // to a heap allocated object are weak the object will be garbage collected. At
the | 855 // to a heap allocated object are weak the object will be garbage collected. At
the |
819 // time of GC the weak pointers will automatically be set to null. | 856 // time of GC the weak pointers will automatically be set to null. |
820 template<typename T> | 857 template<typename T> |
821 class WeakMember : public Member<T> { | 858 class WeakMember : public Member<T> { |
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
865 this->checkPointer(); | 902 this->checkPointer(); |
866 return *this; | 903 return *this; |
867 } | 904 } |
868 | 905 |
869 WeakMember& operator=(std::nullptr_t) | 906 WeakMember& operator=(std::nullptr_t) |
870 { | 907 { |
871 this->m_raw = nullptr; | 908 this->m_raw = nullptr; |
872 return *this; | 909 return *this; |
873 } | 910 } |
874 | 911 |
| 912 // TODO(peria): Remove this get() and use unsafeGet() at only |
| 913 // where it is required. |
| 914 T* get() const |
| 915 { |
| 916 // WeakMember may point to a dead object, so we skip the verification. |
| 917 return Member<T>::unsafeGet(); |
| 918 } |
| 919 |
875 private: | 920 private: |
876 T** cell() const { return const_cast<T**>(&this->m_raw); } | 921 T** cell() const { return const_cast<T**>(&this->m_raw); } |
877 | 922 |
878 template<typename Derived> friend class VisitorHelper; | 923 template<typename Derived> friend class VisitorHelper; |
879 }; | 924 }; |
880 | 925 |
881 // UntracedMember is a pointer to an on-heap object that is not traced for some | 926 // UntracedMember is a pointer to an on-heap object that is not traced for some |
882 // reason. Please don't use this unless you understand what you're doing. | 927 // reason. Please don't use this unless you understand what you're doing. |
883 // Basically, all pointers to on-heap objects must be stored in either of | 928 // Basically, all pointers to on-heap objects must be stored in either of |
884 // Persistent, Member or WeakMember. It is not allowed to leave raw pointers to | 929 // Persistent, Member or WeakMember. It is not allowed to leave raw pointers to |
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
939 } | 984 } |
940 | 985 |
941 UntracedMember& operator=(std::nullptr_t) | 986 UntracedMember& operator=(std::nullptr_t) |
942 { | 987 { |
943 this->m_raw = nullptr; | 988 this->m_raw = nullptr; |
944 return *this; | 989 return *this; |
945 } | 990 } |
946 }; | 991 }; |
947 | 992 |
948 // Comparison operators between (Weak)Members, Persistents, and UntracedMembers. | 993 // Comparison operators between (Weak)Members, Persistents, and UntracedMembers. |
949 template<typename T, typename U> inline bool operator==(const Member<T>& a, cons
t Member<U>& b) { return a.get() == b.get(); } | 994 template<typename T, typename U> inline bool operator==(const Member<T>& a, cons
t Member<U>& b) { return a.unsafeGet() == b.unsafeGet(); } |
950 template<typename T, typename U> inline bool operator!=(const Member<T>& a, cons
t Member<U>& b) { return a.get() != b.get(); } | 995 template<typename T, typename U> inline bool operator!=(const Member<T>& a, cons
t Member<U>& b) { return a.unsafeGet() != b.unsafeGet(); } |
951 template<typename T, typename U> inline bool operator==(const Persistent<T>& a,
const Persistent<U>& b) { return a.get() == b.get(); } | 996 template<typename T, typename U> inline bool operator==(const Persistent<T>& a,
const Persistent<U>& b) { return a.get() == b.get(); } |
952 template<typename T, typename U> inline bool operator!=(const Persistent<T>& a,
const Persistent<U>& b) { return a.get() != b.get(); } | 997 template<typename T, typename U> inline bool operator!=(const Persistent<T>& a,
const Persistent<U>& b) { return a.get() != b.get(); } |
953 | 998 |
954 template<typename T, typename U> inline bool operator==(const Member<T>& a, cons
t Persistent<U>& b) { return a.get() == b.get(); } | 999 template<typename T, typename U> inline bool operator==(const Member<T>& a, cons
t Persistent<U>& b) { return a.unsafeGet() == b.get(); } |
955 template<typename T, typename U> inline bool operator!=(const Member<T>& a, cons
t Persistent<U>& b) { return a.get() != b.get(); } | 1000 template<typename T, typename U> inline bool operator!=(const Member<T>& a, cons
t Persistent<U>& b) { return a.unsafeGet() != b.get(); } |
956 template<typename T, typename U> inline bool operator==(const Persistent<T>& a,
const Member<U>& b) { return a.get() == b.get(); } | 1001 template<typename T, typename U> inline bool operator==(const Persistent<T>& a,
const Member<U>& b) { return a.get() == b.unsafeGet(); } |
957 template<typename T, typename U> inline bool operator!=(const Persistent<T>& a,
const Member<U>& b) { return a.get() != b.get(); } | 1002 template<typename T, typename U> inline bool operator!=(const Persistent<T>& a,
const Member<U>& b) { return a.get() != b.unsafeGet(); } |
958 | 1003 |
959 template<typename T> | 1004 template<typename T> |
960 class DummyBase { | 1005 class DummyBase { |
961 public: | 1006 public: |
962 DummyBase() { } | 1007 DummyBase() { } |
963 ~DummyBase() { } | 1008 ~DummyBase() { } |
964 }; | 1009 }; |
965 | 1010 |
966 // We need this explicit instantiation for component build on Windows. | 1011 // We need this explicit instantiation for component build on Windows. |
967 template<> | 1012 template<> |
(...skipping 439 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1407 | 1452 |
1408 template<typename T> struct PtrHash<blink::Member<T>> : PtrHash<T*> { | 1453 template<typename T> struct PtrHash<blink::Member<T>> : PtrHash<T*> { |
1409 template<typename U> | 1454 template<typename U> |
1410 static unsigned hash(const U& key) { return PtrHash<T*>::hash(key); } | 1455 static unsigned hash(const U& key) { return PtrHash<T*>::hash(key); } |
1411 static bool equal(T* a, const blink::Member<T>& b) { return a == b; } | 1456 static bool equal(T* a, const blink::Member<T>& b) { return a == b; } |
1412 static bool equal(const blink::Member<T>& a, T* b) { return a == b; } | 1457 static bool equal(const blink::Member<T>& a, T* b) { return a == b; } |
1413 template<typename U, typename V> | 1458 template<typename U, typename V> |
1414 static bool equal(const U& a, const V& b) { return a == b; } | 1459 static bool equal(const U& a, const V& b) { return a == b; } |
1415 }; | 1460 }; |
1416 | 1461 |
1417 template<typename T> struct PtrHash<blink::WeakMember<T>> : PtrHash<blink::Membe
r<T>> { | 1462 template<typename T> struct PtrHash<blink::WeakMember<T>> : PtrHash<blink::Membe
r<T>> { }; |
1418 }; | |
1419 | 1463 |
1420 template<typename T> struct PtrHash<blink::UntracedMember<T>> : PtrHash<blink::M
ember<T>> { | 1464 template<typename T> struct PtrHash<blink::UntracedMember<T>> : PtrHash<blink::M
ember<T>> { }; |
1421 }; | |
1422 | 1465 |
1423 // PtrHash is the default hash for hash tables with members. | 1466 // PtrHash is the default hash for hash tables with members. |
1424 template<typename T> struct DefaultHash<blink::Member<T>> { | 1467 template<typename T> struct DefaultHash<blink::Member<T>> { |
1425 using Hash = PtrHash<blink::Member<T>>; | 1468 using Hash = PtrHash<blink::Member<T>>; |
1426 }; | 1469 }; |
1427 | 1470 |
1428 template<typename T> struct DefaultHash<blink::WeakMember<T>> { | 1471 template<typename T> struct DefaultHash<blink::WeakMember<T>> { |
1429 using Hash = PtrHash<blink::WeakMember<T>>; | 1472 using Hash = PtrHash<blink::WeakMember<T>>; |
1430 }; | 1473 }; |
1431 | 1474 |
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1504 // TODO(sof): extend WTF::FunctionWrapper call overloading to also handle (C
rossThread)WeakPersistent. | 1547 // TODO(sof): extend WTF::FunctionWrapper call overloading to also handle (C
rossThread)WeakPersistent. |
1505 static T* unwrap(const StorageType& value) { return value.get(); } | 1548 static T* unwrap(const StorageType& value) { return value.get(); } |
1506 }; | 1549 }; |
1507 | 1550 |
1508 template<typename T> | 1551 template<typename T> |
1509 PassRefPtr<T> adoptRef(blink::RefCountedGarbageCollected<T>*) = delete; | 1552 PassRefPtr<T> adoptRef(blink::RefCountedGarbageCollected<T>*) = delete; |
1510 | 1553 |
1511 } // namespace WTF | 1554 } // namespace WTF |
1512 | 1555 |
1513 #endif | 1556 #endif |
OLD | NEW |