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) \ |