summaryrefslogtreecommitdiff
path: root/test
diff options
context:
space:
mode:
Diffstat (limited to 'test')
-rw-r--r--test/157-void-class/expected.txt (renamed from test/616-cha-interface-default/expected.txt)1
-rw-r--r--test/157-void-class/info.txt0
-rwxr-xr-x[-rw-r--r--]test/157-void-class/run (renamed from test/616-cha-interface/run)8
-rw-r--r--test/157-void-class/src/Main.java57
-rw-r--r--test/536-checker-intrinsic-optimization/src/Main.java31
-rw-r--r--test/616-cha-abstract/src/Main.java4
-rw-r--r--test/616-cha-interface-default/info.txt1
-rw-r--r--test/616-cha-interface-default/run18
-rw-r--r--test/616-cha-interface-default/src/Main.java176
-rw-r--r--test/616-cha-interface/expected.txt1
-rw-r--r--test/616-cha-interface/info.txt1
-rw-r--r--test/616-cha-interface/src/Main.java159
-rw-r--r--test/616-cha-miranda/expected.txt1
-rw-r--r--test/616-cha-miranda/info.txt1
-rw-r--r--test/616-cha-miranda/run18
-rw-r--r--test/616-cha-miranda/src/Main.java163
-rw-r--r--test/913-heaps/expected.txt7
-rw-r--r--test/913-heaps/src/Main.java16
-rw-r--r--test/common/runtime_state.cc3
-rwxr-xr-xtest/etc/run-test-jar16
-rwxr-xr-xtest/run-test16
-rw-r--r--test/testrunner/env.py2
-rwxr-xr-xtest/testrunner/testrunner.py14
23 files changed, 145 insertions, 569 deletions
diff --git a/test/616-cha-interface-default/expected.txt b/test/157-void-class/expected.txt
index 6a5618ebc6..3f61c0b5b0 100644
--- a/test/616-cha-interface-default/expected.txt
+++ b/test/157-void-class/expected.txt
@@ -1 +1,2 @@
JNI_OnLoad called
+void.class = void
diff --git a/test/157-void-class/info.txt b/test/157-void-class/info.txt
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/test/157-void-class/info.txt
diff --git a/test/616-cha-interface/run b/test/157-void-class/run
index d8b4f0d26c..59e852c8cd 100644..100755
--- a/test/616-cha-interface/run
+++ b/test/157-void-class/run
@@ -14,5 +14,9 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-# Run without an app image to prevent the classes to be loaded at startup.
-exec ${RUN} "${@}" --no-app-image
+# Let the test build its own core image with --no-image and use verify-profile,
+# so that the compiler does not try to initialize classes. This leaves the
+# java.lang.Void compile-time verified but uninitialized.
+./default-run "$@" --no-image \
+ --runtime-option -Ximage-compiler-option \
+ --runtime-option --compiler-filter=verify-profile
diff --git a/test/157-void-class/src/Main.java b/test/157-void-class/src/Main.java
new file mode 100644
index 0000000000..322b705f1d
--- /dev/null
+++ b/test/157-void-class/src/Main.java
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2017 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 libcore.util.EmptyArray;
+
+public class Main {
+ public static void main(String[] args) {
+ try {
+ // Check if we're running dalvik or RI.
+ Class<?> class_loader_class = Class.forName("dalvik.system.PathClassLoader");
+ System.loadLibrary(args[0]);
+ } catch (ClassNotFoundException e) {
+ usingRI = true;
+ // Add expected JNI_OnLoad log line to match expected.txt.
+ System.out.println("JNI_OnLoad called");
+ }
+ try {
+ // Initialize all classes needed for old java.lang.Void.TYPE initialization.
+ Runnable.class.getMethod("run", EmptyArray.CLASS).getReturnType();
+ } catch (Exception e) {
+ throw new Error(e);
+ }
+ // Clear the resolved types of the ojluni dex file to make sure there is no entry
+ // for "V", i.e. void.
+ clearResolvedTypes(Integer.class);
+ // With java.lang.Void being compile-time verified but uninitialized, initialize
+ // it now. Previously, this would indirectly initialize TYPE with the current,
+ // i.e. zero-initialized, value of TYPE. The only thing that could prevent the
+ // series of calls leading to this was a cache hit in Class.getDexCacheType()
+ // which we have prevented by clearing the cache above.
+ Class<?> voidClass = void.class;
+ System.out.println("void.class = " + voidClass);
+ }
+
+ public static void clearResolvedTypes(Class<?> c) {
+ if (!usingRI) {
+ nativeClearResolvedTypes(c);
+ }
+ }
+
+ public static native void nativeClearResolvedTypes(Class<?> c);
+
+ static boolean usingRI = false;
+}
diff --git a/test/536-checker-intrinsic-optimization/src/Main.java b/test/536-checker-intrinsic-optimization/src/Main.java
index 52f3f84406..e395e283e0 100644
--- a/test/536-checker-intrinsic-optimization/src/Main.java
+++ b/test/536-checker-intrinsic-optimization/src/Main.java
@@ -330,6 +330,21 @@ public class Main {
// Terminate the scope for the CHECK-NOT search at the reference or length comparison,
// whichever comes first.
/// CHECK: cmp {{w.*,}} {{w.*|#.*}}
+
+ /// CHECK-START-MIPS: boolean Main.stringArgumentNotNull(java.lang.Object) disassembly (after)
+ /// CHECK: InvokeVirtual {{.*\.equals.*}} intrinsic:StringEquals
+ /// CHECK-NOT: beq r0,
+ /// CHECK-NOT: beqz
+ /// CHECK-NOT: beqzc
+ // Terminate the scope for the CHECK-NOT search at the class field or length comparison,
+ // whichever comes first.
+ /// CHECK: lw
+
+ /// CHECK-START-MIPS64: boolean Main.stringArgumentNotNull(java.lang.Object) disassembly (after)
+ /// CHECK: InvokeVirtual {{.*\.equals.*}} intrinsic:StringEquals
+ /// CHECK-NOT: beqzc
+ // Terminate the scope for the CHECK-NOT search at the reference comparison.
+ /// CHECK: beqc
public static boolean stringArgumentNotNull(Object obj) {
obj.getClass();
return "foo".equals(obj);
@@ -384,6 +399,22 @@ public class Main {
/// CHECK-NOT: ldr {{w\d+}}, [{{x\d+}}]
/// CHECK-NOT: ldr {{w\d+}}, [{{x\d+}}, #0]
/// CHECK: cmp {{w\d+}}, {{w\d+|#.*}}
+
+ // Test is brittle as it depends on the class offset being 0.
+ /// CHECK-START-MIPS: boolean Main.stringArgumentIsString() disassembly (after)
+ /// CHECK: InvokeVirtual intrinsic:StringEquals
+ /// CHECK: beq{{(zc)?}}
+ // Check that we don't try to compare the classes.
+ /// CHECK-NOT: lw {{r\d+}}, +0({{r\d+}})
+ /// CHECK: bne{{c?}}
+
+ // Test is brittle as it depends on the class offset being 0.
+ /// CHECK-START-MIPS64: boolean Main.stringArgumentIsString() disassembly (after)
+ /// CHECK: InvokeVirtual intrinsic:StringEquals
+ /// CHECK: beqzc
+ // Check that we don't try to compare the classes.
+ /// CHECK-NOT: lw {{r\d+}}, +0({{r\d+}})
+ /// CHECK: bnec
public static boolean stringArgumentIsString() {
return "foo".equals(myString);
}
diff --git a/test/616-cha-abstract/src/Main.java b/test/616-cha-abstract/src/Main.java
index b33f575dec..e1d7db170d 100644
--- a/test/616-cha-abstract/src/Main.java
+++ b/test/616-cha-abstract/src/Main.java
@@ -39,8 +39,8 @@ class Main2 extends Main1 {
}
public class Main {
- static Base sMain1;
- static Base sMain2;
+ static Main1 sMain1;
+ static Main1 sMain2;
static boolean sIsOptimizing = true;
static boolean sHasJIT = true;
diff --git a/test/616-cha-interface-default/info.txt b/test/616-cha-interface-default/info.txt
deleted file mode 100644
index 1fd330afd4..0000000000
--- a/test/616-cha-interface-default/info.txt
+++ /dev/null
@@ -1 +0,0 @@
-Test for Class Hierarchy Analysis (CHA) on interface method.
diff --git a/test/616-cha-interface-default/run b/test/616-cha-interface-default/run
deleted file mode 100644
index d8b4f0d26c..0000000000
--- a/test/616-cha-interface-default/run
+++ /dev/null
@@ -1,18 +0,0 @@
-#!/bin/bash
-#
-# Copyright (C) 2017 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.
-
-# Run without an app image to prevent the classes to be loaded at startup.
-exec ${RUN} "${@}" --no-app-image
diff --git a/test/616-cha-interface-default/src/Main.java b/test/616-cha-interface-default/src/Main.java
deleted file mode 100644
index 81895b00ac..0000000000
--- a/test/616-cha-interface-default/src/Main.java
+++ /dev/null
@@ -1,176 +0,0 @@
-/*
- * Copyright (C) 2017 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 Base {
- default public void foo(int i) {
- if (i != 1) {
- printError("error1");
- }
- }
-
- default void printError(String msg) {
- System.out.println(msg);
- }
-}
-
-class Main1 implements Base {
-}
-
-class Main2 extends Main1 {
- public void bar() {}
-}
-
-class Main3 implements Base {
- public void foo(int i) {
- if (i != 3) {
- printError("error3");
- }
- }
-}
-
-public class Main {
- static Base sMain1;
- static Base sMain2;
- static Base sMain3;
-
- static boolean sIsOptimizing = true;
- static boolean sHasJIT = true;
- static volatile boolean sOtherThreadStarted;
-
- private static void assertSingleImplementation(Class<?> clazz, String method_name, boolean b) {
- if (hasSingleImplementation(clazz, method_name) != b) {
- System.out.println(clazz + "." + method_name +
- " doesn't have single implementation value of " + b);
- }
- }
-
- static int getValue(Class<?> cls) {
- if (cls == Main1.class || cls == Main2.class) {
- return 1;
- }
- return 3;
- }
-
- // sMain1.foo()/sMain2.foo() will be always be Base.foo() before Main3 is loaded/linked.
- // So sMain1.foo() can be devirtualized to Base.foo() and be inlined.
- // After Dummy.createMain3() which links in Main3, live testImplement() on stack
- // should be deoptimized.
- static void testImplement(boolean createMain3, boolean wait, boolean setHasJIT) {
- if (setHasJIT) {
- if (isInterpreted()) {
- sHasJIT = false;
- }
- return;
- }
-
- if (createMain3 && (sIsOptimizing || sHasJIT)) {
- assertIsManaged();
- }
-
- sMain1.foo(getValue(sMain1.getClass()));
- sMain2.foo(getValue(sMain2.getClass()));
-
- if (createMain3) {
- // Wait for the other thread to start.
- while (!sOtherThreadStarted);
- // Create an Main2 instance and assign it to sMain2.
- // sMain1 is kept the same.
- sMain3 = Dummy.createMain3();
- // Wake up the other thread.
- synchronized(Main.class) {
- Main.class.notify();
- }
- } else if (wait) {
- // This is the other thread.
- synchronized(Main.class) {
- sOtherThreadStarted = true;
- // Wait for Main2 to be linked and deoptimization is triggered.
- try {
- Main.class.wait();
- } catch (Exception e) {
- }
- }
- }
-
- // There should be a deoptimization here right after Main3 is linked by
- // calling Dummy.createMain3(), even though sMain1 didn't change.
- // The behavior here would be different if inline-cache is used, which
- // doesn't deoptimize since sMain1 still hits the type cache.
- sMain1.foo(getValue(sMain1.getClass()));
- if ((createMain3 || wait) && sHasJIT && !sIsOptimizing) {
- // This method should be deoptimized right after Main3 is created.
- assertIsInterpreted();
- }
-
- if (sMain3 != null) {
- sMain3.foo(getValue(sMain3.getClass()));
- }
- }
-
- // Test scenarios under which CHA-based devirtualization happens,
- // and class loading that implements a method can invalidate compiled code.
- public static void main(String[] args) {
- System.loadLibrary(args[0]);
-
- if (isInterpreted()) {
- sIsOptimizing = false;
- }
-
- // sMain1 is an instance of Main1.
- // sMain2 is an instance of Main2.
- // Neither Main1 nor Main2 override default method Base.foo().
- // Main3 hasn't bee loaded yet.
- sMain1 = new Main1();
- sMain2 = new Main2();
-
- ensureJitCompiled(Main.class, "testImplement");
- testImplement(false, false, true);
-
- if (sHasJIT && !sIsOptimizing) {
- assertSingleImplementation(Base.class, "foo", true);
- assertSingleImplementation(Main1.class, "foo", true);
- } else {
- // Main3 is verified ahead-of-time so it's linked in already.
- }
-
- // Create another thread that also calls sMain1.foo().
- // Try to test suspend and deopt another thread.
- new Thread() {
- public void run() {
- testImplement(false, true, false);
- }
- }.start();
-
- // This will create Main3 instance in the middle of testImplement().
- testImplement(true, false, false);
- assertSingleImplementation(Base.class, "foo", false);
- assertSingleImplementation(Main1.class, "foo", true);
- assertSingleImplementation(sMain3.getClass(), "foo", true);
- }
-
- private static native void ensureJitCompiled(Class<?> itf, String method_name);
- private static native void assertIsInterpreted();
- private static native void assertIsManaged();
- private static native boolean isInterpreted();
- private static native boolean hasSingleImplementation(Class<?> clazz, String method_name);
-}
-
-// Put createMain3() in another class to avoid class loading due to verifier.
-class Dummy {
- static Base createMain3() {
- return new Main3();
- }
-}
diff --git a/test/616-cha-interface/expected.txt b/test/616-cha-interface/expected.txt
deleted file mode 100644
index 6a5618ebc6..0000000000
--- a/test/616-cha-interface/expected.txt
+++ /dev/null
@@ -1 +0,0 @@
-JNI_OnLoad called
diff --git a/test/616-cha-interface/info.txt b/test/616-cha-interface/info.txt
deleted file mode 100644
index 1fd330afd4..0000000000
--- a/test/616-cha-interface/info.txt
+++ /dev/null
@@ -1 +0,0 @@
-Test for Class Hierarchy Analysis (CHA) on interface method.
diff --git a/test/616-cha-interface/src/Main.java b/test/616-cha-interface/src/Main.java
deleted file mode 100644
index aee6a95aa8..0000000000
--- a/test/616-cha-interface/src/Main.java
+++ /dev/null
@@ -1,159 +0,0 @@
-/*
- * Copyright (C) 2017 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 Base {
- void foo(int i);
-}
-
-class Main1 implements Base {
- public void foo(int i) {
- if (i != 1) {
- printError("error1");
- }
- }
-
- void printError(String msg) {
- System.out.println(msg);
- }
-}
-
-class Main2 extends Main1 {
- public void foo(int i) {
- if (i != 2) {
- printError("error2");
- }
- }
-}
-
-public class Main {
- static Base sMain1;
- static Base sMain2;
-
- static boolean sIsOptimizing = true;
- static boolean sHasJIT = true;
- static volatile boolean sOtherThreadStarted;
-
- private static void assertSingleImplementation(Class<?> clazz, String method_name, boolean b) {
- if (hasSingleImplementation(clazz, method_name) != b) {
- System.out.println(clazz + "." + method_name +
- " doesn't have single implementation value of " + b);
- }
- }
-
- // sMain1.foo() will be always be Main1.foo() before Main2 is loaded/linked.
- // So sMain1.foo() can be devirtualized to Main1.foo() and be inlined.
- // After Dummy.createMain2() which links in Main2, live testImplement() on stack
- // should be deoptimized.
- static void testImplement(boolean createMain2, boolean wait, boolean setHasJIT) {
- if (setHasJIT) {
- if (isInterpreted()) {
- sHasJIT = false;
- }
- return;
- }
-
- if (createMain2 && (sIsOptimizing || sHasJIT)) {
- assertIsManaged();
- }
-
- sMain1.foo(sMain1.getClass() == Main1.class ? 1 : 2);
-
- if (createMain2) {
- // Wait for the other thread to start.
- while (!sOtherThreadStarted);
- // Create an Main2 instance and assign it to sMain2.
- // sMain1 is kept the same.
- sMain2 = Dummy.createMain2();
- // Wake up the other thread.
- synchronized(Main.class) {
- Main.class.notify();
- }
- } else if (wait) {
- // This is the other thread.
- synchronized(Main.class) {
- sOtherThreadStarted = true;
- // Wait for Main2 to be linked and deoptimization is triggered.
- try {
- Main.class.wait();
- } catch (Exception e) {
- }
- }
- }
-
- // There should be a deoptimization here right after Main2 is linked by
- // calling Dummy.createMain2(), even though sMain1 didn't change.
- // The behavior here would be different if inline-cache is used, which
- // doesn't deoptimize since sMain1 still hits the type cache.
- sMain1.foo(sMain1.getClass() == Main1.class ? 1 : 2);
- if ((createMain2 || wait) && sHasJIT && !sIsOptimizing) {
- // This method should be deoptimized right after Main2 is created.
- assertIsInterpreted();
- }
-
- if (sMain2 != null) {
- sMain2.foo(sMain2.getClass() == Main1.class ? 1 : 2);
- }
- }
-
- // Test scenarios under which CHA-based devirtualization happens,
- // and class loading that overrides a method can invalidate compiled code.
- public static void main(String[] args) {
- System.loadLibrary(args[0]);
-
- if (isInterpreted()) {
- sIsOptimizing = false;
- }
-
- // sMain1 is an instance of Main1. Main2 hasn't bee loaded yet.
- sMain1 = new Main1();
-
- ensureJitCompiled(Main.class, "testImplement");
- testImplement(false, false, true);
-
- if (sHasJIT && !sIsOptimizing) {
- assertSingleImplementation(Base.class, "foo", true);
- assertSingleImplementation(Main1.class, "foo", true);
- } else {
- // Main2 is verified ahead-of-time so it's linked in already.
- }
-
- // Create another thread that also calls sMain1.foo().
- // Try to test suspend and deopt another thread.
- new Thread() {
- public void run() {
- testImplement(false, true, false);
- }
- }.start();
-
- // This will create Main2 instance in the middle of testImplement().
- testImplement(true, false, false);
- assertSingleImplementation(Base.class, "foo", false);
- assertSingleImplementation(Main1.class, "foo", false);
- }
-
- private static native void ensureJitCompiled(Class<?> itf, String method_name);
- private static native void assertIsInterpreted();
- private static native void assertIsManaged();
- private static native boolean isInterpreted();
- private static native boolean hasSingleImplementation(Class<?> clazz, String method_name);
-}
-
-// Put createMain2() in another class to avoid class loading due to verifier.
-class Dummy {
- static Main1 createMain2() {
- return new Main2();
- }
-}
diff --git a/test/616-cha-miranda/expected.txt b/test/616-cha-miranda/expected.txt
deleted file mode 100644
index 6a5618ebc6..0000000000
--- a/test/616-cha-miranda/expected.txt
+++ /dev/null
@@ -1 +0,0 @@
-JNI_OnLoad called
diff --git a/test/616-cha-miranda/info.txt b/test/616-cha-miranda/info.txt
deleted file mode 100644
index c46f33f613..0000000000
--- a/test/616-cha-miranda/info.txt
+++ /dev/null
@@ -1 +0,0 @@
-Test for Class Hierarchy Analysis (CHA) on miranda method.
diff --git a/test/616-cha-miranda/run b/test/616-cha-miranda/run
deleted file mode 100644
index d8b4f0d26c..0000000000
--- a/test/616-cha-miranda/run
+++ /dev/null
@@ -1,18 +0,0 @@
-#!/bin/bash
-#
-# Copyright (C) 2017 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.
-
-# Run without an app image to prevent the classes to be loaded at startup.
-exec ${RUN} "${@}" --no-app-image
diff --git a/test/616-cha-miranda/src/Main.java b/test/616-cha-miranda/src/Main.java
deleted file mode 100644
index e548482eb3..0000000000
--- a/test/616-cha-miranda/src/Main.java
+++ /dev/null
@@ -1,163 +0,0 @@
-/*
- * Copyright (C) 2017 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 void foo(int i);
-}
-
-abstract class Base implements Iface {
- // Iface.foo(int) will be added as a miranda method.
-
- void printError(String msg) {
- System.out.println(msg);
- }
-}
-
-class Main1 extends Base {
- public void foo(int i) {
- if (i != 1) {
- printError("error1");
- }
- }
-}
-
-class Main2 extends Main1 {
- public void foo(int i) {
- if (i != 2) {
- printError("error2");
- }
- }
-}
-
-public class Main {
- static Base sMain1;
- static Base sMain2;
-
- static boolean sIsOptimizing = true;
- static boolean sHasJIT = true;
- static volatile boolean sOtherThreadStarted;
-
- private static void assertSingleImplementation(Class<?> clazz, String method_name, boolean b) {
- if (hasSingleImplementation(clazz, method_name) != b) {
- System.out.println(clazz + "." + method_name +
- " doesn't have single implementation value of " + b);
- }
- }
-
- // sMain1.foo() will be always be Main1.foo() before Main2 is loaded/linked.
- // So sMain1.foo() can be devirtualized to Main1.foo() and be inlined.
- // After Dummy.createMain2() which links in Main2, live testOverride() on stack
- // should be deoptimized.
- static void testOverride(boolean createMain2, boolean wait, boolean setHasJIT) {
- if (setHasJIT) {
- if (isInterpreted()) {
- sHasJIT = false;
- }
- return;
- }
-
- if (createMain2 && (sIsOptimizing || sHasJIT)) {
- assertIsManaged();
- }
-
- sMain1.foo(sMain1.getClass() == Main1.class ? 1 : 2);
-
- if (createMain2) {
- // Wait for the other thread to start.
- while (!sOtherThreadStarted);
- // Create an Main2 instance and assign it to sMain2.
- // sMain1 is kept the same.
- sMain2 = Dummy.createMain2();
- // Wake up the other thread.
- synchronized(Main.class) {
- Main.class.notify();
- }
- } else if (wait) {
- // This is the other thread.
- synchronized(Main.class) {
- sOtherThreadStarted = true;
- // Wait for Main2 to be linked and deoptimization is triggered.
- try {
- Main.class.wait();
- } catch (Exception e) {
- }
- }
- }
-
- // There should be a deoptimization here right after Main2 is linked by
- // calling Dummy.createMain2(), even though sMain1 didn't change.
- // The behavior here would be different if inline-cache is used, which
- // doesn't deoptimize since sMain1 still hits the type cache.
- sMain1.foo(sMain1.getClass() == Main1.class ? 1 : 2);
- if ((createMain2 || wait) && sHasJIT && !sIsOptimizing) {
- // This method should be deoptimized right after Main2 is created.
- assertIsInterpreted();
- }
-
- if (sMain2 != null) {
- sMain2.foo(sMain2.getClass() == Main1.class ? 1 : 2);
- }
- }
-
- // Test scenarios under which CHA-based devirtualization happens,
- // and class loading that overrides a method can invalidate compiled code.
- public static void main(String[] args) {
- System.loadLibrary(args[0]);
-
- if (isInterpreted()) {
- sIsOptimizing = false;
- }
-
- // sMain1 is an instance of Main1. Main2 hasn't bee loaded yet.
- sMain1 = new Main1();
-
- ensureJitCompiled(Main.class, "testOverride");
- testOverride(false, false, true);
-
- if (sHasJIT && !sIsOptimizing) {
- assertSingleImplementation(Base.class, "foo", true);
- assertSingleImplementation(Main1.class, "foo", true);
- } else {
- // Main2 is verified ahead-of-time so it's linked in already.
- }
-
- // Create another thread that also calls sMain1.foo().
- // Try to test suspend and deopt another thread.
- new Thread() {
- public void run() {
- testOverride(false, true, false);
- }
- }.start();
-
- // This will create Main2 instance in the middle of testOverride().
- testOverride(true, false, false);
- assertSingleImplementation(Base.class, "foo", false);
- assertSingleImplementation(Main1.class, "foo", false);
- }
-
- private static native void ensureJitCompiled(Class<?> itf, String method_name);
- private static native void assertIsInterpreted();
- private static native void assertIsManaged();
- private static native boolean isInterpreted();
- private static native boolean hasSingleImplementation(Class<?> clazz, String method_name);
-}
-
-// Put createMain2() in another class to avoid class loading due to verifier.
-class Dummy {
- static Main1 createMain2() {
- return new Main2();
- }
-}
diff --git a/test/913-heaps/expected.txt b/test/913-heaps/expected.txt
index 46805d7272..c96edef903 100644
--- a/test/913-heaps/expected.txt
+++ b/test/913-heaps/expected.txt
@@ -79,8 +79,9 @@ root@root --(thread)--> 3000@0 [size=132, length=-1]
5@1002 --(field@28)--> 1@1000 [size=16, length=-1]
6@1000 --(class)--> 1000@0 [size=123, length=-1]
---
-[1@0 (32, 'HelloWorld')]
+[1@0 (32, 'HelloWorld'), 2@0 (16, '')]
2
+3
2@0 (15, 3xB '010203')
3@0 (16, 2xC '41005a00')
8@0 (32, 2xD '0000000000000000000000000000f03f')
@@ -128,7 +129,6 @@ root@root --(thread)--> 1@1000 [size=16, length=-1]
---- untagged objects
root@root --(stack-local[id=1,tag=3000,depth=2,method=doFollowReferencesTestNonRoot,vreg=13,location= 32])--> 1@1000 [size=16, length=-1]
root@root --(stack-local[id=1,tag=3000,depth=3,method=doFollowReferencesTest,vreg=1,location= 28])--> 3000@0 [size=132, length=-1]
-root@root --(system-class)--> 2@0 [size=32, length=-1]
root@root --(thread)--> 3000@0 [size=132, length=-1]
0@0 --(array-element@0)--> 1@1000 [size=16, length=-1]
1001@0 --(superclass)--> 1000@0 [size=123, length=-1]
@@ -170,7 +170,6 @@ root@root --(jni-local[id=1,tag=3000,depth=0,method=followReferences])--> 1@1000
root@root --(stack-local[id=1,tag=3000,depth=1,method=doFollowReferencesTestImpl,vreg=13,location= 10])--> 1@1000 [size=16, length=-1]
root@root --(stack-local[id=1,tag=3000,depth=1,method=doFollowReferencesTestImpl,vreg=5,location= 10])--> 1@1000 [size=16, length=-1]
root@root --(stack-local[id=1,tag=3000,depth=2,method=doFollowReferencesTestRoot,vreg=4,location= 19])--> 1@1000 [size=16, length=-1]
-root@root --(system-class)--> 2@0 [size=32, length=-1]
root@root --(thread)--> 1@1000 [size=16, length=-1]
root@root --(thread)--> 3000@0 [size=132, length=-1]
1001@0 --(superclass)--> 1000@0 [size=123, length=-1]
@@ -209,7 +208,6 @@ root@root --(thread)--> 3000@0 [size=132, length=-1]
---
---- tagged classes
root@root --(stack-local[id=1,tag=3000,depth=3,method=doFollowReferencesTest,vreg=1,location= 28])--> 3000@0 [size=132, length=-1]
-root@root --(system-class)--> 2@0 [size=32, length=-1]
root@root --(thread)--> 3000@0 [size=132, length=-1]
1001@0 --(superclass)--> 1000@0 [size=123, length=-1]
1002@0 --(interface)--> 2001@0 [size=124, length=-1]
@@ -233,7 +231,6 @@ root@root --(thread)--> 3000@0 [size=132, length=-1]
5@1002 --(class)--> 1002@0 [size=123, length=-1]
6@1000 --(class)--> 1000@0 [size=123, length=-1]
---
-root@root --(system-class)--> 2@0 [size=32, length=-1]
root@root --(thread)--> 3000@0 [size=132, length=-1]
1001@0 --(superclass)--> 1000@0 [size=123, length=-1]
1002@0 --(interface)--> 2001@0 [size=124, length=-1]
diff --git a/test/913-heaps/src/Main.java b/test/913-heaps/src/Main.java
index df89f347e0..14ee2687ec 100644
--- a/test/913-heaps/src/Main.java
+++ b/test/913-heaps/src/Main.java
@@ -25,9 +25,19 @@ public class Main {
doTest();
new TestConfig().doFollowReferencesTest();
+ Runtime.getRuntime().gc();
+ Runtime.getRuntime().gc();
+
doStringTest();
+
+ Runtime.getRuntime().gc();
+ Runtime.getRuntime().gc();
+
doPrimitiveArrayTest();
+ Runtime.getRuntime().gc();
+ Runtime.getRuntime().gc();
+
// Test klass filter.
System.out.println("--- klass ---");
new TestConfig(A.class, 0).doFollowReferencesTest();
@@ -53,14 +63,18 @@ public class Main {
}
public static void doStringTest() throws Exception {
- final String str = "HelloWorld";
+ final String str = new String("HelloWorld");
+ final String str2 = new String("");
Object o = new Object() {
String s = str;
+ String s2 = str2;
};
setTag(str, 1);
+ setTag(str2, 2);
System.out.println(Arrays.toString(followReferencesString(o)));
System.out.println(getTag(str));
+ System.out.println(getTag(str2));
}
public static void doPrimitiveArrayTest() throws Exception {
diff --git a/test/common/runtime_state.cc b/test/common/runtime_state.cc
index a841f9e6a2..c7a57cefb6 100644
--- a/test/common/runtime_state.cc
+++ b/test/common/runtime_state.cc
@@ -180,6 +180,9 @@ extern "C" JNIEXPORT void JNICALL Java_Main_ensureJitCompiled(JNIEnv* env,
}
jit::JitCodeCache* code_cache = jit->GetCodeCache();
+ // Update the code cache to make sure the JIT code does not get deleted.
+ // Note: this will apply to all JIT compilations.
+ code_cache->SetGarbageCollectCode(false);
while (true) {
const void* pc = method->GetEntryPointFromQuickCompiledCode();
if (code_cache->ContainsPc(pc)) {
diff --git a/test/etc/run-test-jar b/test/etc/run-test-jar
index f3d4332009..99926aa9a3 100755
--- a/test/etc/run-test-jar
+++ b/test/etc/run-test-jar
@@ -371,6 +371,22 @@ fi
if [ "$HAVE_IMAGE" = "n" ]; then
+ if [ "${HOST}" = "y" ]; then
+ framework="${ANDROID_HOST_OUT}/framework"
+ bpath_suffix="-hostdex"
+ else
+ framework="${ANDROID_ROOT}/framework"
+ bpath_suffix=""
+ fi
+ # TODO If the target was compiled WITH_DEXPREOPT=true then these tests will
+ # fail since these jar files will be stripped.
+ bpath="${framework}/core-libart${bpath_suffix}.jar"
+ bpath="${bpath}:${framework}/core-oj${bpath_suffix}.jar"
+ bpath="${bpath}:${framework}/conscrypt${bpath_suffix}.jar"
+ bpath="${bpath}:${framework}/okhttp${bpath_suffix}.jar"
+ bpath="${bpath}:${framework}/bouncycastle${bpath_suffix}.jar"
+ # Pass down the bootclasspath
+ FLAGS="${FLAGS} -Xbootclasspath:${bpath}"
# Add 5 minutes to give some time to generate the boot image.
TIME_OUT_VALUE=$((${TIME_OUT_VALUE} + 300))
DALVIKVM_BOOT_OPT="-Ximage:/system/non-existant/core.art"
diff --git a/test/run-test b/test/run-test
index 6134a14696..7d3d813da0 100755
--- a/test/run-test
+++ b/test/run-test
@@ -530,22 +530,6 @@ if [ "$have_image" = "no" ]; then
err_echo "--no-image is only supported on the art runtime"
exit 1
fi
- if [ "$target_mode" = "no" ]; then
- framework="${ANDROID_HOST_OUT}/framework"
- bpath_suffix="-hostdex"
- else
- framework="${android_root}/framework"
- bpath_suffix=""
- fi
- # TODO If the target was compiled WITH_DEXPREOPT=true then these tests will
- # fail since these jar files will be stripped.
- bpath="${framework}/core-libart${bpath_suffix}.jar"
- bpath="${bpath}:${framework}/core-oj${bpath_suffix}.jar"
- bpath="${bpath}:${framework}/conscrypt${bpath_suffix}.jar"
- bpath="${bpath}:${framework}/okhttp${bpath_suffix}.jar"
- bpath="${bpath}:${framework}/bouncycastle${bpath_suffix}.jar"
- # Pass down the bootclasspath
- run_args="${run_args} --runtime-option -Xbootclasspath:${bpath}"
run_args="${run_args} --no-image"
fi
diff --git a/test/testrunner/env.py b/test/testrunner/env.py
index 4336d7772f..ed4b4a9f3e 100644
--- a/test/testrunner/env.py
+++ b/test/testrunner/env.py
@@ -178,6 +178,8 @@ ART_TEST_WITH_STRACE = getEnvBoolean('ART_TEST_DEBUG_GC', False)
EXTRA_DISABLED_TESTS = set(env.get("ART_TEST_RUN_TEST_SKIP", "").split())
+ART_TEST_RUN_TEST_BUILD = getEnvBoolean('ART_TEST_RUN_TEST_BUILD', False)
+
TARGET_2ND_ARCH = get_build_var('TARGET_2ND_ARCH')
TARGET_ARCH = get_build_var('TARGET_ARCH')
if TARGET_2ND_ARCH:
diff --git a/test/testrunner/testrunner.py b/test/testrunner/testrunner.py
index c22b0be9f4..9c8d3b870c 100755
--- a/test/testrunner/testrunner.py
+++ b/test/testrunner/testrunner.py
@@ -704,7 +704,6 @@ def parse_test_name(test_name):
return {match.group(12)}
raise ValueError(test_name + " is not a valid test")
-
def parse_option():
global verbose
global dry_run
@@ -726,7 +725,15 @@ def parse_option():
parser.add_argument('--dry-run', action='store_true', dest='dry_run')
parser.add_argument("--skip", action="append", dest="skips", default=[],
help="Skip the given test in all circumstances.")
- parser.add_argument('-b', '--build-dependencies', action='store_true', dest='build')
+ parser.add_argument('--no-build-dependencies',
+ action='store_false', dest='build',
+ help="Don't build dependencies under any circumstances. This is the " +
+ "behavior if ART_TEST_RUN_TEST_ALWAYS_BUILD is not set to 'true'.")
+ parser.add_argument('-b', '--build-dependencies',
+ action='store_true', dest='build',
+ help="Build dependencies under all circumstances. By default we will " +
+ "not build dependencies unless ART_TEST_RUN_TEST_BUILD=true.")
+ parser.set_defaults(build = env.ART_TEST_RUN_TEST_BUILD)
parser.add_argument('--gdb', action='store_true', dest='gdb')
parser.add_argument('--gdb-arg', dest='gdb_arg')
@@ -804,8 +811,7 @@ def parse_option():
if options.dry_run:
dry_run = True
verbose = True
- if options.build:
- build = True
+ build = options.build
if options.gdb:
n_thread = 1
gdb = True