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 756 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
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 | 774 T* get() const |
775 { | 775 { |
776 static_assert(IsFullyDefined<T>::value, "T is not fully defined."); | 776 static_assert(IsFullyDefined<T>::value, "T is not fully defined."); |
777 #if ENABLE(ASSERT) && defined(ADDRESS_SANITIZER) | |
778 // Verify that this handle points to a live on-heap object, if a pointer | |
779 // has been assigned to this handle out of GarbageCollectedMixin constru ctions. | |
780 if (m_raw && m_gcGeneration != gcGenerationUnchecked && !ThreadState::cu rrent()->isConstructingGCMixin()) { | |
781 HeapObjectHeader* header = HeapObjectHeaderTrait<T>::heapObjectHeade r(m_raw); | |
782 ASSERT(m_gcGeneration == header->gcGeneration()); | |
783 } | |
784 #endif | |
777 return m_raw; | 785 return m_raw; |
778 } | 786 } |
779 | 787 |
780 void clear() { m_raw = nullptr; } | 788 // This method is an accessor without any security checks, and it is |
789 // expected to be used under some limited condition. | |
790 // So do NOT use it, if you do not know what it means. | |
791 // TODO(peria): We should remove this method. | |
792 T* unsafeGet() const | |
793 { | |
794 return m_raw; | |
795 } | |
781 | 796 |
797 void clear() | |
798 { | |
799 m_raw = nullptr; | |
800 } | |
782 | 801 |
783 protected: | 802 protected: |
784 void checkPointer() | 803 void checkPointer() |
haraken
2015/11/20 01:59:06
In a follow-up CL, can you rename this to setPoint
peria
2015/11/20 02:27:00
Acknowledged.
| |
785 { | 804 { |
786 static_assert(IsFullyDefined<T>::value, "T is not fully defined."); | 805 static_assert(IsFullyDefined<T>::value, "T is not fully defined."); |
787 | 806 |
788 #if ENABLE(ASSERT) && defined(ADDRESS_SANITIZER) | 807 #if ENABLE(ASSERT) && defined(ADDRESS_SANITIZER) |
789 if (!m_raw) | 808 if (!m_raw) |
790 return; | 809 return; |
791 // HashTable can store a special value (which is not aligned to the | 810 // HashTable can store a special value (which is not aligned to the |
792 // allocation granularity) to Member<> to represent a deleted entry. | 811 // allocation granularity) to Member<> to represent a deleted entry. |
793 // Thus we treat a pointer that is not aligned to the granularity | 812 // Thus we treat a pointer that is not aligned to the granularity |
794 // as a valid pointer. | 813 // as a valid pointer. |
795 if (reinterpret_cast<intptr_t>(m_raw) % allocationGranularity) | 814 if (reinterpret_cast<intptr_t>(m_raw) % allocationGranularity) |
796 return; | 815 return; |
797 | 816 |
798 // TODO(haraken): What we really want to check here is that the pointer | 817 // m_gcGeneration verifies use-after-free of this Member handle. |
799 // is a traceable object. In other words, the pointer is either of: | 818 // If m_gcGeneration is gcGenerationForFreeListEntry or m_raw is |
800 // | 819 // nullptr, the verification is skipped. |
haraken
2015/11/20 01:59:06
gcGenerationForFreeListEntry => gcGenerationUnchec
peria
2015/11/20 02:27:00
Done.
| |
801 // (a) a pointer to the head of an on-heap object. | 820 // For technical reason, we set gcGenerationForFreeListEntry in |
802 // (b) a pointer to the head of an on-heap mixin object. | 821 // m_gcGeneration in case that this method is called in a constructor |
803 // | 822 // of a GCMixin object. |
haraken
2015/11/20 01:59:06
We set gcGenerationUnchecked while constructing a
peria
2015/11/20 04:14:50
Done.
| |
804 // We can check it by calling Heap::isHeapObjectAlive(m_raw), | 823 // TODO(peria): Set m_gcGeneration even if this is called in a |
805 // but we cannot call it here because it requires to include T.h. | 824 // GCMixin constructor. |
806 // So we currently only try to implement the check for (a), but do | 825 m_gcGeneration = gcGenerationUnchecked; |
807 // not insist that T's definition is in scope. | 826 if (IsFullyDefined<T>::value && !ThreadState::current()->isConstructingG CMixin()) { |
haraken
2015/11/20 01:59:06
Remove the IsFullyDefined<T>::value check. As we d
peria
2015/11/20 02:27:00
Done.
And it is checked statically at the beginnin
| |
808 if (IsFullyDefined<T>::value && !IsGarbageCollectedMixin<T>::value) | 827 HeapObjectHeader* header = HeapObjectHeaderTrait<T>::heapObjectHeade r(m_raw); |
809 ASSERT(HeapObjectHeader::fromPayload(m_raw)->checkHeader()); | 828 m_gcGeneration = header->gcGeneration(); |
829 ASSERT(m_gcGeneration != gcGenerationForFreeListEntry); | |
830 } | |
810 #endif | 831 #endif |
811 } | 832 } |
812 | 833 |
813 T* m_raw; | 834 T* m_raw; |
814 | 835 |
836 #if ENABLE(ASSERT) && defined(ADDRESS_SANITIZER) | |
837 uint32_t m_gcGeneration; | |
838 #endif | |
839 | |
815 template<bool x, WTF::WeakHandlingFlag y, WTF::ShouldWeakPointersBeMarkedStr ongly z, typename U, typename V> friend struct CollectionBackingTraceTrait; | 840 template<bool x, WTF::WeakHandlingFlag y, WTF::ShouldWeakPointersBeMarkedStr ongly z, typename U, typename V> friend struct CollectionBackingTraceTrait; |
816 friend class Visitor; | 841 friend class Visitor; |
817 | |
818 }; | 842 }; |
819 | 843 |
820 // WeakMember is similar to Member in that it is used to point to other oilpan | 844 // WeakMember is similar to Member in that it is used to point to other oilpan |
821 // heap allocated objects. | 845 // heap allocated objects. |
822 // However instead of creating a strong pointer to the object, the WeakMember cr eates | 846 // However instead of creating a strong pointer to the object, the WeakMember cr eates |
823 // a weak pointer, which does not keep the pointee alive. Hence if all pointers to | 847 // a weak pointer, which does not keep the pointee alive. Hence if all pointers to |
824 // to a heap allocated object are weak the object will be garbage collected. At the | 848 // to a heap allocated object are weak the object will be garbage collected. At the |
825 // time of GC the weak pointers will automatically be set to null. | 849 // time of GC the weak pointers will automatically be set to null. |
826 template<typename T> | 850 template<typename T> |
827 class WeakMember : public Member<T> { | 851 class WeakMember : public Member<T> { |
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
871 this->checkPointer(); | 895 this->checkPointer(); |
872 return *this; | 896 return *this; |
873 } | 897 } |
874 | 898 |
875 WeakMember& operator=(std::nullptr_t) | 899 WeakMember& operator=(std::nullptr_t) |
876 { | 900 { |
877 this->m_raw = nullptr; | 901 this->m_raw = nullptr; |
878 return *this; | 902 return *this; |
879 } | 903 } |
880 | 904 |
905 // TODO(peria): Remove this get() and use unsafeGet() at only | |
906 // where it is required. | |
907 T* get() const | |
908 { | |
909 // WeakMember may point to a dead object, so we skip the verification. | |
910 return Member<T>::unsafeGet(); | |
911 } | |
912 | |
881 private: | 913 private: |
882 T** cell() const { return const_cast<T**>(&this->m_raw); } | 914 T** cell() const { return const_cast<T**>(&this->m_raw); } |
883 | 915 |
884 template<typename Derived> friend class VisitorHelper; | 916 template<typename Derived> friend class VisitorHelper; |
885 }; | 917 }; |
886 | 918 |
887 // UntracedMember is a pointer to an on-heap object that is not traced for some | 919 // UntracedMember is a pointer to an on-heap object that is not traced for some |
888 // reason. Please don't use this unless you understand what you're doing. | 920 // reason. Please don't use this unless you understand what you're doing. |
889 // Basically, all pointers to on-heap objects must be stored in either of | 921 // Basically, all pointers to on-heap objects must be stored in either of |
890 // Persistent, Member or WeakMember. It is not allowed to leave raw pointers to | 922 // 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... | |
945 } | 977 } |
946 | 978 |
947 UntracedMember& operator=(std::nullptr_t) | 979 UntracedMember& operator=(std::nullptr_t) |
948 { | 980 { |
949 this->m_raw = nullptr; | 981 this->m_raw = nullptr; |
950 return *this; | 982 return *this; |
951 } | 983 } |
952 }; | 984 }; |
953 | 985 |
954 // Comparison operators between (Weak)Members, Persistents, and UntracedMembers. | 986 // Comparison operators between (Weak)Members, Persistents, and UntracedMembers. |
955 template<typename T, typename U> inline bool operator==(const Member<T>& a, cons t Member<U>& b) { return a.get() == b.get(); } | 987 template<typename T, typename U> inline bool operator==(const Member<T>& a, cons t Member<U>& b) { return a.unsafeGet() == b.unsafeGet(); } |
956 template<typename T, typename U> inline bool operator!=(const Member<T>& a, cons t Member<U>& b) { return a.get() != b.get(); } | 988 template<typename T, typename U> inline bool operator!=(const Member<T>& a, cons t Member<U>& b) { return a.unsafeGet() != b.unsafeGet(); } |
957 template<typename T, typename U> inline bool operator==(const Persistent<T>& a, const Persistent<U>& b) { return a.get() == b.get(); } | 989 template<typename T, typename U> inline bool operator==(const Persistent<T>& a, const Persistent<U>& b) { return a.get() == b.get(); } |
958 template<typename T, typename U> inline bool operator!=(const Persistent<T>& a, const Persistent<U>& b) { return a.get() != b.get(); } | 990 template<typename T, typename U> inline bool operator!=(const Persistent<T>& a, const Persistent<U>& b) { return a.get() != b.get(); } |
959 | 991 |
960 template<typename T, typename U> inline bool operator==(const Member<T>& a, cons t Persistent<U>& b) { return a.get() == b.get(); } | 992 template<typename T, typename U> inline bool operator==(const Member<T>& a, cons t Persistent<U>& b) { return a.unsafeGet() == b.get(); } |
961 template<typename T, typename U> inline bool operator!=(const Member<T>& a, cons t Persistent<U>& b) { return a.get() != b.get(); } | 993 template<typename T, typename U> inline bool operator!=(const Member<T>& a, cons t Persistent<U>& b) { return a.unsafeGet() != b.get(); } |
962 template<typename T, typename U> inline bool operator==(const Persistent<T>& a, const Member<U>& b) { return a.get() == b.get(); } | 994 template<typename T, typename U> inline bool operator==(const Persistent<T>& a, const Member<U>& b) { return a.get() == b.unsafeGet(); } |
963 template<typename T, typename U> inline bool operator!=(const Persistent<T>& a, const Member<U>& b) { return a.get() != b.get(); } | 995 template<typename T, typename U> inline bool operator!=(const Persistent<T>& a, const Member<U>& b) { return a.get() != b.unsafeGet(); } |
964 | 996 |
965 template<typename T> | 997 template<typename T> |
966 class DummyBase { | 998 class DummyBase { |
967 public: | 999 public: |
968 DummyBase() { } | 1000 DummyBase() { } |
969 ~DummyBase() { } | 1001 ~DummyBase() { } |
970 }; | 1002 }; |
971 | 1003 |
972 // We need this explicit instantiation for component build on Windows. | 1004 // We need this explicit instantiation for component build on Windows. |
973 template<> | 1005 template<> |
(...skipping 439 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1413 | 1445 |
1414 template<typename T> struct PtrHash<blink::Member<T>> : PtrHash<T*> { | 1446 template<typename T> struct PtrHash<blink::Member<T>> : PtrHash<T*> { |
1415 template<typename U> | 1447 template<typename U> |
1416 static unsigned hash(const U& key) { return PtrHash<T*>::hash(key); } | 1448 static unsigned hash(const U& key) { return PtrHash<T*>::hash(key); } |
1417 static bool equal(T* a, const blink::Member<T>& b) { return a == b; } | 1449 static bool equal(T* a, const blink::Member<T>& b) { return a == b; } |
1418 static bool equal(const blink::Member<T>& a, T* b) { return a == b; } | 1450 static bool equal(const blink::Member<T>& a, T* b) { return a == b; } |
1419 template<typename U, typename V> | 1451 template<typename U, typename V> |
1420 static bool equal(const U& a, const V& b) { return a == b; } | 1452 static bool equal(const U& a, const V& b) { return a == b; } |
1421 }; | 1453 }; |
1422 | 1454 |
1423 template<typename T> struct PtrHash<blink::WeakMember<T>> : PtrHash<blink::Membe r<T>> { | 1455 template<typename T> struct PtrHash<blink::WeakMember<T>> : PtrHash<blink::Membe r<T>> { }; |
1424 }; | |
1425 | 1456 |
1426 template<typename T> struct PtrHash<blink::UntracedMember<T>> : PtrHash<blink::M ember<T>> { | 1457 template<typename T> struct PtrHash<blink::UntracedMember<T>> : PtrHash<blink::M ember<T>> { }; |
1427 }; | |
1428 | 1458 |
1429 // PtrHash is the default hash for hash tables with members. | 1459 // PtrHash is the default hash for hash tables with members. |
1430 template<typename T> struct DefaultHash<blink::Member<T>> { | 1460 template<typename T> struct DefaultHash<blink::Member<T>> { |
1431 using Hash = PtrHash<blink::Member<T>>; | 1461 using Hash = PtrHash<blink::Member<T>>; |
1432 }; | 1462 }; |
1433 | 1463 |
1434 template<typename T> struct DefaultHash<blink::WeakMember<T>> { | 1464 template<typename T> struct DefaultHash<blink::WeakMember<T>> { |
1435 using Hash = PtrHash<blink::WeakMember<T>>; | 1465 using Hash = PtrHash<blink::WeakMember<T>>; |
1436 }; | 1466 }; |
1437 | 1467 |
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1510 // TODO(sof): extend WTF::FunctionWrapper call overloading to also handle (C rossThread)WeakPersistent. | 1540 // TODO(sof): extend WTF::FunctionWrapper call overloading to also handle (C rossThread)WeakPersistent. |
1511 static T* unwrap(const StorageType& value) { return value.get(); } | 1541 static T* unwrap(const StorageType& value) { return value.get(); } |
1512 }; | 1542 }; |
1513 | 1543 |
1514 template<typename T> | 1544 template<typename T> |
1515 PassRefPtr<T> adoptRef(blink::RefCountedGarbageCollected<T>*) = delete; | 1545 PassRefPtr<T> adoptRef(blink::RefCountedGarbageCollected<T>*) = delete; |
1516 | 1546 |
1517 } // namespace WTF | 1547 } // namespace WTF |
1518 | 1548 |
1519 #endif | 1549 #endif |
OLD | NEW |