Fix VM test 077
Recognize incompatible class changes in resolution of direct methods.
Recognize incompatible changes to invokevirtual by rewriting in the
verifier.
Change-Id: Ie7d938bae39179d44ac3bedb575a3ccf73ac43b2
diff --git a/src/dex_verifier.cc b/src/dex_verifier.cc
index 6c415e6..9ba5d34 100644
--- a/src/dex_verifier.cc
+++ b/src/dex_verifier.cc
@@ -3085,8 +3085,8 @@
(method_type == METHOD_STATIC && !res_method->IsStatic()) ||
((method_type == METHOD_VIRTUAL || method_type == METHOD_INTERFACE) && res_method->IsDirect())
) {
- Fail(VERIFY_ERROR_GENERIC) << "invoke type does not match method type of "
- << PrettyMethod(res_method);
+ Fail(VERIFY_ERROR_CLASS_CHANGE) << "invoke type does not match method type of "
+ << PrettyMethod(res_method);
return NULL;
}
// If we're using invoke-super(method), make sure that the executing method's class' superclass
diff --git a/src/runtime_support.cc b/src/runtime_support.cc
index 3a3eaf1..1222626 100644
--- a/src/runtime_support.cc
+++ b/src/runtime_support.cc
@@ -407,12 +407,19 @@
// Resolve method filling in dex cache
Method* called = linker->ResolveMethod(method_idx, *caller_sp, true);
if (LIKELY(!thread->IsExceptionPending())) {
- // Update CodeAndDirectMethod table
- Method* caller = *caller_sp;
- DexCache* dex_cache = caller->GetDeclaringClass()->GetDexCache();
- dex_cache->GetCodeAndDirectMethods()->SetResolvedDirectMethod(method_idx, called);
- // We got this far, ensure that the declaring class is initialized
- linker->EnsureInitialized(called->GetDeclaringClass(), true);
+ if (LIKELY(called->IsDirect())) {
+ // Update CodeAndDirectMethod table
+ Method* caller = *caller_sp;
+ DexCache* dex_cache = caller->GetDeclaringClass()->GetDexCache();
+ dex_cache->GetCodeAndDirectMethods()->SetResolvedDirectMethod(method_idx, called);
+ // We got this far, ensure that the declaring class is initialized
+ linker->EnsureInitialized(called->GetDeclaringClass(), true);
+ } else {
+ // Direct method has been made virtual
+ thread->ThrowNewExceptionF("Ljava/lang/IncompatibleClassChangeError;",
+ "Expected direct method but found virtual: %s",
+ PrettyMethod(called, true).c_str());
+ }
}
void* code;
if (UNLIKELY(thread->IsExceptionPending())) {