Add a kTypeChecksFailure.
This is to distinguish between a soft failure due to type checks, or a
soft failure due to other reasons.
A follow-up CL will start using that information and use the type checks
in the vdex file to perform fast verification at runtime.
Test: test.py
Bug: 176960283
Change-Id: I04bff9ff26033f41e9439d366667a9aec1f339a0
diff --git a/dex2oat/dex2oat_test.cc b/dex2oat/dex2oat_test.cc
index c0dd84c..7854eaa 100644
--- a/dex2oat/dex2oat_test.cc
+++ b/dex2oat/dex2oat_test.cc
@@ -1351,7 +1351,7 @@
}
TEST_F(Dex2oatVerifierAbort, SoftFail) {
- // Use VerifierDepsMulti as it has hard-failing classes.
+ // Use VerifierDepsMulti as it has soft-failing classes.
std::unique_ptr<const DexFile> dex(OpenTestDexFile("VerifierDepsMulti"));
std::string out_dir = GetScratchDir();
const std::string base_oat_name = out_dir + "/base.oat";
diff --git a/dex2oat/driver/compiler_driver.cc b/dex2oat/driver/compiler_driver.cc
index 605953c..e23d1b0 100644
--- a/dex2oat/driver/compiler_driver.cc
+++ b/dex2oat/driver/compiler_driver.cc
@@ -2058,6 +2058,11 @@
manager_->GetCompiler()->AddSoftVerifierFailure();
break;
}
+ case verifier::FailureKind::kTypeChecksFailure: {
+ // Don't record anything, we will do the type checks from the vdex
+ // file at runtime.
+ break;
+ }
case verifier::FailureKind::kAccessChecksFailure: {
manager_->GetCompiler()->RecordClassStatus(ref, ClassStatus::kVerifiedNeedsAccessChecks);
break;
@@ -2118,7 +2123,8 @@
} else if (klass->IsVerifiedNeedsAccessChecks()) {
DCHECK_EQ(failure_kind, verifier::FailureKind::kAccessChecksFailure);
} else if (klass->ShouldVerifyAtRuntime()) {
- DCHECK_EQ(failure_kind, verifier::FailureKind::kSoftFailure);
+ DCHECK(failure_kind == verifier::FailureKind::kSoftFailure ||
+ failure_kind == verifier::FailureKind::kTypeChecksFailure);
} else {
DCHECK_EQ(failure_kind, verifier::FailureKind::kHardFailure);
}
diff --git a/openjdkjvmti/ti_redefine.cc b/openjdkjvmti/ti_redefine.cc
index 58c1c4e..12d00ad 100644
--- a/openjdkjvmti/ti_redefine.cc
+++ b/openjdkjvmti/ti_redefine.cc
@@ -1630,6 +1630,7 @@
return true;
case art::verifier::FailureKind::kSoftFailure:
case art::verifier::FailureKind::kAccessChecksFailure:
+ case art::verifier::FailureKind::kTypeChecksFailure:
// Soft failures might require interpreter on some methods. It won't prevent redefinition but
// it does mean we need to run the verifier again and potentially update method flags after
// performing the swap.
diff --git a/runtime/class_linker.cc b/runtime/class_linker.cc
index d00c721..9cde319 100644
--- a/runtime/class_linker.cc
+++ b/runtime/class_linker.cc
@@ -4655,12 +4655,14 @@
}
} else {
CHECK(verifier_failure == verifier::FailureKind::kSoftFailure ||
+ verifier_failure == verifier::FailureKind::kTypeChecksFailure ||
verifier_failure == verifier::FailureKind::kAccessChecksFailure);
// Soft failures at compile time should be retried at runtime. Soft
// failures at runtime will be handled by slow paths in the generated
// code. Set status accordingly.
if (Runtime::Current()->IsAotCompiler()) {
- if (verifier_failure == verifier::FailureKind::kSoftFailure) {
+ if (verifier_failure == verifier::FailureKind::kSoftFailure ||
+ verifier_failure == verifier::FailureKind::kTypeChecksFailure) {
mirror::Class::SetStatus(klass, ClassStatus::kRetryVerificationAtRuntime, self);
} else {
mirror::Class::SetStatus(klass, ClassStatus::kVerifiedNeedsAccessChecks, self);
diff --git a/runtime/verifier/method_verifier.cc b/runtime/verifier/method_verifier.cc
index 017846b..c2ad314 100644
--- a/runtime/verifier/method_verifier.cc
+++ b/runtime/verifier/method_verifier.cc
@@ -5176,6 +5176,7 @@
// The AOT/JIT compiled code is not affected.
static inline bool CanRuntimeHandleVerificationFailure(uint32_t encountered_failure_types) {
constexpr uint32_t unresolved_mask =
+ verifier::VerifyError::VERIFY_ERROR_UNRESOLVED_TYPE_CHECK |
verifier::VerifyError::VERIFY_ERROR_NO_CLASS |
verifier::VerifyError::VERIFY_ERROR_CLASS_CHANGE |
verifier::VerifyError::VERIFY_ERROR_INSTANTIATION |
@@ -5250,7 +5251,11 @@
verifier.Dump(LOG_STREAM(INFO));
}
if (CanRuntimeHandleVerificationFailure(verifier.encountered_failure_types_)) {
- result.kind = FailureKind::kAccessChecksFailure;
+ if (verifier.encountered_failure_types_ & VERIFY_ERROR_UNRESOLVED_TYPE_CHECK) {
+ result.kind = FailureKind::kTypeChecksFailure;
+ } else {
+ result.kind = FailureKind::kAccessChecksFailure;
+ }
} else {
result.kind = FailureKind::kSoftFailure;
}
@@ -5565,7 +5570,7 @@
// This will be reported to the runtime as a soft failure.
break;
- // Indication that verification should be retried at runtime.
+ // Indication that verification should be retried at runtime.
case VERIFY_ERROR_BAD_CLASS_SOFT:
if (!allow_soft_failures_) {
flags_.have_pending_hard_failure_ = true;
diff --git a/runtime/verifier/verifier_deps.cc b/runtime/verifier/verifier_deps.cc
index e104d34..0fdc8c6 100644
--- a/runtime/verifier/verifier_deps.cc
+++ b/runtime/verifier/verifier_deps.cc
@@ -300,6 +300,7 @@
break;
}
case verifier::FailureKind::kAccessChecksFailure:
+ case verifier::FailureKind::kTypeChecksFailure:
case verifier::FailureKind::kNoFailure: {
thread_deps->RecordClassVerified(dex_file, class_def);
break;
diff --git a/runtime/verifier/verifier_enums.h b/runtime/verifier/verifier_enums.h
index e3c50aa..16bf004 100644
--- a/runtime/verifier/verifier_enums.h
+++ b/runtime/verifier/verifier_enums.h
@@ -33,6 +33,7 @@
enum class FailureKind {
kNoFailure,
kAccessChecksFailure,
+ kTypeChecksFailure,
kSoftFailure,
kHardFailure,
};
diff --git a/test/VerifierDepsMulti/MySoftVerificationFailure.smali b/test/VerifierDepsMulti/MySoftVerificationFailure.smali
index 6b56a3b..2bede45 100644
--- a/test/VerifierDepsMulti/MySoftVerificationFailure.smali
+++ b/test/VerifierDepsMulti/MySoftVerificationFailure.smali
@@ -17,8 +17,9 @@
.method public final foo()V
.registers 1
- sget-object v0, LMySoftVerificationFailure;->error:LUnknownType;
+ sget-object v0, LMySoftVerificationFailure;->error:Ljava/lang/Object;
+ # Throwing a non-exception class is a soft failure.
throw v0
.end method
-.field public static error:LUnknownType;
+.field public static error:Ljava/lang/Object;