ART: Make verifier fail log level adjustable
To help for build failures.
Change-Id: I6c94dfb50177daa7d89902d78715ccec31bf0e45
diff --git a/compiler/driver/compiler_driver.cc b/compiler/driver/compiler_driver.cc
index ea16cb2..d29d528 100644
--- a/compiler/driver/compiler_driver.cc
+++ b/compiler/driver/compiler_driver.cc
@@ -2212,7 +2212,8 @@
class VerifyClassVisitor : public CompilationVisitor {
public:
- explicit VerifyClassVisitor(const ParallelCompilationManager* manager) : manager_(manager) {}
+ VerifyClassVisitor(const ParallelCompilationManager* manager, LogSeverity log_level)
+ : manager_(manager), log_level_(log_level) {}
virtual void Visit(size_t class_def_index) REQUIRES(!Locks::mutator_lock_) OVERRIDE {
ATRACE_CALL();
@@ -2250,7 +2251,7 @@
&class_def,
Runtime::Current()->GetCompilerCallbacks(),
true /* allow soft failures */,
- true /* log hard failures */,
+ log_level_,
&error_msg) ==
verifier::MethodVerifier::kHardFailure) {
LOG(ERROR) << "Verification failed on class " << PrettyDescriptor(descriptor)
@@ -2259,7 +2260,7 @@
}
} else if (!SkipClass(jclass_loader, dex_file, klass.Get())) {
CHECK(klass->IsResolved()) << PrettyClass(klass.Get());
- class_linker->VerifyClass(soa.Self(), klass);
+ class_linker->VerifyClass(soa.Self(), klass, log_level_);
if (klass->IsErroneous()) {
// ClassLinker::VerifyClass throws, which isn't useful in the compiler.
@@ -2282,6 +2283,7 @@
private:
const ParallelCompilationManager* const manager_;
+ const LogSeverity log_level_;
};
void CompilerDriver::VerifyDexFile(jobject class_loader,
@@ -2294,7 +2296,10 @@
ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
ParallelCompilationManager context(class_linker, class_loader, this, &dex_file, dex_files,
thread_pool);
- VerifyClassVisitor visitor(&context);
+ LogSeverity log_level = GetCompilerOptions().AbortOnHardVerifierFailure()
+ ? LogSeverity::INTERNAL_FATAL
+ : LogSeverity::WARNING;
+ VerifyClassVisitor visitor(&context, log_level);
context.ForAll(0, dex_file.NumClassDefs(), &visitor, thread_count);
}
diff --git a/runtime/base/logging.cc b/runtime/base/logging.cc
index 7a620e3..212e5bd 100644
--- a/runtime/base/logging.cc
+++ b/runtime/base/logging.cc
@@ -185,14 +185,15 @@
LogMessage::LogMessage(const char* file, unsigned int line, LogSeverity severity, int error)
: data_(new LogMessageData(file, line, severity, error)) {
if (PrintDirectly(severity)) {
- static const char* log_characters = "VDIWEFF";
- CHECK_EQ(strlen(log_characters), INTERNAL_FATAL + 1U);
- stream() << ProgramInvocationShortName() << " " << log_characters[static_cast<size_t>(severity)]
+ static constexpr char kLogCharacters[] = { 'N', 'V', 'D', 'I', 'W', 'E', 'F', 'F' };
+ static_assert(arraysize(kLogCharacters) == static_cast<size_t>(INTERNAL_FATAL) + 1,
+ "Wrong character array size");
+ stream() << ProgramInvocationShortName() << " " << kLogCharacters[static_cast<size_t>(severity)]
<< " " << getpid() << " " << ::art::GetTid() << " " << file << ":" << line << "]";
}
}
LogMessage::~LogMessage() {
- if (!PrintDirectly(data_->GetSeverity())) {
+ if (!PrintDirectly(data_->GetSeverity()) && data_->GetSeverity() != LogSeverity::NONE) {
if (data_->GetSeverity() < gMinimumLogSeverity) {
return; // No need to format something we're not going to output.
}
@@ -236,6 +237,7 @@
#ifdef __ANDROID__
static const android_LogPriority kLogSeverityToAndroidLogPriority[] = {
+ ANDROID_LOG_VERBOSE, // NONE, use verbose as stand-in, will never be printed.
ANDROID_LOG_VERBOSE, ANDROID_LOG_DEBUG, ANDROID_LOG_INFO, ANDROID_LOG_WARN,
ANDROID_LOG_ERROR, ANDROID_LOG_FATAL, ANDROID_LOG_FATAL
};
@@ -245,16 +247,20 @@
void LogMessage::LogLine(const char* file, unsigned int line, LogSeverity log_severity,
const char* message) {
+ if (log_severity == LogSeverity::NONE) {
+ return;
+ }
+
#ifdef __ANDROID__
const char* tag = ProgramInvocationShortName();
- int priority = kLogSeverityToAndroidLogPriority[log_severity];
+ int priority = kLogSeverityToAndroidLogPriority[static_cast<size_t>(log_severity)];
if (priority == ANDROID_LOG_FATAL) {
LOG_PRI(priority, tag, "%s:%u] %s", file, line, message);
} else {
LOG_PRI(priority, tag, "%s", message);
}
#else
- static const char* log_characters = "VDIWEFF";
+ static const char* log_characters = "NVDIWEFF";
CHECK_EQ(strlen(log_characters), INTERNAL_FATAL + 1U);
char severity = log_characters[log_severity];
fprintf(stderr, "%s %c %5d %5d %s:%u] %s\n",
@@ -264,10 +270,14 @@
void LogMessage::LogLineLowStack(const char* file, unsigned int line, LogSeverity log_severity,
const char* message) {
+ if (log_severity == LogSeverity::NONE) {
+ return;
+ }
+
#ifdef __ANDROID__
// Use android_writeLog() to avoid stack-based buffers used by android_printLog().
const char* tag = ProgramInvocationShortName();
- int priority = kLogSeverityToAndroidLogPriority[log_severity];
+ int priority = kLogSeverityToAndroidLogPriority[static_cast<size_t>(log_severity)];
char* buf = nullptr;
size_t buf_size = 0u;
if (priority == ANDROID_LOG_FATAL) {
@@ -285,13 +295,14 @@
android_writeLog(priority, tag, message);
}
#else
- static const char* log_characters = "VDIWEFF";
- CHECK_EQ(strlen(log_characters), INTERNAL_FATAL + 1U);
+ static constexpr char kLogCharacters[] = { 'N', 'V', 'D', 'I', 'W', 'E', 'F', 'F' };
+ static_assert(arraysize(kLogCharacters) == static_cast<size_t>(INTERNAL_FATAL) + 1,
+ "Wrong character array size");
const char* program_name = ProgramInvocationShortName();
TEMP_FAILURE_RETRY(write(STDERR_FILENO, program_name, strlen(program_name)));
TEMP_FAILURE_RETRY(write(STDERR_FILENO, " ", 1));
- TEMP_FAILURE_RETRY(write(STDERR_FILENO, &log_characters[log_severity], 1));
+ TEMP_FAILURE_RETRY(write(STDERR_FILENO, &kLogCharacters[static_cast<size_t>(log_severity)], 1));
TEMP_FAILURE_RETRY(write(STDERR_FILENO, " ", 1));
// TODO: pid and tid.
TEMP_FAILURE_RETRY(write(STDERR_FILENO, file, strlen(file)));
diff --git a/runtime/base/logging.h b/runtime/base/logging.h
index 8aaeaac..97280c3 100644
--- a/runtime/base/logging.h
+++ b/runtime/base/logging.h
@@ -24,6 +24,7 @@
namespace art {
enum LogSeverity {
+ NONE, // Fake level, don't log at all.
VERBOSE,
DEBUG,
INFO,
diff --git a/runtime/class_linker.cc b/runtime/class_linker.cc
index 99e38d9..f2c2f03 100644
--- a/runtime/class_linker.cc
+++ b/runtime/class_linker.cc
@@ -3750,7 +3750,7 @@
return false;
}
-void ClassLinker::VerifyClass(Thread* self, Handle<mirror::Class> klass) {
+void ClassLinker::VerifyClass(Thread* self, Handle<mirror::Class> klass, LogSeverity log_level) {
// TODO: assert that the monitor on the Class is held
ObjectLock<mirror::Class> lock(self, klass);
@@ -3853,7 +3853,7 @@
klass.Get(),
runtime->GetCompilerCallbacks(),
runtime->IsAotCompiler(),
- runtime->IsAotCompiler(),
+ log_level,
&error_msg);
}
if (preverified || verifier_failure != verifier::MethodVerifier::kHardFailure) {
diff --git a/runtime/class_linker.h b/runtime/class_linker.h
index b4fbe1c..886f586 100644
--- a/runtime/class_linker.h
+++ b/runtime/class_linker.h
@@ -449,7 +449,9 @@
SHARED_REQUIRES(Locks::mutator_lock_)
REQUIRES(!Roles::uninterruptible_);
- void VerifyClass(Thread* self, Handle<mirror::Class> klass)
+ void VerifyClass(Thread* self,
+ Handle<mirror::Class> klass,
+ LogSeverity log_level = LogSeverity::NONE)
SHARED_REQUIRES(Locks::mutator_lock_)
REQUIRES(!dex_lock_);
bool VerifyClassUsingOatFile(const DexFile& dex_file,
diff --git a/runtime/verifier/method_verifier.cc b/runtime/verifier/method_verifier.cc
index 5109443..3d5f84e 100644
--- a/runtime/verifier/method_verifier.cc
+++ b/runtime/verifier/method_verifier.cc
@@ -122,7 +122,7 @@
mirror::Class* klass,
CompilerCallbacks* callbacks,
bool allow_soft_failures,
- bool log_hard_failures,
+ LogSeverity log_level,
std::string* error) {
if (klass->IsVerified()) {
return kNoFailure;
@@ -161,7 +161,7 @@
class_def,
callbacks,
allow_soft_failures,
- log_hard_failures,
+ log_level,
error);
}
@@ -195,7 +195,7 @@
Handle<mirror::ClassLoader> class_loader,
CompilerCallbacks* callbacks,
bool allow_soft_failures,
- bool log_hard_failures,
+ LogSeverity log_level,
bool need_precise_constants,
std::string* error_string) {
DCHECK(it != nullptr);
@@ -236,7 +236,7 @@
it->GetMethodAccessFlags(),
callbacks,
allow_soft_failures,
- log_hard_failures,
+ log_level,
need_precise_constants,
&hard_failure_msg);
if (result.kind == kHardFailure) {
@@ -266,7 +266,7 @@
const DexFile::ClassDef* class_def,
CompilerCallbacks* callbacks,
bool allow_soft_failures,
- bool log_hard_failures,
+ LogSeverity log_level,
std::string* error) {
DCHECK(class_def != nullptr);
ScopedTrace trace(__FUNCTION__);
@@ -299,7 +299,7 @@
class_loader,
callbacks,
allow_soft_failures,
- log_hard_failures,
+ log_level,
false /* need precise constants */,
error);
// Virtual methods.
@@ -312,7 +312,7 @@
class_loader,
callbacks,
allow_soft_failures,
- log_hard_failures,
+ log_level,
false /* need precise constants */,
error);
@@ -360,7 +360,7 @@
uint32_t method_access_flags,
CompilerCallbacks* callbacks,
bool allow_soft_failures,
- bool log_hard_failures,
+ LogSeverity log_level,
bool need_precise_constants,
std::string* hard_failure_msg) {
MethodVerifier::FailureData result;
@@ -407,9 +407,12 @@
result.kind = kSoftFailure;
} else {
CHECK(verifier.have_pending_hard_failure_);
- if (VLOG_IS_ON(verifier) || log_hard_failures) {
- verifier.DumpFailures(LOG(INFO) << "Verification error in "
- << PrettyMethod(method_idx, *dex_file) << "\n");
+ if (VLOG_IS_ON(verifier)) {
+ log_level = LogSeverity::VERBOSE;
+ }
+ if (log_level > LogSeverity::VERBOSE) {
+ verifier.DumpFailures(LOG(log_level) << "Verification error in "
+ << PrettyMethod(method_idx, *dex_file) << "\n");
}
if (hard_failure_msg != nullptr) {
CHECK(!verifier.failure_messages_.empty());
diff --git a/runtime/verifier/method_verifier.h b/runtime/verifier/method_verifier.h
index ba9bca0..ebb0b8c 100644
--- a/runtime/verifier/method_verifier.h
+++ b/runtime/verifier/method_verifier.h
@@ -142,12 +142,12 @@
kHardFailure,
};
- /* Verify a class. Returns "kNoFailure" on success. */
+ // Verify a class. Returns "kNoFailure" on success.
static FailureKind VerifyClass(Thread* self,
mirror::Class* klass,
CompilerCallbacks* callbacks,
bool allow_soft_failures,
- bool log_hard_failures,
+ LogSeverity log_level,
std::string* error)
SHARED_REQUIRES(Locks::mutator_lock_);
static FailureKind VerifyClass(Thread* self,
@@ -157,7 +157,7 @@
const DexFile::ClassDef* class_def,
CompilerCallbacks* callbacks,
bool allow_soft_failures,
- bool log_hard_failures,
+ LogSeverity log_level,
std::string* error)
SHARED_REQUIRES(Locks::mutator_lock_);
@@ -331,7 +331,7 @@
Handle<mirror::ClassLoader> class_loader,
CompilerCallbacks* callbacks,
bool allow_soft_failures,
- bool log_hard_failures,
+ LogSeverity log_level,
bool need_precise_constants,
std::string* error_string)
SHARED_REQUIRES(Locks::mutator_lock_);
@@ -357,7 +357,7 @@
uint32_t method_access_flags,
CompilerCallbacks* callbacks,
bool allow_soft_failures,
- bool log_hard_failures,
+ LogSeverity log_level,
bool need_precise_constants,
std::string* hard_failure_msg)
SHARED_REQUIRES(Locks::mutator_lock_);
diff --git a/runtime/verifier/method_verifier_test.cc b/runtime/verifier/method_verifier_test.cc
index 946f842..b036313 100644
--- a/runtime/verifier/method_verifier_test.cc
+++ b/runtime/verifier/method_verifier_test.cc
@@ -37,8 +37,13 @@
// Verify the class
std::string error_msg;
- ASSERT_TRUE(MethodVerifier::VerifyClass(self, klass, nullptr, true, true, &error_msg)
- == MethodVerifier::kNoFailure) << error_msg;
+ MethodVerifier::FailureKind failure = MethodVerifier::VerifyClass(self,
+ klass,
+ nullptr,
+ true,
+ LogSeverity::WARNING,
+ &error_msg);
+ ASSERT_TRUE(failure == MethodVerifier::kNoFailure) << error_msg;
}
void VerifyDexFile(const DexFile& dex)