diff options
author | Fedor Indutny <fedor@indutny.com> | 2014-10-10 14:49:02 +0400 |
---|---|---|
committer | Fedor Indutny <fedor@indutny.com> | 2014-10-10 14:49:02 +0400 |
commit | 6bcea4ff932144a5fd02affefd45164fbf471e67 (patch) | |
tree | a8e078c679b12f0daebe10ed254239cb0d79e146 /deps/v8/src/base/macros.h | |
parent | 4fae2356d105e394115188a814097c4a95ae0c5d (diff) | |
download | android-node-v8-6bcea4ff932144a5fd02affefd45164fbf471e67.tar.gz android-node-v8-6bcea4ff932144a5fd02affefd45164fbf471e67.tar.bz2 android-node-v8-6bcea4ff932144a5fd02affefd45164fbf471e67.zip |
deps: update v8 to 3.29.93.1
Diffstat (limited to 'deps/v8/src/base/macros.h')
-rw-r--r-- | deps/v8/src/base/macros.h | 290 |
1 files changed, 221 insertions, 69 deletions
diff --git a/deps/v8/src/base/macros.h b/deps/v8/src/base/macros.h index 50828db57f..cef088cb81 100644 --- a/deps/v8/src/base/macros.h +++ b/deps/v8/src/base/macros.h @@ -5,8 +5,11 @@ #ifndef V8_BASE_MACROS_H_ #define V8_BASE_MACROS_H_ +#include <cstring> + #include "include/v8stdint.h" #include "src/base/build_config.h" +#include "src/base/compiler-specific.h" #include "src/base/logging.h" @@ -20,13 +23,220 @@ (reinterpret_cast<intptr_t>(&(reinterpret_cast<type*>(4)->field)) - 4) -// The expression ARRAY_SIZE(a) is a compile-time constant of type -// size_t which represents the number of elements of the given -// array. You should only use ARRAY_SIZE on statically allocated -// arrays. -#define ARRAY_SIZE(a) \ - ((sizeof(a) / sizeof(*(a))) / \ - static_cast<size_t>(!(sizeof(a) % sizeof(*(a))))) +// ARRAYSIZE_UNSAFE performs essentially the same calculation as arraysize, +// but can be used on anonymous types or types defined inside +// functions. It's less safe than arraysize as it accepts some +// (although not all) pointers. Therefore, you should use arraysize +// whenever possible. +// +// The expression ARRAYSIZE_UNSAFE(a) is a compile-time constant of type +// size_t. +// +// ARRAYSIZE_UNSAFE catches a few type errors. If you see a compiler error +// +// "warning: division by zero in ..." +// +// when using ARRAYSIZE_UNSAFE, you are (wrongfully) giving it a pointer. +// You should only use ARRAYSIZE_UNSAFE on statically allocated arrays. +// +// The following comments are on the implementation details, and can +// be ignored by the users. +// +// ARRAYSIZE_UNSAFE(arr) works by inspecting sizeof(arr) (the # of bytes in +// the array) and sizeof(*(arr)) (the # of bytes in one array +// element). If the former is divisible by the latter, perhaps arr is +// indeed an array, in which case the division result is the # of +// elements in the array. Otherwise, arr cannot possibly be an array, +// and we generate a compiler error to prevent the code from +// compiling. +// +// Since the size of bool is implementation-defined, we need to cast +// !(sizeof(a) & sizeof(*(a))) to size_t in order to ensure the final +// result has type size_t. +// +// This macro is not perfect as it wrongfully accepts certain +// pointers, namely where the pointer size is divisible by the pointee +// size. Since all our code has to go through a 32-bit compiler, +// where a pointer is 4 bytes, this means all pointers to a type whose +// size is 3 or greater than 4 will be (righteously) rejected. +#define ARRAYSIZE_UNSAFE(a) \ + ((sizeof(a) / sizeof(*(a))) / \ + static_cast<size_t>(!(sizeof(a) % sizeof(*(a))))) // NOLINT + + +#if V8_OS_NACL + +// TODO(bmeurer): For some reason, the NaCl toolchain cannot handle the correct +// definition of arraysize() below, so we have to use the unsafe version for +// now. +#define arraysize ARRAYSIZE_UNSAFE + +#else // V8_OS_NACL + +// The arraysize(arr) macro returns the # of elements in an array arr. +// The expression is a compile-time constant, and therefore can be +// used in defining new arrays, for example. If you use arraysize on +// a pointer by mistake, you will get a compile-time error. +// +// One caveat is that arraysize() doesn't accept any array of an +// anonymous type or a type defined inside a function. In these rare +// cases, you have to use the unsafe ARRAYSIZE_UNSAFE() macro below. This is +// due to a limitation in C++'s template system. The limitation might +// eventually be removed, but it hasn't happened yet. +#define arraysize(array) (sizeof(ArraySizeHelper(array))) + + +// This template function declaration is used in defining arraysize. +// Note that the function doesn't need an implementation, as we only +// use its type. +template <typename T, size_t N> +char (&ArraySizeHelper(T (&array)[N]))[N]; + + +#if !V8_CC_MSVC +// That gcc wants both of these prototypes seems mysterious. VC, for +// its part, can't decide which to use (another mystery). Matching of +// template overloads: the final frontier. +template <typename T, size_t N> +char (&ArraySizeHelper(const T (&array)[N]))[N]; +#endif + +#endif // V8_OS_NACL + + +// The COMPILE_ASSERT macro can be used to verify that a compile time +// expression is true. For example, you could use it to verify the +// size of a static array: +// +// COMPILE_ASSERT(ARRAYSIZE_UNSAFE(content_type_names) == CONTENT_NUM_TYPES, +// content_type_names_incorrect_size); +// +// or to make sure a struct is smaller than a certain size: +// +// COMPILE_ASSERT(sizeof(foo) < 128, foo_too_large); +// +// The second argument to the macro is the name of the variable. If +// the expression is false, most compilers will issue a warning/error +// containing the name of the variable. +#if V8_HAS_CXX11_STATIC_ASSERT + +// Under C++11, just use static_assert. +#define COMPILE_ASSERT(expr, msg) static_assert(expr, #msg) + +#else + +template <bool> +struct CompileAssert {}; + +#define COMPILE_ASSERT(expr, msg) \ + typedef CompileAssert<static_cast<bool>(expr)> \ + msg[static_cast<bool>(expr) ? 1 : -1] ALLOW_UNUSED + +// Implementation details of COMPILE_ASSERT: +// +// - COMPILE_ASSERT works by defining an array type that has -1 +// elements (and thus is invalid) when the expression is false. +// +// - The simpler definition +// +// #define COMPILE_ASSERT(expr, msg) typedef char msg[(expr) ? 1 : -1] +// +// does not work, as gcc supports variable-length arrays whose sizes +// are determined at run-time (this is gcc's extension and not part +// of the C++ standard). As a result, gcc fails to reject the +// following code with the simple definition: +// +// int foo; +// COMPILE_ASSERT(foo, msg); // not supposed to compile as foo is +// // not a compile-time constant. +// +// - By using the type CompileAssert<(bool(expr))>, we ensures that +// expr is a compile-time constant. (Template arguments must be +// determined at compile-time.) +// +// - The outer parentheses in CompileAssert<(bool(expr))> are necessary +// to work around a bug in gcc 3.4.4 and 4.0.1. If we had written +// +// CompileAssert<bool(expr)> +// +// instead, these compilers will refuse to compile +// +// COMPILE_ASSERT(5 > 0, some_message); +// +// (They seem to think the ">" in "5 > 0" marks the end of the +// template argument list.) +// +// - The array size is (bool(expr) ? 1 : -1), instead of simply +// +// ((expr) ? 1 : -1). +// +// This is to avoid running into a bug in MS VC 7.1, which +// causes ((0.0) ? 1 : -1) to incorrectly evaluate to 1. + +#endif + + +// bit_cast<Dest,Source> is a template function that implements the +// equivalent of "*reinterpret_cast<Dest*>(&source)". We need this in +// very low-level functions like the protobuf library and fast math +// support. +// +// float f = 3.14159265358979; +// int i = bit_cast<int32>(f); +// // i = 0x40490fdb +// +// The classical address-casting method is: +// +// // WRONG +// float f = 3.14159265358979; // WRONG +// int i = * reinterpret_cast<int*>(&f); // WRONG +// +// The address-casting method actually produces undefined behavior +// according to ISO C++ specification section 3.10 -15 -. Roughly, this +// section says: if an object in memory has one type, and a program +// accesses it with a different type, then the result is undefined +// behavior for most values of "different type". +// +// This is true for any cast syntax, either *(int*)&f or +// *reinterpret_cast<int*>(&f). And it is particularly true for +// conversions between integral lvalues and floating-point lvalues. +// +// The purpose of 3.10 -15- is to allow optimizing compilers to assume +// that expressions with different types refer to different memory. gcc +// 4.0.1 has an optimizer that takes advantage of this. So a +// non-conforming program quietly produces wildly incorrect output. +// +// The problem is not the use of reinterpret_cast. The problem is type +// punning: holding an object in memory of one type and reading its bits +// back using a different type. +// +// The C++ standard is more subtle and complex than this, but that +// is the basic idea. +// +// Anyways ... +// +// bit_cast<> calls memcpy() which is blessed by the standard, +// especially by the example in section 3.9 . Also, of course, +// bit_cast<> wraps up the nasty logic in one place. +// +// Fortunately memcpy() is very fast. In optimized mode, with a +// constant size, gcc 2.95.3, gcc 4.0.1, and msvc 7.1 produce inline +// code with the minimal amount of data movement. On a 32-bit system, +// memcpy(d,s,4) compiles to one load and one store, and memcpy(d,s,8) +// compiles to two loads and two stores. +// +// I tested this code with gcc 2.95.3, gcc 4.0.1, icc 8.1, and msvc 7.1. +// +// WARNING: if Dest or Source is a non-POD type, the result of the memcpy +// is likely to surprise you. +template <class Dest, class Source> +V8_INLINE Dest bit_cast(Source const& source) { + COMPILE_ASSERT(sizeof(Dest) == sizeof(Source), VerifySizesAreEqual); + + Dest dest; + memcpy(&dest, &source, sizeof(dest)); + return dest; +} // A macro to disallow the evil copy constructor and operator= functions @@ -52,8 +262,8 @@ #define NO_INLINE(declarator) V8_NOINLINE declarator -// Newly written code should use V8_WARN_UNUSED_RESULT. -#define MUST_USE_RESULT V8_WARN_UNUSED_RESULT +// Newly written code should use WARN_UNUSED_RESULT. +#define MUST_USE_RESULT WARN_UNUSED_RESULT // Define V8_USE_ADDRESS_SANITIZER macros. @@ -101,7 +311,7 @@ template <int> class StaticAssertionHelper { }; #define STATIC_ASSERT(test) \ typedef \ StaticAssertionHelper<sizeof(StaticAssertion<static_cast<bool>((test))>)> \ - SEMI_STATIC_JOIN(__StaticAssertTypedef__, __LINE__) V8_UNUSED + SEMI_STATIC_JOIN(__StaticAssertTypedef__, __LINE__) ALLOW_UNUSED #endif @@ -115,14 +325,6 @@ inline void USE(T) { } #define IS_POWER_OF_TWO(x) ((x) != 0 && (((x) & ((x) - 1)) == 0)) -// Returns true iff x is a power of 2. Cannot be used with the maximally -// negative value of the type T (the -1 overflows). -template <typename T> -inline bool IsPowerOf2(T x) { - return IS_POWER_OF_TWO(x); -} - - // Define our own macros for writing 64-bit constants. This is less fragile // than defining __STDC_CONSTANT_MACROS before including <stdint.h>, and it // works on compilers that don't have it (like MSVC). @@ -195,7 +397,7 @@ inline T AddressFrom(intptr_t x) { // Return the largest multiple of m which is <= x. template <typename T> inline T RoundDown(T x, intptr_t m) { - DCHECK(IsPowerOf2(m)); + DCHECK(IS_POWER_OF_TWO(m)); return AddressFrom<T>(OffsetFrom(x) & -m); } @@ -206,54 +408,4 @@ inline T RoundUp(T x, intptr_t m) { return RoundDown<T>(static_cast<T>(x + m - 1), m); } - -// Increment a pointer until it has the specified alignment. -// This works like RoundUp, but it works correctly on pointer types where -// sizeof(*pointer) might not be 1. -template<class T> -T AlignUp(T pointer, size_t alignment) { - DCHECK(sizeof(pointer) == sizeof(uintptr_t)); - uintptr_t pointer_raw = reinterpret_cast<uintptr_t>(pointer); - return reinterpret_cast<T>(RoundUp(pointer_raw, alignment)); -} - - -template <typename T, typename U> -inline bool IsAligned(T value, U alignment) { - return (value & (alignment - 1)) == 0; -} - - -// Returns the smallest power of two which is >= x. If you pass in a -// number that is already a power of two, it is returned as is. -// Implementation is from "Hacker's Delight" by Henry S. Warren, Jr., -// figure 3-3, page 48, where the function is called clp2. -inline uint32_t RoundUpToPowerOf2(uint32_t x) { - DCHECK(x <= 0x80000000u); - x = x - 1; - x = x | (x >> 1); - x = x | (x >> 2); - x = x | (x >> 4); - x = x | (x >> 8); - x = x | (x >> 16); - return x + 1; -} - - -inline uint32_t RoundDownToPowerOf2(uint32_t x) { - uint32_t rounded_up = RoundUpToPowerOf2(x); - if (rounded_up > x) return rounded_up >> 1; - return rounded_up; -} - - -// Returns current value of top of the stack. Works correctly with ASAN. -DISABLE_ASAN -inline uintptr_t GetCurrentStackPosition() { - // Takes the address of the limit variable in order to find out where - // the top of stack is right now. - uintptr_t limit = reinterpret_cast<uintptr_t>(&limit); - return limit; -} - #endif // V8_BASE_MACROS_H_ |