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.
diff --git a/test/811-checker-invoke-super-secondary/expected.txt b/test/811-checker-invoke-super-secondary/expected.txt
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/811-checker-invoke-super-secondary/expected.txt
diff --git a/test/811-checker-invoke-super-secondary/info.txt b/test/811-checker-invoke-super-secondary/info.txt
new file mode 100644
index 0000000..1de0057
--- /dev/null
+++ b/test/811-checker-invoke-super-secondary/info.txt
@@ -0,0 +1,2 @@
+Regression test when a super call resolves to a method from a different class
+loader.
diff --git a/test/811-checker-invoke-super-secondary/smali-ex/OtherClass.smali b/test/811-checker-invoke-super-secondary/smali-ex/OtherClass.smali
new file mode 100644
index 0000000..ba58b9c
--- /dev/null
+++ b/test/811-checker-invoke-super-secondary/smali-ex/OtherClass.smali
@@ -0,0 +1,34 @@
+# Copyright 2020 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+.class public LOtherClass;
+.super LOtherSuperClass;
+
+## CHECK-START: void OtherClass.$noinline$foo() register (after)
+## CHECK-DAG:     InvokeStaticOrDirect dex_file_index:<<Index1:\d+>> method_name:SuperSuperClass.$noinline$foo
+## CHECK-DAG:     InvokeStaticOrDirect dex_file_index:<<Index2:\d+>> method_name:SuperSuperClass.$noinline$foo
+## CHECK-EVAL:    <<Index1>> == <<Index2>>
+.method public $noinline$foo()V
+.registers 1
+    invoke-super {p0}, LOtherSuperClass;->$noinline$foo()V
+    invoke-super {p0}, LSuperSuperClass;->$noinline$foo()V
+    return-void
+.end method
+
+.method public constructor <init>()V
+    .registers 1
+    invoke-direct {p0}, Ljava/lang/Object;-><init>()V
+    return-void
+.end method
+
diff --git a/test/811-checker-invoke-super-secondary/smali-ex/OtherSuperClass.smali b/test/811-checker-invoke-super-secondary/smali-ex/OtherSuperClass.smali
new file mode 100644
index 0000000..4b444bb
--- /dev/null
+++ b/test/811-checker-invoke-super-secondary/smali-ex/OtherSuperClass.smali
@@ -0,0 +1,16 @@
+# Copyright 2020 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+.class public LOtherSuperClass;
+.super LSuperClass;
diff --git a/test/811-checker-invoke-super-secondary/smali/SuperClass.smali b/test/811-checker-invoke-super-secondary/smali/SuperClass.smali
new file mode 100644
index 0000000..016da13
--- /dev/null
+++ b/test/811-checker-invoke-super-secondary/smali/SuperClass.smali
@@ -0,0 +1,16 @@
+# Copyright 2020 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+.class public LSuperClass;
+.super LSuperSuperClass;
diff --git a/test/811-checker-invoke-super-secondary/smali/SuperSuperClass.smali b/test/811-checker-invoke-super-secondary/smali/SuperSuperClass.smali
new file mode 100644
index 0000000..4c4569e
--- /dev/null
+++ b/test/811-checker-invoke-super-secondary/smali/SuperSuperClass.smali
@@ -0,0 +1,21 @@
+# Copyright 2020 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+.class public LSuperSuperClass;
+.super Ljava/lang/Object;
+
+.method public $noinline$foo()V
+.registers 1
+    return-void
+.end method
diff --git a/test/811-checker-invoke-super-secondary/src/Main.java b/test/811-checker-invoke-super-secondary/src/Main.java
new file mode 100644
index 0000000..6c9fcc1
--- /dev/null
+++ b/test/811-checker-invoke-super-secondary/src/Main.java
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import dalvik.system.PathClassLoader;
+
+class Main {
+  static final String TEST_NAME = "811-checker-invoke-super-secondary";
+
+  static final String DEX_FILE = System.getenv("DEX_LOCATION") + "/" + TEST_NAME + ".jar";
+
+  static final String SECONDARY_NAME = TEST_NAME + "-ex";
+  static final String SECONDARY_DEX_FILE =
+    System.getenv("DEX_LOCATION") + "/" + SECONDARY_NAME + ".jar";
+
+  public static void main(String[] args) throws Exception {
+    PathClassLoader pcl = new PathClassLoader(SECONDARY_DEX_FILE, Main.class.getClassLoader());
+
+    Class<?> secondaryCls = pcl.loadClass("OtherClass");
+    secondaryCls.getDeclaredMethod("$noinline$foo").invoke(secondaryCls.newInstance());
+  }
+}
diff --git a/test/knownfailures.json b/test/knownfailures.json
index f5a825c..1e0663d 100644
--- a/test/knownfailures.json
+++ b/test/knownfailures.json
@@ -1134,6 +1134,7 @@
                   "808-checker-invoke-super",
                   "809-checker-invoke-super-bss",
                   "810-checker-invoke-super-default",
+                  "811-checker-invoke-super-secondary",
                   "999-redefine-hiddenapi",
                   "1000-non-moving-space-stress",
                   "1001-app-image-regions",