Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(13)

Side by Side Diff: third_party/WebKit/Source/platform/heap/Persistent.h

Issue 1999363002: Split out Members, Persistents and SelfKeepAlive in separate headers. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@sof-gc-type
Patch Set: rebased Created 4 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 /* 1 // Copyright 2016 The Chromium Authors. All rights reserved.
2 * Copyright (C) 2014 Google Inc. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be
3 * 3 // found in the LICENSE file.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are
6 * met:
7 *
8 * * Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * * Redistributions in binary form must reproduce the above
11 * copyright notice, this list of conditions and the following disclaimer
12 * in the documentation and/or other materials provided with the
13 * distribution.
14 * * Neither the name of Google Inc. nor the names of its
15 * contributors may be used to endorse or promote products derived from
16 * this software without specific prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
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.
29 */
30 4
31 #ifndef Handle_h 5 #ifndef Persistent_h
32 #define Handle_h 6 #define Persistent_h
33 7
34 #include "platform/heap/Heap.h" 8 #include "platform/heap/Member.h"
35 #include "platform/heap/HeapAllocator.h"
36 #include "platform/heap/InlinedGlobalMarkingVisitor.h"
37 #include "platform/heap/PersistentNode.h" 9 #include "platform/heap/PersistentNode.h"
38 #include "platform/heap/ThreadState.h"
39 #include "platform/heap/TraceTraits.h"
40 #include "platform/heap/Visitor.h"
41 #include "wtf/Allocator.h" 10 #include "wtf/Allocator.h"
42 #include "wtf/Atomics.h" 11 #include "wtf/Atomics.h"
43 #include "wtf/HashFunctions.h"
44
45 #if defined(LEAK_SANITIZER)
46 #include "wtf/LeakAnnotations.h"
47 #endif
48 12
49 namespace blink { 13 namespace blink {
50 14
51 // Marker used to annotate persistent objects and collections with, 15 // Marker used to annotate persistent objects and collections with,
52 // so as to enable reliable testing for persistent references via 16 // so as to enable reliable testing for persistent references via
53 // a type trait (see TypeTraits.h's IsPersistentReferenceType<>.) 17 // a type trait (see TypeTraits.h's IsPersistentReferenceType<>.)
54 #define IS_PERSISTENT_REFERENCE_TYPE() \ 18 #define IS_PERSISTENT_REFERENCE_TYPE() \
55 public: \ 19 public: \
56 using IsPersistentReferenceTypeMarker = int; \ 20 using IsPersistentReferenceTypeMarker = int; \
57 private: 21 private:
(...skipping 600 matching lines...) Expand 10 before | Expand all | Expand 10 after
658 public: 622 public:
659 PersistentHeapDeque() { } 623 PersistentHeapDeque() { }
660 624
661 template<size_t otherCapacity> 625 template<size_t otherCapacity>
662 PersistentHeapDeque(const HeapDeque<T, otherCapacity>& other) 626 PersistentHeapDeque(const HeapDeque<T, otherCapacity>& other)
663 : PersistentHeapCollectionBase<HeapDeque<T, inlineCapacity>>(other) 627 : PersistentHeapCollectionBase<HeapDeque<T, inlineCapacity>>(other)
664 { 628 {
665 } 629 }
666 }; 630 };
667 631
668 // Members are used in classes to contain strong pointers to other oilpan heap
669 // allocated objects.
670 // All Member fields of a class must be traced in the class' trace method.
671 // During the mark phase of the GC all live objects are marked as live and
672 // all Member fields of a live object will be traced marked as live as well.
673 template<typename T>
674 class Member {
675 DISALLOW_NEW_EXCEPT_PLACEMENT_NEW();
676 public:
677 Member() : m_raw(nullptr)
678 {
679 }
680
681 Member(std::nullptr_t) : m_raw(nullptr)
682 {
683 }
684
685 Member(T* raw) : m_raw(raw)
686 {
687 checkPointer();
688 }
689
690 explicit Member(T& raw) : m_raw(&raw)
691 {
692 checkPointer();
693 }
694
695 Member(WTF::HashTableDeletedValueType) : m_raw(reinterpret_cast<T*>(-1))
696 {
697 }
698
699 bool isHashTableDeletedValue() const { return m_raw == reinterpret_cast<T*>( -1); }
700
701 template<typename U>
702 Member(const Persistent<U>& other) : m_raw(other)
703 {
704 checkPointer();
705 }
706
707 Member(const Member& other) : m_raw(other)
708 {
709 checkPointer();
710 }
711
712 template<typename U>
713 Member(const Member<U>& other) : m_raw(other)
714 {
715 checkPointer();
716 }
717
718 T* release()
719 {
720 T* result = m_raw;
721 m_raw = nullptr;
722 return result;
723 }
724
725 explicit operator bool() const { return m_raw; }
726
727 operator T*() const { return m_raw; }
728
729 T* operator->() const { return m_raw; }
730 T& operator*() const { return *m_raw; }
731
732 template<typename U>
733 Member& operator=(const Persistent<U>& other)
734 {
735 m_raw = other;
736 checkPointer();
737 return *this;
738 }
739
740 template<typename U>
741 Member& operator=(const Member<U>& other)
742 {
743 m_raw = other;
744 checkPointer();
745 return *this;
746 }
747
748 template<typename U>
749 Member& operator=(U* other)
750 {
751 m_raw = other;
752 checkPointer();
753 return *this;
754 }
755
756 Member& operator=(std::nullptr_t)
757 {
758 m_raw = nullptr;
759 return *this;
760 }
761
762 void swap(Member<T>& other)
763 {
764 std::swap(m_raw, other.m_raw);
765 checkPointer();
766 }
767
768 T* get() const { return m_raw; }
769
770 void clear() { m_raw = nullptr; }
771
772
773 protected:
774 void checkPointer()
775 {
776 #if ENABLE(ASSERT) && defined(ADDRESS_SANITIZER)
777 if (!m_raw)
778 return;
779 // HashTable can store a special value (which is not aligned to the
780 // allocation granularity) to Member<> to represent a deleted entry.
781 // Thus we treat a pointer that is not aligned to the granularity
782 // as a valid pointer.
783 if (reinterpret_cast<intptr_t>(m_raw) % allocationGranularity)
784 return;
785
786 // TODO(haraken): What we really want to check here is that the pointer
787 // is a traceable object. In other words, the pointer is either of:
788 //
789 // (a) a pointer to the head of an on-heap object.
790 // (b) a pointer to the head of an on-heap mixin object.
791 //
792 // We can check it by calling ThreadHeap::isHeapObjectAlive(m_raw),
793 // but we cannot call it here because it requires to include T.h.
794 // So we currently only try to implement the check for (a), but do
795 // not insist that T's definition is in scope.
796 if (IsFullyDefined<T>::value && !IsGarbageCollectedMixin<T>::value)
797 ASSERT(HeapObjectHeader::fromPayload(m_raw)->checkHeader());
798 #endif
799 }
800
801 T* m_raw;
802
803 template<bool x, WTF::WeakHandlingFlag y, WTF::ShouldWeakPointersBeMarkedStr ongly z, typename U, typename V> friend struct CollectionBackingTraceTrait;
804 friend class Visitor;
805
806 };
807
808 // WeakMember is similar to Member in that it is used to point to other oilpan
809 // heap allocated objects.
810 // However instead of creating a strong pointer to the object, the WeakMember cr eates
811 // a weak pointer, which does not keep the pointee alive. Hence if all pointers to
812 // to a heap allocated object are weak the object will be garbage collected. At the
813 // time of GC the weak pointers will automatically be set to null.
814 template<typename T>
815 class WeakMember : public Member<T> {
816 public:
817 WeakMember() : Member<T>() { }
818
819 WeakMember(std::nullptr_t) : Member<T>(nullptr) { }
820
821 WeakMember(T* raw) : Member<T>(raw) { }
822
823 WeakMember(WTF::HashTableDeletedValueType x) : Member<T>(x) { }
824
825 template<typename U>
826 WeakMember(const Persistent<U>& other) : Member<T>(other) { }
827
828 template<typename U>
829 WeakMember(const Member<U>& other) : Member<T>(other) { }
830
831 template<typename U>
832 WeakMember& operator=(const Persistent<U>& other)
833 {
834 this->m_raw = other;
835 this->checkPointer();
836 return *this;
837 }
838
839 template<typename U>
840 WeakMember& operator=(const Member<U>& other)
841 {
842 this->m_raw = other;
843 this->checkPointer();
844 return *this;
845 }
846
847 template<typename U>
848 WeakMember& operator=(U* other)
849 {
850 this->m_raw = other;
851 this->checkPointer();
852 return *this;
853 }
854
855 WeakMember& operator=(std::nullptr_t)
856 {
857 this->m_raw = nullptr;
858 return *this;
859 }
860
861 private:
862 T** cell() const { return const_cast<T**>(&this->m_raw); }
863
864 template<typename Derived> friend class VisitorHelper;
865 };
866
867 // UntracedMember is a pointer to an on-heap object that is not traced for some
868 // reason. Please don't use this unless you understand what you're doing.
869 // Basically, all pointers to on-heap objects must be stored in either of
870 // Persistent, Member or WeakMember. It is not allowed to leave raw pointers to
871 // on-heap objects. However, there can be scenarios where you have to use raw
872 // pointers for some reason, and in that case you can use UntracedMember. Of
873 // course, it must be guaranteed that the pointing on-heap object is kept alive
874 // while the raw pointer is pointing to the object.
875 template<typename T>
876 class UntracedMember final : public Member<T> {
877 public:
878 UntracedMember() : Member<T>() { }
879
880 UntracedMember(std::nullptr_t) : Member<T>(nullptr) { }
881
882 UntracedMember(T* raw) : Member<T>(raw) { }
883
884 template<typename U>
885 UntracedMember(const Persistent<U>& other) : Member<T>(other) { }
886
887 template<typename U>
888 UntracedMember(const Member<U>& other) : Member<T>(other) { }
889
890 UntracedMember(WTF::HashTableDeletedValueType x) : Member<T>(x) { }
891
892 template<typename U>
893 UntracedMember& operator=(const Persistent<U>& other)
894 {
895 this->m_raw = other;
896 this->checkPointer();
897 return *this;
898 }
899
900 template<typename U>
901 UntracedMember& operator=(const Member<U>& other)
902 {
903 this->m_raw = other;
904 this->checkPointer();
905 return *this;
906 }
907
908 template<typename U>
909 UntracedMember& operator=(U* other)
910 {
911 this->m_raw = other;
912 this->checkPointer();
913 return *this;
914 }
915
916 UntracedMember& operator=(std::nullptr_t)
917 {
918 this->m_raw = nullptr;
919 return *this;
920 }
921 };
922
923 // Comparison operators between (Weak)Members, Persistents, and UntracedMembers.
924 template<typename T, typename U> inline bool operator==(const Member<T>& a, cons t Member<U>& b) { return a.get() == b.get(); }
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 Persistent<T>& a, const Persistent<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
929 template<typename T, typename U> inline bool operator==(const Member<T>& a, cons t Persistent<U>& b) { return a.get() == b.get(); }
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 Persistent<T>& a, const Member<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
934 template<typename T, bool = IsGarbageCollectedType<T>::value>
935 class RawPtrOrMemberTrait {
936 STATIC_ONLY(RawPtrOrMemberTrait)
937 public:
938 using Type = T*;
939 };
940
941 template<typename T>
942 class RawPtrOrMemberTrait<T, true> {
943 STATIC_ONLY(RawPtrOrMemberTrait)
944 public:
945 using Type = Member<T>;
946 };
947
948 // Abstraction for injecting calls to an object's 'dispose()' method
949 // on leaving a stack scope, ensuring earlier release of resources
950 // than waiting until the object is eventually GCed.
951 template<typename T, void (T::*Disposer)() = (&T::dispose)>
952 class ScopedDisposal {
953 STACK_ALLOCATED();
954 public:
955 ScopedDisposal(T* object)
956 : m_object(object)
957 {
958 }
959
960 ~ScopedDisposal()
961 {
962 if (m_object)
963 (m_object->*Disposer)();
964 }
965
966 void clear() { m_object.clear(); }
967
968 private:
969 typename RawPtrOrMemberTrait<T>::Type m_object;
970 };
971
972 // SelfKeepAlive<Object> is the idiom to use for objects that have to keep
973 // themselves temporarily alive and cannot rely on there being some
974 // external reference in that interval:
975 //
976 // class Opener {
977 // public:
978 // ...
979 // void open()
980 // {
981 // // Retain a self-reference while in an open()ed state:
982 // m_keepAlive = this;
983 // ....
984 // }
985 //
986 // void close()
987 // {
988 // // Clear self-reference that ensured we were kept alive while opened.
989 // m_keepAlive.clear();
990 // ....
991 // }
992 //
993 // private:
994 // ...
995 // SelfKeepAlive m_keepAlive;
996 // };
997 //
998 // The responsibility to call clear() in a timely fashion resides with the imple mentation
999 // of the object.
1000 //
1001 //
1002 template<typename Self>
1003 class SelfKeepAlive final {
1004 DISALLOW_NEW();
1005 public:
1006 SelfKeepAlive()
1007 {
1008 }
1009
1010 explicit SelfKeepAlive(Self* self)
1011 {
1012 assign(self);
1013 }
1014
1015 SelfKeepAlive& operator=(Self* self)
1016 {
1017 assign(self);
1018 return *this;
1019 }
1020
1021 void clear()
1022 {
1023 m_keepAlive.clear();
1024 }
1025
1026 typedef Persistent<Self> (SelfKeepAlive::*UnspecifiedBoolType);
1027 operator UnspecifiedBoolType() const { return m_keepAlive ? &SelfKeepAlive:: m_keepAlive : 0; }
1028
1029 private:
1030 void assign(Self* self)
1031 {
1032 ASSERT(!m_keepAlive || m_keepAlive.get() == self);
1033 m_keepAlive = self;
1034 }
1035
1036 GC_PLUGIN_IGNORE("420515")
1037 Persistent<Self> m_keepAlive;
1038 };
1039
1040 // Only a very reduced form of weak heap object references can currently be held 632 // Only a very reduced form of weak heap object references can currently be held
1041 // by WTF::Closure<>s. i.e., bound as a 'this' pointer only. 633 // by WTF::Closure<>s. i.e., bound as a 'this' pointer only.
1042 // 634 //
1043 // TODO(sof): once wtf/Functional.h is able to work over platform/heap/ types 635 // TODO(sof): once wtf/Functional.h is able to work over platform/heap/ types
1044 // (like CrossThreadWeakPersistent<>), drop the restriction on weak persistent 636 // (like CrossThreadWeakPersistent<>), drop the restriction on weak persistent
1045 // use by function closures (and rename this ad-hoc type.) 637 // use by function closures (and rename this ad-hoc type.)
1046 template<typename T> 638 template<typename T>
1047 class WeakPersistentThisPointer { 639 class WeakPersistentThisPointer {
1048 STACK_ALLOCATED(); 640 STACK_ALLOCATED();
1049 public: 641 public:
(...skipping 18 matching lines...) Expand all
1068 { 660 {
1069 return Persistent<T>(value); 661 return Persistent<T>(value);
1070 } 662 }
1071 663
1072 template <typename T> 664 template <typename T>
1073 CrossThreadPersistent<T> wrapCrossThreadPersistent(T* value) 665 CrossThreadPersistent<T> wrapCrossThreadPersistent(T* value)
1074 { 666 {
1075 return CrossThreadPersistent<T>(value); 667 return CrossThreadPersistent<T>(value);
1076 } 668 }
1077 669
1078 // LEAK_SANITIZER_DISABLED_SCOPE: all allocations made in the current scope 670 // Comparison operators between (Weak)Members, Persistents, and UntracedMembers.
1079 // will be exempted from LSan consideration. 671 template<typename T, typename U> inline bool operator==(const Member<T>& a, cons t Member<U>& b) { return a.get() == b.get(); }
1080 // 672 template<typename T, typename U> inline bool operator!=(const Member<T>& a, cons t Member<U>& b) { return a.get() != b.get(); }
1081 // TODO(sof): move this to wtf/LeakAnnotations.h (LeakSanitizer.h?) once 673 template<typename T, typename U> inline bool operator==(const Persistent<T>& a, const Persistent<U>& b) { return a.get() == b.get(); }
1082 // wtf/ can freely call upon Oilpan functionality. 674 template<typename T, typename U> inline bool operator!=(const Persistent<T>& a, const Persistent<U>& b) { return a.get() != b.get(); }
1083 #if defined(LEAK_SANITIZER)
1084 class LeakSanitizerDisableScope {
1085 STACK_ALLOCATED();
1086 WTF_MAKE_NONCOPYABLE(LeakSanitizerDisableScope);
1087 public:
1088 LeakSanitizerDisableScope()
1089 {
1090 __lsan_disable();
1091 if (ThreadState::current())
1092 ThreadState::current()->enterStaticReferenceRegistrationDisabledScop e();
1093 }
1094 675
1095 ~LeakSanitizerDisableScope() 676 template<typename T, typename U> inline bool operator==(const Member<T>& a, cons t Persistent<U>& b) { return a.get() == b.get(); }
1096 { 677 template<typename T, typename U> inline bool operator!=(const Member<T>& a, cons t Persistent<U>& b) { return a.get() != b.get(); }
1097 __lsan_enable(); 678 template<typename T, typename U> inline bool operator==(const Persistent<T>& a, const Member<U>& b) { return a.get() == b.get(); }
1098 if (ThreadState::current()) 679 template<typename T, typename U> inline bool operator!=(const Persistent<T>& a, const Member<U>& b) { return a.get() != b.get(); }
1099 ThreadState::current()->leaveStaticReferenceRegistrationDisabledScop e();
1100 }
1101 };
1102 #define LEAK_SANITIZER_DISABLED_SCOPE LeakSanitizerDisableScope lsanDisabledScop e
1103 #else
1104 #define LEAK_SANITIZER_DISABLED_SCOPE
1105 #endif
1106 680
1107 } // namespace blink 681 } // namespace blink
1108 682
1109 namespace WTF { 683 namespace WTF {
1110 684
1111 template <typename T>
1112 struct MemberHash : PtrHash<T> {
1113 STATIC_ONLY(MemberHash);
1114 template <typename U>
1115 static unsigned hash(const U& key) { return PtrHash<T>::hash(key); }
1116 template <typename U, typename V>
1117 static bool equal(const U& a, const V& b) { return a == b; }
1118 };
1119
1120 template <typename T>
1121 struct WeakMemberHash : MemberHash<T> {
1122 STATIC_ONLY(WeakMemberHash);
1123 };
1124
1125 template <typename T>
1126 struct UntracedMemberHash : MemberHash<T> {
1127 STATIC_ONLY(UntracedMemberHash);
1128 };
1129
1130 // PtrHash is the default hash for hash tables with members.
1131 template <typename T>
1132 struct DefaultHash<blink::Member<T>> {
1133 STATIC_ONLY(DefaultHash);
1134 using Hash = MemberHash<T>;
1135 };
1136
1137 template <typename T>
1138 struct DefaultHash<blink::WeakMember<T>> {
1139 STATIC_ONLY(DefaultHash);
1140 using Hash = WeakMemberHash<T>;
1141 };
1142
1143 template <typename T>
1144 struct DefaultHash<blink::UntracedMember<T>> {
1145 STATIC_ONLY(DefaultHash);
1146 using Hash = UntracedMemberHash<T>;
1147 };
1148
1149 template<typename T>
1150 struct NeedsTracing<blink::Member<T>> {
1151 STATIC_ONLY(NeedsTracing);
1152 static const bool value = true;
1153 };
1154
1155 template<typename T>
1156 struct IsWeak<blink::WeakMember<T>> {
1157 STATIC_ONLY(IsWeak);
1158 static const bool value = true;
1159 };
1160
1161 template<typename T> 685 template<typename T>
1162 struct ParamStorageTraits<blink::WeakPersistentThisPointer<T>> { 686 struct ParamStorageTraits<blink::WeakPersistentThisPointer<T>> {
1163 STATIC_ONLY(ParamStorageTraits); 687 STATIC_ONLY(ParamStorageTraits);
1164 static_assert(sizeof(T), "T must be fully defined"); 688 static_assert(sizeof(T), "T must be fully defined");
1165 using StorageType = blink::WeakPersistent<T>; 689 using StorageType = blink::WeakPersistent<T>;
1166 690
1167 static StorageType wrap(const blink::WeakPersistentThisPointer<T>& value) { return value.value(); } 691 static StorageType wrap(const blink::WeakPersistentThisPointer<T>& value) { return value.value(); }
1168 692
1169 // WTF::FunctionWrapper<> handles WeakPtr<>, so recast this weak persistent 693 // WTF::FunctionWrapper<> handles WeakPtr<>, so recast this weak persistent
1170 // into it. 694 // into it.
(...skipping 14 matching lines...) Expand all
1185 // WTF::FunctionWrapper<> handles WeakPtr<>, so recast this weak persistent 709 // WTF::FunctionWrapper<> handles WeakPtr<>, so recast this weak persistent
1186 // into it. 710 // into it.
1187 // 711 //
1188 // TODO(sof): remove this hack once wtf/Functional.h can also work with a ty pe like 712 // TODO(sof): remove this hack once wtf/Functional.h can also work with a ty pe like
1189 // CrossThreadWeakPersistent<>. 713 // CrossThreadWeakPersistent<>.
1190 static WeakPtr<T> unwrap(const StorageType& value) { return WeakPtr<T>(WeakR eference<T>::create(value.get())); } 714 static WeakPtr<T> unwrap(const StorageType& value) { return WeakPtr<T>(WeakR eference<T>::create(value.get())); }
1191 }; 715 };
1192 716
1193 } // namespace WTF 717 } // namespace WTF
1194 718
1195 #endif 719 #endif // Persistent_h
OLDNEW
« no previous file with comments | « third_party/WebKit/Source/platform/heap/Member.h ('k') | third_party/WebKit/Source/platform/heap/SelfKeepAlive.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698