/* * Copyright (C) 2008 Apple Inc. All Rights Reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef WTF_StdLibExtras_h #define WTF_StdLibExtras_h #include "wtf/Assertions.h" #include "wtf/CPU.h" #include "wtf/CheckedArithmetic.h" #include "wtf/LeakAnnotations.h" #include #if ENABLE(ASSERT) #include "wtf/Noncopyable.h" #include "wtf/Threading.h" class WTF_EXPORT StaticLocalVerifier { WTF_MAKE_NONCOPYABLE(StaticLocalVerifier); public: StaticLocalVerifier() : m_safelyInitialized(WTF::isBeforeThreadCreated()) , m_thread(WTF::currentThread()) { } bool isNotRacy() { // Make sure that this 1) is safely initialized, 2) keeps being called // on the same thread, or 3) is called within // AtomicallyInitializedStatic (i.e. with a lock held). return m_safelyInitialized || m_thread == WTF::currentThread() || WTF::isAtomicallyInitializedStaticMutexLockHeld(); } private: bool m_safelyInitialized; ThreadIdentifier m_thread; }; #endif // A direct static local to a Blink garbage collected objects isn't allowed; // must be wrapped up with a persistent reference. #define STATIC_ASSERT_FOR_LOCAL_WITH_GARBAGE_COLLECTED_TYPE(Name, Type) \ using Name##NoConstType = std::remove_const::type; \ using Name##NoPointerType = std::remove_pointer::type; \ using Name##NoReferenceType = std::remove_reference::type; \ static_assert(!WTF::IsGarbageCollectedType::value || WTF::IsPersistentReferenceType::value, "Garbage collected static local needs to be wrapped up with a persistent reference") // Use DEFINE_STATIC_LOCAL() to declare and define a static local variable (static T;) // so that it is leaked and its destructors are not called at exit. // // To cooperate with leak detection, the objects held onto by these local statics // will in some cases have to be finalized prior to leak checking. This only applies // to static references to Oilpan heap objects and what they transitively hold on to. // LEAK_SANITIZER_REGISTER_STATIC_LOCAL() takes care of the details. // #if ENABLE(ASSERT) #define DEFINE_STATIC_LOCAL(Type, Name, Arguments) \ STATIC_ASSERT_FOR_LOCAL_WITH_GARBAGE_COLLECTED_TYPE(Name, Type); \ static StaticLocalVerifier Name##StaticLocalVerifier; \ ASSERT(Name##StaticLocalVerifier.isNotRacy()); \ static Type& Name = *LEAK_SANITIZER_REGISTER_STATIC_LOCAL(Type, new Type Arguments) #else #define DEFINE_STATIC_LOCAL(Type, Name, Arguments) \ STATIC_ASSERT_FOR_LOCAL_WITH_GARBAGE_COLLECTED_TYPE(Name, Type); \ static Type& Name = *LEAK_SANITIZER_REGISTER_STATIC_LOCAL(Type, new Type Arguments) #endif // Use this to declare and define a static local pointer to a ref-counted object so that // it is leaked so that the object's destructors are not called at exit. // This macro should be used with ref-counted objects rather than DEFINE_STATIC_LOCAL macro, // as this macro does not lead to an extra memory allocation. #define DEFINE_STATIC_REF(type, name, arguments) \ static type* name = PassRefPtr(arguments).leakRef(); /* * The reinterpret_cast([pointer to Type2]) expressions - where * sizeof(Type1) > sizeof(Type2) - cause the following warning on ARM with GCC: * increases required alignment of target type. * * An implicit or an extra static_cast bypasses the warning. * For more info see the following bugzilla entries: * - https://bugs.webkit.org/show_bug.cgi?id=38045 * - http://gcc.gnu.org/bugzilla/show_bug.cgi?id=43976 */ #if CPU(ARM) && COMPILER(GCC) template bool isPointerTypeAlignmentOkay(Type* ptr) { return !(reinterpret_cast(ptr) % __alignof__(Type)); } template TypePtr reinterpret_cast_ptr(void* ptr) { ASSERT(isPointerTypeAlignmentOkay(reinterpret_cast(ptr))); return reinterpret_cast(ptr); } template TypePtr reinterpret_cast_ptr(const void* ptr) { ASSERT(isPointerTypeAlignmentOkay(reinterpret_cast(ptr))); return reinterpret_cast(ptr); } #else template bool isPointerTypeAlignmentOkay(Type*) { return true; } #define reinterpret_cast_ptr reinterpret_cast #endif namespace WTF { /* * C++'s idea of a reinterpret_cast lacks sufficient cojones. */ template inline TO bitwise_cast(FROM from) { static_assert(sizeof(TO) == sizeof(FROM), "WTF::bitwise_cast sizeof casted types should be equal"); union { FROM from; TO to; } u; u.from = from; return u.to; } template inline To safeCast(From value) { RELEASE_ASSERT(isInBounds(value)); return static_cast(value); } // Use the following macros to prevent errors caused by accidental // implicit casting of function arguments. For example, this can // be used to prevent overflows from non-promoting conversions. // // Example: // // HAS_STRICTLY_TYPED_ARG // void sendData(void* data, STRICTLY_TYPED_ARG(size)) // { // ALLOW_NUMERIC_ARG_TYPES_PROMOTABLE_TO(size_t); // ... // } // // The previous example will prevent callers from passing, for example, an // 'int'. On a 32-bit build, it will prevent use of an 'unsigned long long'. #define HAS_STRICTLY_TYPED_ARG template #define STRICTLY_TYPED_ARG(argName) ActualArgType argName #define STRICT_ARG_TYPE(ExpectedArgType) \ static_assert(std::is_same::value, \ "Strictly typed argument must be of type '" #ExpectedArgType "'." ) #define ALLOW_NUMERIC_ARG_TYPES_PROMOTABLE_TO(ExpectedArgType) \ static_assert(std::numeric_limits::is_integer == std::numeric_limits::is_integer, \ "Conversion between integer and non-integer types not allowed."); \ static_assert(sizeof(ExpectedArgType) >= sizeof(ActualArgType), \ "Truncating conversions not allowed."); \ static_assert(!std::numeric_limits::is_signed || std::numeric_limits::is_signed, \ "Signed to unsigned conversion not allowed."); \ static_assert((sizeof(ExpectedArgType) != sizeof(ActualArgType)) || (std::numeric_limits::is_signed == std::numeric_limits::is_signed), \ "Unsigned to signed conversion not allowed for types with identical size (could overflow)."); // Macro that returns a compile time constant with the length of an array, but gives an error if passed a non-array. template char (&ArrayLengthHelperFunction(T (&)[Size]))[Size]; // GCC needs some help to deduce a 0 length array. #if COMPILER(GCC) template char (&ArrayLengthHelperFunction(T (&)[0]))[0]; #endif #define WTF_ARRAY_LENGTH(array) sizeof(::WTF::ArrayLengthHelperFunction(array)) } // namespace WTF // This version of placement new omits a 0 check. enum NotNullTag { NotNull }; inline void* operator new(size_t, NotNullTag, void* location) { ASSERT(location); return location; } using WTF::bitwise_cast; using WTF::safeCast; #endif // WTF_StdLibExtras_h