| OLD | NEW |
| 1 // Copyright 2012 the V8 project authors. All rights reserved. | 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 | 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_LOGGING_H_ | 5 #ifndef V8_BASE_LOGGING_H_ |
| 6 #define V8_BASE_LOGGING_H_ | 6 #define V8_BASE_LOGGING_H_ |
| 7 | 7 |
| 8 #include <cstring> | 8 #include <cstring> |
| 9 #include <sstream> | 9 #include <sstream> |
| 10 #include <string> | 10 #include <string> |
| 11 | 11 |
| 12 #include "src/base/build_config.h" | 12 #include "src/base/build_config.h" |
| 13 #include "src/base/compiler-specific.h" |
| 13 | 14 |
| 14 extern "C" void V8_Fatal(const char* file, int line, const char* format, ...); | 15 extern "C" void V8_Fatal(const char* file, int line, const char* format, ...); |
| 15 | 16 |
| 16 | 17 |
| 17 // The FATAL, UNREACHABLE and UNIMPLEMENTED macros are useful during | 18 // The FATAL, UNREACHABLE and UNIMPLEMENTED macros are useful during |
| 18 // development, but they should not be relied on in the final product. | 19 // development, but they should not be relied on in the final product. |
| 19 #ifdef DEBUG | 20 #ifdef DEBUG |
| 20 #define FATAL(msg) \ | 21 #define FATAL(msg) \ |
| 21 V8_Fatal(__FILE__, __LINE__, "%s", (msg)) | 22 V8_Fatal(__FILE__, __LINE__, "%s", (msg)) |
| 22 #define UNIMPLEMENTED() \ | 23 #define UNIMPLEMENTED() \ |
| 23 V8_Fatal(__FILE__, __LINE__, "unimplemented code") | 24 V8_Fatal(__FILE__, __LINE__, "unimplemented code") |
| 24 #define UNREACHABLE() \ | 25 #define UNREACHABLE() \ |
| 25 V8_Fatal(__FILE__, __LINE__, "unreachable code") | 26 V8_Fatal(__FILE__, __LINE__, "unreachable code") |
| 26 #else | 27 #else |
| 27 #define FATAL(msg) \ | 28 #define FATAL(msg) \ |
| 28 V8_Fatal("", 0, "%s", (msg)) | 29 V8_Fatal("", 0, "%s", (msg)) |
| 29 #define UNIMPLEMENTED() \ | 30 #define UNIMPLEMENTED() \ |
| 30 V8_Fatal("", 0, "unimplemented code") | 31 V8_Fatal("", 0, "unimplemented code") |
| 31 #define UNREACHABLE() ((void) 0) | 32 #define UNREACHABLE() ((void) 0) |
| 32 #endif | 33 #endif |
| 33 | 34 |
| 34 | 35 |
| 35 namespace v8 { | 36 namespace v8 { |
| 36 namespace base { | 37 namespace base { |
| 38 namespace logging { |
| 39 |
| 40 typedef int LogSeverity; |
| 41 const LogSeverity LOG_INFO = 0; |
| 42 const LogSeverity LOG_FATAL = 1; |
| 43 |
| 44 |
| 45 // A few definitions of macros that don't generate much code. These are used |
| 46 // by LOG() and LOG_IF, etc. Since these are used all over our code, it's |
| 47 // better to have compact code for these operations. |
| 48 #define COMPACT_GOOGLE_LOG_INFO \ |
| 49 ::v8::base::logging::LogMessage(__FILE__, __LINE__, \ |
| 50 ::v8::base::logging::LOG_INFO) |
| 51 #define COMPACT_GOOGLE_LOG_FATAL \ |
| 52 ::v8::base::logging::LogMessage(__FILE__, __LINE__, \ |
| 53 ::v8::base::logging::LOG_FATAL) |
| 54 |
| 55 |
| 56 // Helper macro which avoids evaluating the arguments to a stream if |
| 57 // the condition doesn't hold. |
| 58 #define LAZY_STREAM(stream, condition) \ |
| 59 V8_LIKELY(!(condition)) \ |
| 60 ? (void)0 : ::v8::base::logging::LogMessageVoidify() & (stream) |
| 61 |
| 62 |
| 63 // We use the preprocessor's merging operator, "##", so that, e.g., |
| 64 // LOG(INFO) becomes the token COMPACT_GOOGLE_LOG_INFO. There's some funny |
| 65 // subtle difference between ostream member streaming functions (e.g., |
| 66 // ostream::operator<<(int) and ostream non-member streaming functions |
| 67 // (e.g., ::operator<<(ostream&, string&): it turns out that it's |
| 68 // impossible to stream something like a string directly to an unnamed |
| 69 // ostream. We employ a neat hack by calling the stream() member |
| 70 // function of LogMessage which seems to avoid the problem. |
| 71 #define LOG_STREAM(SEVERITY) COMPACT_GOOGLE_LOG_##SEVERITY.stream() |
| 72 |
| 73 |
| 74 // The actual stream used isn't important. |
| 75 #define EAT_STREAM_PARAMETERS \ |
| 76 true ? (void)0 : ::v8::base::logging::LogMessageVoidify() & LOG_STREAM(FATAL) |
| 77 |
| 37 | 78 |
| 38 // CHECK dies with a fatal error if condition is not true. It is *not* | 79 // CHECK dies with a fatal error if condition is not true. It is *not* |
| 39 // controlled by DEBUG, so the check will be executed regardless of | 80 // controlled by DEBUG, so the check will be executed regardless of |
| 40 // compilation mode. | 81 // compilation mode. |
| 41 // | 82 // |
| 42 // We make sure CHECK et al. always evaluates their arguments, as | 83 // We make sure CHECK et al. always evaluates their arguments, as |
| 43 // doing CHECK(FunctionWithSideEffect()) is a common idiom. | 84 // doing CHECK(FunctionWithSideEffect()) is a common idiom. |
| 44 #define CHECK(condition) \ | 85 #ifdef DEBUG |
| 45 do { \ | |
| 46 if (V8_UNLIKELY(!(condition))) { \ | |
| 47 V8_Fatal(__FILE__, __LINE__, "Check failed: %s.", #condition); \ | |
| 48 } \ | |
| 49 } while (0) | |
| 50 | 86 |
| 87 #ifdef _PREFAST_ |
| 88 // Use __analysis_assume to tell the VC++ static analysis engine that |
| 89 // assert conditions are true, to suppress warnings. The LAZY_STREAM |
| 90 // parameter doesn't reference 'condition' in /analyze builds because |
| 91 // this evaluation confuses /analyze. The !! before condition is because |
| 92 // __analysis_assume gets confused on some conditions: |
| 93 // http://randomascii.wordpress.com/2011/09/13/analyze-for-visual-studio-the-ugl
y-part-5/ |
| 51 | 94 |
| 52 #ifdef DEBUG | 95 #define CHECK(condition) \ |
| 96 __analysis_assume(!!(condition)), LAZY_STREAM(LOG_STREAM(FATAL), false) \ |
| 97 << "Check failed: " #condition ". " |
| 98 |
| 99 #else // _PREFAST_ |
| 100 |
| 101 #define CHECK(condition) \ |
| 102 LAZY_STREAM(LOG_STREAM(FATAL), !(condition)) \ |
| 103 << "Check failed: " << #condition ". " |
| 104 |
| 105 #endif // _PREFAST_ |
| 53 | 106 |
| 54 // Helper macro for binary operators. | 107 // Helper macro for binary operators. |
| 55 // Don't use this macro directly in your code, use CHECK_EQ et al below. | 108 // Don't use this macro directly in your code, use CHECK_EQ et al below. |
| 56 #define CHECK_OP(name, op, lhs, rhs) \ | 109 #define CHECK_OP(name, op, lhs, rhs) \ |
| 57 do { \ | 110 if (std::string* _result = ::v8::base::logging::Check##name##Impl( \ |
| 58 if (std::string* _msg = ::v8::base::Check##name##Impl( \ | 111 (lhs), (rhs), #lhs " " #op " " #rhs)) \ |
| 59 (lhs), (rhs), #lhs " " #op " " #rhs)) { \ | 112 ::v8::base::logging::LogMessage(__FILE__, __LINE__, _result).stream() |
| 60 V8_Fatal(__FILE__, __LINE__, "Check failed: %s.", _msg->c_str()); \ | |
| 61 delete _msg; \ | |
| 62 } \ | |
| 63 } while (0) | |
| 64 | 113 |
| 65 #else | 114 #else // DEBUG |
| 115 |
| 116 #define CHECK(condition) \ |
| 117 V8_UNLIKELY(!(condition)) \ |
| 118 ? V8_Fatal(__FILE__, __LINE__, "Check failed: %s.", #condition) \ |
| 119 : EAT_STREAM_PARAMETERS |
| 66 | 120 |
| 67 // Make all CHECK functions discard their log strings to reduce code | 121 // Make all CHECK functions discard their log strings to reduce code |
| 68 // bloat for official release builds. | 122 // bloat for official release builds. |
| 69 | 123 |
| 70 #define CHECK_OP(name, op, lhs, rhs) CHECK((lhs)op(rhs)) | 124 #define CHECK_OP(name, op, lhs, rhs) CHECK((lhs)op(rhs)) |
| 71 | 125 |
| 72 #endif | 126 #endif // DEBUG |
| 73 | 127 |
| 74 | 128 |
| 75 // Build the error message string. This is separate from the "Impl" | 129 // Build the error message string. This is separate from the "Impl" |
| 76 // function template because it is not performance critical and so can | 130 // function template because it is not performance critical and so can |
| 77 // be out of line, while the "Impl" code should be inline. Caller | 131 // be out of line, while the "Impl" code should be inline. Caller |
| 78 // takes ownership of the returned string. | 132 // takes ownership of the returned string. |
| 79 template <typename Lhs, typename Rhs> | 133 template <typename Lhs, typename Rhs> |
| 80 std::string* MakeCheckOpString(Lhs const& lhs, Rhs const& rhs, | 134 std::string* MakeCheckOpString(Lhs const& lhs, Rhs const& rhs, |
| 81 char const* msg) { | 135 char const* result) { |
| 82 std::ostringstream ss; | 136 std::ostringstream ss; |
| 83 ss << msg << " (" << lhs << " vs. " << rhs << ")"; | 137 ss << result << " (" << lhs << " vs. " << rhs << ")"; |
| 84 return new std::string(ss.str()); | 138 return new std::string(ss.str()); |
| 85 } | 139 } |
| 86 | 140 |
| 87 // Commonly used instantiations of MakeCheckOpString<>. Explicitly instantiated | 141 // Commonly used instantiations of MakeCheckOpString<>. Explicitly instantiated |
| 88 // in logging.cc. | 142 // in logging.cc. |
| 89 #define DEFINE_MAKE_CHECK_OP_STRING(type) \ | 143 #define DEFINE_MAKE_CHECK_OP_STRING(type) \ |
| 90 extern template std::string* MakeCheckOpString<type, type>( \ | 144 extern template std::string* MakeCheckOpString<type, type>( \ |
| 91 type const&, type const&, char const*); | 145 type const&, type const&, char const*); |
| 92 DEFINE_MAKE_CHECK_OP_STRING(int) | 146 DEFINE_MAKE_CHECK_OP_STRING(int) |
| 93 DEFINE_MAKE_CHECK_OP_STRING(long) // NOLINT(runtime/int) | 147 DEFINE_MAKE_CHECK_OP_STRING(long) // NOLINT(runtime/int) |
| 94 DEFINE_MAKE_CHECK_OP_STRING(long long) // NOLINT(runtime/int) | 148 DEFINE_MAKE_CHECK_OP_STRING(long long) // NOLINT(runtime/int) |
| 95 DEFINE_MAKE_CHECK_OP_STRING(unsigned int) | 149 DEFINE_MAKE_CHECK_OP_STRING(unsigned int) |
| 96 DEFINE_MAKE_CHECK_OP_STRING(unsigned long) // NOLINT(runtime/int) | 150 DEFINE_MAKE_CHECK_OP_STRING(unsigned long) // NOLINT(runtime/int) |
| 97 DEFINE_MAKE_CHECK_OP_STRING(unsigned long long) // NOLINT(runtime/int) | 151 DEFINE_MAKE_CHECK_OP_STRING(unsigned long long) // NOLINT(runtime/int) |
| 98 DEFINE_MAKE_CHECK_OP_STRING(char const*) | 152 DEFINE_MAKE_CHECK_OP_STRING(char const*) |
| 99 DEFINE_MAKE_CHECK_OP_STRING(void const*) | 153 DEFINE_MAKE_CHECK_OP_STRING(void const*) |
| 100 #undef DEFINE_MAKE_CHECK_OP_STRING | 154 #undef DEFINE_MAKE_CHECK_OP_STRING |
| 101 | 155 |
| 102 | 156 |
| 103 // Helper functions for CHECK_OP macro. | 157 // Helper functions for CHECK_OP macro. |
| 104 // The (int, int) specialization works around the issue that the compiler | 158 // The (int, int) specialization works around the issue that the compiler |
| 105 // will not instantiate the template version of the function on values of | 159 // will not instantiate the template version of the function on values of |
| 106 // unnamed enum type - see comment below. | 160 // unnamed enum type - see comment below. |
| 107 // The (float, float) and (double, double) instantiations are explicitly | 161 // The (float, float) and (double, double) instantiations are explicitly |
| 108 // externialized to ensure proper 32/64-bit comparisons on x86. | 162 // externialized to ensure proper 32/64-bit comparisons on x86. |
| 109 #define DEFINE_CHECK_OP_IMPL(NAME, op) \ | 163 #define DEFINE_CHECK_OP_IMPL(NAME, op) \ |
| 110 template <typename Lhs, typename Rhs> \ | 164 template <typename Lhs, typename Rhs> \ |
| 111 V8_INLINE std::string* Check##NAME##Impl(Lhs const& lhs, Rhs const& rhs, \ | 165 V8_INLINE std::string* Check##NAME##Impl(Lhs const& lhs, Rhs const& rhs, \ |
| 112 char const* msg) { \ | 166 char const* result) { \ |
| 113 return V8_LIKELY(lhs op rhs) ? nullptr : MakeCheckOpString(lhs, rhs, msg); \ | 167 return V8_LIKELY(lhs op rhs) ? nullptr \ |
| 114 } \ | 168 : MakeCheckOpString(lhs, rhs, result); \ |
| 115 V8_INLINE std::string* Check##NAME##Impl(int lhs, int rhs, \ | 169 } \ |
| 116 char const* msg) { \ | 170 V8_INLINE std::string* Check##NAME##Impl(int lhs, int rhs, \ |
| 117 return V8_LIKELY(lhs op rhs) ? nullptr : MakeCheckOpString(lhs, rhs, msg); \ | 171 char const* result) { \ |
| 118 } \ | 172 return V8_LIKELY(lhs op rhs) ? nullptr \ |
| 119 extern template std::string* Check##NAME##Impl<float, float>( \ | 173 : MakeCheckOpString(lhs, rhs, result); \ |
| 120 float const& lhs, float const& rhs, char const* msg); \ | 174 } \ |
| 121 extern template std::string* Check##NAME##Impl<double, double>( \ | 175 extern template std::string* Check##NAME##Impl<float, float>( \ |
| 122 double const& lhs, double const& rhs, char const* msg); | 176 float const& lhs, float const& rhs, char const* result); \ |
| 123 DEFINE_CHECK_OP_IMPL(EQ, ==) | 177 extern template std::string* Check##NAME##Impl<double, double>( \ |
| 178 double const& lhs, double const& rhs, char const* result); |
| 179 DEFINE_CHECK_OP_IMPL(EQ, == ) |
| 124 DEFINE_CHECK_OP_IMPL(NE, !=) | 180 DEFINE_CHECK_OP_IMPL(NE, !=) |
| 125 DEFINE_CHECK_OP_IMPL(LE, <=) | 181 DEFINE_CHECK_OP_IMPL(LE, <=) |
| 126 DEFINE_CHECK_OP_IMPL(LT, < ) | 182 DEFINE_CHECK_OP_IMPL(LT, < ) |
| 127 DEFINE_CHECK_OP_IMPL(GE, >=) | 183 DEFINE_CHECK_OP_IMPL(GE, >=) |
| 128 DEFINE_CHECK_OP_IMPL(GT, > ) | 184 DEFINE_CHECK_OP_IMPL(GT, > ) |
| 129 #undef DEFINE_CHECK_OP_IMPL | 185 #undef DEFINE_CHECK_OP_IMPL |
| 130 | 186 |
| 131 #define CHECK_EQ(lhs, rhs) CHECK_OP(EQ, ==, lhs, rhs) | 187 #define CHECK_EQ(lhs, rhs) CHECK_OP(EQ, ==, lhs, rhs) |
| 132 #define CHECK_NE(lhs, rhs) CHECK_OP(NE, !=, lhs, rhs) | 188 #define CHECK_NE(lhs, rhs) CHECK_OP(NE, !=, lhs, rhs) |
| 133 #define CHECK_LE(lhs, rhs) CHECK_OP(LE, <=, lhs, rhs) | 189 #define CHECK_LE(lhs, rhs) CHECK_OP(LE, <=, lhs, rhs) |
| 134 #define CHECK_LT(lhs, rhs) CHECK_OP(LT, <, lhs, rhs) | 190 #define CHECK_LT(lhs, rhs) CHECK_OP(LT, <, lhs, rhs) |
| 135 #define CHECK_GE(lhs, rhs) CHECK_OP(GE, >=, lhs, rhs) | 191 #define CHECK_GE(lhs, rhs) CHECK_OP(GE, >=, lhs, rhs) |
| 136 #define CHECK_GT(lhs, rhs) CHECK_OP(GT, >, lhs, rhs) | 192 #define CHECK_GT(lhs, rhs) CHECK_OP(GT, >, lhs, rhs) |
| 137 #define CHECK_NULL(val) CHECK((val) == nullptr) | 193 #define CHECK_NULL(val) CHECK((val) == nullptr) |
| 138 #define CHECK_NOT_NULL(val) CHECK((val) != nullptr) | 194 #define CHECK_NOT_NULL(val) CHECK((val) != nullptr) |
| 139 #define CHECK_IMPLIES(lhs, rhs) CHECK(!(lhs) || (rhs)) | 195 #define CHECK_IMPLIES(lhs, rhs) CHECK(!(lhs) || (rhs)) |
| 140 | 196 |
| 141 | 197 |
| 142 // Exposed for making debugging easier (to see where your function is being | 198 // This class more or less represents a particular log message. You create an |
| 143 // called, just add a call to DumpBacktrace). | 199 // instance of LogMessage and then stream stuff to it. When you finish streaming |
| 144 void DumpBacktrace(); | 200 // to it, the destructor is called and the full message gets streamed to the |
| 201 // appropriate destination. |
| 202 // |
| 203 // You shouldn't actually use LogMessage's constructor to log things, through. |
| 204 // You should use the macros above. |
| 205 class LogMessage FINAL { |
| 206 public: |
| 207 // Used for LOG(severity), CHECK() and friends. |
| 208 LogMessage(char const* file, int line, LogSeverity severity); |
| 145 | 209 |
| 210 // Used for CHECK_EQ() and friends. Takes ownership of the given string. |
| 211 // Implied severity = LOG_FATAL. |
| 212 LogMessage(char const* file, int line, std::string* result); |
| 213 |
| 214 // Used for DCHECK_EQ() and friends. Takes ownership of the given string. |
| 215 LogMessage(char const* file, int line, LogSeverity severity, |
| 216 std::string* result); |
| 217 |
| 218 ~LogMessage(); |
| 219 |
| 220 std::ostream& stream() { return stream_; } |
| 221 |
| 222 private: |
| 223 std::ostringstream stream_; |
| 224 char const* const file_; // The file information passed into the constructor. |
| 225 int const line_; // The line information passed into the constructor. |
| 226 LogSeverity const severity_; |
| 227 |
| 228 // TODO(bmeurer): Use DISALLOW_IMPLICIT_CONSTRUCTORS once macros.h no longer |
| 229 // depends on logging.h. |
| 230 LogMessage() V8_DELETE; |
| 231 LogMessage(LogMessage const&) V8_DELETE; |
| 232 void operator=(LogMessage const&) V8_DELETE; |
| 233 }; |
| 234 |
| 235 |
| 236 // This class is used to explicitly ignore values in the conditional |
| 237 // logging macros. This avoids compiler warnings like "value computed |
| 238 // is not used" and "statement has no effect". |
| 239 class LogMessageVoidify FINAL { |
| 240 public: |
| 241 LogMessageVoidify() {} |
| 242 |
| 243 // This has to be an operator with a precedence lower than << but |
| 244 // higher than ?: |
| 245 void operator&(std::ostream&) {} |
| 246 }; |
| 247 |
| 248 } // namespace logging |
| 146 } // namespace base | 249 } // namespace base |
| 147 } // namespace v8 | 250 } // namespace v8 |
| 148 | 251 |
| 149 | 252 |
| 150 // The DCHECK macro is equivalent to CHECK except that it only | 253 // The DCHECK macro is equivalent to CHECK except that it only |
| 151 // generates code in debug builds. | 254 // generates code in debug builds. |
| 152 // TODO(bmeurer): DCHECK_RESULT(expr) must die! | |
| 153 #ifdef DEBUG | 255 #ifdef DEBUG |
| 154 #define DCHECK_RESULT(expr) CHECK(expr) | |
| 155 #define DCHECK(condition) CHECK(condition) | 256 #define DCHECK(condition) CHECK(condition) |
| 156 #define DCHECK_EQ(v1, v2) CHECK_EQ(v1, v2) | 257 #define DCHECK_EQ(v1, v2) CHECK_EQ(v1, v2) |
| 157 #define DCHECK_NE(v1, v2) CHECK_NE(v1, v2) | 258 #define DCHECK_NE(v1, v2) CHECK_NE(v1, v2) |
| 158 #define DCHECK_GE(v1, v2) CHECK_GE(v1, v2) | 259 #define DCHECK_GE(v1, v2) CHECK_GE(v1, v2) |
| 159 #define DCHECK_LT(v1, v2) CHECK_LT(v1, v2) | 260 #define DCHECK_LT(v1, v2) CHECK_LT(v1, v2) |
| 160 #define DCHECK_LE(v1, v2) CHECK_LE(v1, v2) | 261 #define DCHECK_LE(v1, v2) CHECK_LE(v1, v2) |
| 161 #define DCHECK_NULL(val) CHECK_NULL(val) | 262 #define DCHECK_NULL(val) CHECK_NULL(val) |
| 162 #define DCHECK_NOT_NULL(val) CHECK_NOT_NULL(val) | 263 #define DCHECK_NOT_NULL(val) CHECK_NOT_NULL(val) |
| 163 #define DCHECK_IMPLIES(v1, v2) CHECK_IMPLIES(v1, v2) | 264 #define DCHECK_IMPLIES(v1, v2) CHECK_IMPLIES(v1, v2) |
| 164 #else | 265 #else |
| 165 #define DCHECK_RESULT(expr) (expr) | |
| 166 #define DCHECK(condition) ((void) 0) | 266 #define DCHECK(condition) ((void) 0) |
| 167 #define DCHECK_EQ(v1, v2) ((void) 0) | 267 #define DCHECK_EQ(v1, v2) ((void) 0) |
| 168 #define DCHECK_NE(v1, v2) ((void) 0) | 268 #define DCHECK_NE(v1, v2) ((void) 0) |
| 169 #define DCHECK_GE(v1, v2) ((void) 0) | 269 #define DCHECK_GE(v1, v2) ((void) 0) |
| 170 #define DCHECK_LT(v1, v2) ((void) 0) | 270 #define DCHECK_LT(v1, v2) ((void) 0) |
| 171 #define DCHECK_LE(v1, v2) ((void) 0) | 271 #define DCHECK_LE(v1, v2) ((void) 0) |
| 172 #define DCHECK_NULL(val) ((void) 0) | 272 #define DCHECK_NULL(val) ((void) 0) |
| 173 #define DCHECK_NOT_NULL(val) ((void) 0) | 273 #define DCHECK_NOT_NULL(val) ((void) 0) |
| 174 #define DCHECK_IMPLIES(v1, v2) ((void) 0) | 274 #define DCHECK_IMPLIES(v1, v2) ((void) 0) |
| 175 #endif | 275 #endif |
| 176 | 276 |
| 177 #endif // V8_BASE_LOGGING_H_ | 277 #endif // V8_BASE_LOGGING_H_ |
| OLD | NEW |