diff options
Diffstat (limited to 'test')
29 files changed, 600 insertions, 32 deletions
diff --git a/test/136-daemon-jni-shutdown/daemon_jni_shutdown.cc b/test/136-daemon-jni-shutdown/daemon_jni_shutdown.cc new file mode 100644 index 0000000000..54879fbad9 --- /dev/null +++ b/test/136-daemon-jni-shutdown/daemon_jni_shutdown.cc @@ -0,0 +1,59 @@ +/* + * 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 <iostream> + +#include "base/casts.h" +#include "base/macros.h" +#include "java_vm_ext.h" +#include "jni_env_ext.h" +#include "thread-inl.h" + +namespace art { +namespace { + +static volatile std::atomic<bool> vm_was_shutdown(false); + +extern "C" JNIEXPORT void JNICALL Java_Main_waitAndCallIntoJniEnv(JNIEnv* env, jclass) { + // Wait until the runtime is shutdown. + while (!vm_was_shutdown.load()) { + usleep(1000); + } + std::cout << "About to call exception check\n"; + env->ExceptionCheck(); + LOG(ERROR) << "Should not be reached!"; +} + +// NO_RETURN does not work with extern "C" for target builds. +extern "C" JNIEXPORT void JNICALL Java_Main_destroyJavaVMAndExit(JNIEnv* env, jclass) { + // Fake up the managed stack so we can detach. + Thread* const self = Thread::Current(); + self->SetTopOfStack(nullptr); + self->SetTopOfShadowStack(nullptr); + JavaVM* vm = down_cast<JNIEnvExt*>(env)->vm; + vm->DetachCurrentThread(); + vm->DestroyJavaVM(); + vm_was_shutdown.store(true); + // Give threads some time to get stuck in ExceptionCheck. + usleep(1000000); + if (env != nullptr) { + // Use env != nullptr to trick noreturn. + exit(0); + } +} + +} // namespace +} // namespace art diff --git a/test/136-daemon-jni-shutdown/expected.txt b/test/136-daemon-jni-shutdown/expected.txt new file mode 100644 index 0000000000..f0b6353e9f --- /dev/null +++ b/test/136-daemon-jni-shutdown/expected.txt @@ -0,0 +1,5 @@ +JNI_OnLoad called +About to call exception check +About to call exception check +About to call exception check +About to call exception check diff --git a/test/136-daemon-jni-shutdown/info.txt b/test/136-daemon-jni-shutdown/info.txt new file mode 100644 index 0000000000..06a12dff9e --- /dev/null +++ b/test/136-daemon-jni-shutdown/info.txt @@ -0,0 +1 @@ +Test that daemon threads that call into a JNI env after the runtime is shutdown do not crash.
\ No newline at end of file diff --git a/test/136-daemon-jni-shutdown/src/Main.java b/test/136-daemon-jni-shutdown/src/Main.java new file mode 100644 index 0000000000..6eceb757b1 --- /dev/null +++ b/test/136-daemon-jni-shutdown/src/Main.java @@ -0,0 +1,47 @@ +/* + * 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. + */ + +/** + * Test that daemon threads that call into a JNI env after the runtime is shutdown do not crash. + */ +public class Main { + + public final static int THREAD_COUNT = 4; + + public static void main(String[] args) throws Exception { + System.loadLibrary(args[0]); + + for (int i = 0; i < THREAD_COUNT; i++) { + Thread t = new Thread(new DaemonRunnable()); + t.setDaemon(true); + t.start(); + } + // Give threads time to start and become stuck in waitAndCallIntoJniEnv. + Thread.sleep(1000); + destroyJavaVMAndExit(); + } + + static native void waitAndCallIntoJniEnv(); + static native void destroyJavaVMAndExit(); + + private static class DaemonRunnable implements Runnable { + public void run() { + for (;;) { + waitAndCallIntoJniEnv(); + } + } + } +} diff --git a/test/137-cfi/run b/test/137-cfi/run index ecbbbc7c48..9c567b6813 100755 --- a/test/137-cfi/run +++ b/test/137-cfi/run @@ -14,4 +14,4 @@ # See the License for the specific language governing permissions and # limitations under the License. -exec ${RUN} "$@" +exec ${RUN} "$@" -Xcompiler-option --generate-debug-info diff --git a/test/143-string-value/check b/test/143-string-value/check new file mode 100755 index 0000000000..cdf7b783a3 --- /dev/null +++ b/test/143-string-value/check @@ -0,0 +1,20 @@ +#!/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. + +# Strip run-specific numbers (pid and line number) +sed -e 's/^art E[ ]\+[0-9]\+[ ]\+[0-9]\+ art\/runtime\/native\/java_lang_Class.cc:[0-9]\+\] //' "$2" > "$2.tmp" + +diff --strip-trailing-cr -q "$1" "$2.tmp" >/dev/null diff --git a/test/143-string-value/expected.txt b/test/143-string-value/expected.txt new file mode 100644 index 0000000000..06cdb89e90 --- /dev/null +++ b/test/143-string-value/expected.txt @@ -0,0 +1 @@ +The String#value field is not present on Android versions >= 6.0 diff --git a/test/143-string-value/info.txt b/test/143-string-value/info.txt new file mode 100644 index 0000000000..61ec816ab8 --- /dev/null +++ b/test/143-string-value/info.txt @@ -0,0 +1,2 @@ +Test to ensure we emit an error message when being asked +for String#value. diff --git a/test/143-string-value/src/Main.java b/test/143-string-value/src/Main.java new file mode 100644 index 0000000000..e97069200a --- /dev/null +++ b/test/143-string-value/src/Main.java @@ -0,0 +1,26 @@ +/* + * 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 { + public static void main(String[] args) { + try { + String.class.getDeclaredField("value"); + throw new Error("Expected to fail"); + } catch (ReflectiveOperationException e) { + // Ignore... + } + } +} diff --git a/test/442-checker-constant-folding/src/Main.java b/test/442-checker-constant-folding/src/Main.java index 43bc9d06a2..0e07f47288 100644 --- a/test/442-checker-constant-folding/src/Main.java +++ b/test/442-checker-constant-folding/src/Main.java @@ -120,9 +120,10 @@ public class Main { /// CHECK-DAG: <<Const2:i\d+>> IntConstant 2 /// CHECK-DAG: <<Const5:i\d+>> IntConstant 5 /// CHECK-DAG: <<Const6:i\d+>> IntConstant 6 + /// CHECK-DAG: <<Const11:i\d+>> IntConstant 11 /// CHECK-DAG: <<Add1:i\d+>> Add [<<Const1>>,<<Const2>>] - /// CHECK-DAG: <<Add2:i\d+>> Add [<<Const5>>,<<Const6>>] - /// CHECK-DAG: <<Add3:i\d+>> Add [<<Add1>>,<<Add2>>] + /// CHECK-DAG: Add [<<Const5>>,<<Const6>>] + /// CHECK-DAG: <<Add3:i\d+>> Add [<<Add1>>,<<Const11>>] /// CHECK-DAG: Return [<<Add3>>] /// CHECK-START: int Main.IntAddition2() constant_folding (after) @@ -522,7 +523,7 @@ public class Main { /// CHECK-DAG: <<Const10L:j\d+>> LongConstant 10 /// CHECK-DAG: <<Const3:i\d+>> IntConstant 3 /// CHECK-DAG: <<TypeConv:j\d+>> TypeConversion [<<Const3>>] - /// CHECK-DAG: <<And:j\d+>> And [<<Const10L>>,<<TypeConv>>] + /// CHECK-DAG: <<And:j\d+>> And [<<TypeConv>>,<<Const10L>>] /// CHECK-DAG: Return [<<And>>] /// CHECK-START: long Main.AndLongInt() constant_folding (after) @@ -567,7 +568,7 @@ public class Main { /// CHECK-DAG: <<Const10L:j\d+>> LongConstant 10 /// CHECK-DAG: <<Const3:i\d+>> IntConstant 3 /// CHECK-DAG: <<TypeConv:j\d+>> TypeConversion [<<Const3>>] - /// CHECK-DAG: <<Or:j\d+>> Or [<<Const10L>>,<<TypeConv>>] + /// CHECK-DAG: <<Or:j\d+>> Or [<<TypeConv>>,<<Const10L>>] /// CHECK-DAG: Return [<<Or>>] /// CHECK-START: long Main.OrLongInt() constant_folding (after) @@ -612,7 +613,7 @@ public class Main { /// CHECK-DAG: <<Const10L:j\d+>> LongConstant 10 /// CHECK-DAG: <<Const3:i\d+>> IntConstant 3 /// CHECK-DAG: <<TypeConv:j\d+>> TypeConversion [<<Const3>>] - /// CHECK-DAG: <<Xor:j\d+>> Xor [<<Const10L>>,<<TypeConv>>] + /// CHECK-DAG: <<Xor:j\d+>> Xor [<<TypeConv>>,<<Const10L>>] /// CHECK-DAG: Return [<<Xor>>] /// CHECK-START: long Main.XorLongInt() constant_folding (after) @@ -749,7 +750,7 @@ public class Main { /// CHECK-START: long Main.Mul0(long) constant_folding (before) /// CHECK-DAG: <<Arg:j\d+>> ParameterValue /// CHECK-DAG: <<Const0:j\d+>> LongConstant 0 - /// CHECK-DAG: <<Mul:j\d+>> Mul [<<Arg>>,<<Const0>>] + /// CHECK-DAG: <<Mul:j\d+>> Mul [<<Const0>>,<<Arg>>] /// CHECK-DAG: Return [<<Mul>>] /// CHECK-START: long Main.Mul0(long) constant_folding (after) diff --git a/test/458-checker-instruction-simplification/src/Main.java b/test/458-checker-instruction-simplification/src/Main.java index 6151fc10f2..0fd7801d48 100644 --- a/test/458-checker-instruction-simplification/src/Main.java +++ b/test/458-checker-instruction-simplification/src/Main.java @@ -288,7 +288,7 @@ public class Main { /// CHECK-START: long Main.Mul1(long) instruction_simplifier (before) /// CHECK-DAG: <<Arg:j\d+>> ParameterValue /// CHECK-DAG: <<Const1:j\d+>> LongConstant 1 - /// CHECK-DAG: <<Mul:j\d+>> Mul [<<Arg>>,<<Const1>>] + /// CHECK-DAG: <<Mul:j\d+>> Mul [<<Const1>>,<<Arg>>] /// CHECK-DAG: Return [<<Mul>>] /// CHECK-START: long Main.Mul1(long) instruction_simplifier (after) @@ -323,7 +323,7 @@ public class Main { /// CHECK-START: long Main.MulPowerOfTwo128(long) instruction_simplifier (before) /// CHECK-DAG: <<Arg:j\d+>> ParameterValue /// CHECK-DAG: <<Const128:j\d+>> LongConstant 128 - /// CHECK-DAG: <<Mul:j\d+>> Mul [<<Arg>>,<<Const128>>] + /// CHECK-DAG: <<Mul:j\d+>> Mul [<<Const128>>,<<Arg>>] /// CHECK-DAG: Return [<<Mul>>] /// CHECK-START: long Main.MulPowerOfTwo128(long) instruction_simplifier (after) @@ -705,7 +705,7 @@ public class Main { /// CHECK-DAG: <<Arg:i\d+>> ParameterValue /// CHECK-DAG: <<Neg1:i\d+>> Neg [<<Arg>>] /// CHECK-DAG: <<Neg2:i\d+>> Neg [<<Neg1>>] - /// CHECK-DAG: <<Add:i\d+>> Add [<<Neg1>>,<<Neg2>>] + /// CHECK-DAG: <<Add:i\d+>> Add [<<Neg2>>,<<Neg1>>] /// CHECK-DAG: Return [<<Add>>] /// CHECK-START: int Main.NegNeg2(int) instruction_simplifier (after) @@ -841,13 +841,13 @@ public class Main { /// CHECK-DAG: <<ConstF1:i\d+>> IntConstant -1 /// CHECK-DAG: <<Xor1:i\d+>> Xor [<<Arg>>,<<ConstF1>>] /// CHECK-DAG: <<Xor2:i\d+>> Xor [<<Xor1>>,<<ConstF1>>] - /// CHECK-DAG: <<Add:i\d+>> Add [<<Xor1>>,<<Xor2>>] + /// CHECK-DAG: <<Add:i\d+>> Add [<<Xor2>>,<<Xor1>>] /// CHECK-DAG: Return [<<Add>>] /// CHECK-START: int Main.NotNot2(int) instruction_simplifier (after) /// CHECK-DAG: <<Arg:i\d+>> ParameterValue /// CHECK-DAG: <<Not:i\d+>> Not [<<Arg>>] - /// CHECK-DAG: <<Add:i\d+>> Add [<<Not>>,<<Arg>>] + /// CHECK-DAG: <<Add:i\d+>> Add [<<Arg>>,<<Not>>] /// CHECK-DAG: Return [<<Add>>] /// CHECK-START: int Main.NotNot2(int) instruction_simplifier (after) @@ -1005,7 +1005,7 @@ public class Main { /// CHECK-START: int Main.EqualFalseLhs(boolean) instruction_simplifier (before) /// CHECK-DAG: <<Arg:z\d+>> ParameterValue /// CHECK-DAG: <<Const0:i\d+>> IntConstant 0 - /// CHECK-DAG: <<Cond:z\d+>> Equal [<<Const0>>,<<Arg>>] + /// CHECK-DAG: <<Cond:z\d+>> Equal [<<Arg>>,<<Const0>>] /// CHECK-DAG: If [<<Cond>>] /// CHECK-START: int Main.EqualFalseLhs(boolean) instruction_simplifier (after) @@ -1064,7 +1064,7 @@ public class Main { /// CHECK-START: int Main.NotEqualFalseLhs(boolean) instruction_simplifier (before) /// CHECK-DAG: <<Arg:z\d+>> ParameterValue /// CHECK-DAG: <<Const0:i\d+>> IntConstant 0 - /// CHECK-DAG: <<Cond:z\d+>> NotEqual [<<Const0>>,<<Arg>>] + /// CHECK-DAG: <<Cond:z\d+>> NotEqual [<<Arg>>,<<Const0>>] /// CHECK-DAG: If [<<Cond>>] /// CHECK-START: int Main.NotEqualFalseLhs(boolean) instruction_simplifier (after) @@ -1234,7 +1234,7 @@ public class Main { /// CHECK-START: long Main.mulPow2Minus1(long) instruction_simplifier (before) /// CHECK-DAG: <<Arg:j\d+>> ParameterValue /// CHECK-DAG: <<Const31:j\d+>> LongConstant 31 - /// CHECK: Mul [<<Arg>>,<<Const31>>] + /// CHECK: Mul [<<Const31>>,<<Arg>>] /// CHECK-START: long Main.mulPow2Minus1(long) instruction_simplifier (after) /// CHECK-DAG: <<Arg:j\d+>> ParameterValue 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 6b4da9de27..d0b33b9282 100644 --- a/test/482-checker-loop-back-edge-use/src/Main.java +++ b/test/482-checker-loop-back-edge-use/src/Main.java @@ -163,8 +163,8 @@ public class Main { /// CHECK: <<Arg:z\d+>> StaticFieldGet liveness:<<ArgLiv:\d+>> ranges:{[<<ArgLiv>>,<<ArgLoopUse:\d+>>)} uses:[<<ArgUse:\d+>>,<<ArgLoopUse>>] /// CHECK: If [<<Arg>>] liveness:<<IfLiv:\d+>> /// CHECK: Goto liveness:<<GotoLiv1:\d+>> - /// CHECK: Goto liveness:<<GotoLiv2:\d+>> /// CHECK: Exit + /// CHECK: Goto liveness:<<GotoLiv2:\d+>> /// CHECK-EVAL: <<IfLiv>> + 1 == <<ArgUse>> /// CHECK-EVAL: <<GotoLiv1>> < <<GotoLiv2>> /// CHECK-EVAL: <<GotoLiv1>> + 2 == <<ArgLoopUse>> diff --git a/test/561-divrem/expected.txt b/test/561-divrem/expected.txt new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/test/561-divrem/expected.txt diff --git a/test/561-divrem/info.txt b/test/561-divrem/info.txt new file mode 100644 index 0000000000..71c9601574 --- /dev/null +++ b/test/561-divrem/info.txt @@ -0,0 +1,2 @@ +Regression test for div/rem taking Integer.MIN_VALUE and +Long.MIN_VALUE. diff --git a/test/561-divrem/src/Main.java b/test/561-divrem/src/Main.java new file mode 100644 index 0000000000..082783df2d --- /dev/null +++ b/test/561-divrem/src/Main.java @@ -0,0 +1,103 @@ +/* + * 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 { + public static void assertEquals(int expected, int actual) { + if (expected != actual) { + throw new Error("Expected " + expected + ", got " + actual); + } + } + + public static void assertEquals(long expected, long actual) { + if (expected != actual) { + throw new Error("Expected " + expected + ", got " + actual); + } + } + + public static void main(String[] args) { + assertEquals(0, $noinline$divInt(1)); + assertEquals(1, $noinline$remInt(1)); + + assertEquals(0, $noinline$divInt(-1)); + assertEquals(-1, $noinline$remInt(-1)); + + assertEquals(0, $noinline$divInt(0)); + assertEquals(0, $noinline$remInt(0)); + + assertEquals(1, $noinline$divInt(Integer.MIN_VALUE)); + assertEquals(0, $noinline$remInt(Integer.MIN_VALUE)); + + assertEquals(0, $noinline$divInt(Integer.MAX_VALUE)); + assertEquals(Integer.MAX_VALUE, $noinline$remInt(Integer.MAX_VALUE)); + + assertEquals(0, $noinline$divInt(Integer.MAX_VALUE - 1)); + assertEquals(Integer.MAX_VALUE - 1, $noinline$remInt(Integer.MAX_VALUE - 1)); + + assertEquals(0, $noinline$divInt(Integer.MIN_VALUE + 1)); + assertEquals(Integer.MIN_VALUE + 1, $noinline$remInt(Integer.MIN_VALUE + 1)); + + assertEquals(0L, $noinline$divLong(1L)); + assertEquals(1L, $noinline$remLong(1L)); + + assertEquals(0L, $noinline$divLong(-1L)); + assertEquals(-1L, $noinline$remLong(-1L)); + + assertEquals(0L, $noinline$divLong(0L)); + assertEquals(0L, $noinline$remLong(0L)); + + assertEquals(1L, $noinline$divLong(Long.MIN_VALUE)); + assertEquals(0L, $noinline$remLong(Long.MIN_VALUE)); + + assertEquals(0L, $noinline$divLong(Long.MAX_VALUE)); + assertEquals(Long.MAX_VALUE, $noinline$remLong(Long.MAX_VALUE)); + + assertEquals(0L, $noinline$divLong(Long.MAX_VALUE - 1)); + assertEquals(Long.MAX_VALUE - 1, $noinline$remLong(Long.MAX_VALUE - 1)); + + assertEquals(0L, $noinline$divLong(Integer.MIN_VALUE + 1)); + assertEquals(Long.MIN_VALUE + 1, $noinline$remLong(Long.MIN_VALUE + 1)); + } + + public static int $noinline$divInt(int value) { + if (doThrow) { + throw new Error(""); + } + return value / Integer.MIN_VALUE; + } + + public static int $noinline$remInt(int value) { + if (doThrow) { + throw new Error(""); + } + return value % Integer.MIN_VALUE; + } + + public static long $noinline$divLong(long value) { + if (doThrow) { + throw new Error(""); + } + return value / Long.MIN_VALUE; + } + + public static long $noinline$remLong(long value) { + if (doThrow) { + throw new Error(""); + } + return value % Long.MIN_VALUE; + } + + static boolean doThrow = false; +} diff --git a/test/561-shared-slowpaths/expected.txt b/test/561-shared-slowpaths/expected.txt new file mode 100644 index 0000000000..b0aad4deb5 --- /dev/null +++ b/test/561-shared-slowpaths/expected.txt @@ -0,0 +1 @@ +passed diff --git a/test/561-shared-slowpaths/info.txt b/test/561-shared-slowpaths/info.txt new file mode 100644 index 0000000000..c51e70b452 --- /dev/null +++ b/test/561-shared-slowpaths/info.txt @@ -0,0 +1 @@ +Test on correctness while possibly sharing slow paths. diff --git a/test/561-shared-slowpaths/src/Main.java b/test/561-shared-slowpaths/src/Main.java new file mode 100644 index 0000000000..718b8750a7 --- /dev/null +++ b/test/561-shared-slowpaths/src/Main.java @@ -0,0 +1,154 @@ +/* + * 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. + */ + +// +// Test on correctness in situations where slow paths may be shared +// (actual sharing may vary between different code generators). +// +// +public class Main { + + // A method with two loops that can be optimized with dynamic BCE, + // resulting in a two times a deopt on null, a deopt on lower OOB, + // and a deopt on upper OOB. + private static void init(int[] x, int [] y, int l1, int h1, int l2, int h2) { + for (int i = l1; i < h1; i++) { + x[i] = i; + } + for (int i = l2; i < h2; i++) { + y[i] = i; + } + } + + // Test that each of the six possible exceptions situations for init() + // are correctly handled by the deopt instructions. + public static void main(String[] args) { + int[] x = new int[100]; + int[] y = new int[100]; + int z; + + // All is well. + z = 0; + reset(x, y); + try { + init(x, y, 0, 100, 0, 100); + } catch (Exception e) { + z = 1; + } + expectEquals(z, 0); + for (int i = 0; i < 100; i++) { + expectEquals(x[i], i); + expectEquals(y[i], i); + } + + // Null deopt on x. + z = 0; + reset(x, y); + try { + init(null, y, 0, 100, 0, 100); + } catch (NullPointerException e) { + z = 1; + } + expectEquals(z, 1); + for (int i = 0; i < 100; i++) { + expectEquals(x[i], 0); + expectEquals(y[i], 0); + } + + // Lower out-of-bounds on x. + z = 0; + reset(x, y); + try { + init(x, y, -1, 100, 0, 100); + } catch (ArrayIndexOutOfBoundsException e) { + z = 1; + } + expectEquals(z, 1); + for (int i = 0; i < 100; i++) { + expectEquals(x[i], 0); + expectEquals(y[i], 0); + } + + // Upper out-of-bounds on x. + z = 0; + reset(x, y); + try { + init(x, y, 0, 101, 0, 100); + } catch (ArrayIndexOutOfBoundsException e) { + z = 1; + } + expectEquals(z, 1); + for (int i = 0; i < 100; i++) { + expectEquals(x[i], i); + expectEquals(y[i], 0); + } + + // Null deopt on y. + z = 0; + reset(x, y); + try { + init(x, null, 0, 100, 0, 100); + } catch (NullPointerException e) { + z = 1; + } + expectEquals(z, 1); + for (int i = 0; i < 100; i++) { + expectEquals(x[i], i); + expectEquals(y[i], 0); + } + + // Lower out-of-bounds on y. + z = 0; + reset(x, y); + try { + init(x, y, 0, 100, -1, 100); + } catch (ArrayIndexOutOfBoundsException e) { + z = 1; + } + expectEquals(z, 1); + for (int i = 0; i < 100; i++) { + expectEquals(x[i], i); + expectEquals(y[i], 0); + } + + // Upper out-of-bounds on y. + z = 0; + reset(x, y); + try { + init(x, y, 0, 100, 0, 101); + } catch (ArrayIndexOutOfBoundsException e) { + z = 1; + } + expectEquals(z, 1); + for (int i = 0; i < 100; i++) { + expectEquals(x[i], i); + expectEquals(y[i], i); + } + + System.out.println("passed"); + } + + private static void reset(int[] x, int[] y) { + for (int i = 0; i < x.length; i++) x[i] = 0; + for (int i = 0; i < y.length; i++) y[i] = 0; + } + + private static void expectEquals(int expected, int result) { + if (expected != result) { + throw new Error("Expected: " + expected + ", found: " + result); + } + } +} diff --git a/test/562-bce-preheader/expected.txt b/test/562-bce-preheader/expected.txt new file mode 100644 index 0000000000..b0aad4deb5 --- /dev/null +++ b/test/562-bce-preheader/expected.txt @@ -0,0 +1 @@ +passed diff --git a/test/562-bce-preheader/info.txt b/test/562-bce-preheader/info.txt new file mode 100644 index 0000000000..ae006aca47 --- /dev/null +++ b/test/562-bce-preheader/info.txt @@ -0,0 +1 @@ +Regression test for correct placement of hoisting/deopting code. diff --git a/test/562-bce-preheader/src/Main.java b/test/562-bce-preheader/src/Main.java new file mode 100644 index 0000000000..8de0533591 --- /dev/null +++ b/test/562-bce-preheader/src/Main.java @@ -0,0 +1,107 @@ +/* + * 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 { + + /** + * Method with an outer countable loop and an inner do-while loop. + * Since all work is done in the header of the inner loop, any invariant hoisting + * and deopting should be done in its proper loop preheader, not the true-block + * of the newly generated taken-test after dynamic BCE. + */ + public static int doit(int[][] x, int j) { + float f = 0; + int acc = 0; + for (int i = 0; i < 2; i++) { + // The full body of a do-while loop is the loop header. + do { + // Some "noise" to avoid hoisting the array reference + // before the dynamic BCE phase runs. + f++; + // The invariant array reference with corresponding bounds check + // is a candidate for hoisting when dynamic BCE runs. If it is + // not moved to the proper loop preheader, the wrong values + // cause the test to fail. + acc += x[i][i]; + } while (++j < i); + } + return acc; + } + + /** + * Single countable loop with a clear header and a loop body. In this case, + * after dynamic bce, some invariant hoisting and deopting must go to the + * proper loop preheader and some must go to the true-block. + */ + public static int foo(int[] x, int[] y, int n) { + float f = 0; + int acc = 0; + int i = 0; + while (true) { + // This part is the loop header. + // Some "noise" to avoid hoisting the array reference + // before the dynamic BCE phase runs. + f++; + // The invariant array reference with corresponding bounds check + // is a candidate for hoisting when dynamic BCE runs. If it is + // not moved to the proper loop preheader, the wrong values + // cause the test to fail. + acc += y[0]; + if (++i > n) + break; + // From here on, this part is the loop body. + // The unit-stride array reference is a candidate for dynamic BCE. + // The deopting appears in the true-block. + acc += x[i]; + } + return acc; + } + + public static void main(String args[]) { + int[][] x = new int[2][2]; + int y; + + x[0][0] = 1; + x[1][1] = 2; + + expectEquals(8, doit(x, -6)); + expectEquals(7, doit(x, -5)); + expectEquals(6, doit(x, -4)); + expectEquals(5, doit(x, -3)); + expectEquals(4, doit(x, -2)); + expectEquals(3, doit(x, -1)); + expectEquals(3, doit(x, 0)); + expectEquals(3, doit(x, 1)); + expectEquals(3, doit(x, 22)); + + int a[] = { 1, 2, 3, 5 }; + int b[] = { 7 }; + + expectEquals(7, foo(a, b, -1)); + expectEquals(7, foo(a, b, 0)); + expectEquals(16, foo(a, b, 1)); + expectEquals(26, foo(a, b, 2)); + expectEquals(38, foo(a, b, 3)); + + System.out.println("passed"); + } + + private static void expectEquals(int expected, int result) { + if (expected != result) { + throw new Error("Expected: " + expected + ", found: " + result); + } + } +} diff --git a/test/562-no-intermediate/expected.txt b/test/562-no-intermediate/expected.txt new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/test/562-no-intermediate/expected.txt diff --git a/test/562-no-intermediate/info.txt b/test/562-no-intermediate/info.txt new file mode 100644 index 0000000000..4f21aebd03 --- /dev/null +++ b/test/562-no-intermediate/info.txt @@ -0,0 +1,2 @@ +Regression test for optimizing, checking that there is no +intermediate address between a Java call. diff --git a/test/562-no-intermediate/src/Main.java b/test/562-no-intermediate/src/Main.java new file mode 100644 index 0000000000..3b74d6f269 --- /dev/null +++ b/test/562-no-intermediate/src/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. + */ + +public class Main { + + /// CHECK-START-ARM64: int Main.main(String[]) register_allocator (after) + /// CHECK-NOT: IntermediateAddress + public static void main(String[] args) { + array[index] += Math.cos(42); + } + + static int index = 0; + static double[] array = new double[2]; +} diff --git a/test/701-easy-div-rem/genMain.py b/test/701-easy-div-rem/genMain.py index 75eee17fe6..b6c769fd55 100644 --- a/test/701-easy-div-rem/genMain.py +++ b/test/701-easy-div-rem/genMain.py @@ -13,25 +13,27 @@ # limitations under the License. upper_bound_int_pow2 = 31 +upper_bound_int_pow2_neg = 32 upper_bound_long_pow2 = 63 +upper_bound_long_pow2_neg = 64 upper_bound_constant = 100 all_tests = [ ({'@INT@': 'int', '@SUFFIX@':''}, [('CheckDiv', 'idiv_by_pow2_', [2**i for i in range(upper_bound_int_pow2)]), - ('CheckDiv', 'idiv_by_pow2_neg_', [-2**i for i in range(upper_bound_int_pow2)]), + ('CheckDiv', 'idiv_by_pow2_neg_', [-2**i for i in range(upper_bound_int_pow2_neg)]), ('CheckDiv', 'idiv_by_constant_', [i for i in range(1, upper_bound_constant)]), ('CheckDiv', 'idiv_by_constant_neg_', [-i for i in range(1, upper_bound_constant)]), ('CheckRem', 'irem_by_pow2_', [2**i for i in range(upper_bound_int_pow2)]), - ('CheckRem', 'irem_by_pow2_neg_', [-2**i for i in range(upper_bound_int_pow2)]), + ('CheckRem', 'irem_by_pow2_neg_', [-2**i for i in range(upper_bound_int_pow2_neg)]), ('CheckRem', 'irem_by_constant_', [i for i in range(1, upper_bound_constant)]), ('CheckRem', 'irem_by_constant_neg_', [-i for i in range(1, upper_bound_constant)])]), ({'@INT@': 'long', '@SUFFIX@': 'l'}, [('CheckDiv', 'ldiv_by_pow2_', [2**i for i in range(upper_bound_long_pow2)]), - ('CheckDiv', 'ldiv_by_pow2_neg_', [-2**i for i in range(upper_bound_long_pow2)]), + ('CheckDiv', 'ldiv_by_pow2_neg_', [-2**i for i in range(upper_bound_long_pow2_neg)]), ('CheckDiv', 'ldiv_by_constant_', [i for i in range(1, upper_bound_constant)]), ('CheckDiv', 'ldiv_by_constant_neg_', [-i for i in range(1, upper_bound_constant)]), ('CheckRem', 'lrem_by_pow2_', [2**i for i in range(upper_bound_long_pow2)]), - ('CheckRem', 'lrem_by_pow2_neg_', [-2**i for i in range(upper_bound_long_pow2)]), + ('CheckRem', 'lrem_by_pow2_neg_', [-2**i for i in range(upper_bound_long_pow2_neg)]), ('CheckRem', 'lrem_by_constant_', [i for i in range(1, upper_bound_constant)]), ('CheckRem', 'lrem_by_constant_neg_', [-i for i in range(1, upper_bound_constant)])]) ] diff --git a/test/Android.libarttest.mk b/test/Android.libarttest.mk index f74a516486..b922b4576e 100644 --- a/test/Android.libarttest.mk +++ b/test/Android.libarttest.mk @@ -30,6 +30,7 @@ LIBARTTEST_COMMON_SRC_FILES := \ 051-thread/thread_test.cc \ 117-nopatchoat/nopatchoat.cc \ 1337-gc-coverage/gc_coverage.cc \ + 136-daemon-jni-shutdown/daemon_jni_shutdown.cc \ 137-cfi/cfi.cc \ 139-register-natives/regnative.cc \ 141-class-unload/jni_unload.cc \ diff --git a/test/Android.run-test.mk b/test/Android.run-test.mk index 8c5ff0a938..ee6b7aa4f7 100644 --- a/test/Android.run-test.mk +++ b/test/Android.run-test.mk @@ -267,6 +267,16 @@ endif TEST_ART_BROKEN_PREBUILD_RUN_TESTS := +# 143-string-value tests for a LOG(E) tag, which is only supported on host. +TEST_ART_BROKEN_TARGET_RUN_TESTS := \ + 143-string-value \ + +ART_TEST_KNOWN_BROKEN += $(call all-run-test-names,target,$(RUN_TYPES),$(PREBUILD_TYPES), \ + $(COMPILER_TYPES),$(RELOCATE_TYPES),$(TRACE_TYPES),$(GC_TYPES),$(JNI_TYPES), \ + $(IMAGE_TYPES), $(PICTEST_TYPES), $(DEBUGGABLE_TYPES), $(TEST_ART_BROKEN_TARGET_RUN_TESTS), $(ALL_ADDRESS_SIZES)) + +TEST_ART_BROKEN_TARGET_RUN_TESTS := + # 554-jit-profile-file is disabled because it needs a primary oat file to know what it should save. TEST_ART_BROKEN_NO_PREBUILD_TESTS := \ 117-nopatchoat \ @@ -588,8 +598,7 @@ endif TEST_ART_BROKEN_DEFAULT_HEAP_POISONING_RUN_TESTS := TEST_ART_BROKEN_OPTIMIZING_HEAP_POISONING_RUN_TESTS := - -# Tests broken by multi-image. b/26317072 +# Tests broken by multi-image. TEST_ART_BROKEN_MULTI_IMAGE_RUN_TESTS := \ 476-checker-ctor-memory-barrier \ 530-checker-lse @@ -663,7 +672,8 @@ ART_TEST_HOST_RUN_TEST_DEPENDENCIES := \ $(ART_HOST_OUT_SHARED_LIBRARIES)/libarttestd$(ART_HOST_SHLIB_EXTENSION) \ $(ART_HOST_OUT_SHARED_LIBRARIES)/libnativebridgetest$(ART_HOST_SHLIB_EXTENSION) \ $(ART_HOST_OUT_SHARED_LIBRARIES)/libjavacore$(ART_HOST_SHLIB_EXTENSION) \ - $(ART_HOST_OUT_SHARED_LIBRARIES)/libopenjdk$(ART_HOST_SHLIB_EXTENSION) + $(ART_HOST_OUT_SHARED_LIBRARIES)/libopenjdk$(ART_HOST_SHLIB_EXTENSION) \ + $(ART_HOST_OUT_SHARED_LIBRARIES)/libopenjdkd$(ART_HOST_SHLIB_EXTENSION) ifneq ($(HOST_PREFER_32_BIT),true) ART_TEST_HOST_RUN_TEST_DEPENDENCIES += \ @@ -671,7 +681,8 @@ ART_TEST_HOST_RUN_TEST_DEPENDENCIES += \ $(2ND_ART_HOST_OUT_SHARED_LIBRARIES)/libarttestd$(ART_HOST_SHLIB_EXTENSION) \ $(2ND_ART_HOST_OUT_SHARED_LIBRARIES)/libnativebridgetest$(ART_HOST_SHLIB_EXTENSION) \ $(2ND_ART_HOST_OUT_SHARED_LIBRARIES)/libjavacore$(ART_HOST_SHLIB_EXTENSION) \ - $(2ND_ART_HOST_OUT_SHARED_LIBRARIES)/libopenjdk$(ART_HOST_SHLIB_EXTENSION) + $(2ND_ART_HOST_OUT_SHARED_LIBRARIES)/libopenjdk$(ART_HOST_SHLIB_EXTENSION) \ + $(2ND_ART_HOST_OUT_SHARED_LIBRARIES)/libopenjdkd$(ART_HOST_SHLIB_EXTENSION) endif # Create a rule to build and run a tests following the form: diff --git a/test/etc/run-test-jar b/test/etc/run-test-jar index dacb7b9d3b..e004b6cff4 100755 --- a/test/etc/run-test-jar +++ b/test/etc/run-test-jar @@ -361,9 +361,7 @@ fi dex2oat_cmdline="true" mkdir_cmdline="mkdir -p ${DEX_LOCATION}/dalvik-cache/$ISA" -# TODO: allow app-image to work with multi-image. b/26317072 -app_image="" -# app_image="--app-image-file=$DEX_LOCATION/dalvik-cache/$ISA/$(echo $DEX_LOCATION/$TEST_NAME.jar/classes.art | cut -d/ -f 2- | sed "s:/:@:g")" +app_image="--app-image-file=$DEX_LOCATION/dalvik-cache/$ISA/$(echo $DEX_LOCATION/$TEST_NAME.jar/classes.art | cut -d/ -f 2- | sed "s:/:@:g")" if [ "$PREBUILD" = "y" ]; then dex2oat_cmdline="$INVOKE_WITH $ANDROID_ROOT/bin/dex2oatd \ diff --git a/test/run-test b/test/run-test index ec34e0946a..4f111d2dcf 100755 --- a/test/run-test +++ b/test/run-test @@ -683,11 +683,6 @@ function arch_supports_read_barrier() { # Tests named '<number>-checker-*' will also have their CFGs verified with # Checker when compiled with Optimizing on host. if [[ "$TEST_NAME" =~ ^[0-9]+-checker- ]]; then - # Build Checker DEX files without dx's optimizations so the input to dex2oat - # better resembles the Java source. We always build the DEX the same way, even - # if Checker is not invoked and the test only runs the program. - build_args="${build_args} --dx-option --no-optimize" - # Jack does not necessarily generate the same DEX output than dx. Because these tests depend # on a particular DEX output, keep building them with dx for now (b/19467889). USE_JACK="false" |