5#ifndef V8_BASE_LOGGING_H_
6#define V8_BASE_LOGGING_H_
30 void V8_Fatal(const
char* file,
int line, const
char* format, ...);
31#define FATAL(...) V8_Fatal(__FILE__, __LINE__, __VA_ARGS__)
36#define GRACEFUL_FATAL(...) FATAL(__VA_ARGS__)
40 void V8_Fatal(const
char* format, ...);
41#define GRACEFUL_FATAL(...) V8_Fatal(__VA_ARGS__)
43#if !defined(OFFICIAL_BUILD)
47#define FATAL(...) V8_Fatal(__VA_ARGS__)
51#define FATAL_HELPER(_7, _6, _5, _4, _3, _2, _1, _0, ...) _0
52#define FATAL_DISCARD_ARG(arg) IMMEDIATE_CRASH()
54 FATAL_HELPER(__VA_ARGS__, V8_Fatal, V8_Fatal, V8_Fatal, V8_Fatal, V8_Fatal, \
55 V8_Fatal, FATAL_DISCARD_ARG) \
66#define UNIMPLEMENTED() FATAL(::v8::base::kUnimplementedCodeMessage)
67#define UNREACHABLE() FATAL(::v8::base::kUnreachableCodeMessage)
70#if defined(__GNUC__) && !defined(__clang__) && (__GNUC__ <= 8)
71#define CONSTEXPR_UNREACHABLE() abort()
73#define CONSTEXPR_UNREACHABLE() UNREACHABLE()
106#if !defined(DEBUG) && defined(OFFICIAL_BUILD)
107#define CHECK_FAILED_HANDLER(message) FATAL("ignored")
109#define CHECK_FAILED_HANDLER(message) FATAL("Check failed: %s.", message)
118#define CHECK_WITH_MSG(condition, message) \
120 if (V8_UNLIKELY(!(condition))) { \
121 CHECK_FAILED_HANDLER(message); \
124#define CHECK(condition) CHECK_WITH_MSG(condition, #condition)
128#define DCHECK_WITH_MSG_AND_LOC(condition, message, loc) \
130 if (V8_UNLIKELY(!(condition))) { \
131 V8_Dcheck(loc.FileName(), static_cast<int>(loc.Line()), message); \
134#define DCHECK_WITH_MSG(condition, message) \
136 if (V8_UNLIKELY(!(condition))) { \
137 V8_Dcheck(__FILE__, __LINE__, message); \
140#define DCHECK_WITH_LOC(condition, loc) \
141 DCHECK_WITH_MSG_AND_LOC(condition, #condition, loc)
142#define DCHECK(condition) DCHECK_WITH_MSG(condition, #condition)
146#define CHECK_OP(name, op, lhs, rhs) \
148 if (std::string* _msg = ::v8::base::Check##name##Impl< \
149 typename ::v8::base::pass_value_or_ref<decltype(lhs)>::type, \
150 typename ::v8::base::pass_value_or_ref<decltype(rhs)>::type>( \
151 (lhs), (rhs), #lhs " " #op " " #rhs)) { \
152 FATAL("Check failed: %s.", _msg->c_str()); \
157#define DCHECK_OP(name, op, lhs, rhs) \
159 if (std::string* _msg = ::v8::base::Check##name##Impl< \
160 typename ::v8::base::pass_value_or_ref<decltype(lhs)>::type, \
161 typename ::v8::base::pass_value_or_ref<decltype(rhs)>::type>( \
162 (lhs), (rhs), #lhs " " #op " " #rhs)) { \
163 V8_Dcheck(__FILE__, __LINE__, _msg->c_str()); \
173#define CHECK_OP(name, op, lhs, rhs) \
175 bool _cmp = ::v8::base::Cmp##name##Impl< \
176 typename ::v8::base::pass_value_or_ref<decltype(lhs)>::type, \
177 typename ::v8::base::pass_value_or_ref<decltype(rhs)>::type>((lhs), \
179 CHECK_WITH_MSG(_cmp, #lhs " " #op " " #rhs); \
182#define DCHECK_WITH_MSG(condition, msg) void(0);
187template <
typename... Ts>
190 (..., (oss << std::forward<Ts>(ts)));
196 auto underlying_val =
static_cast<std::underlying_type_t<T>
>(val);
199 if constexpr (
sizeof(underlying_val) == 1) {
200 constexpr bool kIsSigned = std::is_signed_v<
decltype(underlying_val)>;
201 using int_t = std::conditional_t<kIsSigned, int16_t, uint16_t>;
202 return static_cast<int_t
>(underlying_val);
204 return underlying_val;
213 return "<unprintable>";
219 requires(!std::is_function_v<typename std::remove_pointer<T>::type> &&
220 !std::is_enum_v<T> && has_output_operator<T, CheckMessageStream>)
231 requires(std::is_function_v<typename std::remove_pointer_t<T>>)
238 requires(std::is_enum_v<T>)
240 std::string int_str =
249 if ((val_str.length() == 1 && !std::isprint(val_str[0])) ||
250 val_str == int_str) {
262 requires(!has_output_operator<T, CheckMessageStream> &&
264 { t.begin() } -> std::forward_iterator;
270 for (
const auto& val : container) {
283#define DEFINE_PRINT_CHECK_OPERAND_CHAR(type) \
285 V8_BASE_EXPORT std::string PrintCheckOperand<type>(type ch); \
287 V8_BASE_EXPORT std::string PrintCheckOperand<type*>(type * cstr); \
289 V8_BASE_EXPORT std::string PrintCheckOperand<const type*>(const type* cstr);
294#undef DEFINE_PRINT_CHECK_OPERAND_CHAR
300template <
typename Lhs,
typename Rhs>
306 constexpr size_t kMaxInlineLength = 50;
307 if (lhs_str.size() <= kMaxInlineLength &&
308 rhs_str.size() <= kMaxInlineLength) {
309 ss <<
" (" << lhs_str <<
" vs. " << rhs_str <<
")";
311 ss <<
"\n " << lhs_str <<
"\n vs.\n " << rhs_str <<
"\n";
313 return new std::string(ss.str());
318#define EXPLICIT_CHECK_OP_INSTANTIATION(type) \
319 extern template V8_BASE_EXPORT std::string* MakeCheckOpString<type, type>( \
320 type, type, char const*); \
321 extern template V8_BASE_EXPORT std::string PrintCheckOperand<type>(type);
330#undef EXPLICIT_CHECK_OP_INSTANTIATION
340 using decay =
typename std::decay<T>::type;
341 static constexpr bool is_enum = std::is_enum_v<decay>;
343 typename std::conditional<is_enum, decay, Dummy>::type>
::type;
345 typename std::conditional<is_enum, underlying, decay>::type;
346 using type =
typename std::conditional<std::is_same_v<type_or_bool, bool>,
350#define MAKE_UNDERLYING(Type, value) \
351 static_cast<typename comparison_underlying_type<Type>::type>(value)
355template <
typename Lhs,
typename Rhs>
359 static constexpr bool value = std::is_integral_v<lhs_underlying> &&
360 std::is_integral_v<rhs_underlying> &&
361 std::is_signed_v<lhs_underlying> &&
362 std::is_unsigned_v<rhs_underlying>;
365template <
typename Lhs,
typename Rhs>
379#define DEFINE_CMP_IMPL(NAME, op) \
380 template <typename Lhs, typename Rhs> \
381 V8_INLINE constexpr bool Cmp##NAME##Impl(Lhs lhs, Rhs rhs) { \
390#undef DEFINE_CMP_IMPL
394#define MAKE_UNSIGNED(Type, value) \
395 static_cast<typename std::make_unsigned< \
396 typename comparison_underlying_type<Type>::type>::type>(value)
397#define DEFINE_SIGNED_MISMATCH_COMP(CHECK, NAME, IMPL) \
398 template <typename Lhs, typename Rhs> \
399 requires(CHECK<Lhs, Rhs>::value) \
400 V8_INLINE constexpr bool Cmp##NAME##Impl(Lhs lhs, Rhs rhs) { \
422#undef DEFINE_SIGNED_MISMATCH_COMP
426#define DEFINE_CHECK_OP_IMPL(NAME) \
427 template <typename Lhs, typename Rhs> \
428 V8_INLINE constexpr std::string* Check##NAME##Impl(Lhs lhs, Rhs rhs, \
430 using LhsPassT = typename pass_value_or_ref<Lhs>::type; \
431 using RhsPassT = typename pass_value_or_ref<Rhs>::type; \
432 bool cmp = Cmp##NAME##Impl<LhsPassT, RhsPassT>(lhs, rhs); \
433 return V8_LIKELY(cmp) \
435 : MakeCheckOpString<LhsPassT, RhsPassT>(lhs, rhs, msg); \
443#undef DEFINE_CHECK_OP_IMPL
445#define CHECK_EQ(lhs, rhs) CHECK_OP(EQ, ==, lhs, rhs)
446#define CHECK_NE(lhs, rhs) CHECK_OP(NE, !=, lhs, rhs)
447#define CHECK_LE(lhs, rhs) CHECK_OP(LE, <=, lhs, rhs)
448#define CHECK_LT(lhs, rhs) CHECK_OP(LT, <, lhs, rhs)
449#define CHECK_GE(lhs, rhs) CHECK_OP(GE, >=, lhs, rhs)
450#define CHECK_GT(lhs, rhs) CHECK_OP(GT, >, lhs, rhs)
451#define CHECK_NULL(val) CHECK((val) == nullptr)
452#define CHECK_NOT_NULL(val) CHECK((val) != nullptr)
453#define CHECK_IMPLIES(lhs, rhs) \
454 CHECK_WITH_MSG(!(lhs) || (rhs), #lhs " implies " #rhs)
457#define CHECK_BOUNDS(index, limit) \
458 CHECK_LT(static_cast<std::make_unsigned_t<decltype(index)>>(index), \
459 static_cast<std::make_unsigned_t<decltype(limit)>>(limit))
468#define DCHECK_EQ(lhs, rhs) DCHECK_OP(EQ, ==, lhs, rhs)
469#define DCHECK_NE(lhs, rhs) DCHECK_OP(NE, !=, lhs, rhs)
470#define DCHECK_GT(lhs, rhs) DCHECK_OP(GT, >, lhs, rhs)
471#define DCHECK_GE(lhs, rhs) DCHECK_OP(GE, >=, lhs, rhs)
472#define DCHECK_LT(lhs, rhs) DCHECK_OP(LT, <, lhs, rhs)
473#define DCHECK_LE(lhs, rhs) DCHECK_OP(LE, <=, lhs, rhs)
474#define DCHECK_NULL(val) DCHECK((val) == nullptr)
475#define DCHECK_NOT_NULL(val) DCHECK((val) != nullptr)
476#define DCHECK_IMPLIES(lhs, rhs) \
477 DCHECK_WITH_MSG(!(lhs) || (rhs), #lhs " implies " #rhs)
478#define DCHECK_BOUNDS(index, limit) \
479 DCHECK_LT(static_cast<std::make_unsigned_t<decltype(index)>>(index), \
480 static_cast<std::make_unsigned_t<decltype(limit)>>(limit))
482#define DCHECK(condition) ((void) 0)
483#define DCHECK_WITH_LOC(condition, location) ((void)0)
484#define DCHECK_WITH_MSG_AND_LOC(condition, message, location) ((void)0)
485#define DCHECK_EQ(v1, v2) ((void) 0)
486#define DCHECK_NE(v1, v2) ((void) 0)
487#define DCHECK_GT(v1, v2) ((void) 0)
488#define DCHECK_GE(v1, v2) ((void) 0)
489#define DCHECK_LT(v1, v2) ((void) 0)
490#define DCHECK_LE(v1, v2) ((void) 0)
491#define DCHECK_NULL(val) ((void) 0)
492#define DCHECK_NOT_NULL(val) ((void) 0)
493#define DCHECK_IMPLIES(v1, v2) ((void) 0)
494#define DCHECK_BOUNDS(index, limit) ((void)0)
void V8_Fatal(const char *format,...)
#define DEFINE_PRINT_CHECK_OPERAND_CHAR(type)
std::string PrintToString(Ts &&... ts)
auto GetUnderlyingEnumTypeForPrinting(T val)
void SetPrintStackTrace(void(*print_stack_trace)())
V8_NOINLINE std::string * MakeCheckOpString(Lhs lhs, Rhs rhs, char const *msg)
std::string PrintCheckOperand(T val)
void FatalOOM(OOMType type, const char *msg)
constexpr const char * kUnreachableCodeMessage
void SetDcheckFunction(void(*dcheck_function)(const char *, int, const char *))
constexpr const char * kUnimplementedCodeMessage
void SetFatalFunction(void(*fatal_function)(const char *, int, const char *))
#define PRINTF_FORMAT(format_param, dots_param)
#define DEFINE_SIGNED_MISMATCH_COMP(CHECK, NAME, IMPL)
#define DEFINE_CMP_IMPL(NAME, op)
#define MAKE_UNSIGNED(Type, value)
#define DEFINE_CHECK_OP_IMPL(NAME)
#define EXPLICIT_CHECK_OP_INSTANTIATION(type)
#define MAKE_UNDERLYING(Type, value)
V8_BASE_EXPORT V8_NOINLINE void V8_Dcheck(const char *file, int line, const char *message)
typename std::decay< T >::type decay
static constexpr bool is_enum
typename std::conditional< std::is_same_v< type_or_bool, bool >, unsigned int, type_or_bool >::type type
typename std::underlying_type< typename std::conditional< is_enum, decay, Dummy >::type >::type underlying
typename std::conditional< is_enum, underlying, decay >::type type_or_bool
typename comparison_underlying_type< Rhs >::type rhs_underlying
typename comparison_underlying_type< Lhs >::type lhs_underlying