5 #ifndef V8_BASE_LOGGING_H_ 6 #define V8_BASE_LOGGING_H_ 12 #include "src/base/base-export.h" 13 #include "src/base/build_config.h" 14 #include "src/base/compiler-specific.h" 15 #include "src/base/template-utils.h" 17 [[noreturn]] PRINTF_FORMAT(3, 4) V8_BASE_EXPORT V8_NOINLINE
18 void V8_Fatal(const
char* file,
int line, const
char* format, ...);
20 V8_BASE_EXPORT V8_NOINLINE
void V8_Dcheck(const
char* file,
int line,
24 #define FATAL(...) V8_Fatal(__FILE__, __LINE__, __VA_ARGS__) 26 #define FATAL(...) V8_Fatal("", 0, __VA_ARGS__) 28 #define UNIMPLEMENTED() FATAL("unimplemented code") 29 #define UNREACHABLE() FATAL("unreachable code") 35 V8_BASE_EXPORT
void SetPrintStackTrace(
void (*print_stack_trace_)());
38 V8_BASE_EXPORT
void SetDcheckFunction(
void (*dcheck_Function)(
const char*,
int,
47 #define CHECK_WITH_MSG(condition, message) \ 49 if (V8_UNLIKELY(!(condition))) { \ 50 FATAL("Check failed: %s.", message); \ 53 #define CHECK(condition) CHECK_WITH_MSG(condition, #condition) 57 #define DCHECK_WITH_MSG(condition, message) \ 59 if (V8_UNLIKELY(!(condition))) { \ 60 V8_Dcheck(__FILE__, __LINE__, message); \ 63 #define DCHECK(condition) DCHECK_WITH_MSG(condition, #condition) 67 #define CHECK_OP(name, op, lhs, rhs) \ 69 if (std::string* _msg = ::v8::base::Check##name##Impl< \ 70 typename ::v8::base::pass_value_or_ref<decltype(lhs)>::type, \ 71 typename ::v8::base::pass_value_or_ref<decltype(rhs)>::type>( \ 72 (lhs), (rhs), #lhs " " #op " " #rhs)) { \ 73 FATAL("Check failed: %s.", _msg->c_str()); \ 78 #define DCHECK_OP(name, op, lhs, rhs) \ 80 if (std::string* _msg = ::v8::base::Check##name##Impl< \ 81 typename ::v8::base::pass_value_or_ref<decltype(lhs)>::type, \ 82 typename ::v8::base::pass_value_or_ref<decltype(rhs)>::type>( \ 83 (lhs), (rhs), #lhs " " #op " " #rhs)) { \ 84 V8_Dcheck(__FILE__, __LINE__, _msg->c_str()); \ 94 #define CHECK_OP(name, op, lhs, rhs) \ 96 bool _cmp = ::v8::base::Cmp##name##Impl< \ 97 typename ::v8::base::pass_value_or_ref<decltype(lhs)>::type, \ 98 typename ::v8::base::pass_value_or_ref<decltype(rhs)>::type>((lhs), \ 100 CHECK_WITH_MSG(_cmp, #lhs " " #op " " #rhs); \ 103 #define DCHECK_WITH_MSG(condition, msg) void(0); 108 template <
typename T>
109 typename std::enable_if<
110 !std::is_function<typename std::remove_pointer<T>::type>::value &&
111 has_output_operator<T>::value>::type
112 PrintCheckOperand(std::ostream& os, T val) {
113 os << std::forward<T>(val);
121 template <
typename T>
122 typename std::enable_if<
123 std::is_function<typename std::remove_pointer<T>::type>::value>::type
124 PrintCheckOperand(std::ostream& os, T val) {
125 os << reinterpret_cast<const void*>(val);
129 template <
typename T>
130 typename std::enable_if<std::is_enum<T>::value &&
131 !has_output_operator<T>::value>::type
132 PrintCheckOperand(std::ostream& os, T val) {
133 using underlying_t =
typename std::underlying_type<T>::type;
135 using int_t =
typename std::conditional<
136 std::is_same<underlying_t, uint8_t>::value, uint16_t,
137 typename std::conditional<std::is_same<underlying_t, int8_t>::value,
138 int16_t, underlying_t>::type>::type;
139 PrintCheckOperand(os, static_cast<int_t>(static_cast<underlying_t>(val)));
143 template <
typename T>
144 typename std::enable_if<!has_output_operator<T>::value &&
145 !std::is_enum<T>::value>::type
146 PrintCheckOperand(std::ostream& os, T val) {
147 os <<
"<unprintable>";
151 #define DEFINE_PRINT_CHECK_OPERAND_CHAR(type) \ 153 V8_BASE_EXPORT void PrintCheckOperand<type>(std::ostream & os, type ch); \ 155 V8_BASE_EXPORT void PrintCheckOperand<type*>(std::ostream & os, \ 158 V8_BASE_EXPORT void PrintCheckOperand<const type*>(std::ostream & os, \ 161 DEFINE_PRINT_CHECK_OPERAND_CHAR(
char)
162 DEFINE_PRINT_CHECK_OPERAND_CHAR(
signed char)
163 DEFINE_PRINT_CHECK_OPERAND_CHAR(
unsigned char)
164 #undef DEFINE_PRINT_CHECK_OPERAND_CHAR 170 template <
typename Lhs,
typename Rhs>
171 std::string* MakeCheckOpString(Lhs lhs, Rhs rhs,
char const* msg) {
172 std::ostringstream ss;
174 PrintCheckOperand<Lhs>(ss, lhs);
176 PrintCheckOperand<Rhs>(ss, rhs);
178 return new std::string(ss.str());
183 #define EXPLICIT_CHECK_OP_INSTANTIATION(type) \ 184 extern template V8_BASE_EXPORT std::string* MakeCheckOpString<type, type>( \ 185 type, type, char const*); \ 186 extern template V8_BASE_EXPORT void PrintCheckOperand<type>(std::ostream&, \ 189 EXPLICIT_CHECK_OP_INSTANTIATION(
int)
190 EXPLICIT_CHECK_OP_INSTANTIATION(
long)
191 EXPLICIT_CHECK_OP_INSTANTIATION(
long long)
192 EXPLICIT_CHECK_OP_INSTANTIATION(
unsigned int)
193 EXPLICIT_CHECK_OP_INSTANTIATION(
unsigned long)
194 EXPLICIT_CHECK_OP_INSTANTIATION(
unsigned long long)
195 EXPLICIT_CHECK_OP_INSTANTIATION(
void const*)
196 #undef EXPLICIT_CHECK_OP_INSTANTIATION 201 template <
typename T>
202 struct comparison_underlying_type {
206 using decay =
typename std::decay<T>::type;
207 static constexpr
bool is_enum = std::is_enum<decay>::value;
208 using underlying =
typename std::underlying_type<
209 typename std::conditional<is_enum, decay, Dummy>::type>::type;
211 typename std::conditional<is_enum, underlying, decay>::type;
213 typename std::conditional<std::is_same<type_or_bool, bool>::value,
214 unsigned int, type_or_bool>::type;
217 #define MAKE_UNDERLYING(Type, value) \ 218 static_cast<typename comparison_underlying_type<Type>::type>(value) 222 template <
typename Lhs,
typename Rhs>
224 using lhs_underlying =
typename comparison_underlying_type<Lhs>::type;
225 using rhs_underlying =
typename comparison_underlying_type<Rhs>::type;
226 static constexpr
bool value = std::is_integral<lhs_underlying>::value &&
227 std::is_integral<rhs_underlying>::value &&
228 std::is_signed<lhs_underlying>::value &&
229 std::is_unsigned<rhs_underlying>::value;
232 template <
typename Lhs,
typename Rhs>
238 #define MAKE_UNSIGNED(Type, value) \ 239 static_cast<typename std::make_unsigned< \ 240 typename comparison_underlying_type<Type>::type>::type>(value) 241 #define DEFINE_SIGNED_MISMATCH_COMP(CHECK, NAME, IMPL) \ 242 template <typename Lhs, typename Rhs> \ 243 V8_INLINE typename std::enable_if<CHECK<Lhs, Rhs>::value, bool>::type \ 244 Cmp##NAME##Impl(Lhs lhs, Rhs rhs) { \ 248 lhs >= 0 && MAKE_UNSIGNED(Lhs, lhs) ==
249 MAKE_UNDERLYING(Rhs, rhs))
251 lhs < 0 || MAKE_UNSIGNED(Lhs, lhs) <
252 MAKE_UNDERLYING(Rhs, rhs))
254 lhs <= 0 || MAKE_UNSIGNED(Lhs, lhs) <=
255 MAKE_UNDERLYING(Rhs, rhs))
266 #undef DEFINE_SIGNED_MISMATCH_COMP 275 #define DEFINE_CHECK_OP_IMPL(NAME, op) \ 276 template <typename Lhs, typename Rhs> \ 278 typename std::enable_if<!is_signed_vs_unsigned<Lhs, Rhs>::value && \ 279 !is_unsigned_vs_signed<Lhs, Rhs>::value, \ 280 bool>::type Cmp##NAME##Impl(Lhs lhs, Rhs rhs) { \ 283 template <typename Lhs, typename Rhs> \ 284 V8_INLINE std::string* Check##NAME##Impl(Lhs lhs, Rhs rhs, \ 286 using LhsPassT = typename pass_value_or_ref<Lhs>::type; \ 287 using RhsPassT = typename pass_value_or_ref<Rhs>::type; \ 288 bool cmp = Cmp##NAME##Impl<LhsPassT, RhsPassT>(lhs, rhs); \ 289 return V8_LIKELY(cmp) \ 291 : MakeCheckOpString<LhsPassT, RhsPassT>(lhs, rhs, msg); \ 293 extern template V8_BASE_EXPORT std::string* Check##NAME##Impl<float, float>( \ 294 float lhs, float rhs, char const* msg); \ 295 extern template V8_BASE_EXPORT std::string* \ 296 Check##NAME##Impl<double, double>(double lhs, double rhs, \ 298 DEFINE_CHECK_OP_IMPL(EQ, ==)
299 DEFINE_CHECK_OP_IMPL(NE, !=)
300 DEFINE_CHECK_OP_IMPL(LE, <=)
301 DEFINE_CHECK_OP_IMPL(LT, < )
302 DEFINE_CHECK_OP_IMPL(GE, >=)
303 DEFINE_CHECK_OP_IMPL(GT, > )
304 #undef DEFINE_CHECK_OP_IMPL 306 #define CHECK_EQ(lhs, rhs) CHECK_OP(EQ, ==, lhs, rhs) 307 #define CHECK_NE(lhs, rhs) CHECK_OP(NE, !=, lhs, rhs) 308 #define CHECK_LE(lhs, rhs) CHECK_OP(LE, <=, lhs, rhs) 309 #define CHECK_LT(lhs, rhs) CHECK_OP(LT, <, lhs, rhs) 310 #define CHECK_GE(lhs, rhs) CHECK_OP(GE, >=, lhs, rhs) 311 #define CHECK_GT(lhs, rhs) CHECK_OP(GT, >, lhs, rhs) 312 #define CHECK_NULL(val) CHECK((val) == nullptr) 313 #define CHECK_NOT_NULL(val) CHECK((val) != nullptr) 314 #define CHECK_IMPLIES(lhs, rhs) \ 315 CHECK_WITH_MSG(!(lhs) || (rhs), #lhs " implies " #rhs) 324 #define DCHECK_EQ(lhs, rhs) DCHECK_OP(EQ, ==, lhs, rhs) 325 #define DCHECK_NE(lhs, rhs) DCHECK_OP(NE, !=, lhs, rhs) 326 #define DCHECK_GT(lhs, rhs) DCHECK_OP(GT, >, lhs, rhs) 327 #define DCHECK_GE(lhs, rhs) DCHECK_OP(GE, >=, lhs, rhs) 328 #define DCHECK_LT(lhs, rhs) DCHECK_OP(LT, <, lhs, rhs) 329 #define DCHECK_LE(lhs, rhs) DCHECK_OP(LE, <=, lhs, rhs) 330 #define DCHECK_NULL(val) DCHECK((val) == nullptr) 331 #define DCHECK_NOT_NULL(val) DCHECK((val) != nullptr) 332 #define DCHECK_IMPLIES(lhs, rhs) \ 333 DCHECK_WITH_MSG(!(lhs) || (rhs), #lhs " implies " #rhs) 335 #define DCHECK(condition) ((void) 0) 336 #define DCHECK_EQ(v1, v2) ((void) 0) 337 #define DCHECK_NE(v1, v2) ((void) 0) 338 #define DCHECK_GT(v1, v2) ((void) 0) 339 #define DCHECK_GE(v1, v2) ((void) 0) 340 #define DCHECK_LT(v1, v2) ((void) 0) 341 #define DCHECK_LE(v1, v2) ((void) 0) 342 #define DCHECK_NULL(val) ((void) 0) 343 #define DCHECK_NOT_NULL(val) ((void) 0) 344 #define DCHECK_IMPLIES(v1, v2) ((void) 0) 347 #endif // V8_BASE_LOGGING_H_