Optimizing compiler support for directly calling interface methods
This teaches the optimizing compiler how to perform invoke-super on
interfaces. This should make the invokes generally faster.
Bug: 24618811
Change-Id: I7f9b0fb1209775c1c8837ab5d21f8acba3cc72a5
diff --git a/test/563-checker-invoke-super/build b/test/563-checker-invoke-super/build
new file mode 100755
index 0000000..e06193b
--- /dev/null
+++ b/test/563-checker-invoke-super/build
@@ -0,0 +1,28 @@
+#!/bin/bash
+#
+# Copyright 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.
+# Make us exit on a failure.
+#
+set -e
+
+# Hard-wired use of experimental jack.
+# TODO: fix this temporary work-around for lambdas, see b/19467889
+export USE_JACK=true
+export JACK_SERVER=false
+export JACK_REPOSITORY="${ANDROID_BUILD_TOP}/prebuilts/sdk/tools/jacks"
+
+# e.g. /foo/bar/jack-3.10.ALPHA.jar -> 3.10.ALPHA
+export JACK_VERSION="$(find "$JACK_REPOSITORY" -name '*ALPHA*' | sed 's/.*jack-//g' | sed 's/[.]jar//g')"
+./default-build "$@" --experimental default-methods
diff --git a/test/563-checker-invoke-super/expected.txt b/test/563-checker-invoke-super/expected.txt
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/563-checker-invoke-super/expected.txt
diff --git a/test/563-checker-invoke-super/info.txt b/test/563-checker-invoke-super/info.txt
new file mode 100644
index 0000000..23c0d2f
--- /dev/null
+++ b/test/563-checker-invoke-super/info.txt
@@ -0,0 +1,2 @@
+Tests that invoke-super's to interface methods are optimized to direct method
+calls when in the same dex file.
diff --git a/test/563-checker-invoke-super/src/Main.java b/test/563-checker-invoke-super/src/Main.java
new file mode 100644
index 0000000..8554dbd
--- /dev/null
+++ b/test/563-checker-invoke-super/src/Main.java
@@ -0,0 +1,39 @@
+/*
+ * 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 IFace {
+ public default void $noinline$aMethod() { throw new RuntimeException("Should not be called"); }
+}
+
+class ClassImplA implements IFace {
+ /// CHECK-START: void ClassImplA.testSuperInvoke() builder (after)
+ /// CHECK: InvokeStaticOrDirect
+ public void testSuperInvoke() {
+ IFace.super.$noinline$aMethod();
+ }
+}
+
+class ClassImplB extends ClassImplA {
+ /// CHECK-START: void ClassImplB.testSuperInvoke2() builder (after)
+ /// CHECK: InvokeStaticOrDirect
+ public void testSuperInvoke2() {
+ super.$noinline$aMethod();
+ }
+}
+
+public class Main {
+ public static void main(String[] args) { }
+}
diff --git a/test/972-iface-super-multidex/expected.txt b/test/972-iface-super-multidex/expected.txt
new file mode 100644
index 0000000..a9d31a5
--- /dev/null
+++ b/test/972-iface-super-multidex/expected.txt
@@ -0,0 +1,2 @@
+SuperInterface default method called
+Expected ICCE caught
diff --git a/test/972-iface-super-multidex/info.txt b/test/972-iface-super-multidex/info.txt
new file mode 100644
index 0000000..f7948ad
--- /dev/null
+++ b/test/972-iface-super-multidex/info.txt
@@ -0,0 +1,3 @@
+Smali-based tests for experimental interface default methods.
+
+Obviously needs to run under ART or a Java 8 Language runtime and compiler.
diff --git a/test/972-iface-super-multidex/smali-multidex/conflictinterface.smali b/test/972-iface-super-multidex/smali-multidex/conflictinterface.smali
new file mode 100644
index 0000000..2c76213
--- /dev/null
+++ b/test/972-iface-super-multidex/smali-multidex/conflictinterface.smali
@@ -0,0 +1,23 @@
+#
+# 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.
+
+
+.class public abstract interface LConflictInterface;
+.super Ljava/lang/Object;
+.implements LOneConflict;
+.implements LTwoConflict;
+
+# public interface ConflictInterface extends OneConflict, TwoConflict {
+# }
diff --git a/test/972-iface-super-multidex/smali-multidex/oneconflict.smali b/test/972-iface-super-multidex/smali-multidex/oneconflict.smali
new file mode 100644
index 0000000..7001f02
--- /dev/null
+++ b/test/972-iface-super-multidex/smali-multidex/oneconflict.smali
@@ -0,0 +1,31 @@
+#
+# 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.
+
+
+.class public abstract interface LOneConflict;
+.super Ljava/lang/Object;
+
+# public interface OneConflict {
+# public String runDefault() {
+# return "OneConflict default method called";
+# }
+# }
+
+.method public runDefault()Ljava/lang/String;
+.registers 2
+ # Do an invoke super on this class, to confuse runtime/compiler.
+ const-string v0, "OneConflict default method called"
+ return-object v0
+.end method
diff --git a/test/972-iface-super-multidex/smali-multidex/superinterface.smali b/test/972-iface-super-multidex/smali-multidex/superinterface.smali
new file mode 100644
index 0000000..d45ecea
--- /dev/null
+++ b/test/972-iface-super-multidex/smali-multidex/superinterface.smali
@@ -0,0 +1,31 @@
+#
+# 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.
+
+
+.class public abstract interface LSuperInterface;
+.super Ljava/lang/Object;
+
+# public interface SuperInterface {
+# public String runDefault() {
+# return "SuperInterface default method called";
+# }
+# }
+
+.method public runDefault()Ljava/lang/String;
+.registers 2
+ # Do an invoke super on this class, to confuse runtime/compiler.
+ const-string v0, "SuperInterface default method called"
+ return-object v0
+.end method
diff --git a/test/972-iface-super-multidex/smali-multidex/twoconflict.smali b/test/972-iface-super-multidex/smali-multidex/twoconflict.smali
new file mode 100644
index 0000000..b971b74
--- /dev/null
+++ b/test/972-iface-super-multidex/smali-multidex/twoconflict.smali
@@ -0,0 +1,31 @@
+#
+# 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.
+
+
+.class public abstract interface LTwoConflict;
+.super Ljava/lang/Object;
+
+# public interface TwoConflict {
+# public String runDefault() {
+# return "TwoConflict default method called";
+# }
+# }
+
+.method public runDefault()Ljava/lang/String;
+.registers 2
+ # Do an invoke super on this class, to confuse runtime/compiler.
+ const-string v0, "TwoConflict default method called"
+ return-object v0
+.end method
diff --git a/test/972-iface-super-multidex/smali/concreteclass.smali b/test/972-iface-super-multidex/smali/concreteclass.smali
new file mode 100644
index 0000000..703da94
--- /dev/null
+++ b/test/972-iface-super-multidex/smali/concreteclass.smali
@@ -0,0 +1,62 @@
+#
+# 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.
+
+
+.class public LConcreteClass;
+.super Ljava/lang/Object;
+.implements LSuperInterface;
+.implements LConflictInterface;
+
+# public class ConcreteClass implements SuperInterface, ConflictInterface {
+# public String runReal() {
+# return SuperInterface.super.runDefault();
+# }
+# public String runConflict() {
+# return ConflictInterface.super.runDefault();
+# }
+# public String runDefault() {
+# return "This is the wrong class to invoke";
+# }
+# }
+
+.method public constructor <init>()V
+ .registers 1
+ invoke-direct {p0}, Ljava/lang/Object;-><init>()V
+ return-void
+.end method
+
+.method public runConflict()Ljava/lang/String;
+.registers 2
+ # Do an invoke super on this class, to confuse runtime/compiler.
+ invoke-super {p0}, LConflictInterface;->runDefault()Ljava/lang/String;
+ move-result-object v0
+ return-object v0
+.end method
+
+
+
+.method public runReal()Ljava/lang/String;
+.registers 2
+ # Do an invoke super on this class, to confuse runtime/compiler.
+ invoke-super {p0}, LSuperInterface;->runDefault()Ljava/lang/String;
+ move-result-object v0
+ return-object v0
+.end method
+
+.method public runDefault()Ljava/lang/String;
+.registers 2
+ const-string v0, "This is the wrong class to invoke!"
+ return-object v0
+.end method
diff --git a/test/972-iface-super-multidex/src/Main.java b/test/972-iface-super-multidex/src/Main.java
new file mode 100644
index 0000000..3fb3f45
--- /dev/null
+++ b/test/972-iface-super-multidex/src/Main.java
@@ -0,0 +1,55 @@
+/*
+ * Copyright 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.
+ */
+
+import java.lang.reflect.*;
+public class Main {
+ public static void main(String[] args) {
+ Class<?> c = null;
+ try {
+ c = Class.forName("ConcreteClass");
+ } catch (Exception e) {
+ System.out.println("Could not load class");
+ e.printStackTrace();
+ return;
+ }
+ try {
+ Method m = c.getMethod("runReal");
+ System.out.println((String)m.invoke(c.newInstance(), new Object[0]));
+ } catch (Exception e) {
+ System.out.println("Unknown exception occurred");
+ e.printStackTrace();
+ }
+ try {
+ Method m = c.getMethod("runConflict");
+ try {
+ System.out.println((String)m.invoke(c.newInstance(), new Object[0]));
+ } catch (InvocationTargetException e) {
+ throw e.getCause();
+ }
+ } catch (AbstractMethodError e) {
+ System.out.println("Unexpected AME caught");
+ e.printStackTrace();
+ } catch (NoSuchMethodError e) {
+ System.out.println("Unexpected NSME caught");
+ e.printStackTrace();
+ } catch (IncompatibleClassChangeError e) {
+ System.out.println("Expected ICCE caught");
+ } catch (Throwable e) {
+ System.out.println("Unknown exception caught!");
+ e.printStackTrace();
+ }
+ }
+}
diff --git a/test/etc/default-build b/test/etc/default-build
index 7242428..6e855ec 100755
--- a/test/etc/default-build
+++ b/test/etc/default-build
@@ -42,6 +42,12 @@
HAS_SRC_MULTIDEX=false
fi
+if [ -d smali-multidex ]; then
+ HAS_SMALI_MULTIDEX=true
+else
+ HAS_SMALI_MULTIDEX=false
+fi
+
if [ -d src-ex ]; then
HAS_SRC_EX=true
else
@@ -74,6 +80,9 @@
elif [ "x$1" = "x--no-src-multidex" ]; then
HAS_SRC_MULTIDEX=false
shift
+ elif [ "x$1" = "x--no-smali-multidex" ]; then
+ HAS_SMALI_MULTIDEX=false
+ shift
elif [ "x$1" = "x--no-src-ex" ]; then
HAS_SRC_EX=false
shift
@@ -171,6 +180,19 @@
fi
fi
+if [ "${HAS_SMALI_MULTIDEX}" = "true" ]; then
+ # Compile Smali classes
+ ${SMALI} -JXmx512m ${SMALI_ARGS} --output smali_classes2.dex `find smali-multidex -name '*.smali'`
+
+ # Don't bother with dexmerger if we provide our own main function in a smali file.
+ if [ ${HAS_SRC_MULTIDEX} = "true" ]; then
+ ${DXMERGER} classes2.dex classes2.dex smali_classes2.dex
+ else
+ mv smali_classes2.dex classes2.dex
+ fi
+fi
+
+
if [ ${HAS_SRC_EX} = "true" ]; then
if [ ${USE_JACK} = "true" ]; then
# Rename previous "classes.dex" so it is not overwritten.
@@ -198,7 +220,7 @@
fi
# Create a single jar with two dex files for multidex.
-if [ ${HAS_SRC_MULTIDEX} = "true" ]; then
+if [ ${HAS_SRC_MULTIDEX} = "true" ] || [ ${HAS_SMALI_MULTIDEX} = "true" ]; then
zip $TEST_NAME.jar classes.dex classes2.dex
elif [ ${NEED_DEX} = "true" ]; then
zip $TEST_NAME.jar classes.dex