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

Side by Side Diff: Source/platform/heap/Visitor.h

Issue 980653002: Oilpan: disable conservative GCs during initial GC mixin construction. (Closed) Base URL: https://chromium.googlesource.com/chromium/blink.git@master
Patch Set: Add GC mixin test Created 5 years, 9 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
« no previous file with comments | « Source/platform/heap/ThreadState.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 /* 1 /*
2 * Copyright (C) 2013 Google Inc. All rights reserved. 2 * Copyright (C) 2013 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 879 matching lines...) Expand 10 before | Expand all | Expand 10 after
890 TraceTrait<TYPE>::trace(visitor, const_cast<TYPE*>(this)); \ 890 TraceTrait<TYPE>::trace(visitor, const_cast<TYPE*>(this)); \
891 return; \ 891 return; \
892 } \ 892 } \
893 visitor->mark(static_cast<const TYPE*>(this), &blink::TraceTrait<TYPE>:: trace); \ 893 visitor->mark(static_cast<const TYPE*>(this), &blink::TraceTrait<TYPE>:: trace); \
894 } \ 894 } \
895 virtual bool isHeapObjectAlive(VISITOR visitor) const override \ 895 virtual bool isHeapObjectAlive(VISITOR visitor) const override \
896 { \ 896 { \
897 return visitor->isAlive(this); \ 897 return visitor->isAlive(this); \
898 } \ 898 } \
899 private: 899 private:
900
901 // A C++ object's vptr will be initialized to its leftmost base's vtable after
902 // the constructors of all its subclasses have run, so if a subclass constructor
903 // tries to access any of the vtbl entries of its leftmost base prematurely,
904 // it'll find an as-yet incorrect vptr and fail. Which is exactly what a
905 // garbage collector will try to do if it tries to access the leftmost base
906 // while one of the subclass constructors of a GC mixin object triggers a GC.
907 // It is consequently not safe to allow any GCs while these objects are under
908 // (sub constructor) construction.
909 //
910 // To prevent GCs in that restricted window of a mixin object's construction:
911 //
912 // - The initial allocation of the mixin object will enter a no GC scope.
913 // This is done by overriding 'operator new' for mixin instances.
914 // - When the constructor for the mixin is invoked, after all the
915 // derived constructors have run, it will invoke the constructor
916 // for a field whose only purpose is to leave the GC scope.
917 // GarbageCollectedMixinConstructorMarker's constructor takes care of
918 // this and the field is declared by way of USING_GARBAGE_COLLECTED_MIXIN().
919 //
920 // If a GC mixin class, declared so using USING_GARBAGE_COLLECTED_MIXIN(), deriv es
921 // leftmost from another such USING_GARBAGE_COLLECTED_MIXIN-mixin class, extra
922 // care and handling is needed for the above two steps; see comment below.
923
924
925 // Trait template to resolve the effective base GC class to use when allocating
926 // objects at some type T. Requires specialization for Node and CSSValue
927 // derived types to have these be allocated on appropriate heaps.
928 //
929 // FIXME: this trait is needed to support Node's overriding 'operator new'
930 // implementation in combination with GC mixins (step 1 above.) Should
931 // Node' operator new no longer be needed, this trait can be removed.
932 template<typename T, typename Enabled = void>
933 class EffectiveGCBaseTrait {
934 public:
935 using Type = T;
936 };
937
938 #define ALLOCATE_ALL_INSTANCES_ON_SAME_GC_HEAP(TYPE) \
939 template<typename T> \
940 class EffectiveGCBaseTrait<T, typename WTF::EnableIf<WTF::IsSubclass<T, blink::T YPE>::value>::Type> { \
941 public: \
942 using Type = TYPE; \
943 }
944
945 #if ENABLE(OILPAN)
946 #define WILL_HAVE_ALL_INSTANCES_ON_SAME_GC_HEAP(TYPE) ALLOCATE_ALL_INSTANCES_ON_ SAME_GC_HEAP(TYPE)
947 #else
948 #define WILL_HAVE_ALL_INSTANCES_ON_SAME_GC_HEAP(TYPE)
949 #endif
950
951 #define DEFINE_GARBAGE_COLLECTED_MIXIN_CONSTRUCTOR_MARKER(TYPE) \
952 public: \
953 GC_PLUGIN_IGNORE("crbug.com/456823") \
954 void* operator new(size_t size) \
955 { \
956 void* object = Heap::allocate<typename EffectiveGCBaseTrait<TYPE>::Type> (size); \
957 ThreadState* state = ThreadStateFor<ThreadingTrait<TYPE>::Affinity>::sta te(); \
958 state->enterGCForbiddenScope(TYPE::mixinLevels); \
959 return object; \
960 } \
961 private: \
962 GarbageCollectedMixinConstructorMarker<TYPE> m_mixinConstructorMarker;
963
964 #if ENABLE(ASSERT)
965 #define DEFINE_GARBAGE_COLLECTED_MIXIN_NONNESTED_DEBUG() \
966 protected: \
967 virtual void mixinsCannotBeImplicitlyNested() final { /* Please use USING_GA RBAGE_COLLECTED_MIXIN_NESTED(Mixin, DerivedFromOtherMixin); */ }
968 #define DEFINE_GARBAGE_COLLECTED_MIXIN_NESTED_DEBUG(TYPE, SUBTYPE) \
969 protected: \
970 static void declaredNestedMixinsMustBeAccurate() \
971 { \
972 static_assert(WTF::IsSubclass<blink::TYPE, blink::SUBTYPE>::value, "Mixi n class does not derive from its stated, nested mixin class."); \
973 }
974 #else
975 #define DEFINE_GARBAGE_COLLECTED_MIXIN_NONNESTED_DEBUG()
976 #define DEFINE_GARBAGE_COLLECTED_MIXIN_NESTED_DEBUG(TYPE, SUBTYPE)
977 #endif
978
979 // Mixins that wrap/nest others requires extra handling:
980 //
981 // class A : public GarbageCollected<A>, public GarbageCollectedMixin {
982 // USING_GARBAGE_COLLECTED_MIXIN(A);
983 // ...
984 // }'
985 // public B final : public A, public SomeOtherMixinInterface {
986 // USING_GARBAGE_COLLECTED_MIXIN(B);
987 // ...
988 // };
989 //
990 // The "operator new" for B will enter the forbidden GC scope, but
991 // upon construction, two GarbageCollectedMixinConstructorMarker constructors
992 // will run -- one for A (first) and another for B (secondly.) Only
993 // the second one should leave the forbidden GC scope.
994 //
995 // Arrange for the balanced use of the forbidden GC scope counter by
996 // adding on the number of mixin constructor markers for a type.
997 // This is equal to the how many GC mixins that the type nests.
998 //
999 // FIXME: We currently require that a nested GC mixin (e.g., B)
1000 // must declare what it nests: USING_GARBAGE_COLLECTED_MIXIN_NESTED(B, A);
1001 // must be used for it. It's a static error if it doesn't.
1002 //
1003 // It would however be preferable to statically derive the
1004 // "mixin nesting level" for these mixin types and use that without
1005 // having to explicitly state the particular type that a mixin nests.
1006 // It seems like it could be expressible as a compile-time type
1007 // computation..
1008
1009 #define DEFINE_GARBAGE_COLLECTED_MIXIN_NONNESTED() \
1010 protected: \
1011 static const unsigned mixinLevels = 1;
1012 #define DEFINE_GARBAGE_COLLECTED_MIXIN_NESTED(TYPE, SUBTYPE) \
1013 protected: \
1014 static const unsigned mixinLevels = SUBTYPE::mixinLevels + 1;
1015
900 #if ENABLE(INLINED_TRACE) 1016 #if ENABLE(INLINED_TRACE)
901 #define USING_GARBAGE_COLLECTED_MIXIN(TYPE) \ 1017 #define USING_GARBAGE_COLLECTED_MIXIN_BASE(TYPE) \
902 DEFINE_GARBAGE_COLLECTED_MIXIN_METHODS(blink::Visitor*, TYPE) \ 1018 DEFINE_GARBAGE_COLLECTED_MIXIN_METHODS(blink::Visitor*, TYPE) \
903 DEFINE_GARBAGE_COLLECTED_MIXIN_METHODS(blink::InlinedGlobalMarkingVisitor, T YPE) 1019 DEFINE_GARBAGE_COLLECTED_MIXIN_METHODS(blink::InlinedGlobalMarkingVisitor, T YPE) \
1020 DEFINE_GARBAGE_COLLECTED_MIXIN_CONSTRUCTOR_MARKER(TYPE)
904 #else 1021 #else
905 #define USING_GARBAGE_COLLECTED_MIXIN(TYPE) \ 1022 #define USING_GARBAGE_COLLECTED_MIXIN_BASE(TYPE) \
906 DEFINE_GARBAGE_COLLECTED_MIXIN_METHODS(blink::Visitor*, TYPE) 1023 DEFINE_GARBAGE_COLLECTED_MIXIN_METHODS(blink::Visitor*, TYPE) \
1024 DEFINE_GARBAGE_COLLECTED_MIXIN_CONSTRUCTOR_MARKER(TYPE)
907 #endif 1025 #endif
908 1026
1027 #define USING_GARBAGE_COLLECTED_MIXIN(TYPE) \
1028 DEFINE_GARBAGE_COLLECTED_MIXIN_NONNESTED_DEBUG() \
1029 DEFINE_GARBAGE_COLLECTED_MIXIN_NONNESTED() \
1030 USING_GARBAGE_COLLECTED_MIXIN_BASE(TYPE)
1031
1032 #define USING_GARBAGE_COLLECTED_MIXIN_NESTED(TYPE, SUBTYPE) \
1033 DEFINE_GARBAGE_COLLECTED_MIXIN_NESTED_DEBUG(TYPE, SUBTYPE) \
1034 DEFINE_GARBAGE_COLLECTED_MIXIN_NESTED(TYPE, SUBTYPE) \
1035 USING_GARBAGE_COLLECTED_MIXIN_BASE(TYPE)
1036
909 #if ENABLE(OILPAN) 1037 #if ENABLE(OILPAN)
910 #define WILL_BE_USING_GARBAGE_COLLECTED_MIXIN(TYPE) USING_GARBAGE_COLLECTED_MIXI N(TYPE) 1038 #define WILL_BE_USING_GARBAGE_COLLECTED_MIXIN(TYPE) USING_GARBAGE_COLLECTED_MIXI N(TYPE)
1039 #define WILL_BE_USING_GARBAGE_COLLECTED_MIXIN_NESTED(TYPE, NESTEDMIXIN) USING_GA RBAGE_COLLECTED_MIXIN_NESTED(TYPE, NESTEDMIXIN)
911 #else 1040 #else
912 #define WILL_BE_USING_GARBAGE_COLLECTED_MIXIN(TYPE) 1041 #define WILL_BE_USING_GARBAGE_COLLECTED_MIXIN(TYPE)
1042 #define WILL_BE_USING_GARBAGE_COLLECTED_MIXIN_NESTED(TYPE, NESTEDMIXIN)
913 #endif 1043 #endif
914 1044
915 // Template to determine if a class is a GarbageCollectedMixin by checking if it 1045 // Template to determine if a class is a GarbageCollectedMixin by checking if it
916 // has IsGarbageCollectedMixinMarker 1046 // has IsGarbageCollectedMixinMarker
917 template<typename T> 1047 template<typename T>
918 struct IsGarbageCollectedMixin { 1048 struct IsGarbageCollectedMixin {
919 private: 1049 private:
920 typedef char YesType; 1050 typedef char YesType;
921 struct NoType { 1051 struct NoType {
922 char padding[8]; 1052 char padding[8];
923 }; 1053 };
924 1054
925 template <typename U> static YesType checkMarker(typename U::IsGarbageCollec tedMixinMarker*); 1055 template <typename U> static YesType checkMarker(typename U::IsGarbageCollec tedMixinMarker*);
926 template <typename U> static NoType checkMarker(...); 1056 template <typename U> static NoType checkMarker(...);
927 1057
928 public: 1058 public:
929 static const bool value = sizeof(checkMarker<T>(nullptr)) == sizeof(YesType) ; 1059 static const bool value = sizeof(checkMarker<T>(nullptr)) == sizeof(YesType) ;
930 }; 1060 };
931 1061
1062 // An empty class with a constructor that's arranged invoked when all derived co nstructors
1063 // of a mixin instance have completed and it is safe to allow GCs again. See
1064 // AllocateObjectTrait<> comment for more.
1065 //
1066 // USING_GARBAGE_COLLECTED_MIXIN() declares a GarbageCollectedMixinConstructorMa rker<> private
1067 // field. By following Blink convention of using the macro at the top of a class declaration,
1068 // its constructor will run first.
1069 template<typename T>
1070 class GarbageCollectedMixinConstructorMarker {
1071 public:
1072 GarbageCollectedMixinConstructorMarker()
1073 {
1074 // FIXME: if prompt conservative GCs are needed, forced GCs that
1075 // were denied while within this scope, could now be performed.
1076 // For now, assume the next out-of-line allocation request will
1077 // happen soon enough and take care of it. Mixin objects aren't
1078 // overly common.
1079 ThreadState* state = ThreadStateFor<ThreadingTrait<T>::Affinity>::state( );
1080 state->leaveGCForbiddenScope();
1081 }
1082 };
1083
932 #if ENABLE(GC_PROFILING) 1084 #if ENABLE(GC_PROFILING)
933 template<typename T> 1085 template<typename T>
934 struct TypenameStringTrait { 1086 struct TypenameStringTrait {
935 static const String& get() 1087 static const String& get()
936 { 1088 {
937 DEFINE_STATIC_LOCAL(String, typenameString, (WTF::extractTypeNameFromFun ctionName(WTF::extractNameFunction<T>()))); 1089 DEFINE_STATIC_LOCAL(String, typenameString, (WTF::extractTypeNameFromFun ctionName(WTF::extractNameFunction<T>())));
938 return typenameString; 1090 return typenameString;
939 } 1091 }
940 }; 1092 };
941 #endif 1093 #endif
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after
1005 struct GCInfoTrait { 1157 struct GCInfoTrait {
1006 static size_t index() 1158 static size_t index()
1007 { 1159 {
1008 return GCInfoAtBase<typename GetGarbageCollectedBase<T>::type>::index(); 1160 return GCInfoAtBase<typename GetGarbageCollectedBase<T>::type>::index();
1009 } 1161 }
1010 }; 1162 };
1011 1163
1012 } // namespace blink 1164 } // namespace blink
1013 1165
1014 #endif // Visitor_h 1166 #endif // Visitor_h
OLDNEW
« no previous file with comments | « Source/platform/heap/ThreadState.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698