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 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 Loading... |
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 |
OLD | NEW |