summaryrefslogtreecommitdiff
path: root/Source/WTF/wtf/StdLibExtras.h
diff options
context:
space:
mode:
authorLorry Tar Creator <lorry-tar-importer@lorry>2017-06-27 06:07:23 +0000
committerLorry Tar Creator <lorry-tar-importer@lorry>2017-06-27 06:07:23 +0000
commit1bf1084f2b10c3b47fd1a588d85d21ed0eb41d0c (patch)
tree46dcd36c86e7fbc6e5df36deb463b33e9967a6f7 /Source/WTF/wtf/StdLibExtras.h
parent32761a6cee1d0dee366b885b7b9c777e67885688 (diff)
downloadWebKitGtk-tarball-master.tar.gz
Diffstat (limited to 'Source/WTF/wtf/StdLibExtras.h')
-rw-r--r--Source/WTF/wtf/StdLibExtras.h286
1 files changed, 188 insertions, 98 deletions
diff --git a/Source/WTF/wtf/StdLibExtras.h b/Source/WTF/wtf/StdLibExtras.h
index 2e35031da..716661fad 100644
--- a/Source/WTF/wtf/StdLibExtras.h
+++ b/Source/WTF/wtf/StdLibExtras.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2008 Apple Inc. All Rights Reserved.
+ * Copyright (C) 2008, 2016 Apple Inc. All Rights Reserved.
* Copyright (C) 2013 Patrick Gansterer <paroga@paroga.com>
*
* Redistribution and use in source and binary forms, with or without
@@ -28,35 +28,33 @@
#define WTF_StdLibExtras_h
#include <chrono>
+#include <cstring>
#include <memory>
#include <wtf/Assertions.h>
#include <wtf/CheckedArithmetic.h>
+#include <wtf/Compiler.h>
-// Use these to declare and define a static local variable (static T;) so that
-// it is leaked so that its destructors are not called at exit. Using this
-// macro also allows workarounds a compiler bug present in Apple's version of GCC 4.0.1.
-#ifndef DEFINE_STATIC_LOCAL
-#if COMPILER(GCC) && defined(__APPLE_CC__) && __GNUC__ == 4 && __GNUC_MINOR__ == 0 && __GNUC_PATCHLEVEL__ == 1
-#define DEFINE_STATIC_LOCAL(type, name, arguments) \
- static type* name##Ptr = new type arguments; \
- type& name = *name##Ptr
-#else
-#define DEFINE_STATIC_LOCAL(type, name, arguments) \
+// This was used to declare and define a static local variable (static T;) so that
+// it was leaked so that its destructors were not called at exit.
+// Newly written code should use static NeverDestroyed<T> instead.
+#ifndef DEPRECATED_DEFINE_STATIC_LOCAL
+#define DEPRECATED_DEFINE_STATIC_LOCAL(type, name, arguments) \
static type& name = *new type arguments
#endif
-#endif
// Use this macro to declare and define a debug-only global variable that may have a
// non-trivial constructor and destructor. When building with clang, this will suppress
// warnings about global constructors and exit-time destructors.
-#ifndef NDEBUG
-#if COMPILER(CLANG)
-#define DEFINE_DEBUG_ONLY_GLOBAL(type, name, arguments) \
+#define DEFINE_GLOBAL_FOR_LOGGING(type, name, arguments) \
_Pragma("clang diagnostic push") \
_Pragma("clang diagnostic ignored \"-Wglobal-constructors\"") \
_Pragma("clang diagnostic ignored \"-Wexit-time-destructors\"") \
static type name arguments; \
_Pragma("clang diagnostic pop")
+
+#ifndef NDEBUG
+#if COMPILER(CLANG)
+#define DEFINE_DEBUG_ONLY_GLOBAL(type, name, arguments) DEFINE_GLOBAL_FOR_LOGGING(type, name, arguments)
#else
#define DEFINE_DEBUG_ONLY_GLOBAL(type, name, arguments) \
static type name arguments;
@@ -70,10 +68,17 @@
// NULL can cause compiler problems, especially in cases of multiple inheritance.
#define OBJECT_OFFSETOF(class, field) (reinterpret_cast<ptrdiff_t>(&(reinterpret_cast<class*>(0x4000)->field)) - 0x4000)
+#define CAST_OFFSET(from, to) (reinterpret_cast<uintptr_t>(static_cast<to>((reinterpret_cast<from>(0x4000)))) - 0x4000)
+
// STRINGIZE: Can convert any value to quoted string, even expandable macros
#define STRINGIZE(exp) #exp
#define STRINGIZE_VALUE_OF(exp) STRINGIZE(exp)
+// WTF_CONCAT: concatenate two symbols into one, even expandable macros
+#define WTF_CONCAT_INTERNAL_DONT_USE(a, b) a ## b
+#define WTF_CONCAT(a, b) WTF_CONCAT_INTERNAL_DONT_USE(a, b)
+
+
/*
* The reinterpret_cast<Type1*>([pointer to Type2]) expressions - where
* sizeof(Type1) > sizeof(Type2) - cause the following warning on ARM with GCC:
@@ -84,7 +89,7 @@
* - https://bugs.webkit.org/show_bug.cgi?id=38045
* - http://gcc.gnu.org/bugzilla/show_bug.cgi?id=43976
*/
-#if (CPU(ARM) || CPU(MIPS)) && COMPILER(GCC)
+#if (CPU(ARM) || CPU(MIPS)) && COMPILER(GCC_OR_CLANG)
template<typename Type>
inline bool isPointerTypeAlignmentOkay(Type* ptr)
{
@@ -115,8 +120,11 @@ inline bool isPointerTypeAlignmentOkay(Type*)
namespace WTF {
+enum CheckMoveParameterTag { CheckMoveParameter };
+
static const size_t KB = 1024;
static const size_t MB = 1024 * 1024;
+static const size_t GB = 1024 * 1024 * 1024;
inline bool isPointerAligned(void* p)
{
@@ -135,18 +143,20 @@ template<typename ToType, typename FromType>
inline ToType bitwise_cast(FromType from)
{
static_assert(sizeof(FromType) == sizeof(ToType), "bitwise_cast size of FromType and ToType must be equal!");
- union {
- FromType from;
- ToType to;
- } u;
- u.from = from;
- return u.to;
+#if COMPILER_SUPPORTS(BUILTIN_IS_TRIVIALLY_COPYABLE)
+ // Not all recent STL implementations support the std::is_trivially_copyable type trait. Work around this by only checking on toolchains which have the equivalent compiler intrinsic.
+ static_assert(__is_trivially_copyable(ToType), "bitwise_cast of non-trivially-copyable type!");
+ static_assert(__is_trivially_copyable(FromType), "bitwise_cast of non-trivially-copyable type!");
+#endif
+ typename std::remove_const<ToType>::type to { };
+ std::memcpy(&to, &from, sizeof(to));
+ return to;
}
template<typename ToType, typename FromType>
inline ToType safeCast(FromType value)
{
- ASSERT(isInBounds<ToType>(value));
+ RELEASE_ASSERT(isInBounds<ToType>(value));
return static_cast<ToType>(value);
}
@@ -166,23 +176,32 @@ inline size_t bitCount(uint64_t bits)
// Macro that returns a compile time constant with the length of an array, but gives an error if passed a non-array.
template<typename T, size_t Size> char (&ArrayLengthHelperFunction(T (&)[Size]))[Size];
// GCC needs some help to deduce a 0 length array.
-#if COMPILER(GCC)
+#if COMPILER(GCC_OR_CLANG)
template<typename T> char (&ArrayLengthHelperFunction(T (&)[0]))[0];
#endif
#define WTF_ARRAY_LENGTH(array) sizeof(::WTF::ArrayLengthHelperFunction(array))
+ALWAYS_INLINE constexpr size_t roundUpToMultipleOfImpl0(size_t remainderMask, size_t x)
+{
+ return (x + remainderMask) & ~remainderMask;
+}
+
+ALWAYS_INLINE constexpr size_t roundUpToMultipleOfImpl(size_t divisor, size_t x)
+{
+ return roundUpToMultipleOfImpl0(divisor - 1, x);
+}
+
// Efficient implementation that takes advantage of powers of two.
inline size_t roundUpToMultipleOf(size_t divisor, size_t x)
{
ASSERT(divisor && !(divisor & (divisor - 1)));
- size_t remainderMask = divisor - 1;
- return (x + remainderMask) & ~remainderMask;
+ return roundUpToMultipleOfImpl(divisor, x);
}
-template<size_t divisor> inline size_t roundUpToMultipleOf(size_t x)
+template<size_t divisor> inline constexpr size_t roundUpToMultipleOf(size_t x)
{
static_assert(divisor && !(divisor & (divisor - 1)), "divisor must be a power of two!");
- return roundUpToMultipleOf(divisor, x);
+ return roundUpToMultipleOfImpl(divisor, x);
}
enum BinarySearchMode {
@@ -276,32 +295,120 @@ inline void insertIntoBoundedVector(VectorType& vector, size_t size, const Eleme
vector[index] = element;
}
-} // namespace WTF
+// This is here instead of CompilationThread.h to prevent that header from being included
+// everywhere. The fact that this method, and that header, exist outside of JSC is a bug.
+// https://bugs.webkit.org/show_bug.cgi?id=131815
+WTF_EXPORT_PRIVATE bool isCompilationThread();
+
+template<typename Func>
+bool isStatelessLambda()
+{
+ return std::is_empty<Func>::value;
+}
-#if OS(WINCE)
-// Windows CE CRT has does not implement bsearch().
-inline void* wtf_bsearch(const void* key, const void* base, size_t count, size_t size, int (*compare)(const void *, const void *))
-{
- const char* first = static_cast<const char*>(base);
-
- while (count) {
- size_t pos = (count - 1) >> 1;
- const char* item = first + pos * size;
- int compareResult = compare(item, key);
- if (!compareResult)
- return const_cast<char*>(item);
- if (compareResult < 0) {
- count -= (pos + 1);
- first += (pos + 1) * size;
- } else
- count = pos;
+template<typename ResultType, typename Func, typename... ArgumentTypes>
+ResultType callStatelessLambda(ArgumentTypes&&... arguments)
+{
+ uint64_t data[(sizeof(Func) + sizeof(uint64_t) - 1) / sizeof(uint64_t)];
+ memset(data, 0, sizeof(data));
+ return (*bitwise_cast<Func*>(data))(std::forward<ArgumentTypes>(arguments)...);
+}
+
+template<typename T, typename U>
+bool checkAndSet(T& left, U right)
+{
+ if (left == right)
+ return false;
+ left = right;
+ return true;
+}
+
+template<typename T>
+bool findBitInWord(T word, size_t& index, size_t endIndex, bool value)
+{
+ static_assert(std::is_unsigned<T>::value, "Type used in findBitInWord must be unsigned");
+
+ word >>= index;
+
+ while (index < endIndex) {
+ if ((word & 1) == static_cast<T>(value))
+ return true;
+ index++;
+ word >>= 1;
+ }
+
+ index = endIndex;
+ return false;
+}
+
+// Visitor adapted from http://stackoverflow.com/questions/25338795/is-there-a-name-for-this-tuple-creation-idiom
+
+template <class A, class... B>
+struct Visitor : Visitor<A>, Visitor<B...> {
+ Visitor(A a, B... b)
+ : Visitor<A>(a)
+ , Visitor<B...>(b...)
+ {
+ }
+
+ using Visitor<A>::operator ();
+ using Visitor<B...>::operator ();
+};
+
+template <class A>
+struct Visitor<A> : A {
+ Visitor(A a)
+ : A(a)
+ {
}
- return 0;
+ using A::operator();
+};
+
+template <class... F>
+Visitor<F...> makeVisitor(F... f)
+{
+ return Visitor<F...>(f...);
}
-#define bsearch(key, base, count, size, compare) wtf_bsearch(key, base, count, size, compare)
-#endif
+namespace Detail
+{
+ template <typename, template <typename...> class>
+ struct IsTemplate_ : std::false_type
+ {
+ };
+
+ template <typename... Ts, template <typename...> class C>
+ struct IsTemplate_<C<Ts...>, C> : std::true_type
+ {
+ };
+}
+
+template <typename T, template <typename...> class Template>
+struct IsTemplate : public std::integral_constant<bool, Detail::IsTemplate_<T, Template>::value> {};
+
+namespace Detail
+{
+ template <template <typename...> class Base, typename Derived>
+ struct IsBaseOfTemplateImpl
+ {
+ template <typename... Args>
+ static std::true_type test(Base<Args...>*);
+ static std::false_type test(void*);
+
+ static constexpr const bool value = decltype(test(std::declval<typename std::remove_cv<Derived>::type*>()))::value;
+ };
+}
+
+template <template <typename...> class Base, typename Derived>
+struct IsBaseOfTemplate : public std::integral_constant<bool, Detail::IsBaseOfTemplateImpl<Base, Derived>::value> {};
+
+template <class T>
+struct RemoveCVAndReference {
+ typedef typename std::remove_cv<typename std::remove_reference<T>::type>::type type;
+};
+
+} // namespace WTF
// This version of placement new omits a 0 check.
enum NotNullTag { NotNull };
@@ -311,20 +418,9 @@ inline void* operator new(size_t, NotNullTag, void* location)
return location;
}
-#if (COMPILER(GCC) && !COMPILER(CLANG) && !GCC_VERSION_AT_LEAST(4, 8, 1))
-
-// Work-around for Pre-C++11 syntax in MSVC 2010, and prior as well as GCC < 4.8.1.
-namespace std {
- template<class T> struct is_trivially_destructible {
- static const bool value = std::has_trivial_destructor<T>::value;
- };
-}
-#endif
-
// This adds various C++14 features for versions of the STL that may not yet have them.
namespace std {
-// MSVC 2013 supports std::make_unique already.
-#if !defined(_MSC_VER) || _MSC_VER < 1800
+#if COMPILER(CLANG) && __cplusplus < 201400L
template<class T> struct _Unique_if {
typedef unique_ptr<T> _Single_object;
};
@@ -352,58 +448,52 @@ make_unique(size_t n)
template<class T, class... Args> typename _Unique_if<T>::_Known_bound
make_unique(Args&&...) = delete;
-#endif
-// Compile-time integer sequences
-// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3658.html
-// (Note that we only implement index_sequence, and not the more generic integer_sequence).
-template<size_t... indexes> struct index_sequence {
- static size_t size() { return sizeof...(indexes); }
-};
+// std::exchange
+template<class T, class U = T>
+T exchange(T& t, U&& newValue)
+{
+ T oldValue = std::move(t);
+ t = std::forward<U>(newValue);
-template<size_t currentIndex, size_t...indexes> struct make_index_sequence_helper;
+ return oldValue;
+}
+#endif
-template<size_t...indexes> struct make_index_sequence_helper<0, indexes...> {
- typedef std::index_sequence<indexes...> type;
-};
+template<WTF::CheckMoveParameterTag, typename T>
+ALWAYS_INLINE constexpr typename remove_reference<T>::type&& move(T&& value)
+{
+ static_assert(is_lvalue_reference<T>::value, "T is not an lvalue reference; move() is unnecessary.");
-template<size_t currentIndex, size_t...indexes> struct make_index_sequence_helper {
- typedef typename make_index_sequence_helper<currentIndex - 1, currentIndex - 1, indexes...>::type type;
-};
+ using NonRefQualifiedType = typename remove_reference<T>::type;
+ static_assert(!is_const<NonRefQualifiedType>::value, "T is const qualified.");
-template<size_t length> struct make_index_sequence : public make_index_sequence_helper<length>::type { };
+ return move(forward<T>(value));
+}
-#if COMPILER_SUPPORTS(CXX_USER_LITERALS)
-// These literals are available in C++14, so once we require C++14 compilers we can get rid of them here.
-// (User-literals need to have a leading underscore so we add it here - the "real" literals don't have underscores).
-namespace literals {
-namespace chrono_literals {
- CONSTEXPR inline chrono::seconds operator"" _s(unsigned long long s)
- {
- return chrono::seconds(static_cast<chrono::seconds::rep>(s));
- }
+} // namespace std
- CONSTEXPR chrono::milliseconds operator"" _ms(unsigned long long ms)
- {
- return chrono::milliseconds(static_cast<chrono::milliseconds::rep>(ms));
- }
-}
-}
-#endif
-}
+#define WTFMove(value) std::move<WTF::CheckMoveParameter>(value)
using WTF::KB;
using WTF::MB;
+using WTF::GB;
+using WTF::approximateBinarySearch;
+using WTF::binarySearch;
+using WTF::bitwise_cast;
+using WTF::callStatelessLambda;
+using WTF::checkAndSet;
+using WTF::findBitInWord;
using WTF::insertIntoBoundedVector;
+using WTF::isCompilationThread;
using WTF::isPointerAligned;
+using WTF::isStatelessLambda;
using WTF::is8ByteAligned;
-using WTF::binarySearch;
-using WTF::tryBinarySearch;
-using WTF::approximateBinarySearch;
-using WTF::bitwise_cast;
+using WTF::roundUpToMultipleOf;
using WTF::safeCast;
+using WTF::tryBinarySearch;
-#if COMPILER_SUPPORTS(CXX_USER_LITERALS)
+#if !COMPILER(CLANG) || __cplusplus >= 201400L
// We normally don't want to bring in entire std namespaces, but literals are an exception.
using namespace std::literals::chrono_literals;
#endif