ART: Add abort-on-soft-verifier-error
Add an option to abort compilation if any class fails compile-time
verification.
Bug: 65318848
Bug: 67358823
Test: m test-art-host-gtest-dex2oat_test
Change-Id: I5d2a7cd1d2ed048ab39d6f787ecc9eb2f41d3d77
diff --git a/compiler/driver/compiler_driver.cc b/compiler/driver/compiler_driver.cc
index 7573367..547ffbc 100644
--- a/compiler/driver/compiler_driver.cc
+++ b/compiler/driver/compiler_driver.cc
@@ -296,6 +296,7 @@
image_classes_(image_classes),
classes_to_compile_(compiled_classes),
methods_to_compile_(compiled_methods),
+ number_of_soft_verifier_failures_(0),
had_hard_verifier_failure_(false),
parallel_thread_count_(thread_count),
stats_(new AOTCompilationStats),
@@ -923,6 +924,12 @@
LOG(FATAL_WITHOUT_ABORT) << "Had a hard failure verifying all classes, and was asked to abort "
<< "in such situations. Please check the log.";
abort();
+ } else if (number_of_soft_verifier_failures_ > 0 &&
+ GetCompilerOptions().AbortOnSoftVerifierFailure()) {
+ LOG(FATAL_WITHOUT_ABORT) << "Had " << number_of_soft_verifier_failures_ << " soft failure(s) "
+ << "verifying all classes, and was asked to abort in such situations. "
+ << "Please check the log.";
+ abort();
}
if (compiler_options_->IsAnyCompilationEnabled()) {
@@ -2069,13 +2076,13 @@
LOG(ERROR) << "Verification failed on class " << PrettyDescriptor(descriptor)
<< " because: " << error_msg;
manager_->GetCompiler()->SetHadHardVerifierFailure();
+ } else if (failure_kind == verifier::FailureKind::kSoftFailure) {
+ manager_->GetCompiler()->AddSoftVerifierFailure();
} else {
// Force a soft failure for the VerifierDeps. This is a sanity measure, as
// the vdex file already records that the class hasn't been resolved. It avoids
// trying to do future verification optimizations when processing the vdex file.
- DCHECK(failure_kind == verifier::FailureKind::kSoftFailure ||
- failure_kind == verifier::FailureKind::kNoFailure)
- << failure_kind;
+ DCHECK(failure_kind == verifier::FailureKind::kNoFailure) << failure_kind;
failure_kind = verifier::FailureKind::kSoftFailure;
}
} else if (!SkipClass(jclass_loader, dex_file, klass.Get())) {
@@ -2087,6 +2094,8 @@
CHECK(soa.Self()->IsExceptionPending());
soa.Self()->ClearException();
manager_->GetCompiler()->SetHadHardVerifierFailure();
+ } else if (failure_kind == verifier::FailureKind::kSoftFailure) {
+ manager_->GetCompiler()->AddSoftVerifierFailure();
}
CHECK(klass->ShouldVerifyAtRuntime() || klass->IsVerified() || klass->IsErroneous())
@@ -2152,7 +2161,9 @@
ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
ParallelCompilationManager context(class_linker, class_loader, this, &dex_file, dex_files,
thread_pool);
- verifier::HardFailLogMode log_level = GetCompilerOptions().AbortOnHardVerifierFailure()
+ bool abort_on_verifier_failures = GetCompilerOptions().AbortOnHardVerifierFailure()
+ || GetCompilerOptions().AbortOnSoftVerifierFailure();
+ verifier::HardFailLogMode log_level = abort_on_verifier_failures
? verifier::HardFailLogMode::kLogInternalFatal
: verifier::HardFailLogMode::kLogWarning;
VerifyClassVisitor visitor(&context, log_level);
diff --git a/compiler/driver/compiler_driver.h b/compiler/driver/compiler_driver.h
index f16e2ed..da4a580 100644
--- a/compiler/driver/compiler_driver.h
+++ b/compiler/driver/compiler_driver.h
@@ -17,6 +17,7 @@
#ifndef ART_COMPILER_DRIVER_COMPILER_DRIVER_H_
#define ART_COMPILER_DRIVER_COMPILER_DRIVER_H_
+#include <atomic>
#include <set>
#include <string>
#include <unordered_set>
@@ -352,6 +353,9 @@
void SetHadHardVerifierFailure() {
had_hard_verifier_failure_ = true;
}
+ void AddSoftVerifierFailure() {
+ number_of_soft_verifier_failures_++;
+ }
Compiler::Kind GetCompilerKind() {
return compiler_kind_;
@@ -519,6 +523,7 @@
// This option may be restricted to the boot image, depending on a flag in the implementation.
std::unique_ptr<std::unordered_set<std::string>> methods_to_compile_;
+ std::atomic<uint32_t> number_of_soft_verifier_failures_;
bool had_hard_verifier_failure_;
// A thread pool that can (potentially) run tasks in parallel.
diff --git a/compiler/driver/compiler_options.cc b/compiler/driver/compiler_options.cc
index b6cedff..f789314 100644
--- a/compiler/driver/compiler_options.cc
+++ b/compiler/driver/compiler_options.cc
@@ -51,6 +51,7 @@
compile_pic_(false),
verbose_methods_(),
abort_on_hard_verifier_failure_(false),
+ abort_on_soft_verifier_failure_(false),
init_failure_output_(nullptr),
dump_cfg_file_name_(""),
dump_cfg_append_(false),
diff --git a/compiler/driver/compiler_options.h b/compiler/driver/compiler_options.h
index 311dbd5..12de9be 100644
--- a/compiler/driver/compiler_options.h
+++ b/compiler/driver/compiler_options.h
@@ -226,6 +226,9 @@
bool AbortOnHardVerifierFailure() const {
return abort_on_hard_verifier_failure_;
}
+ bool AbortOnSoftVerifierFailure() const {
+ return abort_on_soft_verifier_failure_;
+ }
const std::vector<const DexFile*>* GetNoInlineFromDexFile() const {
return no_inline_from_;
@@ -303,6 +306,8 @@
// Abort compilation with an error if we find a class that fails verification with a hard
// failure.
bool abort_on_hard_verifier_failure_;
+ // Same for soft failures.
+ bool abort_on_soft_verifier_failure_;
// Log initialization of initialization failures to this stream if not null.
std::unique_ptr<std::ostream> init_failure_output_;
diff --git a/compiler/driver/compiler_options_map-inl.h b/compiler/driver/compiler_options_map-inl.h
index 9cb818a..772d1b4 100644
--- a/compiler/driver/compiler_options_map-inl.h
+++ b/compiler/driver/compiler_options_map-inl.h
@@ -60,6 +60,7 @@
}
map.AssignIfExists(Base::TopKProfileThreshold, &options->top_k_profile_threshold_);
map.AssignIfExists(Base::AbortOnHardVerifierFailure, &options->abort_on_hard_verifier_failure_);
+ map.AssignIfExists(Base::AbortOnSoftVerifierFailure, &options->abort_on_soft_verifier_failure_);
if (map.Exists(Base::DumpInitFailures)) {
if (!options->ParseDumpInitFailures(*map.Get(Base::DumpInitFailures), error_msg)) {
return false;
@@ -132,6 +133,9 @@
.Define({"--abort-on-hard-verifier-error", "--no-abort-on-hard-verifier-error"})
.WithValues({true, false})
.IntoKey(Map::AbortOnHardVerifierFailure)
+ .Define({"--abort-on-soft-verifier-error", "--no-abort-on-soft-verifier-error"})
+ .WithValues({true, false})
+ .IntoKey(Map::AbortOnSoftVerifierFailure)
.Define("--dump-init-failures=_")
.template WithType<std::string>()
diff --git a/compiler/driver/compiler_options_map.def b/compiler/driver/compiler_options_map.def
index 570bc5a..cc75634 100644
--- a/compiler/driver/compiler_options_map.def
+++ b/compiler/driver/compiler_options_map.def
@@ -50,6 +50,7 @@
COMPILER_OPTIONS_KEY (Unit, Debuggable)
COMPILER_OPTIONS_KEY (double, TopKProfileThreshold)
COMPILER_OPTIONS_KEY (bool, AbortOnHardVerifierFailure)
+COMPILER_OPTIONS_KEY (bool, AbortOnSoftVerifierFailure)
COMPILER_OPTIONS_KEY (std::string, DumpInitFailures)
COMPILER_OPTIONS_KEY (std::string, DumpCFG)
COMPILER_OPTIONS_KEY (Unit, DumpCFGAppend)