Chromium Code Reviews| 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 |