Fix incompatible class change error for JIT stress mode
There was a problem with miranda methods, when we would dequicken to
one of these, it wouldn't resolve as virtual during the method
lowering resolve. The solution is to try resolving as interface if we
fail to resolve as virtual.
Fixed a bug in dequickening where unreachable register lines with
quick invokes would cause CHECK failuers. In this case we punt to the
interpreter (test 435-try-*).
Added test regression test. Example failure:
java.lang.IncompatibleClassChangeError: The method
'void Main$TheInterface.m()' was expected to be of type virtual but
instead was found to be of type interface (declaration of
'java.lang.reflect.ArtMethod' appears in
out/host/linux-x86/framework/core-libart-hostdex.jar)
at Main.DoStuff(Main.java:37)
at Main.main(Main.java:44)
Bug: 17950037
Change-Id: I39c32cc8849bf02032a4f61a7ce57462b7fcac75
diff --git a/compiler/dex/verified_method.cc b/compiler/dex/verified_method.cc
index 42d66be..5b90ba9 100644
--- a/compiler/dex/verified_method.cc
+++ b/compiler/dex/verified_method.cc
@@ -55,8 +55,8 @@
}
// Only need dequicken info for JIT so far.
- if (Runtime::Current()->UseJit()) {
- verified_method->GenerateDequickenMap(method_verifier);
+ if (Runtime::Current()->UseJit() && !verified_method->GenerateDequickenMap(method_verifier)) {
+ return nullptr;
}
}
@@ -194,9 +194,9 @@
*log2_max_gc_pc = i;
}
-void VerifiedMethod::GenerateDequickenMap(verifier::MethodVerifier* method_verifier) {
+bool VerifiedMethod::GenerateDequickenMap(verifier::MethodVerifier* method_verifier) {
if (method_verifier->HasFailures()) {
- return;
+ return false;
}
const DexFile::CodeItem* code_item = method_verifier->CodeItem();
const uint16_t* insns = code_item->insns_;
@@ -209,8 +209,11 @@
uint32_t dex_pc = inst->GetDexPc(insns);
verifier::RegisterLine* line = method_verifier->GetRegLine(dex_pc);
mirror::ArtMethod* method =
- method_verifier->GetQuickInvokedMethod(inst, line, is_range_quick);
- CHECK(method != nullptr);
+ method_verifier->GetQuickInvokedMethod(inst, line, is_range_quick, true);
+ if (method == nullptr) {
+ // It can be null if the line wasn't verified since it was unreachable.
+ return false;
+ }
// The verifier must know what the type of the object was or else we would have gotten a
// failure. Put the dex method index in the dequicken map since we need this to get number of
// arguments in the compiler.
@@ -220,7 +223,10 @@
uint32_t dex_pc = inst->GetDexPc(insns);
verifier::RegisterLine* line = method_verifier->GetRegLine(dex_pc);
mirror::ArtField* field = method_verifier->GetQuickFieldAccess(inst, line);
- CHECK(field != nullptr);
+ if (field == nullptr) {
+ // It can be null if the line wasn't verified since it was unreachable.
+ return false;
+ }
// The verifier must know what the type of the field was or else we would have gotten a
// failure. Put the dex field index in the dequicken map since we need this for lowering
// in the compiler.
@@ -228,6 +234,7 @@
dequicken_map_.Put(dex_pc, DexFileReference(field->GetDexFile(), field->GetDexFieldIndex()));
}
}
+ return true;
}
void VerifiedMethod::GenerateDevirtMap(verifier::MethodVerifier* method_verifier) {