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