Implement first kind of polymorphic inlining.
Add HClassTableGet to fetch an ArtMethod from the vtable or imt,
and compare it to the only method the profiling saw.
Change-Id: I76afd3689178f10e3be048aa3ac9a97c6f63295d
diff --git a/test/566-polymorphic-inlining/expected.txt b/test/566-polymorphic-inlining/expected.txt
new file mode 100644
index 0000000..6a5618e
--- /dev/null
+++ b/test/566-polymorphic-inlining/expected.txt
@@ -0,0 +1 @@
+JNI_OnLoad called
diff --git a/test/566-polymorphic-inlining/info.txt b/test/566-polymorphic-inlining/info.txt
new file mode 100644
index 0000000..1a47f89
--- /dev/null
+++ b/test/566-polymorphic-inlining/info.txt
@@ -0,0 +1 @@
+Test polymorphic inlining.
diff --git a/test/566-polymorphic-inlining/polymorphic_inline.cc b/test/566-polymorphic-inlining/polymorphic_inline.cc
new file mode 100644
index 0000000..5801b36
--- /dev/null
+++ b/test/566-polymorphic-inlining/polymorphic_inline.cc
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2016 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.
+ */
+
+#include "art_method.h"
+#include "jit/jit.h"
+#include "jit/jit_code_cache.h"
+#include "oat_quick_method_header.h"
+#include "scoped_thread_state_change.h"
+#include "stack_map.h"
+
+namespace art {
+
+static void do_checks(jclass cls, const char* method_name) {
+ ScopedObjectAccess soa(Thread::Current());
+ mirror::Class* klass = soa.Decode<mirror::Class*>(cls);
+ jit::Jit* jit = Runtime::Current()->GetJit();
+ jit::JitCodeCache* code_cache = jit->GetCodeCache();
+ ArtMethod* method = klass->FindDeclaredDirectMethodByName(method_name, sizeof(void*));
+ OatQuickMethodHeader* header = OatQuickMethodHeader::FromEntryPoint(
+ method->GetEntryPointFromQuickCompiledCode());
+ CHECK(code_cache->ContainsPc(header->GetCode()));
+
+ CodeInfo info = header->GetOptimizedCodeInfo();
+ CHECK(info.HasInlineInfo());
+}
+
+extern "C" JNIEXPORT void JNICALL Java_Main_ensureJittedAndPolymorphicInline(JNIEnv*, jclass cls) {
+ jit::Jit* jit = Runtime::Current()->GetJit();
+ if (jit == nullptr) {
+ return;
+ }
+
+ do_checks(cls, "testInvokeVirtual");
+ do_checks(cls, "testInvokeInterface");
+}
+
+} // namespace art
diff --git a/test/566-polymorphic-inlining/src/Main.java b/test/566-polymorphic-inlining/src/Main.java
new file mode 100644
index 0000000..7283e86
--- /dev/null
+++ b/test/566-polymorphic-inlining/src/Main.java
@@ -0,0 +1,95 @@
+/*
+ * Copyright (C) 2016 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 Class sameInvokeInterface();
+}
+
+public class Main implements Itf {
+ public static void assertEquals(Object expected, Object actual) {
+ if (expected != actual) {
+ throw new Error("Expected " + expected + ", got " + actual);
+ }
+ }
+
+ public static void main(String[] args) throws Exception {
+ System.loadLibrary(args[0]);
+ Main[] mains = new Main[3];
+ Itf[] itfs = new Itf[3];
+ itfs[0] = mains[0] = new Main();
+ itfs[1] = mains[1] = new Subclass();
+ itfs[2] = mains[2] = new OtherSubclass();
+
+ // Make testInvokeVirtual and testInvokeInterface hot to get them jitted.
+ // We pass Main and Subclass to get polymorphic inlining based on calling
+ // the same method.
+ for (int i = 0; i < 10000; ++i) {
+ testInvokeVirtual(mains[0]);
+ testInvokeVirtual(mains[1]);
+ testInvokeInterface(itfs[0]);
+ testInvokeInterface(itfs[1]);
+ }
+
+ ensureJittedAndPolymorphicInline();
+
+ // At this point, the JIT should have compiled both methods, and inline
+ // sameInvokeVirtual and sameInvokeInterface.
+ assertEquals(Main.class, testInvokeVirtual(mains[0]));
+ assertEquals(Main.class, testInvokeVirtual(mains[1]));
+
+ assertEquals(Itf.class, testInvokeInterface(itfs[0]));
+ assertEquals(Itf.class, testInvokeInterface(itfs[1]));
+
+ // This will trigger a deoptimization of the compiled code.
+ assertEquals(OtherSubclass.class, testInvokeVirtual(mains[2]));
+ assertEquals(OtherSubclass.class, testInvokeInterface(itfs[2]));
+ }
+
+ public Class sameInvokeVirtual() {
+ field.getClass(); // null check to ensure we get an inlined frame in the CodeInfo
+ return Main.class;
+ }
+
+ public Class sameInvokeInterface() {
+ field.getClass(); // null check to ensure we get an inlined frame in the CodeInfo
+ return Itf.class;
+ }
+
+ public static Class testInvokeInterface(Itf i) {
+ return i.sameInvokeInterface();
+ }
+
+ public static Class testInvokeVirtual(Main m) {
+ return m.sameInvokeVirtual();
+ }
+
+ public Object field = new Object();
+
+ public static native void ensureJittedAndPolymorphicInline();
+}
+
+class Subclass extends Main {
+}
+
+class OtherSubclass extends Main {
+ public Class sameInvokeVirtual() {
+ return OtherSubclass.class;
+ }
+
+ public Class sameInvokeInterface() {
+ return OtherSubclass.class;
+ }
+}
diff --git a/test/Android.libarttest.mk b/test/Android.libarttest.mk
index b922b45..faaf1f0 100644
--- a/test/Android.libarttest.mk
+++ b/test/Android.libarttest.mk
@@ -39,7 +39,8 @@
461-get-reference-vreg/get_reference_vreg_jni.cc \
466-get-live-vreg/get_live_vreg_jni.cc \
497-inlining-and-class-loader/clear_dex_cache.cc \
- 543-env-long-ref/env_long_ref.cc
+ 543-env-long-ref/env_long_ref.cc \
+ 566-polymorphic-inlining/polymorphic_inline.cc
ART_TARGET_LIBARTTEST_$(ART_PHONY_TEST_TARGET_SUFFIX) += $(ART_TARGET_TEST_OUT)/$(TARGET_ARCH)/libarttest.so
ART_TARGET_LIBARTTEST_$(ART_PHONY_TEST_TARGET_SUFFIX) += $(ART_TARGET_TEST_OUT)/$(TARGET_ARCH)/libarttestd.so