| Index: src/base/macros.h
|
| diff --git a/src/base/macros.h b/src/base/macros.h
|
| index a951c2ba81f903468da7665245b76757cefe391a..7a3561878b6debcdfb248370d2ef48b3eef62938 100644
|
| --- a/src/base/macros.h
|
| +++ b/src/base/macros.h
|
| @@ -5,6 +5,8 @@
|
| #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"
|
| @@ -102,6 +104,141 @@ char (&ArraySizeHelper(const T (&array)[N]))[N];
|
| #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>
|
| +inline Dest bit_cast(const Source& 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
|
| // This should be used in the private: declarations for a class
|
| #define DISALLOW_COPY_AND_ASSIGN(TypeName) \
|
|
|