Commit 28df916b authored by Andrew Grieve's avatar Andrew Grieve Committed by Commit Bot

Discard CHECK failure messages for official builds to save binary size

FATAL() calls with more than one argument are preserved.

The rest of chrome does this as well. Stack traces and minidumps should
be sufficient for analyzing the reason for crashes.

This saves 110kb for Android arm32.

Bug: chromium:958807
Change-Id: I88a1ec82f1ed7bd5e7dbccf6d645d5584f16de82
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/1598159
Commit-Queue: Andrew Grieve <agrieve@chromium.org>
Reviewed-by: 's avatarMichael Starzinger <mstarzinger@chromium.org>
Reviewed-by: 's avatarRoss McIlroy <rmcilroy@chromium.org>
Cr-Commit-Position: refs/heads/master@{#61426}
parent baf84940
...@@ -53,7 +53,12 @@ void PrettyPrintChar(std::ostream& os, int ch) { ...@@ -53,7 +53,12 @@ void PrettyPrintChar(std::ostream& os, int ch) {
} }
void DefaultDcheckHandler(const char* file, int line, const char* message) { void DefaultDcheckHandler(const char* file, int line, const char* message) {
#ifdef DEBUG
V8_Fatal(file, line, "Debug check failed: %s.", message); V8_Fatal(file, line, "Debug check failed: %s.", message);
#else
// This case happens only for unit tests.
V8_Fatal("Debug check failed: %s.", message);
#endif
} }
} // namespace } // namespace
...@@ -144,7 +149,13 @@ class FailureMessage { ...@@ -144,7 +149,13 @@ class FailureMessage {
} // namespace } // namespace
#ifdef DEBUG
void V8_Fatal(const char* file, int line, const char* format, ...) { void V8_Fatal(const char* file, int line, const char* format, ...) {
#else
void V8_Fatal(const char* format, ...) {
const char* file = "";
int line = 0;
#endif
va_list arguments; va_list arguments;
va_start(arguments, format); va_start(arguments, format);
// Format the error message into a stack object for later retrieveal by the // Format the error message into a stack object for later retrieveal by the
...@@ -171,6 +182,15 @@ void V8_Fatal(const char* file, int line, const char* format, ...) { ...@@ -171,6 +182,15 @@ void V8_Fatal(const char* file, int line, const char* format, ...) {
v8::base::OS::Abort(); v8::base::OS::Abort();
} }
#if !defined(DEBUG) && defined(OFFICIAL_BUILD)
void V8_FatalNoContext() {
v8::base::OS::PrintError("V8 CHECK or FATAL\n");
if (v8::base::g_print_stack_trace) v8::base::g_print_stack_trace();
fflush(stderr);
v8::base::OS::Abort();
}
#endif
void V8_Dcheck(const char* file, int line, const char* message) { void V8_Dcheck(const char* file, int line, const char* message) {
v8::base::g_dcheck_function(file, line, message); v8::base::g_dcheck_function(file, line, message);
} }
...@@ -14,17 +14,40 @@ ...@@ -14,17 +14,40 @@
#include "src/base/compiler-specific.h" #include "src/base/compiler-specific.h"
#include "src/base/template-utils.h" #include "src/base/template-utils.h"
[[noreturn]] PRINTF_FORMAT(3, 4) V8_BASE_EXPORT V8_NOINLINE
void V8_Fatal(const char* file, int line, const char* format, ...);
V8_BASE_EXPORT V8_NOINLINE void V8_Dcheck(const char* file, int line, V8_BASE_EXPORT V8_NOINLINE void V8_Dcheck(const char* file, int line,
const char* message); const char* message);
#ifdef DEBUG #ifdef DEBUG
// In debug, include file, line, and full error message for all
// FATAL() calls.
[[noreturn]] PRINTF_FORMAT(3, 4) V8_BASE_EXPORT V8_NOINLINE
void V8_Fatal(const char* file, int line, const char* format, ...);
#define FATAL(...) V8_Fatal(__FILE__, __LINE__, __VA_ARGS__) #define FATAL(...) V8_Fatal(__FILE__, __LINE__, __VA_ARGS__)
#elif !defined(OFFICIAL_BUILD)
// In non-official release, include full error message, but drop file & line
// numbers. It saves binary size to drop the |file| & |line| as opposed to just
// passing in "", 0 for them.
[[noreturn]] PRINTF_FORMAT(1, 2) V8_BASE_EXPORT V8_NOINLINE
void V8_Fatal(const char* format, ...);
#define FATAL V8_Fatal
#else #else
#define FATAL(...) V8_Fatal("", 0, __VA_ARGS__) // In official builds, include only messages that contain parameters because
// single-message errors can always be derived from stack traces.
[[noreturn]] V8_BASE_EXPORT V8_NOINLINE void V8_FatalNoContext();
[[noreturn]] PRINTF_FORMAT(1, 2) V8_BASE_EXPORT V8_NOINLINE
void V8_Fatal(const char* format, ...);
// FATAL(msg) -> V8_FatalNoContext()
// FATAL(msg, ...) -> V8_Fatal()
#define FATAL_HELPER(_7, _6, _5, _4, _3, _2, _1, _0, ...) _0
#define FATAL_DISCARD_ARG(arg) V8_FatalNoContext()
#define FATAL(...) \
FATAL_HELPER(__VA_ARGS__, V8_Fatal, V8_Fatal, V8_Fatal, V8_Fatal, V8_Fatal, \
V8_Fatal, V8_Fatal, FATAL_DISCARD_ARG) \
(__VA_ARGS__)
#endif #endif
#define UNIMPLEMENTED() FATAL("unimplemented code") #define UNIMPLEMENTED() FATAL("unimplemented code")
#define UNREACHABLE() FATAL("unreachable code") #define UNREACHABLE() FATAL("unreachable code")
...@@ -38,6 +61,14 @@ V8_BASE_EXPORT void SetPrintStackTrace(void (*print_stack_trace_)()); ...@@ -38,6 +61,14 @@ V8_BASE_EXPORT void SetPrintStackTrace(void (*print_stack_trace_)());
V8_BASE_EXPORT void SetDcheckFunction(void (*dcheck_Function)(const char*, int, V8_BASE_EXPORT void SetDcheckFunction(void (*dcheck_Function)(const char*, int,
const char*)); const char*));
// In official builds, assume all check failures can be debugged given just the
// stack trace.
#if !defined(DEBUG) && defined(OFFICIAL_BUILD)
#define CHECK_FAILED_HANDLER(message) FATAL("ignored")
#else
#define CHECK_FAILED_HANDLER(message) FATAL("Check failed: %s.", message)
#endif
// CHECK dies with a fatal error if condition is not true. It is *not* // CHECK dies with a fatal error if condition is not true. It is *not*
// controlled by DEBUG, so the check will be executed regardless of // controlled by DEBUG, so the check will be executed regardless of
// compilation mode. // compilation mode.
...@@ -47,7 +78,7 @@ V8_BASE_EXPORT void SetDcheckFunction(void (*dcheck_Function)(const char*, int, ...@@ -47,7 +78,7 @@ V8_BASE_EXPORT void SetDcheckFunction(void (*dcheck_Function)(const char*, int,
#define CHECK_WITH_MSG(condition, message) \ #define CHECK_WITH_MSG(condition, message) \
do { \ do { \
if (V8_UNLIKELY(!(condition))) { \ if (V8_UNLIKELY(!(condition))) { \
FATAL("Check failed: %s.", message); \ CHECK_FAILED_HANDLER(message); \
} \ } \
} while (false) } while (false)
#define CHECK(condition) CHECK_WITH_MSG(condition, #condition) #define CHECK(condition) CHECK_WITH_MSG(condition, #condition)
......
...@@ -1917,10 +1917,10 @@ Address CheckObjectType(Address raw_value, Address raw_type, ...@@ -1917,10 +1917,10 @@ Address CheckObjectType(Address raw_value, Address raw_type,
} }
std::stringstream value_description; std::stringstream value_description;
value->Print(value_description); value->Print(value_description);
V8_Fatal(__FILE__, __LINE__, FATAL(
"Type cast failed in %s\n" "Type cast failed in %s\n"
" Expected %s but found %s", " Expected %s but found %s",
location->ToAsciiArray(), expected, value_description.str().c_str()); location->ToAsciiArray(), expected, value_description.str().c_str());
#else #else
UNREACHABLE(); UNREACHABLE();
#endif #endif
......
...@@ -1452,8 +1452,8 @@ class WasmDecoder : public Decoder { ...@@ -1452,8 +1452,8 @@ class WasmDecoder : public Decoder {
V8_FALLTHROUGH; V8_FALLTHROUGH;
} }
default: default:
V8_Fatal(__FILE__, __LINE__, "unimplemented opcode: %x (%s)", opcode, FATAL("unimplemented opcode: %x (%s)", opcode,
WasmOpcodes::OpcodeName(opcode)); WasmOpcodes::OpcodeName(opcode));
return {0, 0}; return {0, 0};
} }
#undef DECLARE_OPCODE_CASE #undef DECLARE_OPCODE_CASE
......
...@@ -796,8 +796,8 @@ class TestEnvironment : public HandleAndZoneScope { ...@@ -796,8 +796,8 @@ class TestEnvironment : public HandleAndZoneScope {
layout_[i]); layout_[i]);
std::ostringstream actual_str; std::ostringstream actual_str;
PrintStateValue(actual_str, main_isolate(), actual_value, layout_[i]); PrintStateValue(actual_str, main_isolate(), actual_value, layout_[i]);
V8_Fatal(__FILE__, __LINE__, "Expected: '%s' but got '%s'", FATAL("Expected: '%s' but got '%s'", expected_str.str().c_str(),
expected_str.str().c_str(), actual_str.str().c_str()); actual_str.str().c_str());
} }
} }
} }
......
...@@ -670,17 +670,16 @@ TEST(CompileFunctionInContextScriptOrigin) { ...@@ -670,17 +670,16 @@ TEST(CompileFunctionInContextScriptOrigin) {
} }
void TestCompileFunctionInContextToStringImpl() { void TestCompileFunctionInContextToStringImpl() {
#define CHECK_NOT_CAUGHT(__local_context__, try_catch, __op__) \ #define CHECK_NOT_CAUGHT(__local_context__, try_catch, __op__) \
do { \ do { \
const char* op = (__op__); \ const char* op = (__op__); \
v8::Local<v8::Context> context = (__local_context__); \ v8::Local<v8::Context> context = (__local_context__); \
if (try_catch.HasCaught()) { \ if (try_catch.HasCaught()) { \
v8::String::Utf8Value error( \ v8::String::Utf8Value error( \
CcTest::isolate(), \ CcTest::isolate(), \
try_catch.Exception()->ToString(context).ToLocalChecked()); \ try_catch.Exception()->ToString(context).ToLocalChecked()); \
V8_Fatal(__FILE__, __LINE__, \ FATAL("Unexpected exception thrown during %s:\n\t%s\n", op, *error); \
"Unexpected exception thrown during %s:\n\t%s\n", op, *error); \ } \
} \
} while (false) } while (false)
{ // NOLINT { // NOLINT
......
...@@ -140,9 +140,9 @@ bool DisassembleAndCompare(byte* begin, UseRegex use_regex, ...@@ -140,9 +140,9 @@ bool DisassembleAndCompare(byte* begin, UseRegex use_regex,
// Verify that all invocations of the COMPARE macro passed successfully. // Verify that all invocations of the COMPARE macro passed successfully.
// Exit with a failure if at least one of the tests failed. // Exit with a failure if at least one of the tests failed.
#define VERIFY_RUN() \ #define VERIFY_RUN() \
if (failure) { \ if (failure) { \
V8_Fatal(__FILE__, __LINE__, "ARM Disassembler tests failed.\n"); \ FATAL("ARM Disassembler tests failed.\n"); \
} }
// clang-format off // clang-format off
......
...@@ -94,9 +94,9 @@ bool DisassembleAndCompare(byte* pc, const char* compare_string) { ...@@ -94,9 +94,9 @@ bool DisassembleAndCompare(byte* pc, const char* compare_string) {
// Verify that all invocations of the COMPARE macro passed successfully. // Verify that all invocations of the COMPARE macro passed successfully.
// Exit with a failure if at least one of the tests failed. // Exit with a failure if at least one of the tests failed.
#define VERIFY_RUN() \ #define VERIFY_RUN() \
if (failure) { \ if (failure) { \
V8_Fatal(__FILE__, __LINE__, "MIPS Disassembler tests failed.\n"); \ FATAL("MIPS Disassembler tests failed.\n"); \
} }
#define COMPARE_PC_REL_COMPACT(asm_, compare_string, offset) \ #define COMPARE_PC_REL_COMPACT(asm_, compare_string, offset) \
......
...@@ -94,9 +94,9 @@ bool DisassembleAndCompare(byte* pc, const char* compare_string) { ...@@ -94,9 +94,9 @@ bool DisassembleAndCompare(byte* pc, const char* compare_string) {
// Verify that all invocations of the COMPARE macro passed successfully. // Verify that all invocations of the COMPARE macro passed successfully.
// Exit with a failure if at least one of the tests failed. // Exit with a failure if at least one of the tests failed.
#define VERIFY_RUN() \ #define VERIFY_RUN() \
if (failure) { \ if (failure) { \
V8_Fatal(__FILE__, __LINE__, "MIPS Disassembler tests failed.\n"); \ FATAL("MIPS Disassembler tests failed.\n"); \
} }
#define COMPARE_PC_REL_COMPACT(asm_, compare_string, offset) \ #define COMPARE_PC_REL_COMPACT(asm_, compare_string, offset) \
......
...@@ -90,9 +90,9 @@ bool DisassembleAndCompare(byte* pc, const char* compare_string) { ...@@ -90,9 +90,9 @@ bool DisassembleAndCompare(byte* pc, const char* compare_string) {
// Verify that all invocations of the COMPARE macro passed successfully. // Verify that all invocations of the COMPARE macro passed successfully.
// Exit with a failure if at least one of the tests failed. // Exit with a failure if at least one of the tests failed.
#define VERIFY_RUN() \ #define VERIFY_RUN() \
if (failure) { \ if (failure) { \
V8_Fatal(__FILE__, __LINE__, "PPC Disassembler tests failed.\n"); \ FATAL("PPC Disassembler tests failed.\n"); \
} }
TEST(DisasmPPC) { TEST(DisasmPPC) {
......
...@@ -88,9 +88,9 @@ bool DisassembleAndCompare(byte* pc, const char* compare_string) { ...@@ -88,9 +88,9 @@ bool DisassembleAndCompare(byte* pc, const char* compare_string) {
// Verify that all invocations of the COMPARE macro passed successfully. // Verify that all invocations of the COMPARE macro passed successfully.
// Exit with a failure if at least one of the tests failed. // Exit with a failure if at least one of the tests failed.
#define VERIFY_RUN() \ #define VERIFY_RUN() \
if (failure) { \ if (failure) { \
V8_Fatal(__FILE__, __LINE__, "S390 Disassembler tests failed.\n"); \ FATAL("S390 Disassembler tests failed.\n"); \
} }
TEST(TwoBytes) { TEST(TwoBytes) {
......
...@@ -181,9 +181,8 @@ class ScopedLoggerInitializer { ...@@ -181,9 +181,8 @@ class ScopedLoggerInitializer {
printf("%s\n", log_.at(i).c_str()); printf("%s\n", log_.at(i).c_str());
} }
printf("%zu\n", current); printf("%zu\n", current);
V8_Fatal(__FILE__, __LINE__, "%s, ... %p apperead twice:\n %s", FATAL("%s, ... %p apperead twice:\n %s", search_term.c_str(),
search_term.c_str(), reinterpret_cast<void*>(address), reinterpret_cast<void*>(address), current_line.c_str());
current_line.c_str());
} }
} }
map.insert({address, current_line}); map.insert({address, current_line});
...@@ -941,22 +940,22 @@ void ValidateMapDetailsLogging(v8::Isolate* isolate, ...@@ -941,22 +940,22 @@ void ValidateMapDetailsLogging(v8::Isolate* isolate,
if (map_create_addresses.find(address) == map_create_addresses.end()) { if (map_create_addresses.find(address) == map_create_addresses.end()) {
// logger->PrintLog(); // logger->PrintLog();
i::Map::cast(obj)->Print(); i::Map::cast(obj)->Print();
V8_Fatal(__FILE__, __LINE__, FATAL(
"Map (%p, #%zu) creation not logged during startup with " "Map (%p, #%zu) creation not logged during startup with "
"--trace-maps!" "--trace-maps!"
"\n# Expected Log Line: map-create, ... %p", "\n# Expected Log Line: map-create, ... %p",
reinterpret_cast<void*>(obj->ptr()), i, reinterpret_cast<void*>(obj->ptr()), i,
reinterpret_cast<void*>(obj->ptr())); reinterpret_cast<void*>(obj->ptr()));
} else if (map_details_addresses.find(address) == } else if (map_details_addresses.find(address) ==
map_details_addresses.end()) { map_details_addresses.end()) {
// logger->PrintLog(); // logger->PrintLog();
i::Map::cast(obj)->Print(); i::Map::cast(obj)->Print();
V8_Fatal(__FILE__, __LINE__, FATAL(
"Map (%p, #%zu) details not logged during startup with " "Map (%p, #%zu) details not logged during startup with "
"--trace-maps!" "--trace-maps!"
"\n# Expected Log Line: map-details, ... %p", "\n# Expected Log Line: map-details, ... %p",
reinterpret_cast<void*>(obj->ptr()), i, reinterpret_cast<void*>(obj->ptr()), i,
reinterpret_cast<void*>(obj->ptr())); reinterpret_cast<void*>(obj->ptr()));
} }
} }
} }
......
...@@ -20,16 +20,15 @@ using v8::Utils; ...@@ -20,16 +20,15 @@ using v8::Utils;
namespace { namespace {
#define CHECK_CSTREQ(exp, found) \ #define CHECK_CSTREQ(exp, found) \
do { \ do { \
const char* exp_ = (exp); \ const char* exp_ = (exp); \
const char* found_ = (found); \ const char* found_ = (found); \
DCHECK_NOT_NULL(exp); \ DCHECK_NOT_NULL(exp); \
if (V8_UNLIKELY(found_ == nullptr || strcmp(exp_, found_) != 0)) { \ if (V8_UNLIKELY(found_ == nullptr || strcmp(exp_, found_) != 0)) { \
V8_Fatal(__FILE__, __LINE__, \ FATAL("Check failed: (%s) != (%s) ('%s' vs '%s').", #exp, #found, exp_, \
"Check failed: (%s) != (%s) ('%s' vs '%s').", #exp, #found, \ found_ ? found_ : "<null>"); \
exp_, found_ ? found_ : "<null>"); \ } \
} \
} while (false) } while (false)
void PrintStackTrace(v8::Isolate* isolate, v8::Local<v8::StackTrace> stack) { void PrintStackTrace(v8::Isolate* isolate, v8::Local<v8::StackTrace> stack) {
......
...@@ -21,16 +21,15 @@ using v8::Utils; ...@@ -21,16 +21,15 @@ using v8::Utils;
namespace { namespace {
#define CHECK_CSTREQ(exp, found) \ #define CHECK_CSTREQ(exp, found) \
do { \ do { \
const char* exp_ = (exp); \ const char* exp_ = (exp); \
const char* found_ = (found); \ const char* found_ = (found); \
DCHECK_NOT_NULL(exp); \ DCHECK_NOT_NULL(exp); \
if (V8_UNLIKELY(found_ == nullptr || strcmp(exp_, found_) != 0)) { \ if (V8_UNLIKELY(found_ == nullptr || strcmp(exp_, found_) != 0)) { \
V8_Fatal(__FILE__, __LINE__, \ FATAL("Check failed: (%s) != (%s) ('%s' vs '%s').", #exp, #found, exp_, \
"Check failed: (%s) != (%s) ('%s' vs '%s').", #exp, #found, \ found_ ? found_ : "<null>"); \
exp_, found_ ? found_ : "<null>"); \ } \
} \
} while (false) } while (false)
struct ExceptionInfo { struct ExceptionInfo {
......
...@@ -374,8 +374,7 @@ void CompileRunAndVerify(FuzzerArgs* args, const std::string& source) { ...@@ -374,8 +374,7 @@ void CompileRunAndVerify(FuzzerArgs* args, const std::string& source) {
uint32_t hash = StringHasher::HashSequentialString( uint32_t hash = StringHasher::HashSequentialString(
args->input_data, static_cast<int>(args->input_length), args->input_data, static_cast<int>(args->input_length),
kRegExpBuiltinsFuzzerHashSeed); kRegExpBuiltinsFuzzerHashSeed);
V8_Fatal(__FILE__, __LINE__, FATAL("!ResultAreIdentical(args); RegExpBuiltinsFuzzerHash=%x", hash);
"!ResultAreIdentical(args); RegExpBuiltinsFuzzerHash=%x", hash);
} }
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment