Line data Source code
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
3 : // found in the LICENSE file.
4 :
5 : #ifndef V8_BASE_MACROS_H_
6 : #define V8_BASE_MACROS_H_
7 :
8 : #include "src/base/compiler-specific.h"
9 : #include "src/base/format-macros.h"
10 : #include "src/base/logging.h"
11 :
12 : // No-op macro which is used to work around MSVC's funky VA_ARGS support.
13 : #define EXPAND(x) x
14 :
15 : // TODO(all) Replace all uses of this macro with C++'s offsetof. To do that, we
16 : // have to make sure that only standard-layout types and simple field
17 : // designators are used.
18 : #define OFFSET_OF(type, field) \
19 : (reinterpret_cast<intptr_t>(&(reinterpret_cast<type*>(16)->field)) - 16)
20 :
21 :
22 : // The arraysize(arr) macro returns the # of elements in an array arr.
23 : // The expression is a compile-time constant, and therefore can be
24 : // used in defining new arrays, for example. If you use arraysize on
25 : // a pointer by mistake, you will get a compile-time error.
26 : #define arraysize(array) (sizeof(ArraySizeHelper(array)))
27 :
28 :
29 : // This template function declaration is used in defining arraysize.
30 : // Note that the function doesn't need an implementation, as we only
31 : // use its type.
32 : template <typename T, size_t N>
33 : char (&ArraySizeHelper(T (&array)[N]))[N];
34 :
35 :
36 : #if !V8_CC_MSVC
37 : // That gcc wants both of these prototypes seems mysterious. VC, for
38 : // its part, can't decide which to use (another mystery). Matching of
39 : // template overloads: the final frontier.
40 : template <typename T, size_t N>
41 : char (&ArraySizeHelper(const T (&array)[N]))[N];
42 : #endif
43 :
44 :
45 : // bit_cast<Dest,Source> is a template function that implements the
46 : // equivalent of "*reinterpret_cast<Dest*>(&source)". We need this in
47 : // very low-level functions like the protobuf library and fast math
48 : // support.
49 : //
50 : // float f = 3.14159265358979;
51 : // int i = bit_cast<int32>(f);
52 : // // i = 0x40490fdb
53 : //
54 : // The classical address-casting method is:
55 : //
56 : // // WRONG
57 : // float f = 3.14159265358979; // WRONG
58 : // int i = * reinterpret_cast<int*>(&f); // WRONG
59 : //
60 : // The address-casting method actually produces undefined behavior
61 : // according to ISO C++ specification section 3.10 -15 -. Roughly, this
62 : // section says: if an object in memory has one type, and a program
63 : // accesses it with a different type, then the result is undefined
64 : // behavior for most values of "different type".
65 : //
66 : // This is true for any cast syntax, either *(int*)&f or
67 : // *reinterpret_cast<int*>(&f). And it is particularly true for
68 : // conversions between integral lvalues and floating-point lvalues.
69 : //
70 : // The purpose of 3.10 -15- is to allow optimizing compilers to assume
71 : // that expressions with different types refer to different memory. gcc
72 : // 4.0.1 has an optimizer that takes advantage of this. So a
73 : // non-conforming program quietly produces wildly incorrect output.
74 : //
75 : // The problem is not the use of reinterpret_cast. The problem is type
76 : // punning: holding an object in memory of one type and reading its bits
77 : // back using a different type.
78 : //
79 : // The C++ standard is more subtle and complex than this, but that
80 : // is the basic idea.
81 : //
82 : // Anyways ...
83 : //
84 : // bit_cast<> calls memcpy() which is blessed by the standard,
85 : // especially by the example in section 3.9 . Also, of course,
86 : // bit_cast<> wraps up the nasty logic in one place.
87 : //
88 : // Fortunately memcpy() is very fast. In optimized mode, with a
89 : // constant size, gcc 2.95.3, gcc 4.0.1, and msvc 7.1 produce inline
90 : // code with the minimal amount of data movement. On a 32-bit system,
91 : // memcpy(d,s,4) compiles to one load and one store, and memcpy(d,s,8)
92 : // compiles to two loads and two stores.
93 : //
94 : // I tested this code with gcc 2.95.3, gcc 4.0.1, icc 8.1, and msvc 7.1.
95 : //
96 : // WARNING: if Dest or Source is a non-POD type, the result of the memcpy
97 : // is likely to surprise you.
98 : template <class Dest, class Source>
99 : V8_INLINE Dest bit_cast(Source const& source) {
100 : static_assert(sizeof(Dest) == sizeof(Source),
101 : "source and dest must be same size");
102 1296574 : Dest dest;
103 : memcpy(&dest, &source, sizeof(dest));
104 72583256 : return dest;
105 : }
106 :
107 : // Explicitly declare the assignment operator as deleted.
108 : #define DISALLOW_ASSIGN(TypeName) TypeName& operator=(const TypeName&) = delete;
109 :
110 : // Explicitly declare the copy constructor and assignment operator as deleted.
111 : #define DISALLOW_COPY_AND_ASSIGN(TypeName) \
112 : TypeName(const TypeName&) = delete; \
113 : DISALLOW_ASSIGN(TypeName)
114 :
115 : // Explicitly declare all implicit constructors as deleted, namely the
116 : // default constructor, copy constructor and operator= functions.
117 : // This is especially useful for classes containing only static methods.
118 : #define DISALLOW_IMPLICIT_CONSTRUCTORS(TypeName) \
119 : TypeName() = delete; \
120 : DISALLOW_COPY_AND_ASSIGN(TypeName)
121 :
122 : // Disallow copying a type, but provide default construction, move construction
123 : // and move assignment. Especially useful for move-only structs.
124 : #define MOVE_ONLY_WITH_DEFAULT_CONSTRUCTORS(TypeName) \
125 : TypeName() = default; \
126 : MOVE_ONLY_NO_DEFAULT_CONSTRUCTOR(TypeName)
127 :
128 : // Disallow copying a type, and only provide move construction and move
129 : // assignment. Especially useful for move-only structs.
130 : #define MOVE_ONLY_NO_DEFAULT_CONSTRUCTOR(TypeName) \
131 : TypeName(TypeName&&) = default; \
132 : TypeName& operator=(TypeName&&) = default; \
133 : DISALLOW_COPY_AND_ASSIGN(TypeName)
134 :
135 : // A macro to disallow the dynamic allocation.
136 : // This should be used in the private: declarations for a class
137 : // Declaring operator new and delete as deleted is not spec compliant.
138 : // Extract from 3.2.2 of C++11 spec:
139 : // [...] A non-placement deallocation function for a class is
140 : // odr-used by the definition of the destructor of that class, [...]
141 : #define DISALLOW_NEW_AND_DELETE() \
142 : void* operator new(size_t) { base::OS::Abort(); } \
143 : void* operator new[](size_t) { base::OS::Abort(); }; \
144 : void operator delete(void*, size_t) { base::OS::Abort(); } \
145 : void operator delete[](void*, size_t) { base::OS::Abort(); }
146 :
147 : // Newly written code should use V8_INLINE and V8_NOINLINE directly.
148 : #define INLINE(declarator) V8_INLINE declarator
149 : #define NO_INLINE(declarator) V8_NOINLINE declarator
150 :
151 :
152 : // Newly written code should use WARN_UNUSED_RESULT.
153 : #define MUST_USE_RESULT WARN_UNUSED_RESULT
154 :
155 :
156 : // Define V8_USE_ADDRESS_SANITIZER macros.
157 : #if defined(__has_feature)
158 : #if __has_feature(address_sanitizer)
159 : #define V8_USE_ADDRESS_SANITIZER 1
160 : #endif
161 : #endif
162 :
163 : // Define DISABLE_ASAN macros.
164 : #ifdef V8_USE_ADDRESS_SANITIZER
165 : #define DISABLE_ASAN __attribute__((no_sanitize_address))
166 : #else
167 : #define DISABLE_ASAN
168 : #endif
169 :
170 : // DISABLE_CFI_PERF -- Disable Control Flow Integrity checks for Perf reasons.
171 : #if !defined(DISABLE_CFI_PERF)
172 : #if defined(__clang__) && defined(__has_attribute)
173 : #if __has_attribute(no_sanitize)
174 : #define DISABLE_CFI_PERF __attribute__((no_sanitize("cfi")))
175 : #endif
176 : #endif
177 : #endif
178 : #if !defined(DISABLE_CFI_PERF)
179 : #define DISABLE_CFI_PERF
180 : #endif
181 :
182 : #if V8_CC_GNU
183 : #define V8_IMMEDIATE_CRASH() __builtin_trap()
184 : #else
185 : #define V8_IMMEDIATE_CRASH() ((void(*)())0)()
186 : #endif
187 :
188 :
189 : // TODO(all) Replace all uses of this macro with static_assert, remove macro.
190 : #define STATIC_ASSERT(test) static_assert(test, #test)
191 :
192 : // TODO(rongjie) Remove this workaround once we require gcc >= 5.0
193 : #if __GNUG__ && __GNUC__ < 5
194 : #define IS_TRIVIALLY_COPYABLE(T) \
195 : (__has_trivial_copy(T) && __has_trivial_destructor(T))
196 : #else
197 : #define IS_TRIVIALLY_COPYABLE(T) std::is_trivially_copyable<T>::value
198 : #endif
199 :
200 : // The USE(x, ...) template is used to silence C++ compiler warnings
201 : // issued for (yet) unused variables (typically parameters).
202 : // The arguments are guaranteed to be evaluated from left to right.
203 : struct Use {
204 : template <typename T>
205 372037823 : Use(T&&) {} // NOLINT(runtime/explicit)
206 : };
207 : #define USE(...) \
208 : do { \
209 : ::Use unused_tmp_array_for_use_macro[]{__VA_ARGS__}; \
210 : (void)unused_tmp_array_for_use_macro; \
211 : } while (false)
212 :
213 : // Define our own macros for writing 64-bit constants. This is less fragile
214 : // than defining __STDC_CONSTANT_MACROS before including <stdint.h>, and it
215 : // works on compilers that don't have it (like MSVC).
216 : #if V8_CC_MSVC
217 : # define V8_UINT64_C(x) (x ## UI64)
218 : # define V8_INT64_C(x) (x ## I64)
219 : # if V8_HOST_ARCH_64_BIT
220 : # define V8_INTPTR_C(x) (x ## I64)
221 : # define V8_PTR_PREFIX "ll"
222 : # else
223 : # define V8_INTPTR_C(x) (x)
224 : # define V8_PTR_PREFIX ""
225 : # endif // V8_HOST_ARCH_64_BIT
226 : #elif V8_CC_MINGW64
227 : # define V8_UINT64_C(x) (x ## ULL)
228 : # define V8_INT64_C(x) (x ## LL)
229 : # define V8_INTPTR_C(x) (x ## LL)
230 : # define V8_PTR_PREFIX "I64"
231 : #elif V8_HOST_ARCH_64_BIT
232 : # if V8_OS_MACOSX || V8_OS_OPENBSD
233 : # define V8_UINT64_C(x) (x ## ULL)
234 : # define V8_INT64_C(x) (x ## LL)
235 : # else
236 : # define V8_UINT64_C(x) (x ## UL)
237 : # define V8_INT64_C(x) (x ## L)
238 : # endif
239 : # define V8_INTPTR_C(x) (x ## L)
240 : # define V8_PTR_PREFIX "l"
241 : #else
242 : # define V8_UINT64_C(x) (x ## ULL)
243 : # define V8_INT64_C(x) (x ## LL)
244 : # define V8_INTPTR_C(x) (x)
245 : #if V8_OS_AIX
246 : #define V8_PTR_PREFIX "l"
247 : #else
248 : # define V8_PTR_PREFIX ""
249 : #endif
250 : #endif
251 :
252 : #define V8PRIxPTR V8_PTR_PREFIX "x"
253 : #define V8PRIdPTR V8_PTR_PREFIX "d"
254 : #define V8PRIuPTR V8_PTR_PREFIX "u"
255 :
256 : // ptrdiff_t is 't' according to the standard, but MSVC uses 'I'.
257 : #if V8_CC_MSVC
258 : #define V8PRIxPTRDIFF "Ix"
259 : #define V8PRIdPTRDIFF "Id"
260 : #define V8PRIuPTRDIFF "Iu"
261 : #else
262 : #define V8PRIxPTRDIFF "tx"
263 : #define V8PRIdPTRDIFF "td"
264 : #define V8PRIuPTRDIFF "tu"
265 : #endif
266 :
267 : // Fix for Mac OS X defining uintptr_t as "unsigned long":
268 : #if V8_OS_MACOSX
269 : #undef V8PRIxPTR
270 : #define V8PRIxPTR "lx"
271 : #undef V8PRIdPTR
272 : #define V8PRIdPTR "ld"
273 : #undef V8PRIuPTR
274 : #define V8PRIuPTR "lxu"
275 : #endif
276 :
277 : // The following macro works on both 32 and 64-bit platforms.
278 : // Usage: instead of writing 0x1234567890123456
279 : // write V8_2PART_UINT64_C(0x12345678,90123456);
280 : #define V8_2PART_UINT64_C(a, b) (((static_cast<uint64_t>(a) << 32) + 0x##b##u))
281 :
282 :
283 : // Compute the 0-relative offset of some absolute value x of type T.
284 : // This allows conversion of Addresses and integral types into
285 : // 0-relative int offsets.
286 : template <typename T>
287 : constexpr inline intptr_t OffsetFrom(T x) {
288 27466197702 : return x - static_cast<T>(0);
289 : }
290 :
291 :
292 : // Compute the absolute value of type T for some 0-relative offset x.
293 : // This allows conversion of 0-relative int offsets into Addresses and
294 : // integral types.
295 : template <typename T>
296 : constexpr inline T AddressFrom(intptr_t x) {
297 2514092676 : return static_cast<T>(static_cast<T>(0) + x);
298 : }
299 :
300 :
301 : // Return the largest multiple of m which is <= x.
302 : template <typename T>
303 : inline T RoundDown(T x, intptr_t m) {
304 : // m must be a power of two.
305 : DCHECK(m != 0 && ((m & (m - 1)) == 0));
306 3037418444 : return AddressFrom<T>(OffsetFrom(x) & -m);
307 : }
308 : template <intptr_t m, typename T>
309 : constexpr inline T RoundDown(T x) {
310 : // m must be a power of two.
311 : STATIC_ASSERT(m != 0 && ((m & (m - 1)) == 0));
312 : return AddressFrom<T>(OffsetFrom(x) & -m);
313 : }
314 :
315 : // Return the smallest multiple of m which is >= x.
316 : template <typename T>
317 488 : inline T RoundUp(T x, intptr_t m) {
318 3015328678 : return RoundDown<T>(static_cast<T>(x + m - 1), m);
319 : }
320 : template <intptr_t m, typename T>
321 : constexpr inline T RoundUp(T x) {
322 : return RoundDown<m, T>(static_cast<T>(x + m - 1));
323 : }
324 :
325 : inline void* AlignedAddress(void* address, size_t alignment) {
326 : // The alignment must be a power of two.
327 : DCHECK_EQ(alignment & (alignment - 1), 0u);
328 494817 : return reinterpret_cast<void*>(reinterpret_cast<uintptr_t>(address) &
329 494817 : ~static_cast<uintptr_t>(alignment - 1));
330 : }
331 :
332 : #endif // V8_BASE_MACROS_H_
|