LCOV - code coverage report
Current view: top level - src/base - macros.h (source / functions) Hit Total Coverage
Test: app.info Lines: 10 10 100.0 %
Date: 2017-10-20 Functions: 2 2 100.0 %

          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_

Generated by: LCOV version 1.10