Another fix for the resolution trampoline and invokesuper.
We need to fully resolve the target method before updating the BSS.
Test: 811
Bug: 169047229
Change-Id: I2f3a6d60e3e44b00daea4af15c02b55e1c9098d6
diff --git a/runtime/entrypoints/quick/quick_trampoline_entrypoints.cc b/runtime/entrypoints/quick/quick_trampoline_entrypoints.cc
index 45c50b0..39987c1 100644
--- a/runtime/entrypoints/quick/quick_trampoline_entrypoints.cc
+++ b/runtime/entrypoints/quick/quick_trampoline_entrypoints.cc
@@ -1317,24 +1317,6 @@
DCHECK_EQ(caller->GetDexFile(), called_method.dex_file);
called = linker->ResolveMethod<ClassLinker::ResolveMode::kCheckICCEAndIAE>(
self, called_method.index, caller, invoke_type);
-
- // If successful, update .bss entry in oat file if any.
- if (called != nullptr) {
- // We only put non copied methods in the BSS. Putting a copy can lead to an
- // odd situation where the ArtMethod being executed is unrelated to the
- // receiver of the method.
- called = called->GetCanonicalMethod();
- if (invoke_type == kSuper) {
- if (called->GetDexFile() == called_method.dex_file) {
- called_method.index = called->GetDexMethodIndex();
- } else {
- called_method.index = called->FindDexMethodIndexInOtherDexFile(
- *called_method.dex_file, called_method.index);
- DCHECK_NE(called_method.index, dex::kDexNoIndex);
- }
- }
- MaybeUpdateBssMethodEntry(called, called_method);
- }
}
const void* code = nullptr;
if (LIKELY(!self->IsExceptionPending())) {
@@ -1368,6 +1350,24 @@
<< mirror::Object::PrettyTypeOf(receiver) << " "
<< invoke_type << " " << orig_called->GetVtableIndex();
}
+ // Now that we know the actual target, update .bss entry in oat file, if
+ // any.
+ if (!called_method_known_on_entry) {
+ // We only put non copied methods in the BSS. Putting a copy can lead to an
+ // odd situation where the ArtMethod being executed is unrelated to the
+ // receiver of the method.
+ called = called->GetCanonicalMethod();
+ if (invoke_type == kSuper) {
+ if (called->GetDexFile() == called_method.dex_file) {
+ called_method.index = called->GetDexMethodIndex();
+ } else {
+ called_method.index = called->FindDexMethodIndexInOtherDexFile(
+ *called_method.dex_file, called_method.index);
+ DCHECK_NE(called_method.index, dex::kDexNoIndex);
+ }
+ }
+ MaybeUpdateBssMethodEntry(called, called_method);
+ }
// Static invokes need class initialization check but instance invokes can proceed even if
// the class is erroneous, i.e. in the edge case of escaping instances of erroneous classes.