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

Generated by: LCOV version 1.10