OLD | NEW |
---|---|
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 Loading... | |
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 | |
902 // vtable after the constructors of all its subclasses have run, | |
903 // so if a subclass constructor tries to access any of the vtbl | |
904 // entries of its leftmost base prematurely, it'll find an as-yet | |
905 // incorrect vptr and fail. Which is exactly what a garbage collector | |
906 // will try to do if it tries to access the leftmost base while one | |
907 // of the subclass constructors of a GC mixin object triggers a GC. | |
908 // It is consequently not safe to allow any GCs while these objects | |
909 // are under (sub constructor) construction. | |
910 // | |
911 // To achieve that, the construction of mixins are handled in a | |
912 // special manner: | |
913 // | |
914 // - The initial allocation of the mixin object will enter a no GC scope. | |
915 // This is done by overriding 'operator new' for mixin instances. | |
916 // - When the constructor for the mixin is invoked, after all the | |
917 // derived constructors have run, it will invoke the constructor | |
918 // for a field whose only purpose is to leave the GC scope. | |
919 // GarbageCollectedMixinConstructorMarker's constructor takes care of | |
920 // this and the field is declared by way of USING_GARBAGE_COLLECTED_MIXIN(). | |
921 | |
922 // Trait template to resolve the effective base GC class to use when allocating | |
923 // objects at some type T. Requires specialization for Node and CSSValue | |
924 // derived types to have these be allocated on appropriate heaps. | |
925 template<typename T, typename Enabled = void> | |
926 class EffectiveGCBaseTrait { | |
927 public: | |
928 using Type = T; | |
929 }; | |
930 | |
931 // FIXME: move these forward declarations and the | |
932 // EffectiveGCBaseTrait<> specializations out of | |
933 // here and into the header files for the respective types. | |
934 class Node; | |
935 class CSSValue; | |
936 | |
937 template<typename T> | |
938 class EffectiveGCBaseTrait<T, typename WTF::EnableIf<WTF::IsSubclass<T, blink::N ode>::value>::Type> { | |
939 public: | |
940 using Type = Node; | |
941 }; | |
942 | |
943 template<typename T> | |
944 class EffectiveGCBaseTrait<T, typename WTF::EnableIf<WTF::IsSubclass<T, blink::C SSValue>::value>::Type> { | |
945 public: | |
946 using Type = CSSValue; | |
947 }; | |
948 | |
949 #define DEFINE_GARBAGE_COLLECTED_MIXIN_CONSTRUCTOR_MARKER(TYPE) \ | |
950 public: \ | |
951 GC_PLUGIN_IGNORE("crbug.com/456823") \ | |
952 void* operator new(size_t size) \ | |
haraken
2015/03/06 13:01:01
As far as I grep in the code base, GARBAGE_COLLECT
| |
953 { \ | |
954 void* object = Heap::allocate<typename EffectiveGCBaseTrait<TYPE>::Type> (size); \ | |
955 ThreadState* state = ThreadStateFor<ThreadingTrait<TYPE>::Affinity>::sta te(); \ | |
956 state->enterGCForbiddenScope(TYPE::mixinLevels); \ | |
957 return object; \ | |
958 } \ | |
959 private: \ | |
960 GarbageCollectedMixinConstructorMarker<TYPE> m_mixinConstructorMarker; | |
961 | |
962 #if ENABLE(ASSERT) | |
963 #define DEFINE_GARBAGE_COLLECTED_MIXIN_NONNESTED_DEBUG() \ | |
964 protected: \ | |
965 virtual void mixinsCannotBeImplicitlyNested() final { } | |
966 #define DEFINE_GARBAGE_COLLECTED_MIXIN_NESTED_DEBUG(TYPE, SUBTYPE) \ | |
967 protected: \ | |
968 static void mixinsNestingOthersMustBeDeclaredAsSuch() \ | |
969 { \ | |
970 static_assert(WTF::IsSubclass<blink::TYPE, blink::SUBTYPE>::value, "Mixi n class does not derive from its nested mixin class; use USING_GARBAGE_COLLECTED _MIXIN_NESTED()."); \ | |
971 } | |
972 #else | |
973 #define DEFINE_GARBAGE_COLLECTED_MIXIN_NONNESTED_DEBUG() | |
974 #define DEFINE_GARBAGE_COLLECTED_MIXIN_NESTED_DEBUG(TYPE, SUBTYPE) | |
975 #endif | |
976 | |
977 #define DEFINE_GARBAGE_COLLECTED_MIXIN_NONNESTED() \ | |
978 protected: \ | |
979 static const unsigned mixinLevels = 1; | |
980 #define DEFINE_GARBAGE_COLLECTED_MIXIN_NESTED(TYPE, SUBTYPE) \ | |
haraken
2015/03/06 13:01:01
Just to confirm: This mechanism can detect the fol
sof
2015/03/06 16:11:06
The final mixinsCannotBeImplicitlyNested() empty m
| |
981 protected: \ | |
982 static const unsigned mixinLevels = SUBTYPE::mixinLevels + 1; | |
983 | |
900 #if ENABLE(INLINED_TRACE) | 984 #if ENABLE(INLINED_TRACE) |
901 #define USING_GARBAGE_COLLECTED_MIXIN(TYPE) \ | 985 #define USING_GARBAGE_COLLECTED_MIXIN_BASE(TYPE) \ |
902 DEFINE_GARBAGE_COLLECTED_MIXIN_METHODS(blink::Visitor*, TYPE) \ | 986 DEFINE_GARBAGE_COLLECTED_MIXIN_METHODS(blink::Visitor*, TYPE) \ |
903 DEFINE_GARBAGE_COLLECTED_MIXIN_METHODS(blink::InlinedGlobalMarkingVisitor, T YPE) | 987 DEFINE_GARBAGE_COLLECTED_MIXIN_METHODS(blink::InlinedGlobalMarkingVisitor, T YPE) \ |
988 DEFINE_GARBAGE_COLLECTED_MIXIN_CONSTRUCTOR_MARKER(TYPE) | |
904 #else | 989 #else |
905 #define USING_GARBAGE_COLLECTED_MIXIN(TYPE) \ | 990 #define USING_GARBAGE_COLLECTED_MIXIN_BASE(TYPE) \ |
906 DEFINE_GARBAGE_COLLECTED_MIXIN_METHODS(blink::Visitor*, TYPE) | 991 DEFINE_GARBAGE_COLLECTED_MIXIN_METHODS(blink::Visitor*, TYPE) \ |
992 DEFINE_GARBAGE_COLLECTED_MIXIN_CONSTRUCTOR_MARKER(TYPE) | |
907 #endif | 993 #endif |
908 | 994 |
995 #define USING_GARBAGE_COLLECTED_MIXIN(TYPE) \ | |
996 DEFINE_GARBAGE_COLLECTED_MIXIN_NONNESTED_DEBUG() \ | |
997 DEFINE_GARBAGE_COLLECTED_MIXIN_NONNESTED() \ | |
998 USING_GARBAGE_COLLECTED_MIXIN_BASE(TYPE) | |
999 | |
1000 #define USING_GARBAGE_COLLECTED_MIXIN_NESTED(TYPE, SUBTYPE) \ | |
1001 DEFINE_GARBAGE_COLLECTED_MIXIN_NESTED_DEBUG(TYPE, SUBTYPE) \ | |
1002 DEFINE_GARBAGE_COLLECTED_MIXIN_NESTED(TYPE, SUBTYPE) \ | |
1003 USING_GARBAGE_COLLECTED_MIXIN_BASE(TYPE) | |
1004 | |
909 #if ENABLE(OILPAN) | 1005 #if ENABLE(OILPAN) |
910 #define WILL_BE_USING_GARBAGE_COLLECTED_MIXIN(TYPE) USING_GARBAGE_COLLECTED_MIXI N(TYPE) | 1006 #define WILL_BE_USING_GARBAGE_COLLECTED_MIXIN(TYPE) USING_GARBAGE_COLLECTED_MIXI N(TYPE) |
1007 #define WILL_BE_USING_GARBAGE_COLLECTED_MIXIN_NESTED(TYPE, NESTEDMIXIN) USING_GA RBAGE_COLLECTED_MIXIN_NESTED(TYPE, NESTEDMIXIN) | |
911 #else | 1008 #else |
912 #define WILL_BE_USING_GARBAGE_COLLECTED_MIXIN(TYPE) | 1009 #define WILL_BE_USING_GARBAGE_COLLECTED_MIXIN(TYPE) |
1010 #define WILL_BE_USING_GARBAGE_COLLECTED_MIXIN_NESTED(TYPE, NESTEDMIXIN) | |
913 #endif | 1011 #endif |
914 | 1012 |
915 // Template to determine if a class is a GarbageCollectedMixin by checking if it | 1013 // Template to determine if a class is a GarbageCollectedMixin by checking if it |
916 // has IsGarbageCollectedMixinMarker | 1014 // has IsGarbageCollectedMixinMarker |
917 template<typename T> | 1015 template<typename T> |
918 struct IsGarbageCollectedMixin { | 1016 struct IsGarbageCollectedMixin { |
919 private: | 1017 private: |
920 typedef char YesType; | 1018 typedef char YesType; |
921 struct NoType { | 1019 struct NoType { |
922 char padding[8]; | 1020 char padding[8]; |
923 }; | 1021 }; |
924 | 1022 |
925 template <typename U> static YesType checkMarker(typename U::IsGarbageCollec tedMixinMarker*); | 1023 template <typename U> static YesType checkMarker(typename U::IsGarbageCollec tedMixinMarker*); |
926 template <typename U> static NoType checkMarker(...); | 1024 template <typename U> static NoType checkMarker(...); |
927 | 1025 |
928 public: | 1026 public: |
929 static const bool value = sizeof(checkMarker<T>(nullptr)) == sizeof(YesType) ; | 1027 static const bool value = sizeof(checkMarker<T>(nullptr)) == sizeof(YesType) ; |
930 }; | 1028 }; |
931 | 1029 |
1030 // An empty class with a constructor that's arranged invoked when all derived co nstructors | |
1031 // of a mixin instance have completed and it is safe to allow GCs again. See | |
1032 // AllocateObjectTrait<> comment for more. | |
1033 // | |
1034 // USING_GARBAGE_COLLECTED_MIXIN() declares a GarbageCollectedMixinConstructorMa rker<> private | |
1035 // field. By following Blink convention of using the macro at the top of a class declaration, | |
1036 // its constructor will run first. | |
1037 template<typename T> | |
1038 class GarbageCollectedMixinConstructorMarker { | |
1039 public: | |
1040 GarbageCollectedMixinConstructorMarker() | |
1041 { | |
1042 // FIXME: if prompt conservative GCs are needed, forced GCs that | |
1043 // were denied while within this scope, could now be performed. | |
1044 // For now, assume the next out-of-line allocation request will | |
1045 // happen soon enough and take care of it. Mixin objects aren't | |
1046 // overly common. | |
1047 ThreadState* state = ThreadStateFor<ThreadingTrait<T>::Affinity>::state( ); | |
1048 state->leaveGCForbiddenScope(); | |
1049 } | |
1050 }; | |
1051 | |
932 #if ENABLE(GC_PROFILING) | 1052 #if ENABLE(GC_PROFILING) |
933 template<typename T> | 1053 template<typename T> |
934 struct TypenameStringTrait { | 1054 struct TypenameStringTrait { |
935 static const String& get() | 1055 static const String& get() |
936 { | 1056 { |
937 DEFINE_STATIC_LOCAL(String, typenameString, (WTF::extractTypeNameFromFun ctionName(WTF::extractNameFunction<T>()))); | 1057 DEFINE_STATIC_LOCAL(String, typenameString, (WTF::extractTypeNameFromFun ctionName(WTF::extractNameFunction<T>()))); |
938 return typenameString; | 1058 return typenameString; |
939 } | 1059 } |
940 }; | 1060 }; |
941 #endif | 1061 #endif |
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1005 struct GCInfoTrait { | 1125 struct GCInfoTrait { |
1006 static size_t index() | 1126 static size_t index() |
1007 { | 1127 { |
1008 return GCInfoAtBase<typename GetGarbageCollectedBase<T>::type>::index(); | 1128 return GCInfoAtBase<typename GetGarbageCollectedBase<T>::type>::index(); |
1009 } | 1129 } |
1010 }; | 1130 }; |
1011 | 1131 |
1012 } // namespace blink | 1132 } // namespace blink |
1013 | 1133 |
1014 #endif // Visitor_h | 1134 #endif // Visitor_h |
OLD | NEW |