| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright (C) 2008 Apple Inc. All Rights Reserved. | 2 * Copyright (C) 2008 Apple 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 | 5 * modification, are permitted provided that the following conditions |
| 6 * are met: | 6 * are met: |
| 7 * 1. Redistributions of source code must retain the above copyright | 7 * 1. Redistributions of source code must retain the above copyright |
| 8 * notice, this list of conditions and the following disclaimer. | 8 * notice, this list of conditions and the following disclaimer. |
| 9 * 2. Redistributions in binary form must reproduce the above copyright | 9 * 2. Redistributions in binary form must reproduce the above copyright |
| 10 * notice, this list of conditions and the following disclaimer in the | 10 * notice, this list of conditions and the following disclaimer in the |
| (...skipping 19 matching lines...) Expand all Loading... |
| 30 #include "wtf/CPU.h" | 30 #include "wtf/CPU.h" |
| 31 #include "wtf/CheckedArithmetic.h" | 31 #include "wtf/CheckedArithmetic.h" |
| 32 #include "wtf/LeakAnnotations.h" | 32 #include "wtf/LeakAnnotations.h" |
| 33 #include <cstddef> | 33 #include <cstddef> |
| 34 | 34 |
| 35 #if ENABLE(ASSERT) | 35 #if ENABLE(ASSERT) |
| 36 #include "wtf/Noncopyable.h" | 36 #include "wtf/Noncopyable.h" |
| 37 #include "wtf/Threading.h" | 37 #include "wtf/Threading.h" |
| 38 | 38 |
| 39 class WTF_EXPORT StaticLocalVerifier { | 39 class WTF_EXPORT StaticLocalVerifier { |
| 40 WTF_MAKE_NONCOPYABLE(StaticLocalVerifier); | 40 WTF_MAKE_NONCOPYABLE(StaticLocalVerifier); |
| 41 public: | |
| 42 StaticLocalVerifier() | |
| 43 : m_safelyInitialized(WTF::isBeforeThreadCreated()) | |
| 44 , m_thread(WTF::currentThread()) | |
| 45 { | |
| 46 } | |
| 47 | 41 |
| 48 bool isNotRacy() | 42 public: |
| 49 { | 43 StaticLocalVerifier() |
| 50 // Make sure that this 1) is safely initialized, 2) keeps being called | 44 : m_safelyInitialized(WTF::isBeforeThreadCreated()), |
| 51 // on the same thread, or 3) is called within | 45 m_thread(WTF::currentThread()) {} |
| 52 // AtomicallyInitializedStatic (i.e. with a lock held). | |
| 53 return m_safelyInitialized || m_thread == WTF::currentThread() || WTF::i
sAtomicallyInitializedStaticMutexLockHeld(); | |
| 54 } | |
| 55 | 46 |
| 56 private: | 47 bool isNotRacy() { |
| 57 bool m_safelyInitialized; | 48 // Make sure that this 1) is safely initialized, 2) keeps being called |
| 58 ThreadIdentifier m_thread; | 49 // on the same thread, or 3) is called within |
| 50 // AtomicallyInitializedStatic (i.e. with a lock held). |
| 51 return m_safelyInitialized || m_thread == WTF::currentThread() || |
| 52 WTF::isAtomicallyInitializedStaticMutexLockHeld(); |
| 53 } |
| 54 |
| 55 private: |
| 56 bool m_safelyInitialized; |
| 57 ThreadIdentifier m_thread; |
| 59 }; | 58 }; |
| 60 #endif | 59 #endif |
| 61 | 60 |
| 62 // A direct static local to a Blink garbage collected objects isn't allowed; | 61 // A direct static local to a Blink garbage collected objects isn't allowed; |
| 63 // must be wrapped up with a persistent reference. | 62 // must be wrapped up with a persistent reference. |
| 64 #define STATIC_ASSERT_FOR_LOCAL_WITH_GARBAGE_COLLECTED_TYPE(Name, Type) \ | 63 #define STATIC_ASSERT_FOR_LOCAL_WITH_GARBAGE_COLLECTED_TYPE(Name, Type) \ |
| 65 using Name##NoConstType = std::remove_const<Type>::type; \ | 64 using Name##NoConstType = std::remove_const<Type>::type; \ |
| 66 using Name##NoPointerType = std::remove_pointer<Name##NoConstType>::type; \ | 65 using Name##NoPointerType = std::remove_pointer<Name##NoConstType>::type; \ |
| 67 using Name##NoReferenceType = std::remove_reference<Name##NoPointerType>::ty
pe; \ | 66 using Name##NoReferenceType = \ |
| 68 static_assert(!WTF::IsGarbageCollectedType<Name##NoReferenceType>::value ||
WTF::IsPersistentReferenceType<Name##NoReferenceType>::value, "Garbage collected
static local needs to be wrapped up with a persistent reference") | 67 std::remove_reference<Name##NoPointerType>::type; \ |
| 68 static_assert( \ |
| 69 !WTF::IsGarbageCollectedType<Name##NoReferenceType>::value || \ |
| 70 WTF::IsPersistentReferenceType<Name##NoReferenceType>::value, \ |
| 71 "Garbage collected static local needs to be wrapped up with a " \ |
| 72 "persistent reference") |
| 69 | 73 |
| 70 // Use DEFINE_STATIC_LOCAL() to declare and define a static local variable (stat
ic T;) | 74 // Use DEFINE_STATIC_LOCAL() to declare and define a static local variable (stat
ic T;) |
| 71 // so that it is leaked and its destructors are not called at exit. | 75 // so that it is leaked and its destructors are not called at exit. |
| 72 // | 76 // |
| 73 // To cooperate with leak detection, the objects held onto by these local static
s | 77 // To cooperate with leak detection, the objects held onto by these local static
s |
| 74 // will in some cases have to be finalized prior to leak checking. This only app
lies | 78 // will in some cases have to be finalized prior to leak checking. This only app
lies |
| 75 // to static references to Oilpan heap objects and what they transitively hold o
n to. | 79 // to static references to Oilpan heap objects and what they transitively hold o
n to. |
| 76 // LEAK_SANITIZER_REGISTER_STATIC_LOCAL() takes care of the details. | 80 // LEAK_SANITIZER_REGISTER_STATIC_LOCAL() takes care of the details. |
| 77 // | 81 // |
| 78 #if ENABLE(ASSERT) | 82 #if ENABLE(ASSERT) |
| 79 #define DEFINE_STATIC_LOCAL(Type, Name, Arguments) \ | 83 #define DEFINE_STATIC_LOCAL(Type, Name, Arguments) \ |
| 80 STATIC_ASSERT_FOR_LOCAL_WITH_GARBAGE_COLLECTED_TYPE(Name, Type); \ | 84 STATIC_ASSERT_FOR_LOCAL_WITH_GARBAGE_COLLECTED_TYPE(Name, Type); \ |
| 81 static StaticLocalVerifier Name##StaticLocalVerifier; \ | 85 static StaticLocalVerifier Name##StaticLocalVerifier; \ |
| 82 ASSERT(Name##StaticLocalVerifier.isNotRacy()); \ | 86 ASSERT(Name##StaticLocalVerifier.isNotRacy()); \ |
| 83 static Type& Name = *LEAK_SANITIZER_REGISTER_STATIC_LOCAL(Type, new Type Arg
uments) | 87 static Type& Name = \ |
| 88 *LEAK_SANITIZER_REGISTER_STATIC_LOCAL(Type, new Type Arguments) |
| 84 #else | 89 #else |
| 85 #define DEFINE_STATIC_LOCAL(Type, Name, Arguments) \ | 90 #define DEFINE_STATIC_LOCAL(Type, Name, Arguments) \ |
| 86 STATIC_ASSERT_FOR_LOCAL_WITH_GARBAGE_COLLECTED_TYPE(Name, Type); \ | 91 STATIC_ASSERT_FOR_LOCAL_WITH_GARBAGE_COLLECTED_TYPE(Name, Type); \ |
| 87 static Type& Name = *LEAK_SANITIZER_REGISTER_STATIC_LOCAL(Type, new Type Arg
uments) | 92 static Type& Name = \ |
| 93 *LEAK_SANITIZER_REGISTER_STATIC_LOCAL(Type, new Type Arguments) |
| 88 #endif | 94 #endif |
| 89 | 95 |
| 90 // Use this to declare and define a static local pointer to a ref-counted object
so that | 96 // Use this to declare and define a static local pointer to a ref-counted object
so that |
| 91 // it is leaked so that the object's destructors are not called at exit. | 97 // it is leaked so that the object's destructors are not called at exit. |
| 92 // This macro should be used with ref-counted objects rather than DEFINE_STATIC_
LOCAL macro, | 98 // This macro should be used with ref-counted objects rather than DEFINE_STATIC_
LOCAL macro, |
| 93 // as this macro does not lead to an extra memory allocation. | 99 // as this macro does not lead to an extra memory allocation. |
| 94 #define DEFINE_STATIC_REF(type, name, arguments) \ | 100 #define DEFINE_STATIC_REF(type, name, arguments) \ |
| 95 static type* name = PassRefPtr<type>(arguments).leakRef(); | 101 static type* name = PassRefPtr<type>(arguments).leakRef(); |
| 96 | 102 |
| 97 /* | 103 /* |
| 98 * The reinterpret_cast<Type1*>([pointer to Type2]) expressions - where | 104 * The reinterpret_cast<Type1*>([pointer to Type2]) expressions - where |
| 99 * sizeof(Type1) > sizeof(Type2) - cause the following warning on ARM with GCC: | 105 * sizeof(Type1) > sizeof(Type2) - cause the following warning on ARM with GCC: |
| 100 * increases required alignment of target type. | 106 * increases required alignment of target type. |
| 101 * | 107 * |
| 102 * An implicit or an extra static_cast<void*> bypasses the warning. | 108 * An implicit or an extra static_cast<void*> bypasses the warning. |
| 103 * For more info see the following bugzilla entries: | 109 * For more info see the following bugzilla entries: |
| 104 * - https://bugs.webkit.org/show_bug.cgi?id=38045 | 110 * - https://bugs.webkit.org/show_bug.cgi?id=38045 |
| 105 * - http://gcc.gnu.org/bugzilla/show_bug.cgi?id=43976 | 111 * - http://gcc.gnu.org/bugzilla/show_bug.cgi?id=43976 |
| 106 */ | 112 */ |
| 107 #if CPU(ARM) && COMPILER(GCC) | 113 #if CPU(ARM) && COMPILER(GCC) |
| 108 template<typename Type> | 114 template <typename Type> |
| 109 bool isPointerTypeAlignmentOkay(Type* ptr) | 115 bool isPointerTypeAlignmentOkay(Type* ptr) { |
| 110 { | 116 return !(reinterpret_cast<intptr_t>(ptr) % __alignof__(Type)); |
| 111 return !(reinterpret_cast<intptr_t>(ptr) % __alignof__(Type)); | |
| 112 } | 117 } |
| 113 | 118 |
| 114 template<typename TypePtr> | 119 template <typename TypePtr> |
| 115 TypePtr reinterpret_cast_ptr(void* ptr) | 120 TypePtr reinterpret_cast_ptr(void* ptr) { |
| 116 { | 121 ASSERT(isPointerTypeAlignmentOkay(reinterpret_cast<TypePtr>(ptr))); |
| 117 ASSERT(isPointerTypeAlignmentOkay(reinterpret_cast<TypePtr>(ptr))); | 122 return reinterpret_cast<TypePtr>(ptr); |
| 118 return reinterpret_cast<TypePtr>(ptr); | |
| 119 } | 123 } |
| 120 | 124 |
| 121 template<typename TypePtr> | 125 template <typename TypePtr> |
| 122 TypePtr reinterpret_cast_ptr(const void* ptr) | 126 TypePtr reinterpret_cast_ptr(const void* ptr) { |
| 123 { | 127 ASSERT(isPointerTypeAlignmentOkay(reinterpret_cast<TypePtr>(ptr))); |
| 124 ASSERT(isPointerTypeAlignmentOkay(reinterpret_cast<TypePtr>(ptr))); | 128 return reinterpret_cast<TypePtr>(ptr); |
| 125 return reinterpret_cast<TypePtr>(ptr); | |
| 126 } | 129 } |
| 127 #else | 130 #else |
| 128 template<typename Type> | 131 template <typename Type> |
| 129 bool isPointerTypeAlignmentOkay(Type*) | 132 bool isPointerTypeAlignmentOkay(Type*) { |
| 130 { | 133 return true; |
| 131 return true; | |
| 132 } | 134 } |
| 133 #define reinterpret_cast_ptr reinterpret_cast | 135 #define reinterpret_cast_ptr reinterpret_cast |
| 134 #endif | 136 #endif |
| 135 | 137 |
| 136 namespace WTF { | 138 namespace WTF { |
| 137 | 139 |
| 138 /* | 140 /* |
| 139 * C++'s idea of a reinterpret_cast lacks sufficient cojones. | 141 * C++'s idea of a reinterpret_cast lacks sufficient cojones. |
| 140 */ | 142 */ |
| 141 template<typename TO, typename FROM> | 143 template <typename TO, typename FROM> |
| 142 inline TO bitwise_cast(FROM from) | 144 inline TO bitwise_cast(FROM from) { |
| 143 { | 145 static_assert(sizeof(TO) == sizeof(FROM), |
| 144 static_assert(sizeof(TO) == sizeof(FROM), "WTF::bitwise_cast sizeof casted t
ypes should be equal"); | 146 "WTF::bitwise_cast sizeof casted types should be equal"); |
| 145 union { | 147 union { |
| 146 FROM from; | 148 FROM from; |
| 147 TO to; | 149 TO to; |
| 148 } u; | 150 } u; |
| 149 u.from = from; | 151 u.from = from; |
| 150 return u.to; | 152 return u.to; |
| 151 } | 153 } |
| 152 | 154 |
| 153 template<typename To, typename From> | 155 template <typename To, typename From> |
| 154 inline To safeCast(From value) | 156 inline To safeCast(From value) { |
| 155 { | 157 RELEASE_ASSERT(isInBounds<To>(value)); |
| 156 RELEASE_ASSERT(isInBounds<To>(value)); | 158 return static_cast<To>(value); |
| 157 return static_cast<To>(value); | |
| 158 } | 159 } |
| 159 | 160 |
| 160 // Use the following macros to prevent errors caused by accidental | 161 // Use the following macros to prevent errors caused by accidental |
| 161 // implicit casting of function arguments. For example, this can | 162 // implicit casting of function arguments. For example, this can |
| 162 // be used to prevent overflows from non-promoting conversions. | 163 // be used to prevent overflows from non-promoting conversions. |
| 163 // | 164 // |
| 164 // Example: | 165 // Example: |
| 165 // | 166 // |
| 166 // HAS_STRICTLY_TYPED_ARG | 167 // HAS_STRICTLY_TYPED_ARG |
| 167 // void sendData(void* data, STRICTLY_TYPED_ARG(size)) | 168 // void sendData(void* data, STRICTLY_TYPED_ARG(size)) |
| 168 // { | 169 // { |
| 169 // ALLOW_NUMERIC_ARG_TYPES_PROMOTABLE_TO(size_t); | 170 // ALLOW_NUMERIC_ARG_TYPES_PROMOTABLE_TO(size_t); |
| 170 // ... | 171 // ... |
| 171 // } | 172 // } |
| 172 // | 173 // |
| 173 // The previous example will prevent callers from passing, for example, an | 174 // The previous example will prevent callers from passing, for example, an |
| 174 // 'int'. On a 32-bit build, it will prevent use of an 'unsigned long long'. | 175 // 'int'. On a 32-bit build, it will prevent use of an 'unsigned long long'. |
| 175 #define HAS_STRICTLY_TYPED_ARG template<typename ActualArgType> | 176 #define HAS_STRICTLY_TYPED_ARG template <typename ActualArgType> |
| 176 #define STRICTLY_TYPED_ARG(argName) ActualArgType argName | 177 #define STRICTLY_TYPED_ARG(argName) ActualArgType argName |
| 177 #define STRICT_ARG_TYPE(ExpectedArgType) \ | 178 #define STRICT_ARG_TYPE(ExpectedArgType) \ |
| 178 static_assert(std::is_same<ActualArgType, ExpectedArgType>::value, \ | 179 static_assert(std::is_same<ActualArgType, ExpectedArgType>::value, \ |
| 179 "Strictly typed argument must be of type '" #ExpectedArgType "'." ) | 180 "Strictly typed argument must be of type '" #ExpectedArgType \ |
| 180 #define ALLOW_NUMERIC_ARG_TYPES_PROMOTABLE_TO(ExpectedArgType) \ | 181 "'.") |
| 181 static_assert(std::numeric_limits<ExpectedArgType>::is_integer == std::numer
ic_limits<ActualArgType>::is_integer, \ | 182 #define ALLOW_NUMERIC_ARG_TYPES_PROMOTABLE_TO(ExpectedArgType) \ |
| 182 "Conversion between integer and non-integer types not allowed."); \ | 183 static_assert( \ |
| 183 static_assert(sizeof(ExpectedArgType) >= sizeof(ActualArgType), \ | 184 std::numeric_limits<ExpectedArgType>::is_integer == \ |
| 184 "Truncating conversions not allowed."); \ | 185 std::numeric_limits<ActualArgType>::is_integer, \ |
| 185 static_assert(!std::numeric_limits<ActualArgType>::is_signed || std::numeric
_limits<ExpectedArgType>::is_signed, \ | 186 "Conversion between integer and non-integer types not allowed."); \ |
| 186 "Signed to unsigned conversion not allowed."); \ | 187 static_assert(sizeof(ExpectedArgType) >= sizeof(ActualArgType), \ |
| 187 static_assert((sizeof(ExpectedArgType) != sizeof(ActualArgType)) || (std::nu
meric_limits<ActualArgType>::is_signed == std::numeric_limits<ExpectedArgType>::
is_signed), \ | 188 "Truncating conversions not allowed."); \ |
| 188 "Unsigned to signed conversion not allowed for types with identical size
(could overflow)."); | 189 static_assert(!std::numeric_limits<ActualArgType>::is_signed || \ |
| 190 std::numeric_limits<ExpectedArgType>::is_signed, \ |
| 191 "Signed to unsigned conversion not allowed."); \ |
| 192 static_assert((sizeof(ExpectedArgType) != sizeof(ActualArgType)) || \ |
| 193 (std::numeric_limits<ActualArgType>::is_signed == \ |
| 194 std::numeric_limits<ExpectedArgType>::is_signed), \ |
| 195 "Unsigned to signed conversion not allowed for types with " \ |
| 196 "identical size (could overflow)."); |
| 189 | 197 |
| 190 // Macro that returns a compile time constant with the length of an array, but g
ives an error if passed a non-array. | 198 // Macro that returns a compile time constant with the length of an array, but g
ives an error if passed a non-array. |
| 191 template<typename T, size_t Size> char (&ArrayLengthHelperFunction(T (&)[Size]))
[Size]; | 199 template <typename T, size_t Size> |
| 200 char (&ArrayLengthHelperFunction(T (&)[Size]))[Size]; |
| 192 // GCC needs some help to deduce a 0 length array. | 201 // GCC needs some help to deduce a 0 length array. |
| 193 #if COMPILER(GCC) | 202 #if COMPILER(GCC) |
| 194 template<typename T> char (&ArrayLengthHelperFunction(T (&)[0]))[0]; | 203 template <typename T> |
| 204 char (&ArrayLengthHelperFunction(T (&)[0]))[0]; |
| 195 #endif | 205 #endif |
| 196 #define WTF_ARRAY_LENGTH(array) sizeof(::WTF::ArrayLengthHelperFunction(array)) | 206 #define WTF_ARRAY_LENGTH(array) sizeof(::WTF::ArrayLengthHelperFunction(array)) |
| 197 | 207 |
| 198 } // namespace WTF | 208 } // namespace WTF |
| 199 | 209 |
| 200 // This version of placement new omits a 0 check. | 210 // This version of placement new omits a 0 check. |
| 201 enum NotNullTag { NotNull }; | 211 enum NotNullTag { NotNull }; |
| 202 inline void* operator new(size_t, NotNullTag, void* location) | 212 inline void* operator new(size_t, NotNullTag, void* location) { |
| 203 { | 213 ASSERT(location); |
| 204 ASSERT(location); | 214 return location; |
| 205 return location; | |
| 206 } | 215 } |
| 207 | 216 |
| 208 using WTF::bitwise_cast; | 217 using WTF::bitwise_cast; |
| 209 using WTF::safeCast; | 218 using WTF::safeCast; |
| 210 | 219 |
| 211 #endif // WTF_StdLibExtras_h | 220 #endif // WTF_StdLibExtras_h |
| OLD | NEW |