LCOV - code coverage report
Current view: top level - src/base - logging.h (source / functions) Hit Total Coverage
Test: app.info Lines: 2 11 18.2 %
Date: 2017-04-26 Functions: 0 22 0.0 %

          Line data    Source code
       1             : // Copyright 2012 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_LOGGING_H_
       6             : #define V8_BASE_LOGGING_H_
       7             : 
       8             : #include <cstring>
       9             : #include <sstream>
      10             : #include <string>
      11             : 
      12             : #include "src/base/base-export.h"
      13             : #include "src/base/build_config.h"
      14             : #include "src/base/compiler-specific.h"
      15             : 
      16             : extern "C" PRINTF_FORMAT(3, 4) V8_NORETURN V8_BASE_EXPORT
      17             :     void V8_Fatal(const char* file, int line, const char* format, ...);
      18             : 
      19             : // The FATAL, UNREACHABLE and UNIMPLEMENTED macros are useful during
      20             : // development, but they should not be relied on in the final product.
      21             : #ifdef DEBUG
      22             : #define FATAL(msg)                              \
      23             :   V8_Fatal(__FILE__, __LINE__, "%s", (msg))
      24             : #define UNIMPLEMENTED()                         \
      25             :   V8_Fatal(__FILE__, __LINE__, "unimplemented code")
      26             : #define UNREACHABLE()                           \
      27             :   V8_Fatal(__FILE__, __LINE__, "unreachable code")
      28             : #else
      29             : #define FATAL(msg)                              \
      30             :   V8_Fatal("", 0, "%s", (msg))
      31             : #define UNIMPLEMENTED()                         \
      32             :   V8_Fatal("", 0, "unimplemented code")
      33             : #define UNREACHABLE() V8_Fatal("", 0, "unreachable code")
      34             : #endif
      35             : 
      36             : 
      37             : namespace v8 {
      38             : namespace base {
      39             : 
      40             : // Overwrite the default function that prints a stack trace.
      41             : V8_BASE_EXPORT void SetPrintStackTrace(void (*print_stack_trace_)());
      42             : 
      43             : // CHECK dies with a fatal error if condition is not true.  It is *not*
      44             : // controlled by DEBUG, so the check will be executed regardless of
      45             : // compilation mode.
      46             : //
      47             : // We make sure CHECK et al. always evaluates their arguments, as
      48             : // doing CHECK(FunctionWithSideEffect()) is a common idiom.
      49             : #define CHECK_WITH_MSG(condition, message)                        \
      50             :   do {                                                            \
      51             :     if (V8_UNLIKELY(!(condition))) {                              \
      52             :       V8_Fatal(__FILE__, __LINE__, "Check failed: %s.", message); \
      53             :     }                                                             \
      54             :   } while (0)
      55             : #define CHECK(condition) CHECK_WITH_MSG(condition, #condition)
      56             : 
      57             : #ifdef DEBUG
      58             : 
      59             : // Helper macro for binary operators.
      60             : // Don't use this macro directly in your code, use CHECK_EQ et al below.
      61             : #define CHECK_OP(name, op, lhs, rhs)                                     \
      62             :   do {                                                                   \
      63             :     if (std::string* _msg =                                              \
      64             :             ::v8::base::Check##name##Impl<decltype(lhs), decltype(rhs)>( \
      65             :                 (lhs), (rhs), #lhs " " #op " " #rhs)) {                  \
      66             :       V8_Fatal(__FILE__, __LINE__, "Check failed: %s.", _msg->c_str());  \
      67             :       delete _msg;                                                       \
      68             :     }                                                                    \
      69             :   } while (0)
      70             : 
      71             : #else
      72             : 
      73             : // Make all CHECK functions discard their log strings to reduce code
      74             : // bloat for official release builds.
      75             : 
      76             : #define CHECK_OP(name, op, lhs, rhs)                                         \
      77             :   do {                                                                       \
      78             :     bool _cmp =                                                              \
      79             :         ::v8::base::Cmp##name##Impl<decltype(lhs), decltype(rhs)>(lhs, rhs); \
      80             :     CHECK_WITH_MSG(_cmp, #lhs " " #op " " #rhs);                             \
      81             :   } while (0)
      82             : 
      83             : #endif
      84             : 
      85             : // Helper to determine how to pass values: Pass scalars and arrays by value,
      86             : // others by const reference. std::decay<T> provides the type which should be
      87             : // used to pass T by value, e.g. converts array to pointer and removes const,
      88             : // volatile and reference.
      89             : template <typename T>
      90             : struct PassType : public std::conditional<
      91             :                       std::is_scalar<typename std::decay<T>::type>::value,
      92             :                       typename std::decay<T>::type, T const&> {};
      93             : 
      94             : // Build the error message string.  This is separate from the "Impl"
      95             : // function template because it is not performance critical and so can
      96             : // be out of line, while the "Impl" code should be inline. Caller
      97             : // takes ownership of the returned string.
      98             : template <typename Lhs, typename Rhs>
      99           0 : std::string* MakeCheckOpString(typename PassType<Lhs>::type lhs,
     100             :                                typename PassType<Rhs>::type rhs,
     101             :                                char const* msg) {
     102           0 :   std::ostringstream ss;
     103           0 :   ss << msg << " (" << lhs << " vs. " << rhs << ")";
     104           0 :   return new std::string(ss.str());
     105             : }
     106             : 
     107             : // Commonly used instantiations of MakeCheckOpString<>. Explicitly instantiated
     108             : // in logging.cc.
     109             : #define DEFINE_MAKE_CHECK_OP_STRING(type)                                    \
     110             :   extern template V8_BASE_EXPORT std::string* MakeCheckOpString<type, type>( \
     111             :       type, type, char const*);
     112             : DEFINE_MAKE_CHECK_OP_STRING(int)
     113             : DEFINE_MAKE_CHECK_OP_STRING(long)       // NOLINT(runtime/int)
     114             : DEFINE_MAKE_CHECK_OP_STRING(long long)  // NOLINT(runtime/int)
     115             : DEFINE_MAKE_CHECK_OP_STRING(unsigned int)
     116             : DEFINE_MAKE_CHECK_OP_STRING(unsigned long)       // NOLINT(runtime/int)
     117             : DEFINE_MAKE_CHECK_OP_STRING(unsigned long long)  // NOLINT(runtime/int)
     118             : DEFINE_MAKE_CHECK_OP_STRING(char const*)
     119             : DEFINE_MAKE_CHECK_OP_STRING(void const*)
     120             : #undef DEFINE_MAKE_CHECK_OP_STRING
     121             : 
     122             : // is_signed_vs_unsigned::value is true if both types are integral, Lhs is
     123             : // signed, and Rhs is unsigned. False in all other cases.
     124             : template <typename Lhs, typename Rhs>
     125             : struct is_signed_vs_unsigned {
     126             :   enum : bool {
     127             :     value = std::is_integral<Lhs>::value && std::is_integral<Rhs>::value &&
     128             :             std::is_signed<Lhs>::value && std::is_unsigned<Rhs>::value
     129             :   };
     130             : };
     131             : // Same thing, other way around: Lhs is unsigned, Rhs signed.
     132             : template <typename Lhs, typename Rhs>
     133             : struct is_unsigned_vs_signed : public is_signed_vs_unsigned<Rhs, Lhs> {};
     134             : 
     135             : // Specialize the compare functions for signed vs. unsigned comparisons.
     136             : // std::enable_if ensures that this template is only instantiable if both Lhs
     137             : // and Rhs are integral types, and their signedness does not match.
     138             : #define MAKE_UNSIGNED(Type, value) \
     139             :   static_cast<typename std::make_unsigned<Type>::type>(value)
     140             : #define DEFINE_SIGNED_MISMATCH_COMP(CHECK, NAME, IMPL)                  \
     141             :   template <typename Lhs, typename Rhs>                                 \
     142             :   V8_INLINE typename std::enable_if<CHECK<Lhs, Rhs>::value, bool>::type \
     143             :       Cmp##NAME##Impl(Lhs const& lhs, Rhs const& rhs) {                 \
     144             :     return IMPL;                                                        \
     145             :   }
     146      243826 : DEFINE_SIGNED_MISMATCH_COMP(is_signed_vs_unsigned, EQ,
     147             :                             lhs >= 0 && MAKE_UNSIGNED(Lhs, lhs) == rhs)
     148             : DEFINE_SIGNED_MISMATCH_COMP(is_signed_vs_unsigned, LT,
     149             :                             lhs < 0 || MAKE_UNSIGNED(Lhs, lhs) < rhs)
     150             : DEFINE_SIGNED_MISMATCH_COMP(is_signed_vs_unsigned, LE,
     151             :                             lhs <= 0 || MAKE_UNSIGNED(Lhs, lhs) <= rhs)
     152             : DEFINE_SIGNED_MISMATCH_COMP(is_signed_vs_unsigned, NE, !CmpEQImpl(lhs, rhs))
     153             : DEFINE_SIGNED_MISMATCH_COMP(is_signed_vs_unsigned, GT, !CmpLEImpl(lhs, rhs))
     154             : DEFINE_SIGNED_MISMATCH_COMP(is_signed_vs_unsigned, GE, !CmpLTImpl(lhs, rhs))
     155             : DEFINE_SIGNED_MISMATCH_COMP(is_unsigned_vs_signed, EQ, CmpEQImpl(rhs, lhs))
     156             : DEFINE_SIGNED_MISMATCH_COMP(is_unsigned_vs_signed, NE, CmpNEImpl(rhs, lhs))
     157             : DEFINE_SIGNED_MISMATCH_COMP(is_unsigned_vs_signed, LT, CmpGTImpl(rhs, lhs))
     158             : DEFINE_SIGNED_MISMATCH_COMP(is_unsigned_vs_signed, LE, CmpGEImpl(rhs, lhs))
     159             : DEFINE_SIGNED_MISMATCH_COMP(is_unsigned_vs_signed, GT, CmpLTImpl(rhs, lhs))
     160             : DEFINE_SIGNED_MISMATCH_COMP(is_unsigned_vs_signed, GE, CmpLEImpl(rhs, lhs))
     161             : #undef MAKE_UNSIGNED
     162             : #undef DEFINE_SIGNED_MISMATCH_COMP
     163             : 
     164             : // Helper functions for CHECK_OP macro.
     165             : // The (float, float) and (double, double) instantiations are explicitly
     166             : // externalized to ensure proper 32/64-bit comparisons on x86.
     167             : // The Cmp##NAME##Impl function is only instantiable if one of the two types is
     168             : // not integral or their signedness matches (i.e. whenever no specialization is
     169             : // required, see above). Otherwise it is disabled by the enable_if construct,
     170             : // and the compiler will pick a specialization from above.
     171             : #define DEFINE_CHECK_OP_IMPL(NAME, op)                                         \
     172             :   template <typename Lhs, typename Rhs>                                        \
     173             :   V8_INLINE                                                                    \
     174             :       typename std::enable_if<!is_signed_vs_unsigned<Lhs, Rhs>::value &&       \
     175             :                                   !is_unsigned_vs_signed<Lhs, Rhs>::value,     \
     176             :                               bool>::type                                      \
     177             :           Cmp##NAME##Impl(typename PassType<Lhs>::type lhs,                    \
     178             :                           typename PassType<Rhs>::type rhs) {                  \
     179             :     return lhs op rhs;                                                         \
     180             :   }                                                                            \
     181             :   template <typename Lhs, typename Rhs>                                        \
     182             :   V8_INLINE std::string* Check##NAME##Impl(typename PassType<Lhs>::type lhs,   \
     183             :                                            typename PassType<Rhs>::type rhs,   \
     184             :                                            char const* msg) {                  \
     185             :     bool cmp = Cmp##NAME##Impl<Lhs, Rhs>(lhs, rhs);                            \
     186             :     return V8_LIKELY(cmp) ? nullptr                                            \
     187             :                           : MakeCheckOpString<Lhs, Rhs>(lhs, rhs, msg);        \
     188             :   }                                                                            \
     189             :   extern template V8_BASE_EXPORT std::string* Check##NAME##Impl<float, float>( \
     190             :       float lhs, float rhs, char const* msg);                                  \
     191             :   extern template V8_BASE_EXPORT std::string*                                  \
     192             :       Check##NAME##Impl<double, double>(double lhs, double rhs,                \
     193             :                                         char const* msg);
     194           0 : DEFINE_CHECK_OP_IMPL(EQ, ==)
     195           0 : DEFINE_CHECK_OP_IMPL(NE, !=)
     196   297318908 : DEFINE_CHECK_OP_IMPL(LE, <=)
     197           0 : DEFINE_CHECK_OP_IMPL(LT, < )
     198           0 : DEFINE_CHECK_OP_IMPL(GE, >=)
     199           0 : DEFINE_CHECK_OP_IMPL(GT, > )
     200             : #undef DEFINE_CHECK_OP_IMPL
     201             : 
     202             : #define CHECK_EQ(lhs, rhs) CHECK_OP(EQ, ==, lhs, rhs)
     203             : #define CHECK_NE(lhs, rhs) CHECK_OP(NE, !=, lhs, rhs)
     204             : #define CHECK_LE(lhs, rhs) CHECK_OP(LE, <=, lhs, rhs)
     205             : #define CHECK_LT(lhs, rhs) CHECK_OP(LT, <, lhs, rhs)
     206             : #define CHECK_GE(lhs, rhs) CHECK_OP(GE, >=, lhs, rhs)
     207             : #define CHECK_GT(lhs, rhs) CHECK_OP(GT, >, lhs, rhs)
     208             : #define CHECK_NULL(val) CHECK((val) == nullptr)
     209             : #define CHECK_NOT_NULL(val) CHECK((val) != nullptr)
     210             : #define CHECK_IMPLIES(lhs, rhs) \
     211             :   CHECK_WITH_MSG(!(lhs) || (rhs), #lhs " implies " #rhs)
     212             : 
     213             : }  // namespace base
     214             : }  // namespace v8
     215             : 
     216             : 
     217             : // The DCHECK macro is equivalent to CHECK except that it only
     218             : // generates code in debug builds.
     219             : #ifdef DEBUG
     220             : #define DCHECK(condition)      CHECK(condition)
     221             : #define DCHECK_EQ(v1, v2)      CHECK_EQ(v1, v2)
     222             : #define DCHECK_NE(v1, v2)      CHECK_NE(v1, v2)
     223             : #define DCHECK_GT(v1, v2)      CHECK_GT(v1, v2)
     224             : #define DCHECK_GE(v1, v2)      CHECK_GE(v1, v2)
     225             : #define DCHECK_LT(v1, v2)      CHECK_LT(v1, v2)
     226             : #define DCHECK_LE(v1, v2)      CHECK_LE(v1, v2)
     227             : #define DCHECK_NULL(val)       CHECK_NULL(val)
     228             : #define DCHECK_NOT_NULL(val)   CHECK_NOT_NULL(val)
     229             : #define DCHECK_IMPLIES(v1, v2) CHECK_IMPLIES(v1, v2)
     230             : #else
     231             : #define DCHECK(condition)      ((void) 0)
     232             : #define DCHECK_EQ(v1, v2)      ((void) 0)
     233             : #define DCHECK_NE(v1, v2)      ((void) 0)
     234             : #define DCHECK_GT(v1, v2)      ((void) 0)
     235             : #define DCHECK_GE(v1, v2)      ((void) 0)
     236             : #define DCHECK_LT(v1, v2)      ((void) 0)
     237             : #define DCHECK_LE(v1, v2)      ((void) 0)
     238             : #define DCHECK_NULL(val)       ((void) 0)
     239             : #define DCHECK_NOT_NULL(val)   ((void) 0)
     240             : #define DCHECK_IMPLIES(v1, v2) ((void) 0)
     241             : #endif
     242             : 
     243             : #endif  // V8_BASE_LOGGING_H_

Generated by: LCOV version 1.10