diff options
Diffstat (limited to 'test')
41 files changed, 558 insertions, 28 deletions
diff --git a/test/004-StackWalk/src/Main.java b/test/004-StackWalk/src/Main.java index 883ce2c9fe..072b1d0c4d 100644 --- a/test/004-StackWalk/src/Main.java +++ b/test/004-StackWalk/src/Main.java @@ -2,14 +2,14 @@ public class Main { public Main() { } + boolean doThrow = false; + int $noinline$f() throws Exception { g(1); g(2); - // This loop currently defeats inlining of `f`. - for (int i = 0; i < 10; i++) { - Thread.sleep(0); - } + // This currently defeats inlining of `f`. + if (doThrow) { throw new Error(); } return 0; } diff --git a/test/048-reflect-v8/build b/test/048-reflect-v8/build new file mode 100644 index 0000000000..4ea1838465 --- /dev/null +++ b/test/048-reflect-v8/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/048-reflect-v8/expected.txt b/test/048-reflect-v8/expected.txt new file mode 100644 index 0000000000..2d0b4ccb6b --- /dev/null +++ b/test/048-reflect-v8/expected.txt @@ -0,0 +1,4 @@ +Main$DefaultInterface is default = yes +Main$RegularInterface is default = no +Main$ImplementsWithDefault is default = yes +Main$ImplementsWithRegular is default = no diff --git a/test/048-reflect-v8/info.txt b/test/048-reflect-v8/info.txt new file mode 100644 index 0000000000..a336d301d6 --- /dev/null +++ b/test/048-reflect-v8/info.txt @@ -0,0 +1 @@ +Test reflection for 1.8 APIs diff --git a/test/048-reflect-v8/run b/test/048-reflect-v8/run new file mode 100644 index 0000000000..ba3318a1fd --- /dev/null +++ b/test/048-reflect-v8/run @@ -0,0 +1,19 @@ +#!/bin/bash +# +# 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. + + +# Ensure that the default methods are turned on for dalvikvm and dex2oat +${RUN} "$@" --experimental default-methods diff --git a/test/048-reflect-v8/src/Main.java b/test/048-reflect-v8/src/Main.java new file mode 100644 index 0000000000..7fa2a923d7 --- /dev/null +++ b/test/048-reflect-v8/src/Main.java @@ -0,0 +1,56 @@ +/* + * 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. + */ + +import java.lang.reflect.Method; + +public class Main { + interface DefaultInterface { + default void sayHi() { + System.out.println("hi default"); + } + } + + interface RegularInterface { + void sayHi(); + } + + class ImplementsWithDefault implements DefaultInterface {} + class ImplementsWithRegular implements RegularInterface { + public void sayHi() { + System.out.println("hello specific"); + } + } + + private static void printIsDefault(Class<?> klass) { + Method m; + try { + m = klass.getMethod("sayHi"); + } catch (Throwable t) { + System.out.println(t); + return; + } + + boolean isDefault = m.isDefault(); + System.out.println(klass.getName() + " is default = " + (isDefault ? "yes" : "no")); + } + + public static void main(String[] args) { + printIsDefault(DefaultInterface.class); + printIsDefault(RegularInterface.class); + printIsDefault(ImplementsWithDefault.class); + printIsDefault(ImplementsWithRegular.class); + } +} diff --git a/test/127-secondarydex/build b/test/127-checker-secondarydex/build index 0d9f4d6291..0d9f4d6291 100755 --- a/test/127-secondarydex/build +++ b/test/127-checker-secondarydex/build diff --git a/test/127-secondarydex/expected.txt b/test/127-checker-secondarydex/expected.txt index 1c8defb6ec..1c8defb6ec 100644 --- a/test/127-secondarydex/expected.txt +++ b/test/127-checker-secondarydex/expected.txt diff --git a/test/127-secondarydex/info.txt b/test/127-checker-secondarydex/info.txt index 0479d1a784..0479d1a784 100644 --- a/test/127-secondarydex/info.txt +++ b/test/127-checker-secondarydex/info.txt diff --git a/test/127-secondarydex/run b/test/127-checker-secondarydex/run index d8c3c798bf..d8c3c798bf 100755 --- a/test/127-secondarydex/run +++ b/test/127-checker-secondarydex/run diff --git a/test/127-secondarydex/src/Main.java b/test/127-checker-secondarydex/src/Main.java index 0ede8ed2b2..0ede8ed2b2 100644 --- a/test/127-secondarydex/src/Main.java +++ b/test/127-checker-secondarydex/src/Main.java diff --git a/test/127-secondarydex/src/Super.java b/test/127-checker-secondarydex/src/Super.java index 7608d4a7c8..7608d4a7c8 100644 --- a/test/127-secondarydex/src/Super.java +++ b/test/127-checker-secondarydex/src/Super.java diff --git a/test/127-secondarydex/src/Test.java b/test/127-checker-secondarydex/src/Test.java index 8547e791c2..266ed191bc 100644 --- a/test/127-secondarydex/src/Test.java +++ b/test/127-checker-secondarydex/src/Test.java @@ -23,6 +23,13 @@ public class Test extends Super { System.out.println("Test"); } + /// CHECK-START: java.lang.Integer Test.toInteger() ssa_builder (after) + /// CHECK: LoadClass needs_access_check:false klass:java.lang.Integer + + public Integer toInteger() { + return new Integer(42); + } + public String toString() { return new String("Test"); } diff --git a/test/137-cfi/cfi.cc b/test/137-cfi/cfi.cc index 9bfe42922b..77301d20e8 100644 --- a/test/137-cfi/cfi.cc +++ b/test/137-cfi/cfi.cc @@ -76,7 +76,7 @@ static bool CheckStack(Backtrace* bt, const std::vector<std::string>& seq) { } } - printf("Can not find %s in backtrace:\n", seq[cur_search_index].c_str()); + printf("Cannot find %s in backtrace:\n", seq[cur_search_index].c_str()); for (Backtrace::const_iterator it = bt->begin(); it != bt->end(); ++it) { if (BacktraceMap::IsValid(it->map)) { printf(" %s\n", it->func_name.c_str()); @@ -112,7 +112,7 @@ extern "C" JNIEXPORT jboolean JNICALL Java_Main_unwindInProcess(JNIEnv*, jobject std::unique_ptr<Backtrace> bt(Backtrace::Create(BACKTRACE_CURRENT_PROCESS, GetTid())); if (!bt->Unwind(0, nullptr)) { - printf("Can not unwind in process.\n"); + printf("Cannot unwind in process.\n"); return JNI_FALSE; } else if (bt->NumFrames() == 0) { printf("No frames for unwind in process.\n"); @@ -205,7 +205,7 @@ extern "C" JNIEXPORT jboolean JNICALL Java_Main_unwindOtherProcess(JNIEnv*, jobj std::unique_ptr<Backtrace> bt(Backtrace::Create(pid, BACKTRACE_CURRENT_THREAD)); bool result = true; if (!bt->Unwind(0, nullptr)) { - printf("Can not unwind other process.\n"); + printf("Cannot unwind other process.\n"); result = false; } else if (bt->NumFrames() == 0) { printf("No frames for unwind of other process.\n"); diff --git a/test/141-class-unload/src/Main.java b/test/141-class-unload/src/Main.java index 0640b364c9..bcb697a396 100644 --- a/test/141-class-unload/src/Main.java +++ b/test/141-class-unload/src/Main.java @@ -79,7 +79,7 @@ public class Main { private static void testUnloadClass(Constructor constructor) throws Exception { WeakReference<Class> klass = setUpUnloadClass(constructor); - // No strong refernces to class loader, should get unloaded. + // No strong references to class loader, should get unloaded. Runtime.getRuntime().gc(); WeakReference<Class> klass2 = setUpUnloadClass(constructor); Runtime.getRuntime().gc(); @@ -91,7 +91,7 @@ public class Main { private static void testUnloadLoader(Constructor constructor) throws Exception { WeakReference<ClassLoader> loader = setUpUnloadLoader(constructor, true); - // No strong refernces to class loader, should get unloaded. + // No strong references to class loader, should get unloaded. Runtime.getRuntime().gc(); // If the weak reference is cleared, then it was unloaded. System.out.println(loader.get()); @@ -109,7 +109,7 @@ public class Main { private static void testLoadAndUnloadLibrary(Constructor constructor) throws Exception { WeakReference<ClassLoader> loader = setUpLoadLibrary(constructor); - // No strong refernces to class loader, should get unloaded. + // No strong references to class loader, should get unloaded. Runtime.getRuntime().gc(); // If the weak reference is cleared, then it was unloaded. System.out.println(loader.get()); diff --git a/test/482-checker-loop-back-edge-use/src/Main.java b/test/482-checker-loop-back-edge-use/src/Main.java index d0b33b9282..f8f0aa3f0a 100644 --- a/test/482-checker-loop-back-edge-use/src/Main.java +++ b/test/482-checker-loop-back-edge-use/src/Main.java @@ -40,6 +40,9 @@ public class Main { /// CHECK-EVAL: <<GotoLiv2>> + 2 == <<ArgLoopUse2>> public static void loop2(boolean incoming) { + // Add some code at entry to avoid having the entry block be a pre header. + // This avoids having to create a synthesized block. + System.out.println("Enter"); while (true) { System.out.println("foo"); while (incoming) {} @@ -170,6 +173,9 @@ public class Main { /// CHECK-EVAL: <<GotoLiv1>> + 2 == <<ArgLoopUse>> public static void loop9() { + // Add some code at entry to avoid having the entry block be a pre header. + // This avoids having to create a synthesized block. + System.out.println("Enter"); while (Runtime.getRuntime() != null) { // 'incoming' must only have a use in the inner loop. boolean incoming = field; diff --git a/test/510-checker-try-catch/smali/SsaBuilder.smali b/test/510-checker-try-catch/smali/SsaBuilder.smali index 710e849c45..a6a5bfebee 100644 --- a/test/510-checker-try-catch/smali/SsaBuilder.smali +++ b/test/510-checker-try-catch/smali/SsaBuilder.smali @@ -21,7 +21,7 @@ ## CHECK-START: int SsaBuilder.testSimplifyCatchBlock(int, int, int) ssa_builder (after) -## CHECK: name "B0" +## CHECK: name "B1" ## CHECK-NEXT: from_bci ## CHECK-NEXT: to_bci ## CHECK-NEXT: predecessors @@ -39,12 +39,15 @@ ## CHECK: name "<<BExtracted>>" ## CHECK-NEXT: from_bci ## CHECK-NEXT: to_bci -## CHECK-NEXT: predecessors "B0" "<<BCatch>>" +## CHECK-NEXT: predecessors "B1" "<<BCatch>>" ## CHECK-NOT: flags "catch_block" ## CHECK: Add .method public static testSimplifyCatchBlock(III)I .registers 4 + # Avoid entry block be a pre header, which leads to + # the cfg simplifier to add a synthesized block. + goto :catch_all :catch_all add-int/2addr p0, p1 diff --git a/test/559-checker-irreducible-loop/smali/IrreducibleLoop.smali b/test/559-checker-irreducible-loop/smali/IrreducibleLoop.smali index 30a648d764..971ad84241 100644 --- a/test/559-checker-irreducible-loop/smali/IrreducibleLoop.smali +++ b/test/559-checker-irreducible-loop/smali/IrreducibleLoop.smali @@ -91,9 +91,7 @@ goto :other_loop_entry .end method -# Check that if a irreducible loop entry is dead, the loop can become -# natural. -# We start with: +# Check that dce does not apply for irreducible loops. # # entry # / \ @@ -106,18 +104,8 @@ ## CHECK-START: int IrreducibleLoop.dce(int) dead_code_elimination (before) ## CHECK: irreducible:true -# And end with: -# -# entry -# / -# / -# loop_entry -# / \- -# exit \- -# other_loop_entry - ## CHECK-START: int IrreducibleLoop.dce(int) dead_code_elimination (after) -## CHECK-NOT: irreducible:true +## CHECK: irreducible:true .method public static dce(I)I .registers 3 const/16 v0, 42 diff --git a/test/563-checker-fakestring/smali/TestCase.smali b/test/563-checker-fakestring/smali/TestCase.smali index cd52f3d55d..54312a43d0 100644 --- a/test/563-checker-fakestring/smali/TestCase.smali +++ b/test/563-checker-fakestring/smali/TestCase.smali @@ -64,9 +64,15 @@ .end method -# Test deoptimization between String's allocation and initialization. +# Test deoptimization between String's allocation and initialization. When not +# compiling --debuggable, the NewInstance will be optimized out. ## CHECK-START: int TestCase.deoptimizeNewInstance(int[], byte[]) register (after) +## CHECK: <<Null:l\d+>> NullConstant +## CHECK: Deoptimize env:[[<<Null>>,{{.*]]}} +## CHECK: InvokeStaticOrDirect method_name:java.lang.String.<init> + +## CHECK-START-DEBUGGABLE: int TestCase.deoptimizeNewInstance(int[], byte[]) register (after) ## CHECK: <<String:l\d+>> NewInstance ## CHECK: Deoptimize env:[[<<String>>,{{.*]]}} ## CHECK: InvokeStaticOrDirect method_name:java.lang.String.<init> @@ -98,3 +104,79 @@ return v2 .end method + +# Test that a redundant NewInstance is removed if not used and not compiling +# --debuggable. + +## CHECK-START: java.lang.String TestCase.removeNewInstance(byte[]) register (after) +## CHECK-NOT: NewInstance +## CHECK-NOT: LoadClass + +## CHECK-START-DEBUGGABLE: java.lang.String TestCase.removeNewInstance(byte[]) register (after) +## CHECK: NewInstance + +.method public static removeNewInstance([B)Ljava/lang/String; + .registers 5 + + new-instance v0, Ljava/lang/String; + const-string v1, "UTF8" + invoke-direct {v0, p0, v1}, Ljava/lang/String;-><init>([BLjava/lang/String;)V + return-object v0 + +.end method + +# Test that the compiler does not assume that the first argument of String.<init> +# is a NewInstance by inserting an irreducible loop between them (b/26676472). + +# We verify the type of the input instruction (Phi) in debuggable mode, because +# it is eliminated by later stages of SsaBuilder otherwise. + +## CHECK-START-DEBUGGABLE: java.lang.String TestCase.thisNotNewInstance1(byte[], boolean) register (after) +## CHECK-DAG: InvokeStaticOrDirect env:[[<<Phi:l\d+>>,{{.*]]}} +## CHECK-DAG: <<Phi>> Phi + +.method public static thisNotNewInstance1([BZ)Ljava/lang/String; + .registers 5 + + new-instance v0, Ljava/lang/String; + + # Irreducible loop + if-eqz p1, :loop_entry + :loop_header + const v1, 0x1 + xor-int p1, p1, v1 + :loop_entry + if-eqz p1, :string_init + goto :loop_header + + :string_init + const-string v1, "UTF8" + invoke-direct {v0, p0, v1}, Ljava/lang/String;-><init>([BLjava/lang/String;)V + return-object v0 + +.end method + +## CHECK-START-DEBUGGABLE: java.lang.String TestCase.thisNotNewInstance2(byte[], boolean) register (after) +## CHECK-DAG: InvokeStaticOrDirect env:[[<<Phi:l\d+>>,{{.*]]}} +## CHECK-DAG: <<Phi>> Phi + +.method public static thisNotNewInstance2([BZ)Ljava/lang/String; + .registers 5 + + new-instance v0, Ljava/lang/String; + + # Irreducible loop + if-eqz p1, :loop_entry + :loop_header + if-eqz p1, :string_init + :loop_entry + const v1, 0x1 + xor-int p1, p1, v1 + goto :loop_header + + :string_init + const-string v1, "UTF8" + invoke-direct {v0, p0, v1}, Ljava/lang/String;-><init>([BLjava/lang/String;)V + return-object v0 + +.end method diff --git a/test/563-checker-fakestring/src/Main.java b/test/563-checker-fakestring/src/Main.java index 750f7184ee..1ac8a5bfcf 100644 --- a/test/563-checker-fakestring/src/Main.java +++ b/test/563-checker-fakestring/src/Main.java @@ -57,5 +57,26 @@ public class Main { } } } + + { + Method m = c.getMethod("removeNewInstance", byte[].class); + String result = (String) m.invoke(null, new Object[] { testData }); + assertEqual(testString, result); + } + + { + Method m = c.getMethod("thisNotNewInstance1", byte[].class, boolean.class); + String result = (String) m.invoke(null, new Object[] { testData, true }); + assertEqual(testString, result); + result = (String) m.invoke(null, new Object[] { testData, false }); + assertEqual(testString, result); + } + { + Method m = c.getMethod("thisNotNewInstance2", byte[].class, boolean.class); + String result = (String) m.invoke(null, new Object[] { testData, true }); + assertEqual(testString, result); + result = (String) m.invoke(null, new Object[] { testData, false }); + assertEqual(testString, result); + } } } diff --git a/test/564-checker-bitcount/expected.txt b/test/564-checker-bitcount/expected.txt new file mode 100644 index 0000000000..b0aad4deb5 --- /dev/null +++ b/test/564-checker-bitcount/expected.txt @@ -0,0 +1 @@ +passed diff --git a/test/564-checker-bitcount/info.txt b/test/564-checker-bitcount/info.txt new file mode 100644 index 0000000000..57db66b8ca --- /dev/null +++ b/test/564-checker-bitcount/info.txt @@ -0,0 +1 @@ +Unit test for 32-bit and 64-bit bit count operation. diff --git a/test/564-checker-bitcount/src/Main.java b/test/564-checker-bitcount/src/Main.java new file mode 100644 index 0000000000..b250145ef3 --- /dev/null +++ b/test/564-checker-bitcount/src/Main.java @@ -0,0 +1,90 @@ +/* + * 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. + */ + +public class Main { + + // TODO: make this work when b/26700769 is done. + // + // CHECK-START-X86_64: int Main.bits32(int) disassembly (after) + // CHECK-DAG: popcnt + // + // CHECK-START-X86_64: int Main.bits32(int) disassembly (after) + // CHECK-NOT: call + private static int bits32(int x) { + return Integer.bitCount(x); + } + + // TODO: make this work when b/26700769 is done. + // + // CHECK-START-X86_64: int Main.bits64(long) disassembly (after) + // CHECK-DAG: popcnt + // + // CHECK-START-X86_64: int Main.bits64(long) disassembly (after) + // CHECK-NOT: call + private static int bits64(long x) { + return Long.bitCount(x); + } + + public static void main(String args[]) { + expectEquals32(bits32(0x00000000), 0); + expectEquals32(bits32(0x00000001), 1); + expectEquals32(bits32(0x10000000), 1); + expectEquals32(bits32(0x10000001), 2); + expectEquals32(bits32(0x00000003), 2); + expectEquals32(bits32(0x70000000), 3); + expectEquals32(bits32(0x000F0000), 4); + expectEquals32(bits32(0x00001111), 4); + expectEquals32(bits32(0x11110000), 4); + expectEquals32(bits32(0x11111111), 8); + expectEquals32(bits32(0x12345678), 13); + expectEquals32(bits32(0x9ABCDEF0), 19); + expectEquals32(bits32(0xFFFFFFFF), 32); + + for (int i = 0; i < 32; i++) { + expectEquals32(bits32(1 << i), 1); + } + + expectEquals64(bits64(0x0000000000000000L), 0); + expectEquals64(bits64(0x0000000000000001L), 1); + expectEquals64(bits64(0x1000000000000000L), 1); + expectEquals64(bits64(0x1000000000000001L), 2); + expectEquals64(bits64(0x0000000000000003L), 2); + expectEquals64(bits64(0x7000000000000000L), 3); + expectEquals64(bits64(0x000F000000000000L), 4); + expectEquals64(bits64(0x0000000011111111L), 8); + expectEquals64(bits64(0x1111111100000000L), 8); + expectEquals64(bits64(0x1111111111111111L), 16); + expectEquals64(bits64(0x123456789ABCDEF1L), 33); + expectEquals64(bits64(0xFFFFFFFFFFFFFFFFL), 64); + + for (int i = 0; i < 64; i++) { + expectEquals64(bits64(1L << i), 1); + } + + System.out.println("passed"); + } + + private static void expectEquals32(int expected, int result) { + if (expected != result) { + throw new Error("Expected: " + expected + ", found: " + result); + } + } + private static void expectEquals64(long expected, long result) { + if (expected != result) { + throw new Error("Expected: " + expected + ", found: " + result); + } + } +} diff --git a/test/564-checker-inline-loop/expected.txt b/test/564-checker-inline-loop/expected.txt new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/test/564-checker-inline-loop/expected.txt diff --git a/test/564-checker-inline-loop/info.txt b/test/564-checker-inline-loop/info.txt new file mode 100644 index 0000000000..a590bc6f23 --- /dev/null +++ b/test/564-checker-inline-loop/info.txt @@ -0,0 +1 @@ +Tests inlining of loops in the optimizing compiler. diff --git a/test/564-checker-inline-loop/src/Main.java b/test/564-checker-inline-loop/src/Main.java new file mode 100644 index 0000000000..6929913864 --- /dev/null +++ b/test/564-checker-inline-loop/src/Main.java @@ -0,0 +1,64 @@ +/* + * 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. + */ + +public class Main { + + /// CHECK-START: int Main.inlineLoop() inliner (before) + /// CHECK-DAG: <<Invoke:i\d+>> InvokeStaticOrDirect + /// CHECK-DAG: Return [<<Invoke>>] + + /// CHECK-START: int Main.inlineLoop() inliner (after) + /// CHECK-NOT: InvokeStaticOrDirect + + /// CHECK-START: int Main.inlineLoop() inliner (after) + /// CHECK-DAG: <<Constant:i\d+>> IntConstant 42 + /// CHECK-DAG: Return [<<Constant>>] + + /// CHECK-START: int Main.inlineLoop() licm (after) + /// CHECK: Goto loop:{{B\d+}} + + public static int inlineLoop() { + return loopMethod(); + } + + /// CHECK-START: void Main.inlineWithinLoop() inliner (before) + /// CHECK: InvokeStaticOrDirect + + /// CHECK-START: void Main.inlineWithinLoop() inliner (after) + /// CHECK-NOT: InvokeStaticOrDirect + + /// CHECK-START: void Main.inlineWithinLoop() licm (after) + /// CHECK-DAG: Goto loop:<<OuterLoop:B\d+>> outer_loop:none + /// CHECK-DAG: Goto outer_loop:<<OuterLoop>> + + public static void inlineWithinLoop() { + while (doLoop) { + loopMethod(); + } + } + + public static int loopMethod() { + while (doLoop) {} + return 42; + } + + public static boolean doLoop = false; + + public static void main(String[] args) { + inlineLoop(); + inlineWithinLoop(); + } +} diff --git a/test/564-checker-irreducible-loop/expected.txt b/test/564-checker-irreducible-loop/expected.txt new file mode 100644 index 0000000000..d81cc0710e --- /dev/null +++ b/test/564-checker-irreducible-loop/expected.txt @@ -0,0 +1 @@ +42 diff --git a/test/564-checker-irreducible-loop/info.txt b/test/564-checker-irreducible-loop/info.txt new file mode 100644 index 0000000000..1e0dd02284 --- /dev/null +++ b/test/564-checker-irreducible-loop/info.txt @@ -0,0 +1,2 @@ +Regression test for optimizing in the presence of +an irreducible loop. diff --git a/test/564-checker-irreducible-loop/smali/IrreducibleLoop.smali b/test/564-checker-irreducible-loop/smali/IrreducibleLoop.smali new file mode 100644 index 0000000000..b82ed921a5 --- /dev/null +++ b/test/564-checker-irreducible-loop/smali/IrreducibleLoop.smali @@ -0,0 +1,61 @@ +# 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 LIrreducibleLoop; + +.super Ljava/lang/Object; + +## CHECK-START-X86: int IrreducibleLoop.simpleLoop(int) dead_code_elimination (before) +## CHECK-DAG: <<Method:(i|j)\d+>> CurrentMethod +## CHECK-DAG: <<Constant:i\d+>> IntConstant 42 +## CHECK-DAG: InvokeStaticOrDirect [<<Constant>>,<<Method>>] loop:{{B\d+}} irreducible:true +## CHECK-DAG: InvokeStaticOrDirect [<<Constant>>,<<Method>>] loop:none +.method public static simpleLoop(I)I + .registers 3 + const/16 v0, 42 + if-eqz p0, :loop_entry + goto :other_loop_pre_entry + + # The then part: beginning of the irreducible loop. + :loop_entry + if-nez p0, :exit + invoke-static {v0},LIrreducibleLoop;->$noinline$m(I)V + :other_loop_entry + goto :loop_entry + + # The else part: a block uses the ArtMethod and branches to + # a block that doesn't. The register allocator used to trip there, as the + # ArtMethod was a live_in of the last block before the loop, but did not have + # a location due to our liveness analysis. + :other_loop_pre_entry + if-eqz p0, :other_loop_entry + invoke-static {v0},LIrreducibleLoop;->$noinline$m(I)V + goto :other_loop_entry + + :exit + return v0 +.end method + +.method public static $noinline$m(I)V + .registers 3 + const/16 v0, 0 + sget-boolean v1,LIrreducibleLoop;->doThrow:Z + if-eqz v1, :exit + # Prevent inlining. + throw v0 + :exit + return-void +.end method + +.field public static doThrow:Z diff --git a/test/564-checker-irreducible-loop/src/Main.java b/test/564-checker-irreducible-loop/src/Main.java new file mode 100644 index 0000000000..94e3357e5d --- /dev/null +++ b/test/564-checker-irreducible-loop/src/Main.java @@ -0,0 +1,29 @@ +/* + * 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. + */ + +import java.lang.reflect.Method; + +public class Main { + // Workaround for b/18051191. + class InnerClass {} + + public static void main(String[] args) throws Exception { + Class<?> c = Class.forName("IrreducibleLoop"); + Method m = c.getMethod("simpleLoop", int.class); + Object[] arguments = { 42 }; + System.out.println(m.invoke(null, arguments)); + } +} diff --git a/test/971-iface-super-partial-compile-generated/build b/test/971-iface-super/build index 1e9f8aadd5..1e9f8aadd5 100755 --- a/test/971-iface-super-partial-compile-generated/build +++ b/test/971-iface-super/build diff --git a/test/971-iface-super-partial-compile-generated/expected.txt b/test/971-iface-super/expected.txt index 1ddd65d177..1ddd65d177 100644 --- a/test/971-iface-super-partial-compile-generated/expected.txt +++ b/test/971-iface-super/expected.txt diff --git a/test/971-iface-super-partial-compile-generated/info.txt b/test/971-iface-super/info.txt index bc1c42816e..bc1c42816e 100644 --- a/test/971-iface-super-partial-compile-generated/info.txt +++ b/test/971-iface-super/info.txt diff --git a/test/971-iface-super-partial-compile-generated/run b/test/971-iface-super/run index 6d2930d463..6d2930d463 100755 --- a/test/971-iface-super-partial-compile-generated/run +++ b/test/971-iface-super/run diff --git a/test/971-iface-super-partial-compile-generated/util-src/generate_java.py b/test/971-iface-super/util-src/generate_java.py index 99b0479c8f..99b0479c8f 100755 --- a/test/971-iface-super-partial-compile-generated/util-src/generate_java.py +++ b/test/971-iface-super/util-src/generate_java.py diff --git a/test/971-iface-super-partial-compile-generated/util-src/generate_smali.py b/test/971-iface-super/util-src/generate_smali.py index f01c9043b9..f01c9043b9 100755 --- a/test/971-iface-super-partial-compile-generated/util-src/generate_smali.py +++ b/test/971-iface-super/util-src/generate_smali.py diff --git a/test/Android.run-test.mk b/test/Android.run-test.mk index f62d0e921f..48e10c3378 100644 --- a/test/Android.run-test.mk +++ b/test/Android.run-test.mk @@ -70,6 +70,7 @@ $$(dmart_target): $(TEST_ART_RUN_TEST_DEPENDENCIES) $(TARGET_JACK_CLASSPATH_DEPE $(hide) DX=$(abspath $(DX)) JASMIN=$(abspath $(HOST_OUT_EXECUTABLES)/jasmin) \ SMALI=$(abspath $(HOST_OUT_EXECUTABLES)/smali) \ DXMERGER=$(abspath $(HOST_OUT_EXECUTABLES)/dexmerger) \ + JACK_VERSION=$(JACK_DEFAULT_VERSION) \ JACK=$(abspath $(JACK)) \ JACK_CLASSPATH=$(TARGET_JACK_CLASSPATH) \ JILL_JAR=$(abspath $(JILL_JAR)) \ @@ -242,7 +243,7 @@ TEST_ART_PYTHON3_DEPENDENCY_RUN_TESTS := \ 968-default-partial-compile-generated \ 969-iface-super \ 970-iface-super-resolution-generated \ - 971-iface-super-partial-compile-generated + 971-iface-super # Check if we have python3 to run our tests. ifeq ($(wildcard /usr/bin/python3),) @@ -620,6 +621,11 @@ ART_TEST_KNOWN_BROKEN += $(call all-run-test-names,$(TARGET_TYPES),$(RUN_TYPES), TEST_ART_BROKEN_MULTI_IMAGE_RUN_TESTS := +# Test is flaky b/26733951. +ART_TEST_KNOWN_BROKEN += $(call all-run-test-names,$(TARGET_TYPES),$(RUN_TYPES),$(PREBUILD_TYPES), \ + $(COMPILER_TYPES),$(RELOCATE_TYPES),$(TRACE_TYPES),$(GC_TYPES),$(JNI_TYPES),$(IMAGE_TYPES), \ + $(PICTEST_TYPES),$(DEBUGGABLE_TYPES),961-default-iface-resolution-generated,$(ALL_ADDRESS_SIZES)) + # Clear variables ahead of appending to them when defining tests. $(foreach target, $(TARGET_TYPES), $(eval ART_RUN_TEST_$(call name-to-var,$(target))_RULES :=)) $(foreach target, $(TARGET_TYPES), \ @@ -967,6 +973,7 @@ $$(run_test_rule_name): $(TEST_ART_RUN_TEST_DEPENDENCIES) $(HOST_OUT_EXECUTABLES JASMIN=$(abspath $(HOST_OUT_EXECUTABLES)/jasmin) \ SMALI=$(abspath $(HOST_OUT_EXECUTABLES)/smali) \ DXMERGER=$(abspath $(HOST_OUT_EXECUTABLES)/dexmerger) \ + JACK_VERSION=$(JACK_DEFAULT_VERSION) \ JACK=$(abspath $(JACK)) \ JACK_CLASSPATH=$$(PRIVATE_JACK_CLASSPATH) \ JILL_JAR=$(abspath $(JILL_JAR)) \ diff --git a/test/ProfileTestMultiDex/Main.java b/test/ProfileTestMultiDex/Main.java new file mode 100644 index 0000000000..41532ea8f7 --- /dev/null +++ b/test/ProfileTestMultiDex/Main.java @@ -0,0 +1,27 @@ +/* + * 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 Main { + public String getA() { + return "A"; + } + public String getB() { + return "B"; + } + public String getC() { + return "C"; + } +} diff --git a/test/ProfileTestMultiDex/Second.java b/test/ProfileTestMultiDex/Second.java new file mode 100644 index 0000000000..4ac5abc300 --- /dev/null +++ b/test/ProfileTestMultiDex/Second.java @@ -0,0 +1,27 @@ +/* + * 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 Second { + public String getX() { + return "X"; + } + public String getY() { + return "Y"; + } + public String getZ() { + return "Z"; + } +} diff --git a/test/ProfileTestMultiDex/main.jpp b/test/ProfileTestMultiDex/main.jpp new file mode 100644 index 0000000000..f2e3b4e14c --- /dev/null +++ b/test/ProfileTestMultiDex/main.jpp @@ -0,0 +1,3 @@ +main: + @@com.android.jack.annotations.ForceInMainDex + class Second diff --git a/test/ProfileTestMultiDex/main.list b/test/ProfileTestMultiDex/main.list new file mode 100644 index 0000000000..44ba78ead5 --- /dev/null +++ b/test/ProfileTestMultiDex/main.list @@ -0,0 +1 @@ +Main.class |