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 "include/v8stdint.h" | 8 #include "include/v8stdint.h" |
9 #include "src/base/build_config.h" | 9 #include "src/base/build_config.h" |
10 #include "src/base/logging.h" | 10 #include "src/base/logging.h" |
11 | 11 |
12 | 12 |
13 // The expression OFFSET_OF(type, field) computes the byte-offset | 13 // The expression OFFSET_OF(type, field) computes the byte-offset |
14 // of the specified field relative to the containing type. This | 14 // of the specified field relative to the containing type. This |
15 // corresponds to 'offsetof' (in stddef.h), except that it doesn't | 15 // corresponds to 'offsetof' (in stddef.h), except that it doesn't |
16 // use 0 or NULL, which causes a problem with the compiler warnings | 16 // use 0 or NULL, which causes a problem with the compiler warnings |
17 // we have enabled (which is also why 'offsetof' doesn't seem to work). | 17 // we have enabled (which is also why 'offsetof' doesn't seem to work). |
18 // Here we simply use the non-zero value 4, which seems to work. | 18 // Here we simply use the non-zero value 4, which seems to work. |
19 #define OFFSET_OF(type, field) \ | 19 #define OFFSET_OF(type, field) \ |
20 (reinterpret_cast<intptr_t>(&(reinterpret_cast<type*>(4)->field)) - 4) | 20 (reinterpret_cast<intptr_t>(&(reinterpret_cast<type*>(4)->field)) - 4) |
21 | 21 |
22 | 22 |
23 // The expression ARRAY_SIZE(a) is a compile-time constant of type | 23 // The arraysize(arr) macro returns the # of elements in an array arr. |
24 // size_t which represents the number of elements of the given | 24 // The expression is a compile-time constant, and therefore can be |
25 // array. You should only use ARRAY_SIZE on statically allocated | 25 // used in defining new arrays, for example. If you use arraysize on |
26 // arrays. | 26 // a pointer by mistake, you will get a compile-time error. |
27 #define ARRAY_SIZE(a) \ | 27 // |
28 ((sizeof(a) / sizeof(*(a))) / \ | 28 // One caveat is that arraysize() doesn't accept any array of an |
29 static_cast<size_t>(!(sizeof(a) % sizeof(*(a))))) | 29 // anonymous type or a type defined inside a function. In these rare |
30 // cases, you have to use the unsafe ARRAYSIZE_UNSAFE() macro below. This is | |
31 // due to a limitation in C++'s template system. The limitation might | |
32 // eventually be removed, but it hasn't happened yet. | |
33 #define arraysize(array) (sizeof(ArraySizeHelper(array))) | |
34 | |
35 | |
36 // This template function declaration is used in defining arraysize. | |
37 // Note that the function doesn't need an implementation, as we only | |
38 // use its type. | |
39 template <typename T, size_t N> | |
40 char (&ArraySizeHelper(T (&array)[N]))[N]; | |
41 | |
42 | |
43 #if V8_CC_GNU | |
44 // That gcc wants both of these prototypes seems mysterious. VC, for | |
45 // its part, can't decide which to use (another mystery). Matching of | |
46 // template overloads: the final frontier. | |
47 template <typename T, size_t N> | |
48 char (&ArraySizeHelper(const T (&array)[N]))[N]; | |
49 #endif | |
50 | |
51 | |
52 // ARRAYSIZE_UNSAFE performs essentially the same calculation as arraysize, | |
53 // but can be used on anonymous types or types defined inside | |
54 // functions. It's less safe than arraysize as it accepts some | |
55 // (although not all) pointers. Therefore, you should use arraysize | |
56 // whenever possible. | |
57 // | |
58 // The expression ARRAYSIZE_UNSAFE(a) is a compile-time constant of type | |
59 // size_t. | |
60 // | |
61 // ARRAYSIZE_UNSAFE catches a few type errors. If you see a compiler error | |
62 // | |
63 // "warning: division by zero in ..." | |
64 // | |
65 // when using ARRAYSIZE_UNSAFE, you are (wrongfully) giving it a pointer. | |
66 // You should only use ARRAYSIZE_UNSAFE on statically allocated arrays. | |
67 // | |
68 // The following comments are on the implementation details, and can | |
69 // be ignored by the users. | |
70 // | |
71 // ARRAYSIZE_UNSAFE(arr) works by inspecting sizeof(arr) (the # of bytes in | |
72 // the array) and sizeof(*(arr)) (the # of bytes in one array | |
73 // element). If the former is divisible by the latter, perhaps arr is | |
74 // indeed an array, in which case the division result is the # of | |
75 // elements in the array. Otherwise, arr cannot possibly be an array, | |
76 // and we generate a compiler error to prevent the code from | |
77 // compiling. | |
78 // | |
79 // Since the size of bool is implementation-defined, we need to cast | |
80 // !(sizeof(a) & sizeof(*(a))) to size_t in order to ensure the final | |
81 // result has type size_t. | |
82 // | |
83 // This macro is not perfect as it wrongfully accepts certain | |
84 // pointers, namely where the pointer size is divisible by the pointee | |
85 // size. Since all our code has to go through a 32-bit compiler, | |
86 // where a pointer is 4 bytes, this means all pointers to a type whose | |
87 // size is 3 or greater than 4 will be (righteously) rejected. | |
88 #define ARRAYSIZE_UNSAFE(a) \ | |
Yang
2014/08/26 09:17:22
Do we actually need this?
| |
89 ((sizeof(a) / sizeof(*(a))) / \ | |
90 static_cast<size_t>(!(sizeof(a) % sizeof(*(a))))) // NOLINT | |
30 | 91 |
31 | 92 |
32 // A macro to disallow the evil copy constructor and operator= functions | 93 // A macro to disallow the evil copy constructor and operator= functions |
33 // This should be used in the private: declarations for a class | 94 // This should be used in the private: declarations for a class |
34 #define DISALLOW_COPY_AND_ASSIGN(TypeName) \ | 95 #define DISALLOW_COPY_AND_ASSIGN(TypeName) \ |
35 TypeName(const TypeName&) V8_DELETE; \ | 96 TypeName(const TypeName&) V8_DELETE; \ |
36 void operator=(const TypeName&) V8_DELETE | 97 void operator=(const TypeName&) V8_DELETE |
37 | 98 |
38 | 99 |
39 // A macro to disallow all the implicit constructors, namely the | 100 // A macro to disallow all the implicit constructors, namely the |
(...skipping 210 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
250 // Returns current value of top of the stack. Works correctly with ASAN. | 311 // Returns current value of top of the stack. Works correctly with ASAN. |
251 DISABLE_ASAN | 312 DISABLE_ASAN |
252 inline uintptr_t GetCurrentStackPosition() { | 313 inline uintptr_t GetCurrentStackPosition() { |
253 // Takes the address of the limit variable in order to find out where | 314 // Takes the address of the limit variable in order to find out where |
254 // the top of stack is right now. | 315 // the top of stack is right now. |
255 uintptr_t limit = reinterpret_cast<uintptr_t>(&limit); | 316 uintptr_t limit = reinterpret_cast<uintptr_t>(&limit); |
256 return limit; | 317 return limit; |
257 } | 318 } |
258 | 319 |
259 #endif // V8_BASE_MACROS_H_ | 320 #endif // V8_BASE_MACROS_H_ |
OLD | NEW |