summaryrefslogtreecommitdiff
path: root/test
diff options
context:
space:
mode:
Diffstat (limited to 'test')
-rw-r--r--test/529-checker-unresolved/build48
-rw-r--r--test/529-checker-unresolved/expected.txt5
-rw-r--r--test/529-checker-unresolved/info.txt1
-rw-r--r--test/529-checker-unresolved/run18
-rw-r--r--test/529-checker-unresolved/src/Main.java56
-rw-r--r--test/529-checker-unresolved/src/Unresolved.java54
-rw-r--r--test/530-checker-loops/expected.txt0
-rw-r--r--test/530-checker-loops/info.txt1
-rw-r--r--test/530-checker-loops/src/Main.java354
-rwxr-xr-xtest/etc/run-test-jar5
10 files changed, 542 insertions, 0 deletions
diff --git a/test/529-checker-unresolved/build b/test/529-checker-unresolved/build
new file mode 100644
index 0000000000..8c3c4f8952
--- /dev/null
+++ b/test/529-checker-unresolved/build
@@ -0,0 +1,48 @@
+#!/bin/bash
+#
+# Copyright (C) 2015 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.
+
+# Stop if something fails.
+set -e
+
+# We can't use src-ex testing infrastructure because src and src-ex are compiled
+# with javac independetely and can't share code (without reflection).
+
+mkdir classes
+${JAVAC} -d classes `find src -name '*.java'`
+
+mkdir classes-ex
+mv classes/UnresolvedClass.class classes-ex
+mv classes/UnresolvedInterface.class classes-ex
+mv classes/UnresolvedSuperClass.class classes-ex
+
+if [ ${USE_JACK} = "true" ]; then
+ # Create .jack files from classes generated with javac.
+ ${JILL} classes --output classes.jack
+ ${JILL} classes-ex --output classes-ex.jack
+
+ # Create DEX files from .jack files.
+ ${JACK} --import classes.jack --output-dex .
+ zip $TEST_NAME.jar classes.dex
+ ${JACK} --import classes-ex.jack --output-dex .
+ zip ${TEST_NAME}-ex.jar classes.dex
+else
+ if [ ${NEED_DEX} = "true" ]; then
+ ${DX} -JXmx256m --debug --dex --dump-to=classes.lst --output=classes.dex --dump-width=1000 classes
+ zip $TEST_NAME.jar classes.dex
+ ${DX} -JXmx256m --debug --dex --dump-to=classes-ex.lst --output=classes.dex --dump-width=1000 classes-ex
+ zip ${TEST_NAME}-ex.jar classes.dex
+ fi
+fi
diff --git a/test/529-checker-unresolved/expected.txt b/test/529-checker-unresolved/expected.txt
new file mode 100644
index 0000000000..358048c75b
--- /dev/null
+++ b/test/529-checker-unresolved/expected.txt
@@ -0,0 +1,5 @@
+UnresolvedClass.directCall()
+UnresolvedClass.staticMethod()
+UnresolvedClass.virtualMethod()
+UnresolvedClass.interfaceMethod()
+UnresolvedClass.superMethod()
diff --git a/test/529-checker-unresolved/info.txt b/test/529-checker-unresolved/info.txt
new file mode 100644
index 0000000000..14efcc07e1
--- /dev/null
+++ b/test/529-checker-unresolved/info.txt
@@ -0,0 +1 @@
+Test calling of unresolved methods.
diff --git a/test/529-checker-unresolved/run b/test/529-checker-unresolved/run
new file mode 100644
index 0000000000..63fdb8c749
--- /dev/null
+++ b/test/529-checker-unresolved/run
@@ -0,0 +1,18 @@
+#!/bin/bash
+#
+# Copyright (C) 2015 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.
+
+# Use secondary switch to add secondary dex file to class path.
+exec ${RUN} "${@}" --secondary
diff --git a/test/529-checker-unresolved/src/Main.java b/test/529-checker-unresolved/src/Main.java
new file mode 100644
index 0000000000..6f047974b3
--- /dev/null
+++ b/test/529-checker-unresolved/src/Main.java
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2015 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.
+ */
+
+public class Main extends UnresolvedSuperClass {
+
+ /// CHECK-START: void Main.callInvokeUnresolvedStatic() register (before)
+ /// CHECK: InvokeUnresolved invoke_type:static
+ static public void callInvokeUnresolvedStatic() {
+ UnresolvedClass.staticMethod();
+ }
+
+ /// CHECK-START: void Main.callInvokeUnresolvedVirtual(UnresolvedClass) register (before)
+ /// CHECK: InvokeUnresolved invoke_type:virtual
+ static public void callInvokeUnresolvedVirtual(UnresolvedClass c) {
+ c.virtualMethod();
+ }
+
+ /// CHECK-START: void Main.callInvokeUnresolvedInterface(UnresolvedInterface) register (before)
+ /// CHECK: InvokeUnresolved invoke_type:interface
+ static public void callInvokeUnresolvedInterface(UnresolvedInterface c) {
+ c.interfaceMethod();
+ }
+
+ static public void callInvokeUnresolvedSuper(Main c) {
+ c.superMethod();
+ }
+
+ /// CHECK-START: void Main.superMethod() register (before)
+ /// CHECK: InvokeUnresolved invoke_type:super
+ public void superMethod() {
+ super.superMethod();
+ }
+
+ /// CHECK-START: void Main.main(java.lang.String[]) register (before)
+ /// CHECK: InvokeUnresolved invoke_type:direct
+ static public void main(String[] args) {
+ UnresolvedClass c = new UnresolvedClass();
+ callInvokeUnresolvedStatic();
+ callInvokeUnresolvedVirtual(c);
+ callInvokeUnresolvedInterface(c);
+ callInvokeUnresolvedSuper(new Main());
+ }
+}
diff --git a/test/529-checker-unresolved/src/Unresolved.java b/test/529-checker-unresolved/src/Unresolved.java
new file mode 100644
index 0000000000..5bf92dd331
--- /dev/null
+++ b/test/529-checker-unresolved/src/Unresolved.java
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2015 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 UnresolvedInterface {
+ void interfaceMethod();
+}
+
+class UnresolvedSuperClass {
+ public void superMethod() {
+ System.out.println("UnresolvedClass.superMethod()");
+ }
+}
+
+class UnresolvedClass extends UnresolvedSuperClass implements UnresolvedInterface {
+ static public void staticMethod() {
+ System.out.println("UnresolvedClass.staticMethod()");
+ }
+
+ public UnresolvedClass() {
+ System.out.println("UnresolvedClass.directCall()");
+ }
+
+ public void virtualMethod() {
+ System.out.println("UnresolvedClass.virtualMethod()");
+ }
+
+ public void interfaceMethod() {
+ System.out.println("UnresolvedClass.interfaceMethod()");
+ }
+}
+
+final class UnresolvedFinalClass {
+ public void directMethod() {
+ System.out.println("UnresolvedFinalClass.directMethod()");
+ }
+}
+
+class UnresolvedAtRuntime {
+ public void unresolvedAtRuntime() { }
+}
+
diff --git a/test/530-checker-loops/expected.txt b/test/530-checker-loops/expected.txt
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/test/530-checker-loops/expected.txt
diff --git a/test/530-checker-loops/info.txt b/test/530-checker-loops/info.txt
new file mode 100644
index 0000000000..f5d334d011
--- /dev/null
+++ b/test/530-checker-loops/info.txt
@@ -0,0 +1 @@
+Test on loop optimizations.
diff --git a/test/530-checker-loops/src/Main.java b/test/530-checker-loops/src/Main.java
new file mode 100644
index 0000000000..e518a61f88
--- /dev/null
+++ b/test/530-checker-loops/src/Main.java
@@ -0,0 +1,354 @@
+/*
+ * Copyright (C) 2015 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.
+ */
+
+//
+// Test on loop optimizations.
+//
+public class Main {
+
+ static int sResult;
+
+ //
+ // Various sequence variables where bound checks can be removed from loop.
+ //
+
+ /// CHECK-START: int Main.linear(int[]) BCE (before)
+ /// CHECK-DAG: BoundsCheck
+ /// CHECK-START: int Main.linear(int[]) BCE (after)
+ /// CHECK-NOT: BoundsCheck
+ private static int linear(int[] x) {
+ int result = 0;
+ for (int i = 0; i < x.length; i++) {
+ result += x[i];
+ }
+ return result;
+ }
+
+ /// CHECK-START: int Main.linearDown(int[]) BCE (before)
+ /// CHECK-DAG: BoundsCheck
+ /// CHECK-START: int Main.linearDown(int[]) BCE (after)
+ /// CHECK-NOT: BoundsCheck
+ private static int linearDown(int[] x) {
+ int result = 0;
+ for (int i = x.length - 1; i >= 0; i--) {
+ result += x[i];
+ }
+ return result;
+ }
+
+ /// CHECK-START: int Main.linearObscure(int[]) BCE (before)
+ /// CHECK-DAG: BoundsCheck
+ /// CHECK-START: int Main.linearObscure(int[]) BCE (after)
+ /// CHECK-NOT: BoundsCheck
+ private static int linearObscure(int[] x) {
+ int result = 0;
+ for (int i = x.length - 1; i >= 0; i--) {
+ int k = i + 5;
+ result += x[k - 5];
+ }
+ return result;
+ }
+
+ /// CHECK-START: int Main.linearWhile(int[]) BCE (before)
+ /// CHECK-DAG: BoundsCheck
+ /// CHECK-START: int Main.linearWhile(int[]) BCE (after)
+ /// CHECK-NOT: BoundsCheck
+ private static int linearWhile(int[] x) {
+ int i = 0;
+ int result = 0;
+ while (i < x.length) {
+ result += x[i++];
+ }
+ return result;
+ }
+
+ /// CHECK-START: int Main.wrapAroundThenLinear(int[]) BCE (before)
+ /// CHECK-DAG: BoundsCheck
+ /// CHECK-START: int Main.wrapAroundThenLinear(int[]) BCE (after)
+ /// CHECK-NOT: BoundsCheck
+ private static int wrapAroundThenLinear(int[] x) {
+ // Loop with wrap around (length - 1, 0, 1, 2, ..).
+ int w = x.length - 1;
+ int result = 0;
+ for (int i = 0; i < x.length; i++) {
+ result += x[w];
+ w = i;
+ }
+ return result;
+ }
+
+ /// CHECK-START: int[] Main.linearWithParameter(int) BCE (before)
+ /// CHECK-DAG: BoundsCheck
+ /// CHECK-START: int[] Main.linearWithParameter(int) BCE (after)
+ /// CHECK-NOT: BoundsCheck
+ private static int[] linearWithParameter(int n) {
+ int[] x = new int[n];
+ for (int i = 0; i < n; i++) {
+ x[i] = i;
+ }
+ return x;
+ }
+
+ /// CHECK-START: int Main.linearWithCompoundStride() BCE (before)
+ /// CHECK-DAG: BoundsCheck
+ /// CHECK-START: int Main.linearWithCompoundStride() BCE (after)
+ /// CHECK-NOT: BoundsCheck
+ private static int linearWithCompoundStride() {
+ int[] x = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14 };
+ int result = 0;
+ for (int i = 0; i <= 12; ) {
+ i++;
+ result += x[i];
+ i++;
+ }
+ return result;
+ }
+
+ /// CHECK-START: int Main.linearWithLargePositiveStride() BCE (before)
+ /// CHECK-DAG: BoundsCheck
+ /// CHECK-START: int Main.linearWithLargePositiveStride() BCE (after)
+ /// CHECK-NOT: BoundsCheck
+ private static int linearWithLargePositiveStride() {
+ int[] x = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 };
+ int result = 0;
+ int k = 0;
+ // Range analysis has no problem with a trip-count defined by a
+ // reasonably large positive stride.
+ for (int i = 1; i <= 10 * 10000000 + 1; i += 10000000) {
+ result += x[k++];
+ }
+ return result;
+ }
+
+ /// CHECK-START: int Main.linearWithVeryLargePositiveStride() BCE (before)
+ /// CHECK-DAG: BoundsCheck
+ /// CHECK-START: int Main.linearWithVeryLargePositiveStride() BCE (after)
+ /// CHECK-DAG: BoundsCheck
+ private static int linearWithVeryLargePositiveStride() {
+ int[] x = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 };
+ int result = 0;
+ int k = 0;
+ // Range analysis conservatively bails due to potential of wrap-around
+ // arithmetic while computing the trip-count for this very large stride.
+ for (int i = 1; i < 2147483647; i += 195225786) {
+ result += x[k++];
+ }
+ return result;
+ }
+
+ /// CHECK-START: int Main.linearWithLargeNegativeStride() BCE (before)
+ /// CHECK-DAG: BoundsCheck
+ /// CHECK-START: int Main.linearWithLargeNegativeStride() BCE (after)
+ /// CHECK-NOT: BoundsCheck
+ private static int linearWithLargeNegativeStride() {
+ int[] x = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 };
+ int result = 0;
+ int k = 0;
+ // Range analysis has no problem with a trip-count defined by a
+ // reasonably large negative stride.
+ for (int i = -1; i >= -10 * 10000000 - 1; i -= 10000000) {
+ result += x[k++];
+ }
+ return result;
+ }
+
+ /// CHECK-START: int Main.linearWithVeryLargeNegativeStride() BCE (before)
+ /// CHECK-DAG: BoundsCheck
+ /// CHECK-START: int Main.linearWithVeryLargeNegativeStride() BCE (after)
+ /// CHECK-DAG: BoundsCheck
+ private static int linearWithVeryLargeNegativeStride() {
+ int[] x = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 };
+ int result = 0;
+ int k = 0;
+ // Range analysis conservatively bails due to potential of wrap-around
+ // arithmetic while computing the trip-count for this very large stride.
+ for (int i = -2; i > -2147483648; i -= 195225786) {
+ result += x[k++];
+ }
+ return result;
+ }
+
+ /// CHECK-START: int Main.periodicIdiom(int) BCE (before)
+ /// CHECK-DAG: BoundsCheck
+ /// CHECK-START: int Main.periodicIdiom(int) BCE (after)
+ /// CHECK-NOT: BoundsCheck
+ private static int periodicIdiom(int tc) {
+ int[] x = { 1, 3 };
+ // Loop with periodic sequence (0, 1).
+ int k = 0;
+ int result = 0;
+ for (int i = 0; i < tc; i++) {
+ result += x[k];
+ k = 1 - k;
+ }
+ return result;
+ }
+
+ /// CHECK-START: int Main.periodicSequence2(int) BCE (before)
+ /// CHECK-DAG: BoundsCheck
+ /// CHECK-START: int Main.periodicSequence2(int) BCE (after)
+ /// CHECK-NOT: BoundsCheck
+ private static int periodicSequence2(int tc) {
+ int[] x = { 1, 3 };
+ // Loop with periodic sequence (0, 1).
+ int k = 0;
+ int l = 1;
+ int result = 0;
+ for (int i = 0; i < tc; i++) {
+ result += x[k];
+ int t = l;
+ l = k;
+ k = t;
+ }
+ return result;
+ }
+
+ /// CHECK-START: int Main.periodicSequence4(int) BCE (before)
+ /// CHECK-DAG: BoundsCheck
+ /// CHECK-DAG: BoundsCheck
+ /// CHECK-DAG: BoundsCheck
+ /// CHECK-DAG: BoundsCheck
+ /// CHECK-START: int Main.periodicSequence4(int) BCE (after)
+ /// CHECK-NOT: BoundsCheck
+ private static int periodicSequence4(int tc) {
+ int[] x = { 1, 3, 5, 7 };
+ // Loop with periodic sequence (0, 1, 2, 3).
+ int k = 0;
+ int l = 1;
+ int m = 2;
+ int n = 3;
+ int result = 0;
+ for (int i = 0; i < tc; i++) {
+ result += x[k] + x[l] + x[m] + x[n]; // all used at once
+ int t = n;
+ n = k;
+ k = l;
+ l = m;
+ m = t;
+ }
+ return result;
+ }
+
+ //
+ // Cases that actually go out of bounds. These test cases
+ // ensure the exceptions are thrown at the right places.
+ //
+
+ private static void lowerOOB(int[] x) {
+ for (int i = -1; i < x.length; i++) {
+ sResult += x[i];
+ }
+ }
+
+ private static void upperOOB(int[] x) {
+ for (int i = 0; i <= x.length; i++) {
+ sResult += x[i];
+ }
+ }
+
+ //
+ // Verifier.
+ //
+
+ public static void main(String[] args) {
+ int[] empty = { };
+ int[] x = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
+
+ // Linear and wrap-around.
+ expectEquals(0, linear(empty));
+ expectEquals(55, linear(x));
+ expectEquals(0, linearDown(empty));
+ expectEquals(55, linearDown(x));
+ expectEquals(0, linearObscure(empty));
+ expectEquals(55, linearObscure(x));
+ expectEquals(0, linearWhile(empty));
+ expectEquals(55, linearWhile(x));
+ expectEquals(0, wrapAroundThenLinear(empty));
+ expectEquals(55, wrapAroundThenLinear(x));
+
+ // Linear with parameter.
+ sResult = 0;
+ try {
+ linearWithParameter(-1);
+ } catch (NegativeArraySizeException e) {
+ sResult = 1;
+ }
+ expectEquals(1, sResult);
+ for (int n = 0; n < 32; n++) {
+ int[] r = linearWithParameter(n);
+ expectEquals(n, r.length);
+ for (int i = 0; i < n; i++) {
+ expectEquals(i, r[i]);
+ }
+ }
+
+ // Linear with non-unit strides.
+ expectEquals(56, linearWithCompoundStride());
+ expectEquals(66, linearWithLargePositiveStride());
+ expectEquals(66, linearWithVeryLargePositiveStride());
+ expectEquals(66, linearWithLargeNegativeStride());
+ expectEquals(66, linearWithVeryLargeNegativeStride());
+
+ // Periodic adds (1, 3), one at the time.
+ expectEquals(0, periodicIdiom(-1));
+ for (int tc = 0; tc < 32; tc++) {
+ int expected = (tc >> 1) << 2;
+ if ((tc & 1) != 0)
+ expected += 1;
+ expectEquals(expected, periodicIdiom(tc));
+ }
+
+ // Periodic adds (1, 3), one at the time.
+ expectEquals(0, periodicSequence2(-1));
+ for (int tc = 0; tc < 32; tc++) {
+ int expected = (tc >> 1) << 2;
+ if ((tc & 1) != 0)
+ expected += 1;
+ expectEquals(expected, periodicSequence2(tc));
+ }
+
+ // Periodic adds (1, 3, 5, 7), all at once.
+ expectEquals(0, periodicSequence4(-1));
+ for (int tc = 0; tc < 32; tc++) {
+ expectEquals(tc * 16, periodicSequence4(tc));
+ }
+
+ // Lower bound goes OOB.
+ sResult = 0;
+ try {
+ lowerOOB(x);
+ } catch (ArrayIndexOutOfBoundsException e) {
+ sResult += 1000;
+ }
+ expectEquals(1000, sResult);
+
+ // Upper bound goes OOB.
+ sResult = 0;
+ try {
+ upperOOB(x);
+ } catch (ArrayIndexOutOfBoundsException e) {
+ sResult += 1000;
+ }
+ expectEquals(1055, sResult);
+
+ }
+
+ private static void expectEquals(int expected, int result) {
+ if (expected != result) {
+ throw new Error("Expected: " + expected + ", found: " + result);
+ }
+ }
+}
diff --git a/test/etc/run-test-jar b/test/etc/run-test-jar
index efc0bfb1b9..fbefa073c4 100755
--- a/test/etc/run-test-jar
+++ b/test/etc/run-test-jar
@@ -117,6 +117,11 @@ while true; do
shift
elif [ "x$1" = "x--secondary" ]; then
SECONDARY_DEX=":$DEX_LOCATION/$TEST_NAME-ex.jar"
+ # Enable cfg-append to make sure we get the dump for both dex files.
+ # (otherwise the runtime compilation of the secondary dex will overwrite
+ # the dump of the first one)
+ FLAGS="${FLAGS} -Xcompiler-option --dump-cfg-append"
+ COMPILE_FLAGS="${COMPILE_FLAGS} --dump-cfg-append"
shift
elif [ "x$1" = "x--debug" ]; then
DEBUGGER="y"