Correctly handle non-invokable methods in InitializeMethodsCode

Non-invokable methods were handled correctly when there is no
instrumentation but it was not obvious or explicitly handled. For ex: we
could still install AOT code but we never pass AOT code for
non-invokable methods. When instrumentation was enabled, non-invokable
methods weren't handled correctly. This CL makes the handling explicit
by initializing the entrypoint to QuickToInterpreterEntryBridge.

Bug: 206029744
Test: art/testrunner.py -t 2240-tracing-non-invokable-method
Change-Id: Idf2e95e29791d0e4244afa5dfe36e5b78649853c
diff --git a/openjdkjvmti/events.cc b/openjdkjvmti/events.cc
index e23beec..82165d0 100644
--- a/openjdkjvmti/events.cc
+++ b/openjdkjvmti/events.cc
@@ -1255,7 +1255,7 @@
       }
       for (auto& m : klass->GetMethods(art::kRuntimePointerSize)) {
         const void* code = m.GetEntryPointFromQuickCompiledCode();
-        if (m.IsNative() || m.IsProxyMethod()) {
+        if (m.IsNative() || m.IsProxyMethod() || !m.IsInvokable()) {
           continue;
         } else if (!runtime_->GetClassLinker()->IsQuickToInterpreterBridge(code) &&
                    !runtime_->IsAsyncDeoptimizeable(&m, reinterpret_cast<uintptr_t>(code))) {
diff --git a/runtime/instrumentation.cc b/runtime/instrumentation.cc
index f4584ad..6c6ecb7 100644
--- a/runtime/instrumentation.cc
+++ b/runtime/instrumentation.cc
@@ -356,6 +356,13 @@
 
 void Instrumentation::InitializeMethodsCode(ArtMethod* method, const void* aot_code)
     REQUIRES_SHARED(Locks::mutator_lock_) {
+  if (!method->IsInvokable()) {
+    DCHECK(method->GetEntryPointFromQuickCompiledCode() == nullptr ||
+           Runtime::Current()->GetClassLinker()->IsQuickToInterpreterBridge(
+               method->GetEntryPointFromQuickCompiledCode()));
+    UpdateEntryPoints(method, GetQuickToInterpreterBridge());
+  }
+
   // Use instrumentation entrypoints if instrumentation is installed.
   if (UNLIKELY(EntryExitStubsInstalled()) && !IsProxyInit(method)) {
     if (!method->IsNative() && InterpretOnly(method)) {
diff --git a/runtime/runtime.cc b/runtime/runtime.cc
index 6bb0049..4b161c6 100644
--- a/runtime/runtime.cc
+++ b/runtime/runtime.cc
@@ -3201,6 +3201,9 @@
     auto pointer_size = Runtime::Current()->GetClassLinker()->GetImagePointerSize();
     for (auto& m : klass->GetMethods(pointer_size)) {
       const void* code = m.GetEntryPointFromQuickCompiledCode();
+      if (!m.IsInvokable()) {
+        continue;
+      }
       // For java debuggable runtimes we also deoptimize native methods. For other cases (boot
       // image profiling) we don't need to deoptimize native methods. If this changes also
       // update Instrumentation::CanUseAotCode.
diff --git a/test/2240-tracing-non-invokable-method/expected-stderr.txt b/test/2240-tracing-non-invokable-method/expected-stderr.txt
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/2240-tracing-non-invokable-method/expected-stderr.txt
diff --git a/test/2240-tracing-non-invokable-method/expected-stdout.txt b/test/2240-tracing-non-invokable-method/expected-stdout.txt
new file mode 100644
index 0000000..6a5618e
--- /dev/null
+++ b/test/2240-tracing-non-invokable-method/expected-stdout.txt
@@ -0,0 +1 @@
+JNI_OnLoad called
diff --git a/test/2240-tracing-non-invokable-method/info.txt b/test/2240-tracing-non-invokable-method/info.txt
new file mode 100644
index 0000000..27877aa
--- /dev/null
+++ b/test/2240-tracing-non-invokable-method/info.txt
@@ -0,0 +1,2 @@
+Tests that tracing handles non-invokable methods correctly without updating the
+entrypoints for non-invokable methods.
diff --git a/test/2240-tracing-non-invokable-method/run b/test/2240-tracing-non-invokable-method/run
new file mode 100755
index 0000000..1f7edfc
--- /dev/null
+++ b/test/2240-tracing-non-invokable-method/run
@@ -0,0 +1,17 @@
+#!/bin/bash
+#
+# Copyright 2022 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.
+
+./default-run "$@" --runtime-option -Xmethod-trace --runtime-option -Xmethod-trace-file:/dev/null
diff --git a/test/2240-tracing-non-invokable-method/src/Main.java b/test/2240-tracing-non-invokable-method/src/Main.java
new file mode 100644
index 0000000..e5a4e43
--- /dev/null
+++ b/test/2240-tracing-non-invokable-method/src/Main.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2022 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.
+ */
+
+interface Itf {
+  public default void m() throws Exception {
+    throw new Exception("Don't inline me");
+  }
+  public default void mConflict() throws Exception {
+    throw new Exception("Don't inline me");
+  }
+}
+
+// This is redefined in src2 with a mConflict method.
+interface Itf2 {
+}
+
+public class Main implements Itf, Itf2 {
+
+  public static void main(String[] args) {
+    System.loadLibrary(args[0]);
+
+    try {
+      itf.mConflict();
+      throw new Error("Expected IncompatibleClassChangeError");
+    } catch (Exception e) {
+      throw new Error("Unexpected exception");
+    } catch (IncompatibleClassChangeError e) {
+      // Expected.
+    }
+  }
+
+  static Itf itf = new Main();
+}
diff --git a/test/2240-tracing-non-invokable-method/src2/Itf2.java b/test/2240-tracing-non-invokable-method/src2/Itf2.java
new file mode 100644
index 0000000..e962411
--- /dev/null
+++ b/test/2240-tracing-non-invokable-method/src2/Itf2.java
@@ -0,0 +1,20 @@
+/*
+ * Copyright (C) 2022 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.
+ */
+
+interface Itf2 {
+  public default void mConflict(){
+  }
+}
diff --git a/test/knownfailures.json b/test/knownfailures.json
index 5f67734..2971b27 100644
--- a/test/knownfailures.json
+++ b/test/knownfailures.json
@@ -1211,7 +1211,8 @@
                   "2036-structural-subclass-shadow",
                   "2038-hiddenapi-jvmti-ext",
                   "2040-huge-native-alloc",
-                  "2238-checker-polymorphic-recursive-inlining"],
+                  "2238-checker-polymorphic-recursive-inlining",
+                  "2240-tracing-non-invokable-method"],
         "variant": "jvm",
         "description": ["Doesn't run on RI."]
     },