OLD | NEW |
1 // Copyright 2014 the V8 project authors. All rights reserved. | 1 // Copyright 2014 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #ifndef V8_BASE_MACROS_H_ | 5 #ifndef V8_BASE_MACROS_H_ |
6 #define V8_BASE_MACROS_H_ | 6 #define V8_BASE_MACROS_H_ |
7 | 7 |
| 8 #include <cstring> |
| 9 |
8 #include "include/v8stdint.h" | 10 #include "include/v8stdint.h" |
9 #include "src/base/build_config.h" | 11 #include "src/base/build_config.h" |
10 #include "src/base/compiler-specific.h" | 12 #include "src/base/compiler-specific.h" |
11 #include "src/base/logging.h" | 13 #include "src/base/logging.h" |
12 | 14 |
13 | 15 |
14 // The expression OFFSET_OF(type, field) computes the byte-offset | 16 // The expression OFFSET_OF(type, field) computes the byte-offset |
15 // of the specified field relative to the containing type. This | 17 // of the specified field relative to the containing type. This |
16 // corresponds to 'offsetof' (in stddef.h), except that it doesn't | 18 // corresponds to 'offsetof' (in stddef.h), except that it doesn't |
17 // use 0 or NULL, which causes a problem with the compiler warnings | 19 // use 0 or NULL, which causes a problem with the compiler warnings |
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
95 // That gcc wants both of these prototypes seems mysterious. VC, for | 97 // That gcc wants both of these prototypes seems mysterious. VC, for |
96 // its part, can't decide which to use (another mystery). Matching of | 98 // its part, can't decide which to use (another mystery). Matching of |
97 // template overloads: the final frontier. | 99 // template overloads: the final frontier. |
98 template <typename T, size_t N> | 100 template <typename T, size_t N> |
99 char (&ArraySizeHelper(const T (&array)[N]))[N]; | 101 char (&ArraySizeHelper(const T (&array)[N]))[N]; |
100 #endif | 102 #endif |
101 | 103 |
102 #endif // V8_OS_NACL | 104 #endif // V8_OS_NACL |
103 | 105 |
104 | 106 |
| 107 // The COMPILE_ASSERT macro can be used to verify that a compile time |
| 108 // expression is true. For example, you could use it to verify the |
| 109 // size of a static array: |
| 110 // |
| 111 // COMPILE_ASSERT(ARRAYSIZE_UNSAFE(content_type_names) == CONTENT_NUM_TYPES, |
| 112 // content_type_names_incorrect_size); |
| 113 // |
| 114 // or to make sure a struct is smaller than a certain size: |
| 115 // |
| 116 // COMPILE_ASSERT(sizeof(foo) < 128, foo_too_large); |
| 117 // |
| 118 // The second argument to the macro is the name of the variable. If |
| 119 // the expression is false, most compilers will issue a warning/error |
| 120 // containing the name of the variable. |
| 121 #if V8_HAS_CXX11_STATIC_ASSERT |
| 122 |
| 123 // Under C++11, just use static_assert. |
| 124 #define COMPILE_ASSERT(expr, msg) static_assert(expr, #msg) |
| 125 |
| 126 #else |
| 127 |
| 128 template <bool> |
| 129 struct CompileAssert {}; |
| 130 |
| 131 #define COMPILE_ASSERT(expr, msg) \ |
| 132 typedef CompileAssert<static_cast<bool>(expr)> \ |
| 133 msg[static_cast<bool>(expr) ? 1 : -1] ALLOW_UNUSED |
| 134 |
| 135 // Implementation details of COMPILE_ASSERT: |
| 136 // |
| 137 // - COMPILE_ASSERT works by defining an array type that has -1 |
| 138 // elements (and thus is invalid) when the expression is false. |
| 139 // |
| 140 // - The simpler definition |
| 141 // |
| 142 // #define COMPILE_ASSERT(expr, msg) typedef char msg[(expr) ? 1 : -1] |
| 143 // |
| 144 // does not work, as gcc supports variable-length arrays whose sizes |
| 145 // are determined at run-time (this is gcc's extension and not part |
| 146 // of the C++ standard). As a result, gcc fails to reject the |
| 147 // following code with the simple definition: |
| 148 // |
| 149 // int foo; |
| 150 // COMPILE_ASSERT(foo, msg); // not supposed to compile as foo is |
| 151 // // not a compile-time constant. |
| 152 // |
| 153 // - By using the type CompileAssert<(bool(expr))>, we ensures that |
| 154 // expr is a compile-time constant. (Template arguments must be |
| 155 // determined at compile-time.) |
| 156 // |
| 157 // - The outer parentheses in CompileAssert<(bool(expr))> are necessary |
| 158 // to work around a bug in gcc 3.4.4 and 4.0.1. If we had written |
| 159 // |
| 160 // CompileAssert<bool(expr)> |
| 161 // |
| 162 // instead, these compilers will refuse to compile |
| 163 // |
| 164 // COMPILE_ASSERT(5 > 0, some_message); |
| 165 // |
| 166 // (They seem to think the ">" in "5 > 0" marks the end of the |
| 167 // template argument list.) |
| 168 // |
| 169 // - The array size is (bool(expr) ? 1 : -1), instead of simply |
| 170 // |
| 171 // ((expr) ? 1 : -1). |
| 172 // |
| 173 // This is to avoid running into a bug in MS VC 7.1, which |
| 174 // causes ((0.0) ? 1 : -1) to incorrectly evaluate to 1. |
| 175 |
| 176 #endif |
| 177 |
| 178 |
| 179 // bit_cast<Dest,Source> is a template function that implements the |
| 180 // equivalent of "*reinterpret_cast<Dest*>(&source)". We need this in |
| 181 // very low-level functions like the protobuf library and fast math |
| 182 // support. |
| 183 // |
| 184 // float f = 3.14159265358979; |
| 185 // int i = bit_cast<int32>(f); |
| 186 // // i = 0x40490fdb |
| 187 // |
| 188 // The classical address-casting method is: |
| 189 // |
| 190 // // WRONG |
| 191 // float f = 3.14159265358979; // WRONG |
| 192 // int i = * reinterpret_cast<int*>(&f); // WRONG |
| 193 // |
| 194 // The address-casting method actually produces undefined behavior |
| 195 // according to ISO C++ specification section 3.10 -15 -. Roughly, this |
| 196 // section says: if an object in memory has one type, and a program |
| 197 // accesses it with a different type, then the result is undefined |
| 198 // behavior for most values of "different type". |
| 199 // |
| 200 // This is true for any cast syntax, either *(int*)&f or |
| 201 // *reinterpret_cast<int*>(&f). And it is particularly true for |
| 202 // conversions between integral lvalues and floating-point lvalues. |
| 203 // |
| 204 // The purpose of 3.10 -15- is to allow optimizing compilers to assume |
| 205 // that expressions with different types refer to different memory. gcc |
| 206 // 4.0.1 has an optimizer that takes advantage of this. So a |
| 207 // non-conforming program quietly produces wildly incorrect output. |
| 208 // |
| 209 // The problem is not the use of reinterpret_cast. The problem is type |
| 210 // punning: holding an object in memory of one type and reading its bits |
| 211 // back using a different type. |
| 212 // |
| 213 // The C++ standard is more subtle and complex than this, but that |
| 214 // is the basic idea. |
| 215 // |
| 216 // Anyways ... |
| 217 // |
| 218 // bit_cast<> calls memcpy() which is blessed by the standard, |
| 219 // especially by the example in section 3.9 . Also, of course, |
| 220 // bit_cast<> wraps up the nasty logic in one place. |
| 221 // |
| 222 // Fortunately memcpy() is very fast. In optimized mode, with a |
| 223 // constant size, gcc 2.95.3, gcc 4.0.1, and msvc 7.1 produce inline |
| 224 // code with the minimal amount of data movement. On a 32-bit system, |
| 225 // memcpy(d,s,4) compiles to one load and one store, and memcpy(d,s,8) |
| 226 // compiles to two loads and two stores. |
| 227 // |
| 228 // I tested this code with gcc 2.95.3, gcc 4.0.1, icc 8.1, and msvc 7.1. |
| 229 // |
| 230 // WARNING: if Dest or Source is a non-POD type, the result of the memcpy |
| 231 // is likely to surprise you. |
| 232 template <class Dest, class Source> |
| 233 inline Dest bit_cast(const Source& source) { |
| 234 COMPILE_ASSERT(sizeof(Dest) == sizeof(Source), VerifySizesAreEqual); |
| 235 |
| 236 Dest dest; |
| 237 memcpy(&dest, &source, sizeof(dest)); |
| 238 return dest; |
| 239 } |
| 240 |
| 241 |
105 // A macro to disallow the evil copy constructor and operator= functions | 242 // A macro to disallow the evil copy constructor and operator= functions |
106 // This should be used in the private: declarations for a class | 243 // This should be used in the private: declarations for a class |
107 #define DISALLOW_COPY_AND_ASSIGN(TypeName) \ | 244 #define DISALLOW_COPY_AND_ASSIGN(TypeName) \ |
108 TypeName(const TypeName&) V8_DELETE; \ | 245 TypeName(const TypeName&) V8_DELETE; \ |
109 void operator=(const TypeName&) V8_DELETE | 246 void operator=(const TypeName&) V8_DELETE |
110 | 247 |
111 | 248 |
112 // A macro to disallow all the implicit constructors, namely the | 249 // A macro to disallow all the implicit constructors, namely the |
113 // default constructor, copy constructor and operator= functions. | 250 // default constructor, copy constructor and operator= functions. |
114 // | 251 // |
(...skipping 150 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
265 } | 402 } |
266 | 403 |
267 | 404 |
268 // Return the smallest multiple of m which is >= x. | 405 // Return the smallest multiple of m which is >= x. |
269 template <typename T> | 406 template <typename T> |
270 inline T RoundUp(T x, intptr_t m) { | 407 inline T RoundUp(T x, intptr_t m) { |
271 return RoundDown<T>(static_cast<T>(x + m - 1), m); | 408 return RoundDown<T>(static_cast<T>(x + m - 1), m); |
272 } | 409 } |
273 | 410 |
274 #endif // V8_BASE_MACROS_H_ | 411 #endif // V8_BASE_MACROS_H_ |
OLD | NEW |