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)