summaryrefslogtreecommitdiff
path: root/test
diff options
context:
space:
mode:
Diffstat (limited to 'test')
-rw-r--r--test/004-NativeAllocations/src/Main.java30
-rw-r--r--test/098-ddmc/src/Main.java16
-rw-r--r--test/135-MirandaDispatch/expected.txt1
-rw-r--r--test/135-MirandaDispatch/smali/b_21646347.smali15
-rw-r--r--test/135-MirandaDispatch/src/Main.java9
-rw-r--r--test/137-cfi/cfi.cc14
-rw-r--r--test/137-cfi/src/Main.java25
-rw-r--r--test/441-checker-inliner/src/Main.java12
-rw-r--r--test/449-checker-bce/src/Main.java167
-rw-r--r--test/450-checker-types/src/Main.java12
-rw-r--r--test/478-checker-clinit-check-pruning/src/Main.java6
-rw-r--r--test/491-current-method/expected.txt0
-rw-r--r--test/491-current-method/info.txt2
-rw-r--r--test/491-current-method/src/Main.java70
-rw-r--r--test/492-checker-inline-invoke-interface/expected.txt5
-rw-r--r--test/492-checker-inline-invoke-interface/info.txt1
-rw-r--r--test/492-checker-inline-invoke-interface/src/Main.java50
-rw-r--r--test/493-checker-inline-invoke-interface/expected.txt5
-rw-r--r--test/493-checker-inline-invoke-interface/info.txt2
-rw-r--r--test/493-checker-inline-invoke-interface/src/Main.java48
-rw-r--r--test/494-checker-instanceof-tests/expected.txt0
-rw-r--r--test/494-checker-instanceof-tests/info.txt1
-rw-r--r--test/494-checker-instanceof-tests/src/Main.java203
-rw-r--r--test/495-checker-checkcast-tests/expected.txt0
-rw-r--r--test/495-checker-checkcast-tests/info.txt1
-rw-r--r--test/495-checker-checkcast-tests/src/Main.java204
-rw-r--r--test/800-smali/expected.txt1
-rw-r--r--test/800-smali/smali/b_17410612.smali14
-rw-r--r--test/800-smali/src/Main.java2
-rw-r--r--test/Android.libarttest.mk1
-rw-r--r--test/Android.libnativebridgetest.mk1
-rw-r--r--test/Android.run-test.mk24
-rwxr-xr-xtest/etc/run-test-jar4
-rwxr-xr-xtest/run-test7
34 files changed, 891 insertions, 62 deletions
diff --git a/test/004-NativeAllocations/src/Main.java b/test/004-NativeAllocations/src/Main.java
index a99fe92081..92f4e21f40 100644
--- a/test/004-NativeAllocations/src/Main.java
+++ b/test/004-NativeAllocations/src/Main.java
@@ -19,6 +19,8 @@ import java.lang.Runtime;
public class Main {
static Object nativeLock = new Object();
+ static Object deadlockLock = new Object();
+ static boolean aboutToDeadlockLock = false;
static int nativeBytes = 0;
static Object runtime;
static Method register_native_allocation;
@@ -28,13 +30,15 @@ public class Main {
static class NativeAllocation {
private int bytes;
- NativeAllocation(int bytes) throws Exception {
+ NativeAllocation(int bytes, boolean testingDeadlock) throws Exception {
this.bytes = bytes;
register_native_allocation.invoke(runtime, bytes);
synchronized (nativeLock) {
- nativeBytes += bytes;
- if (nativeBytes > maxMem) {
- throw new OutOfMemoryError();
+ if (!testingDeadlock) {
+ nativeBytes += bytes;
+ if (nativeBytes > maxMem) {
+ throw new OutOfMemoryError();
+ }
}
}
}
@@ -44,6 +48,9 @@ public class Main {
nativeBytes -= bytes;
}
register_native_free.invoke(runtime, bytes);
+ aboutToDeadlockLock = true;
+ synchronized (deadlockLock) {
+ }
}
}
@@ -59,7 +66,20 @@ public class Main {
int allocation_count = 256;
NativeAllocation[] allocations = new NativeAllocation[count];
for (int i = 0; i < allocation_count; ++i) {
- allocations[i % count] = new NativeAllocation(size);
+ allocations[i % count] = new NativeAllocation(size, false);
+ }
+ // Test that we don't get a deadlock if we are holding nativeLock. If there is no timeout,
+ // then we will get a finalizer timeout exception.
+ aboutToDeadlockLock = false;
+ synchronized (deadlockLock) {
+ for (int i = 0; aboutToDeadlockLock != true; ++i) {
+ allocations[i % count] = new NativeAllocation(size, true);
+ }
+ // Do more allocations now that the finalizer thread is deadlocked so that we force
+ // finalization and timeout.
+ for (int i = 0; i < 10; ++i) {
+ allocations[i % count] = new NativeAllocation(size, true);
+ }
}
System.out.println("Test complete");
}
diff --git a/test/098-ddmc/src/Main.java b/test/098-ddmc/src/Main.java
index f41ff2a94a..4914ba2289 100644
--- a/test/098-ddmc/src/Main.java
+++ b/test/098-ddmc/src/Main.java
@@ -43,14 +43,24 @@ public class Main {
System.out.println("Confirm when we overflow, we don't roll over to zero. b/17392248");
final int overflowAllocations = 64 * 1024; // Won't fit in unsigned 16-bit value.
+ // TODO: Temporary fix. Keep the new objects live so they are not garbage collected.
+ // This will cause OOM exception for GC stress tests. The root cause is changed behaviour of
+ // getRecentAllocations(). Working on restoring its old behaviour. b/20037135
+ Object[] objects = new Object[overflowAllocations];
for (int i = 0; i < overflowAllocations; i++) {
- new Object();
+ objects[i] = new Object();
}
Allocations after = new Allocations(DdmVmInternal.getRecentAllocations());
System.out.println("before < overflowAllocations=" + (before.numberOfEntries < overflowAllocations));
System.out.println("after > before=" + (after.numberOfEntries > before.numberOfEntries));
System.out.println("after.numberOfEntries=" + after.numberOfEntries);
+ // TODO: Temporary fix as above. b/20037135
+ objects = null;
+ Runtime.getRuntime().gc();
+ final int fillerStrings = 16 * 1024;
+ String[] strings = new String[fillerStrings];
+
System.out.println("Disable and confirm back to empty");
DdmVmInternal.enableRecentAllocations(false);
System.out.println("status=" + DdmVmInternal.getRecentAllocationStatus());
@@ -66,8 +76,8 @@ public class Main {
System.out.println("Confirm we can reenable twice in a row without losing allocations");
DdmVmInternal.enableRecentAllocations(true);
System.out.println("status=" + DdmVmInternal.getRecentAllocationStatus());
- for (int i = 0; i < 16 * 1024; i++) {
- new String("fnord");
+ for (int i = 0; i < fillerStrings; i++) {
+ strings[i] = new String("fnord");
}
Allocations first = new Allocations(DdmVmInternal.getRecentAllocations());
DdmVmInternal.enableRecentAllocations(true);
diff --git a/test/135-MirandaDispatch/expected.txt b/test/135-MirandaDispatch/expected.txt
index 134d8d0b47..5b098e5fac 100644
--- a/test/135-MirandaDispatch/expected.txt
+++ b/test/135-MirandaDispatch/expected.txt
@@ -1 +1,2 @@
+b/21646347
Finishing
diff --git a/test/135-MirandaDispatch/smali/b_21646347.smali b/test/135-MirandaDispatch/smali/b_21646347.smali
new file mode 100644
index 0000000000..b4979a5357
--- /dev/null
+++ b/test/135-MirandaDispatch/smali/b_21646347.smali
@@ -0,0 +1,15 @@
+.class public LB21646347;
+
+# If an invoke-virtual dispatches to a miranda method, ensure that we test for the receiver
+# being a subclass of the abstract class, not postpone the check because the miranda method's
+# declaring class is an interface.
+
+.super Ljava/lang/Object;
+
+.method public static run(LB21646347;)V
+ .registers 1
+ # Invoke the miranda method on an object of this class. This should fail type-checking,
+ # instead of letting this pass as the declaring class is an interface.
+ invoke-virtual {v0}, LMain$AbstractClass;->m()V
+ return-void
+.end method
diff --git a/test/135-MirandaDispatch/src/Main.java b/test/135-MirandaDispatch/src/Main.java
index bb005b0103..ada8cefead 100644
--- a/test/135-MirandaDispatch/src/Main.java
+++ b/test/135-MirandaDispatch/src/Main.java
@@ -46,6 +46,15 @@ public class Main {
if (counter != loopIterations * loopIterations) {
System.out.println("Expected " + loopIterations * loopIterations + " got " + counter);
}
+
+ try {
+ Class<?> b21646347 = Class.forName("B21646347");
+ throw new RuntimeException("Expected a VerifyError");
+ } catch (VerifyError expected) {
+ System.out.println("b/21646347");
+ } catch (Throwable t) {
+ t.printStackTrace();
+ }
System.out.println("Finishing");
}
}
diff --git a/test/137-cfi/cfi.cc b/test/137-cfi/cfi.cc
index b2d7e55214..83f77114f6 100644
--- a/test/137-cfi/cfi.cc
+++ b/test/137-cfi/cfi.cc
@@ -73,6 +73,13 @@ 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());
+ for (Backtrace::const_iterator it = bt->begin(); it != bt->end(); ++it) {
+ if (BacktraceMap::IsValid(it->map)) {
+ printf(" %s\n", it->func_name.c_str());
+ }
+ }
+
return false;
}
#endif
@@ -83,8 +90,10 @@ 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");
return JNI_FALSE;
} else if (bt->NumFrames() == 0) {
+ printf("No frames for unwind in process.\n");
return JNI_FALSE;
}
@@ -94,6 +103,7 @@ extern "C" JNIEXPORT jboolean JNICALL Java_Main_unwindInProcess(JNIEnv*, jobject
std::vector<std::string> seq = {
"Java_Main_unwindInProcess", // This function.
"boolean Main.unwindInProcess(int, boolean)", // The corresponding Java native method frame.
+ "int java.util.Arrays.binarySearch(java.lang.Object[], int, int, java.lang.Object, java.util.Comparator)", // Framework method.
"void Main.main(java.lang.String[])" // The Java entry method.
};
@@ -155,6 +165,7 @@ extern "C" JNIEXPORT jboolean JNICALL Java_Main_unwindOtherProcess(JNIEnv*, jobj
if (ptrace(PTRACE_ATTACH, pid, 0, 0)) {
// Were not able to attach, bad.
+ printf("Failed to attach to other process.\n");
PLOG(ERROR) << "Failed to attach.";
kill(pid, SIGCONT);
return JNI_FALSE;
@@ -172,8 +183,10 @@ 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");
result = false;
} else if (bt->NumFrames() == 0) {
+ printf("No frames for unwind of other process.\n");
result = false;
}
@@ -185,6 +198,7 @@ extern "C" JNIEXPORT jboolean JNICALL Java_Main_unwindOtherProcess(JNIEnv*, jobj
// Note: For some reason, the name isn't
// resolved, so don't look for it right now.
"boolean Main.sleep(int, boolean, double)", // The corresponding Java native method frame.
+ "int java.util.Arrays.binarySearch(java.lang.Object[], int, int, java.lang.Object, java.util.Comparator)", // Framework method.
"void Main.main(java.lang.String[])" // The Java entry method.
};
diff --git a/test/137-cfi/src/Main.java b/test/137-cfi/src/Main.java
index e184e66e6f..658ba53099 100644
--- a/test/137-cfi/src/Main.java
+++ b/test/137-cfi/src/Main.java
@@ -20,8 +20,10 @@ import java.io.InputStream;
import java.io.OutputStream;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
+import java.util.Arrays;
+import java.util.Comparator;
-public class Main {
+public class Main implements Comparator<Main> {
// Whether to test local unwinding. Libunwind uses linker info to find executables. As we do
// not dlopen at the moment, this doesn't work, so keep it off for now.
public final static boolean TEST_LOCAL_UNWINDING = false;
@@ -32,6 +34,8 @@ public class Main {
private boolean secondary;
+ private boolean passed;
+
public Main(boolean secondary) {
this.secondary = secondary;
}
@@ -60,13 +64,13 @@ public class Main {
}
private void runSecondary() {
- foo(true);
+ foo();
throw new RuntimeException("Didn't expect to get back...");
}
private void runPrimary() {
// First do the in-process unwinding.
- if (TEST_LOCAL_UNWINDING && !foo(false)) {
+ if (TEST_LOCAL_UNWINDING && !foo()) {
System.out.println("Unwinding self failed.");
}
@@ -134,8 +138,19 @@ public class Main {
}
}
- public boolean foo(boolean b) {
- return bar(b);
+ public boolean foo() {
+ // Call bar via Arrays.binarySearch.
+ // This tests that we can unwind from framework code.
+ Main[] array = { this, this, this };
+ Arrays.binarySearch(array, 0, 3, this /* value */, this /* comparator */);
+ return passed;
+ }
+
+ public int compare(Main lhs, Main rhs) {
+ passed = bar(secondary);
+ // Returning "equal" ensures that we terminate search
+ // after first item and thus call bar() only once.
+ return 0;
}
public boolean bar(boolean b) {
diff --git a/test/441-checker-inliner/src/Main.java b/test/441-checker-inliner/src/Main.java
index df969a488e..3899d7fb26 100644
--- a/test/441-checker-inliner/src/Main.java
+++ b/test/441-checker-inliner/src/Main.java
@@ -19,7 +19,7 @@ public class Main {
/// CHECK-START: void Main.InlineVoid() inliner (before)
/// CHECK-DAG: <<Const42:i\d+>> IntConstant 42
/// CHECK-DAG: InvokeStaticOrDirect
- /// CHECK-DAG: InvokeStaticOrDirect [<<Const42>>]
+ /// CHECK-DAG: InvokeStaticOrDirect [<<Const42>>,{{[ij]\d+}}]
/// CHECK-START: void Main.InlineVoid() inliner (after)
/// CHECK-NOT: InvokeStaticOrDirect
@@ -31,7 +31,7 @@ public class Main {
/// CHECK-START: int Main.InlineParameter(int) inliner (before)
/// CHECK-DAG: <<Param:i\d+>> ParameterValue
- /// CHECK-DAG: <<Result:i\d+>> InvokeStaticOrDirect [<<Param>>]
+ /// CHECK-DAG: <<Result:i\d+>> InvokeStaticOrDirect [<<Param>>,{{[ij]\d+}}]
/// CHECK-DAG: Return [<<Result>>]
/// CHECK-START: int Main.InlineParameter(int) inliner (after)
@@ -44,7 +44,7 @@ public class Main {
/// CHECK-START: long Main.InlineWideParameter(long) inliner (before)
/// CHECK-DAG: <<Param:j\d+>> ParameterValue
- /// CHECK-DAG: <<Result:j\d+>> InvokeStaticOrDirect [<<Param>>]
+ /// CHECK-DAG: <<Result:j\d+>> InvokeStaticOrDirect [<<Param>>,{{[ij]\d+}}]
/// CHECK-DAG: Return [<<Result>>]
/// CHECK-START: long Main.InlineWideParameter(long) inliner (after)
@@ -57,7 +57,7 @@ public class Main {
/// CHECK-START: java.lang.Object Main.InlineReferenceParameter(java.lang.Object) inliner (before)
/// CHECK-DAG: <<Param:l\d+>> ParameterValue
- /// CHECK-DAG: <<Result:l\d+>> InvokeStaticOrDirect [<<Param>>]
+ /// CHECK-DAG: <<Result:l\d+>> InvokeStaticOrDirect [<<Param>>,{{[ij]\d+}}]
/// CHECK-DAG: Return [<<Result>>]
/// CHECK-START: java.lang.Object Main.InlineReferenceParameter(java.lang.Object) inliner (after)
@@ -130,8 +130,8 @@ public class Main {
/// CHECK-DAG: <<Const1:i\d+>> IntConstant 1
/// CHECK-DAG: <<Const3:i\d+>> IntConstant 3
/// CHECK-DAG: <<Const5:i\d+>> IntConstant 5
- /// CHECK-DAG: <<Add:i\d+>> InvokeStaticOrDirect [<<Const1>>,<<Const3>>]
- /// CHECK-DAG: <<Sub:i\d+>> InvokeStaticOrDirect [<<Const5>>,<<Const3>>]
+ /// CHECK-DAG: <<Add:i\d+>> InvokeStaticOrDirect [<<Const1>>,<<Const3>>,{{[ij]\d+}}]
+ /// CHECK-DAG: <<Sub:i\d+>> InvokeStaticOrDirect [<<Const5>>,<<Const3>>,{{[ij]\d+}}]
/// CHECK-DAG: <<Phi:i\d+>> Phi [<<Add>>,<<Sub>>]
/// CHECK-DAG: Return [<<Phi>>]
diff --git a/test/449-checker-bce/src/Main.java b/test/449-checker-bce/src/Main.java
index 8960df896b..ed6fc1ee2b 100644
--- a/test/449-checker-bce/src/Main.java
+++ b/test/449-checker-bce/src/Main.java
@@ -617,15 +617,21 @@ public class Main {
/// CHECK: ArrayGet
/// CHECK-START: void Main.foo1(int[], int, int) BCE (after)
- /// CHECK: Deoptimize
- /// CHECK: Deoptimize
- /// CHECK: Deoptimize
- /// CHECK-NOT: Deoptimize
/// CHECK: Phi
/// CHECK-NOT: BoundsCheck
/// CHECK: ArraySet
/// CHECK-NOT: BoundsCheck
/// CHECK: ArrayGet
+ // Added blocks for deoptimization.
+ /// CHECK: If
+ /// CHECK: Goto
+ /// CHECK: Deoptimize
+ /// CHECK: Deoptimize
+ /// CHECK: Deoptimize
+ /// CHECK-NOT: Deoptimize
+ /// CHECK: Goto
+ /// CHECK: Phi
+ /// CHECK: Goto
void foo1(int[] array, int start, int end) {
// Three HDeoptimize will be added. One for
@@ -646,15 +652,21 @@ public class Main {
/// CHECK: ArrayGet
/// CHECK-START: void Main.foo2(int[], int, int) BCE (after)
- /// CHECK: Deoptimize
- /// CHECK: Deoptimize
- /// CHECK: Deoptimize
- /// CHECK-NOT: Deoptimize
/// CHECK: Phi
/// CHECK-NOT: BoundsCheck
/// CHECK: ArraySet
/// CHECK-NOT: BoundsCheck
/// CHECK: ArrayGet
+ // Added blocks for deoptimization.
+ /// CHECK: If
+ /// CHECK: Goto
+ /// CHECK: Deoptimize
+ /// CHECK: Deoptimize
+ /// CHECK: Deoptimize
+ /// CHECK-NOT: Deoptimize
+ /// CHECK: Goto
+ /// CHECK: Phi
+ /// CHECK: Goto
void foo2(int[] array, int start, int end) {
// Three HDeoptimize will be added. One for
@@ -675,14 +687,20 @@ public class Main {
/// CHECK: ArrayGet
/// CHECK-START: void Main.foo3(int[], int) BCE (after)
- /// CHECK: Deoptimize
- /// CHECK: Deoptimize
- /// CHECK-NOT: Deoptimize
/// CHECK: Phi
/// CHECK-NOT: BoundsCheck
/// CHECK: ArraySet
/// CHECK-NOT: BoundsCheck
/// CHECK: ArrayGet
+ // Added blocks for deoptimization.
+ /// CHECK: If
+ /// CHECK: Goto
+ /// CHECK: Deoptimize
+ /// CHECK: Deoptimize
+ /// CHECK-NOT: Deoptimize
+ /// CHECK: Goto
+ /// CHECK: Phi
+ /// CHECK: Goto
void foo3(int[] array, int end) {
// Two HDeoptimize will be added. One for end < array.length,
@@ -694,6 +712,7 @@ public class Main {
}
}
+
/// CHECK-START: void Main.foo4(int[], int) BCE (before)
/// CHECK: BoundsCheck
/// CHECK: ArraySet
@@ -701,14 +720,20 @@ public class Main {
/// CHECK: ArrayGet
/// CHECK-START: void Main.foo4(int[], int) BCE (after)
- /// CHECK: Deoptimize
- /// CHECK: Deoptimize
- /// CHECK-NOT: Deoptimize
/// CHECK: Phi
/// CHECK-NOT: BoundsCheck
/// CHECK: ArraySet
/// CHECK-NOT: BoundsCheck
/// CHECK: ArrayGet
+ // Added blocks for deoptimization.
+ /// CHECK: If
+ /// CHECK: Goto
+ /// CHECK: Deoptimize
+ /// CHECK: Deoptimize
+ /// CHECK-NOT: Deoptimize
+ /// CHECK: Goto
+ /// CHECK: Phi
+ /// CHECK: Goto
void foo4(int[] array, int end) {
// Two HDeoptimize will be added. One for end <= array.length,
@@ -734,8 +759,6 @@ public class Main {
/// CHECK-START: void Main.foo5(int[], int) BCE (after)
/// CHECK-NOT: BoundsCheck
/// CHECK: ArraySet
- /// CHECK: Deoptimize
- /// CHECK-NOT: Deoptimize
/// CHECK: Phi
/// CHECK-NOT: BoundsCheck
/// CHECK: ArrayGet
@@ -743,6 +766,15 @@ public class Main {
/// CHECK: ArrayGet
/// CHECK-NOT: BoundsCheck
/// CHECK: ArrayGet
+ // Added blocks for deoptimization.
+ /// CHECK: If
+ /// CHECK: Goto
+ /// CHECK: Deoptimize
+ /// CHECK-NOT: Deoptimize
+ /// CHECK: Goto
+ // array.length is defined before the loop header so no phi is needed.
+ /// CHECK-NOT: Phi
+ /// CHECK: Goto
void foo5(int[] array, int end) {
// Bounds check in this loop can be eliminated without deoptimization.
@@ -774,10 +806,6 @@ public class Main {
/// CHECK: ArraySet
/// CHECK-START: void Main.foo6(int[], int, int) BCE (after)
- /// CHECK: Deoptimize
- /// CHECK: Deoptimize
- /// CHECK: Deoptimize
- /// CHECK-NOT: Deoptimize
/// CHECK: Phi
/// CHECK-NOT: BoundsCheck
/// CHECK: ArrayGet
@@ -791,6 +819,17 @@ public class Main {
/// CHECK: ArrayGet
/// CHECK-NOT: BoundsCheck
/// CHECK: ArraySet
+ // Added blocks for deoptimization.
+ /// CHECK: If
+ /// CHECK: Goto
+ /// CHECK: Deoptimize
+ /// CHECK: Deoptimize
+ /// CHECK: Deoptimize
+ /// CHECK-NOT: Deoptimize
+ /// CHECK: Goto
+ /// CHECK: Phi
+ /// CHECK: Goto
+ /// CHECK-NOT: Deoptimize
void foo6(int[] array, int start, int end) {
// Three HDeoptimize will be added. One for
@@ -810,15 +849,21 @@ public class Main {
/// CHECK: ArrayGet
/// CHECK-START: void Main.foo7(int[], int, int, boolean) BCE (after)
- /// CHECK: Deoptimize
- /// CHECK: Deoptimize
- /// CHECK: Deoptimize
- /// CHECK-NOT: Deoptimize
/// CHECK: Phi
/// CHECK: BoundsCheck
/// CHECK: ArrayGet
/// CHECK-NOT: BoundsCheck
/// CHECK: ArrayGet
+ // Added blocks for deoptimization.
+ /// CHECK: If
+ /// CHECK: Goto
+ /// CHECK: Deoptimize
+ /// CHECK: Deoptimize
+ /// CHECK: Deoptimize
+ /// CHECK-NOT: Deoptimize
+ /// CHECK: Goto
+ /// CHECK: Phi
+ /// CHECK: Goto
void foo7(int[] array, int start, int end, boolean lowEnd) {
// Three HDeoptimize will be added. One for
@@ -837,6 +882,73 @@ public class Main {
}
+ /// CHECK-START: void Main.foo8(int[][], int, int) BCE (before)
+ /// CHECK: BoundsCheck
+ /// CHECK: ArrayGet
+ /// CHECK: BoundsCheck
+ /// CHECK: ArraySet
+
+ /// CHECK-START: void Main.foo8(int[][], int, int) BCE (after)
+ /// CHECK: Phi
+ /// CHECK-NOT: BoundsCheck
+ /// CHECK: ArrayGet
+ /// CHECK: Phi
+ /// CHECK-NOT: BoundsCheck
+ /// CHECK: ArraySet
+ // Added blocks for deoptimization.
+ /// CHECK: If
+ /// CHECK: Goto
+ /// CHECK: Deoptimize
+ /// CHECK: Deoptimize
+ /// CHECK: Deoptimize
+ /// CHECK: Deoptimize
+ /// CHECK: Deoptimize
+ /// CHECK: Deoptimize
+ /// CHECK-NOT: Deoptimize
+ /// CHECK: Goto
+ /// CHECK: Phi
+ /// CHECK: Goto
+
+ void foo8(int[][] matrix, int start, int end) {
+ // Three HDeoptimize will be added for the outer loop.
+ // start >= 0, end <= matrix.length, and null check on matrix.
+ // Three HDeoptimize will be added for the inner loop
+ // start >= 0 (TODO: this may be optimized away),
+ // end <= row.length, and null check on row.
+ for (int i = start; i < end; i++) {
+ int[] row = matrix[i];
+ for (int j = start; j < end; j++) {
+ row[j] = 1;
+ }
+ }
+ }
+
+
+ /// CHECK-START: void Main.foo9(int[]) BCE (before)
+ /// CHECK: NullCheck
+ /// CHECK: BoundsCheck
+ /// CHECK: ArrayGet
+
+ /// CHECK-START: void Main.foo9(int[]) BCE (after)
+ // The loop is guaranteed to be entered. No need to transform the
+ // loop for loop body entry test.
+ /// CHECK: Deoptimize
+ /// CHECK: Deoptimize
+ /// CHECK-NOT: Deoptimize
+ /// CHECK: Phi
+ /// CHECK-NOT: NullCheck
+ /// CHECK-NOT: BoundsCheck
+ /// CHECK: ArrayGet
+
+ void foo9(int[] array) {
+ // Two HDeoptimize will be added. One for
+ // 10 <= array.length, and one for null check on array.
+ for (int i = 0 ; i < 10; i++) {
+ sum += array[i];
+ }
+ }
+
+
/// CHECK-START: void Main.partialLooping(int[], int, int) BCE (before)
/// CHECK: BoundsCheck
/// CHECK: ArraySet
@@ -951,6 +1063,13 @@ public class Main {
main.foo6(new int[10], 2, 7);
main = new Main();
+ int[] array9 = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
+ main.foo9(array9);
+ if (main.sum != 45) {
+ System.out.println("foo9 failed!");
+ }
+
+ main = new Main();
int[] array = new int[4];
main.partialLooping(new int[3], 0, 4);
if ((array[0] != 1) && (array[1] != 1) &&
diff --git a/test/450-checker-types/src/Main.java b/test/450-checker-types/src/Main.java
index 4056275d3d..9fb1e367b0 100644
--- a/test/450-checker-types/src/Main.java
+++ b/test/450-checker-types/src/Main.java
@@ -364,6 +364,18 @@ public class Main {
((SubclassA)b).$noinline$g();
}
+ public SubclassA $noinline$getSubclass() { throw new RuntimeException(); }
+
+ /// CHECK-START: void Main.testInvokeSimpleRemove() instruction_simplifier_after_types (before)
+ /// CHECK: CheckCast
+
+ /// CHECK-START: void Main.testInvokeSimpleRemove() instruction_simplifier_after_types (after)
+ /// CHECK-NOT: CheckCast
+ public void testInvokeSimpleRemove() {
+ Super b = $noinline$getSubclass();
+ ((SubclassA)b).$noinline$g();
+ }
+
public static void main(String[] args) {
}
}
diff --git a/test/478-checker-clinit-check-pruning/src/Main.java b/test/478-checker-clinit-check-pruning/src/Main.java
index a2c98c9363..e6aab630f9 100644
--- a/test/478-checker-clinit-check-pruning/src/Main.java
+++ b/test/478-checker-clinit-check-pruning/src/Main.java
@@ -26,7 +26,7 @@ public class Main {
/// CHECK-START: void Main.invokeStaticInlined() builder (after)
/// CHECK-DAG: <<LoadClass:l\d+>> LoadClass gen_clinit_check:false
/// CHECK-DAG: <<ClinitCheck:l\d+>> ClinitCheck [<<LoadClass>>]
- /// CHECK-DAG: InvokeStaticOrDirect [<<ClinitCheck>>]
+ /// CHECK-DAG: InvokeStaticOrDirect [{{[ij]\d+}},<<ClinitCheck>>]
/// CHECK-START: void Main.invokeStaticInlined() inliner (after)
/// CHECK-DAG: <<LoadClass:l\d+>> LoadClass gen_clinit_check:false
@@ -69,12 +69,12 @@ public class Main {
/// CHECK-START: void Main.invokeStaticNotInlined() builder (after)
/// CHECK-DAG: <<LoadClass:l\d+>> LoadClass gen_clinit_check:false
/// CHECK-DAG: <<ClinitCheck:l\d+>> ClinitCheck [<<LoadClass>>]
- /// CHECK-DAG: InvokeStaticOrDirect [<<ClinitCheck>>]
+ /// CHECK-DAG: InvokeStaticOrDirect [{{[ij]\d+}},<<ClinitCheck>>]
/// CHECK-START: void Main.invokeStaticNotInlined() inliner (after)
/// CHECK-DAG: <<LoadClass:l\d+>> LoadClass gen_clinit_check:false
/// CHECK-DAG: <<ClinitCheck:l\d+>> ClinitCheck [<<LoadClass>>]
- /// CHECK-DAG: InvokeStaticOrDirect [<<ClinitCheck>>]
+ /// CHECK-DAG: InvokeStaticOrDirect [{{[ij]\d+}},<<ClinitCheck>>]
// The following checks ensure the clinit check and load class
// instructions added by the builder are pruned by the
diff --git a/test/491-current-method/expected.txt b/test/491-current-method/expected.txt
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/test/491-current-method/expected.txt
diff --git a/test/491-current-method/info.txt b/test/491-current-method/info.txt
new file mode 100644
index 0000000000..e9678da769
--- /dev/null
+++ b/test/491-current-method/info.txt
@@ -0,0 +1,2 @@
+Regression test for optimizing that used to
+crash in the presence of slow paths with intrinsics.
diff --git a/test/491-current-method/src/Main.java b/test/491-current-method/src/Main.java
new file mode 100644
index 0000000000..87ef05218d
--- /dev/null
+++ b/test/491-current-method/src/Main.java
@@ -0,0 +1,70 @@
+/*
+ * 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.
+ */
+
+class Main {
+
+ // The code below is written in a way that will crash
+ // the generated code at the time of submission of this test.
+ // Therefore, changes to the register allocator may
+ // affect the reproducibility of the crash.
+ public static void $noinline$foo(int a, int b, int c) {
+ // The division on x86 will take EAX and EDX, leaving ECX
+ // to put the ART current method.
+ c = c / 42;
+ // We use the empty string for forcing the slow path.
+ // The slow path for charAt when it is intrinsified, will
+ // move the parameter to ECX, and therefore overwrite the ART
+ // current method.
+ "".charAt(c);
+
+ // Do more things in the method to prevent inlining.
+ c = c / 42;
+ "".charAt(c);
+ c = c / 42;
+ "".charAt(c);
+ c = c / 42;
+ "".charAt(c);
+ c = c / 42;
+ "".charAt(c);
+ c = c / 42;
+ "".charAt(c);
+ c = c / 42;
+ "".charAt(c);
+ c = c / 42;
+ "".charAt(c);
+ c = c / 42;
+ "".charAt(c);
+ c = c / 42;
+ "".charAt(c);
+ c = c / 42;
+ "".charAt(c);
+ c = c / 42;
+ "".charAt(c);
+ }
+
+ public static void main(String[] args) {
+ boolean didThrow = false;
+ try {
+ $noinline$foo(1, 2, 3);
+ } catch (Throwable e) {
+ didThrow = true;
+ }
+
+ if (!didThrow) {
+ throw new Error("Expected an exception from charAt");
+ }
+ }
+}
diff --git a/test/492-checker-inline-invoke-interface/expected.txt b/test/492-checker-inline-invoke-interface/expected.txt
new file mode 100644
index 0000000000..b0014d7529
--- /dev/null
+++ b/test/492-checker-inline-invoke-interface/expected.txt
@@ -0,0 +1,5 @@
+Hello from clinit
+java.lang.Exception
+ at ForceStatic.<clinit>(Main.java:24)
+ at Main.$inline$foo(Main.java:31)
+ at Main.main(Main.java:48)
diff --git a/test/492-checker-inline-invoke-interface/info.txt b/test/492-checker-inline-invoke-interface/info.txt
new file mode 100644
index 0000000000..4a0a5ff1d3
--- /dev/null
+++ b/test/492-checker-inline-invoke-interface/info.txt
@@ -0,0 +1 @@
+Checker test to ensure we can inline interface calls.
diff --git a/test/492-checker-inline-invoke-interface/src/Main.java b/test/492-checker-inline-invoke-interface/src/Main.java
new file mode 100644
index 0000000000..9a4548542b
--- /dev/null
+++ b/test/492-checker-inline-invoke-interface/src/Main.java
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+interface Itf {
+ public void $inline$foo();
+}
+
+class ForceStatic {
+ static {
+ System.out.println("Hello from clinit");
+ new Exception().printStackTrace();
+ }
+ static int field;
+}
+
+public class Main implements Itf {
+ public void $inline$foo() {
+ int a = ForceStatic.field;
+ }
+
+ /// CHECK-START: void Main.main(java.lang.String[]) inliner (before)
+ /// CHECK: InvokeStaticOrDirect
+ /// CHECK: InvokeStaticOrDirect
+
+ /// CHECK-START: void Main.main(java.lang.String[]) inliner (before)
+ /// CHECK-NOT: ClinitCheck
+
+ /// CHECK-START: void Main.main(java.lang.String[]) inliner (after)
+ /// CHECK-NOT: InvokeStaticOrDirect
+
+ /// CHECK-START: void Main.main(java.lang.String[]) inliner (after)
+ /// CHECK: ClinitCheck
+ public static void main(String[] args) {
+ Itf itf = new Main();
+ itf.$inline$foo();
+ }
+}
diff --git a/test/493-checker-inline-invoke-interface/expected.txt b/test/493-checker-inline-invoke-interface/expected.txt
new file mode 100644
index 0000000000..93620a6fb5
--- /dev/null
+++ b/test/493-checker-inline-invoke-interface/expected.txt
@@ -0,0 +1,5 @@
+Hello from clinit
+java.lang.Exception
+ at ForceStatic.<clinit>(Main.java:24)
+ at Main.foo(Main.java:31)
+ at Main.main(Main.java:42)
diff --git a/test/493-checker-inline-invoke-interface/info.txt b/test/493-checker-inline-invoke-interface/info.txt
new file mode 100644
index 0000000000..bac9c82c9d
--- /dev/null
+++ b/test/493-checker-inline-invoke-interface/info.txt
@@ -0,0 +1,2 @@
+Check that we can optimize interface calls without
+requiring the verifier to sharpen them.
diff --git a/test/493-checker-inline-invoke-interface/src/Main.java b/test/493-checker-inline-invoke-interface/src/Main.java
new file mode 100644
index 0000000000..44b727fe55
--- /dev/null
+++ b/test/493-checker-inline-invoke-interface/src/Main.java
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+interface Itf {
+ public void foo();
+}
+
+class ForceStatic {
+ static {
+ System.out.println("Hello from clinit");
+ new Exception().printStackTrace();
+ }
+ static int field;
+}
+
+public class Main implements Itf {
+ public void foo() {
+ int a = ForceStatic.field;
+ }
+
+ /// CHECK-START: void Main.main(java.lang.String[]) inliner (before)
+ /// CHECK: InvokeStaticOrDirect
+ /// CHECK: InvokeInterface
+
+ /// CHECK-START: void Main.main(java.lang.String[]) inliner (after)
+ /// CHECK-NOT: Invoke{{.*}}
+ public static void main(String[] args) {
+ Itf itf = bar();
+ itf.foo();
+ }
+
+ public static Itf bar() {
+ return new Main();
+ }
+}
diff --git a/test/494-checker-instanceof-tests/expected.txt b/test/494-checker-instanceof-tests/expected.txt
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/test/494-checker-instanceof-tests/expected.txt
diff --git a/test/494-checker-instanceof-tests/info.txt b/test/494-checker-instanceof-tests/info.txt
new file mode 100644
index 0000000000..59e20bd6a9
--- /dev/null
+++ b/test/494-checker-instanceof-tests/info.txt
@@ -0,0 +1 @@
+Checker test for optimizations on instanceof.
diff --git a/test/494-checker-instanceof-tests/src/Main.java b/test/494-checker-instanceof-tests/src/Main.java
new file mode 100644
index 0000000000..bff9c72ded
--- /dev/null
+++ b/test/494-checker-instanceof-tests/src/Main.java
@@ -0,0 +1,203 @@
+/*
+ * 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 boolean $inline$classTypeTest(Object o) {
+ return o instanceof SubMain;
+ }
+
+ public static boolean $inline$interfaceTypeTest(Object o) {
+ return o instanceof Itf;
+ }
+
+ public static SubMain subMain;
+ public static Main mainField;
+ public static Unrelated unrelatedField;
+ public static FinalUnrelated finalUnrelatedField;
+
+ /// CHECK-START: boolean Main.classTypeTestNull() register (after)
+ /// CHECK-DAG: <<Const:i\d+>> IntConstant 0
+ /// CHECK-DAG: Return [<<Const>>]
+ public static boolean classTypeTestNull() {
+ return $inline$classTypeTest(null);
+ }
+
+ /// CHECK-START: boolean Main.classTypeTestExactMain() register (after)
+ /// CHECK-DAG: <<Const:i\d+>> IntConstant 0
+ /// CHECK-DAG: Return [<<Const>>]
+ public static boolean classTypeTestExactMain() {
+ return $inline$classTypeTest(new Main());
+ }
+
+ /// CHECK-START: boolean Main.classTypeTestExactSubMain() register (after)
+ /// CHECK-DAG: <<Const:i\d+>> IntConstant 1
+ /// CHECK-DAG: Return [<<Const>>]
+ public static boolean classTypeTestExactSubMain() {
+ return $inline$classTypeTest(new SubMain());
+ }
+
+ /// CHECK-START: boolean Main.classTypeTestSubMainOrNull() register (after)
+ /// CHECK-DAG: <<Value:z\d+>> NotEqual
+ /// CHECK-DAG: Return [<<Value>>]
+ public static boolean classTypeTestSubMainOrNull() {
+ return $inline$classTypeTest(subMain);
+ }
+
+ /// CHECK-START: boolean Main.classTypeTestMainOrNull() register (after)
+ /// CHECK-DAG: <<Value:z\d+>> InstanceOf
+ /// CHECK-DAG: Return [<<Value>>]
+ public static boolean classTypeTestMainOrNull() {
+ return $inline$classTypeTest(mainField);
+ }
+
+ /// CHECK-START: boolean Main.classTypeTestUnrelated() register (after)
+ /// CHECK-DAG: <<Const:i\d+>> IntConstant 0
+ /// CHECK-DAG: Return [<<Const>>]
+ public static boolean classTypeTestUnrelated() {
+ return $inline$classTypeTest(unrelatedField);
+ }
+
+ /// CHECK-START: boolean Main.classTypeTestFinalUnrelated() register (after)
+ /// CHECK-DAG: <<Const:i\d+>> IntConstant 0
+ /// CHECK-DAG: Return [<<Const>>]
+ public static boolean classTypeTestFinalUnrelated() {
+ return $inline$classTypeTest(finalUnrelatedField);
+ }
+
+ /// CHECK-START: boolean Main.interfaceTypeTestNull() register (after)
+ /// CHECK-DAG: <<Const:i\d+>> IntConstant 0
+ /// CHECK-DAG: Return [<<Const>>]
+ public static boolean interfaceTypeTestNull() {
+ return $inline$interfaceTypeTest(null);
+ }
+
+ /// CHECK-START: boolean Main.interfaceTypeTestExactMain() register (after)
+ /// CHECK-DAG: <<Const:i\d+>> IntConstant 0
+ /// CHECK-DAG: Return [<<Const>>]
+ public static boolean interfaceTypeTestExactMain() {
+ return $inline$interfaceTypeTest(new Main());
+ }
+
+ /// CHECK-START: boolean Main.interfaceTypeTestExactSubMain() register (after)
+ /// CHECK-DAG: <<Const:i\d+>> IntConstant 1
+ /// CHECK-DAG: Return [<<Const>>]
+ public static boolean interfaceTypeTestExactSubMain() {
+ return $inline$interfaceTypeTest(new SubMain());
+ }
+
+ /// CHECK-START: boolean Main.interfaceTypeTestSubMainOrNull() register (after)
+ /// CHECK-DAG: <<Value:z\d+>> NotEqual
+ /// CHECK-DAG: Return [<<Value>>]
+ public static boolean interfaceTypeTestSubMainOrNull() {
+ return $inline$interfaceTypeTest(subMain);
+ }
+
+ /// CHECK-START: boolean Main.interfaceTypeTestMainOrNull() register (after)
+ /// CHECK-DAG: <<Value:z\d+>> InstanceOf
+ /// CHECK-DAG: Return [<<Value>>]
+ public static boolean interfaceTypeTestMainOrNull() {
+ return $inline$interfaceTypeTest(mainField);
+ }
+
+ /// CHECK-START: boolean Main.interfaceTypeTestUnrelated() register (after)
+ /// CHECK-DAG: <<Value:z\d+>> InstanceOf
+ /// CHECK-DAG: Return [<<Value>>]
+ public static boolean interfaceTypeTestUnrelated() {
+ // This method is the main difference between doing an instanceof on an interface
+ // or a class. We have to keep the instanceof in case a subclass of Unrelated
+ // implements the interface.
+ return $inline$interfaceTypeTest(unrelatedField);
+ }
+
+ /// CHECK-START: boolean Main.interfaceTypeTestFinalUnrelated() register (after)
+ /// CHECK-DAG: <<Const:i\d+>> IntConstant 0
+ /// CHECK-DAG: Return [<<Const>>]
+ public static boolean interfaceTypeTestFinalUnrelated() {
+ return $inline$interfaceTypeTest(finalUnrelatedField);
+ }
+
+ public static void expect(boolean expected, boolean actual) {
+ if (expected != actual) {
+ throw new Error("Unexpected result");
+ }
+ }
+
+ public static void main(String[] args) {
+ expect(false, classTypeTestNull());
+ expect(false, classTypeTestExactMain());
+ expect(true, classTypeTestExactSubMain());
+
+ subMain = null;
+ expect(false, classTypeTestSubMainOrNull());
+ subMain = new SubMain();
+ expect(true, classTypeTestSubMainOrNull());
+
+ mainField = null;
+ expect(false, classTypeTestMainOrNull());
+ mainField = new Main();
+ expect(false, classTypeTestMainOrNull());
+ mainField = new SubMain();
+ expect(true, classTypeTestMainOrNull());
+
+ unrelatedField = null;
+ expect(false, classTypeTestUnrelated());
+ unrelatedField = new Unrelated();
+ expect(false, classTypeTestUnrelated());
+
+ finalUnrelatedField = null;
+ expect(false, classTypeTestFinalUnrelated());
+ finalUnrelatedField = new FinalUnrelated();
+ expect(false, classTypeTestFinalUnrelated());
+
+ expect(false, interfaceTypeTestNull());
+ expect(false, interfaceTypeTestExactMain());
+ expect(true, interfaceTypeTestExactSubMain());
+
+ subMain = null;
+ expect(false, interfaceTypeTestSubMainOrNull());
+ subMain = new SubMain();
+ expect(true, interfaceTypeTestSubMainOrNull());
+
+ mainField = null;
+ expect(false, interfaceTypeTestMainOrNull());
+ mainField = new Main();
+ expect(false, interfaceTypeTestMainOrNull());
+ mainField = new SubMain();
+ expect(true, interfaceTypeTestMainOrNull());
+
+ unrelatedField = null;
+ expect(false, interfaceTypeTestUnrelated());
+ unrelatedField = new Unrelated();
+ expect(false, interfaceTypeTestUnrelated());
+
+ finalUnrelatedField = null;
+ expect(false, interfaceTypeTestFinalUnrelated());
+ finalUnrelatedField = new FinalUnrelated();
+ expect(false, interfaceTypeTestFinalUnrelated());
+ }
+}
+
+interface Itf {
+}
+
+class SubMain extends Main implements Itf {
+}
+
+class Unrelated {
+}
+
+final class FinalUnrelated {
+}
diff --git a/test/495-checker-checkcast-tests/expected.txt b/test/495-checker-checkcast-tests/expected.txt
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/test/495-checker-checkcast-tests/expected.txt
diff --git a/test/495-checker-checkcast-tests/info.txt b/test/495-checker-checkcast-tests/info.txt
new file mode 100644
index 0000000000..4517b22c69
--- /dev/null
+++ b/test/495-checker-checkcast-tests/info.txt
@@ -0,0 +1 @@
+Checker tests for optimizations on checkcast.
diff --git a/test/495-checker-checkcast-tests/src/Main.java b/test/495-checker-checkcast-tests/src/Main.java
new file mode 100644
index 0000000000..aa6d5a75f7
--- /dev/null
+++ b/test/495-checker-checkcast-tests/src/Main.java
@@ -0,0 +1,204 @@
+/*
+ * 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 boolean $inline$classTypeTest(Object o) {
+ return ((SubMain)o) == o;
+ }
+
+ public static boolean $inline$interfaceTypeTest(Object o) {
+ return ((Itf)o) == o;
+ }
+
+ public static SubMain subMain;
+ public static Main mainField;
+ public static Unrelated unrelatedField;
+ public static FinalUnrelated finalUnrelatedField;
+
+ /// CHECK-START: boolean Main.classTypeTestNull() register (after)
+ /// CHECK-NOT: CheckCast
+ public static boolean classTypeTestNull() {
+ return $inline$classTypeTest(null);
+ }
+
+ /// CHECK-START: boolean Main.classTypeTestExactMain() register (after)
+ /// CHECK: CheckCast
+ public static boolean classTypeTestExactMain() {
+ return $inline$classTypeTest(new Main());
+ }
+
+ /// CHECK-START: boolean Main.classTypeTestExactSubMain() register (after)
+ /// CHECK-NOT: CheckCast
+ public static boolean classTypeTestExactSubMain() {
+ return $inline$classTypeTest(new SubMain());
+ }
+
+ /// CHECK-START: boolean Main.classTypeTestSubMainOrNull() register (after)
+ /// CHECK-NOT: CheckCast
+ public static boolean classTypeTestSubMainOrNull() {
+ return $inline$classTypeTest(subMain);
+ }
+
+ /// CHECK-START: boolean Main.classTypeTestMainOrNull() register (after)
+ /// CHECK: CheckCast
+ public static boolean classTypeTestMainOrNull() {
+ return $inline$classTypeTest(mainField);
+ }
+
+ /// CHECK-START: boolean Main.classTypeTestUnrelated() register (after)
+ /// CHECK: CheckCast
+ public static boolean classTypeTestUnrelated() {
+ return $inline$classTypeTest(unrelatedField);
+ }
+
+ /// CHECK-START: boolean Main.classTypeTestFinalUnrelated() register (after)
+ /// CHECK: CheckCast
+ public static boolean classTypeTestFinalUnrelated() {
+ return $inline$classTypeTest(finalUnrelatedField);
+ }
+
+ /// CHECK-START: boolean Main.interfaceTypeTestNull() register (after)
+ /// CHECK-NOT: CheckCast
+ public static boolean interfaceTypeTestNull() {
+ return $inline$interfaceTypeTest(null);
+ }
+
+ /// CHECK-START: boolean Main.interfaceTypeTestExactMain() register (after)
+ /// CHECK: CheckCast
+ public static boolean interfaceTypeTestExactMain() {
+ return $inline$interfaceTypeTest(new Main());
+ }
+
+ /// CHECK-START: boolean Main.interfaceTypeTestExactSubMain() register (after)
+ /// CHECK-NOT: CheckCast
+ public static boolean interfaceTypeTestExactSubMain() {
+ return $inline$interfaceTypeTest(new SubMain());
+ }
+
+ /// CHECK-START: boolean Main.interfaceTypeTestSubMainOrNull() register (after)
+ /// CHECK-NOT: CheckCast
+ public static boolean interfaceTypeTestSubMainOrNull() {
+ return $inline$interfaceTypeTest(subMain);
+ }
+
+ /// CHECK-START: boolean Main.interfaceTypeTestMainOrNull() register (after)
+ /// CHECK: CheckCast
+ public static boolean interfaceTypeTestMainOrNull() {
+ return $inline$interfaceTypeTest(mainField);
+ }
+
+ /// CHECK-START: boolean Main.interfaceTypeTestUnrelated() register (after)
+ /// CHECK: CheckCast
+ public static boolean interfaceTypeTestUnrelated() {
+ return $inline$interfaceTypeTest(unrelatedField);
+ }
+
+ /// CHECK-START: boolean Main.interfaceTypeTestFinalUnrelated() register (after)
+ /// CHECK: CheckCast
+ public static boolean interfaceTypeTestFinalUnrelated() {
+ return $inline$interfaceTypeTest(finalUnrelatedField);
+ }
+
+ public static void main(String[] args) {
+ classTypeTestNull();
+ try {
+ classTypeTestExactMain();
+ throw new Error("ClassCastException expected");
+ } catch (ClassCastException e) {}
+ classTypeTestExactSubMain();
+
+ subMain = null;
+ classTypeTestSubMainOrNull();
+ subMain = new SubMain();
+ classTypeTestSubMainOrNull();
+
+ mainField = null;
+ classTypeTestMainOrNull();
+ mainField = new Main();
+ try {
+ classTypeTestMainOrNull();
+ throw new Error("ClassCastException expected");
+ } catch (ClassCastException e) {}
+ mainField = new SubMain();
+ classTypeTestMainOrNull();
+
+ unrelatedField = null;
+ classTypeTestUnrelated();
+ unrelatedField = new Unrelated();
+ try {
+ classTypeTestUnrelated();
+ throw new Error("ClassCastException expected");
+ } catch (ClassCastException e) {}
+
+ finalUnrelatedField = null;
+ classTypeTestFinalUnrelated();
+ finalUnrelatedField = new FinalUnrelated();
+ try {
+ classTypeTestFinalUnrelated();
+ throw new Error("ClassCastException expected");
+ } catch (ClassCastException e) {}
+
+ interfaceTypeTestNull();
+ try {
+ interfaceTypeTestExactMain();
+ throw new Error("ClassCastException expected");
+ } catch (ClassCastException e) {}
+ interfaceTypeTestExactSubMain();
+
+ subMain = null;
+ interfaceTypeTestSubMainOrNull();
+ subMain = new SubMain();
+ interfaceTypeTestSubMainOrNull();
+
+ mainField = null;
+ interfaceTypeTestMainOrNull();
+ mainField = new Main();
+ try {
+ interfaceTypeTestMainOrNull();
+ throw new Error("ClassCastException expected");
+ } catch (ClassCastException e) {}
+ mainField = new SubMain();
+ interfaceTypeTestMainOrNull();
+
+ unrelatedField = null;
+ interfaceTypeTestUnrelated();
+ unrelatedField = new Unrelated();
+ try {
+ interfaceTypeTestUnrelated();
+ throw new Error("ClassCastException expected");
+ } catch (ClassCastException e) {}
+
+ finalUnrelatedField = null;
+ interfaceTypeTestFinalUnrelated();
+ finalUnrelatedField = new FinalUnrelated();
+ try {
+ interfaceTypeTestFinalUnrelated();
+ throw new Error("ClassCastException expected");
+ } catch (ClassCastException e) {}
+ }
+}
+
+interface Itf {
+}
+
+class SubMain extends Main implements Itf {
+}
+
+class Unrelated {
+}
+
+final class FinalUnrelated {
+}
diff --git a/test/800-smali/expected.txt b/test/800-smali/expected.txt
index a6b216bf3a..85656374c5 100644
--- a/test/800-smali/expected.txt
+++ b/test/800-smali/expected.txt
@@ -16,4 +16,5 @@ MoveExc
MoveExceptionOnEntry
EmptySparseSwitch
b/20224106
+b/17410612
Done!
diff --git a/test/800-smali/smali/b_17410612.smali b/test/800-smali/smali/b_17410612.smali
new file mode 100644
index 0000000000..17718cbf60
--- /dev/null
+++ b/test/800-smali/smali/b_17410612.smali
@@ -0,0 +1,14 @@
+.class public LB17410612;
+
+# Test that an invoke with a long parameter has the long parameter in
+# a pair. This should fail in the verifier and not an abort in the compiler.
+
+.super Ljava/lang/Object;
+
+.method public static run()V
+ .registers 4
+ const-wide v0, 0 # Make (v0, v1) a long
+ const-wide v2, 0 # Make (v2, v3) a long
+ invoke-static {v0, v3}, Ljava/lang/Long;->valueOf(J)Ljava/lang/Long;
+ return-void
+.end method
diff --git a/test/800-smali/src/Main.java b/test/800-smali/src/Main.java
index 3e88364089..33df06d87a 100644
--- a/test/800-smali/src/Main.java
+++ b/test/800-smali/src/Main.java
@@ -81,6 +81,8 @@ public class Main {
null));
testCases.add(new TestCase("b/20224106", "B20224106", "run", null, new VerifyError(),
0));
+ testCases.add(new TestCase("b/17410612", "B17410612", "run", null, new VerifyError(),
+ 0));
}
public void runTests() {
diff --git a/test/Android.libarttest.mk b/test/Android.libarttest.mk
index 57d06c49cd..847ad0d2f7 100644
--- a/test/Android.libarttest.mk
+++ b/test/Android.libarttest.mk
@@ -74,6 +74,7 @@ define build-libarttest
else # host
LOCAL_CLANG := $(ART_HOST_CLANG)
LOCAL_CFLAGS := $(ART_HOST_CFLAGS) $(ART_HOST_DEBUG_CFLAGS)
+ LOCAL_ASFLAGS := $(ART_HOST_ASFLAGS)
LOCAL_LDLIBS := $(ART_HOST_LDLIBS) -ldl -lpthread
LOCAL_IS_HOST_MODULE := true
LOCAL_MULTILIB := both
diff --git a/test/Android.libnativebridgetest.mk b/test/Android.libnativebridgetest.mk
index 5a5f72584f..e8cc7e45ce 100644
--- a/test/Android.libnativebridgetest.mk
+++ b/test/Android.libnativebridgetest.mk
@@ -60,6 +60,7 @@ define build-libnativebridgetest
else # host
LOCAL_CLANG := $(ART_HOST_CLANG)
LOCAL_CFLAGS := $(ART_HOST_CFLAGS) $(ART_HOST_DEBUG_CFLAGS)
+ LOCAL_ASFLAGS := $(ART_HOST_ASFLAGS)
LOCAL_SHARED_LIBRARIES := libcutils
LOCAL_LDLIBS := $(ART_HOST_LDLIBS) -ldl -lpthread
ifeq ($(HOST_OS),linux)
diff --git a/test/Android.run-test.mk b/test/Android.run-test.mk
index fa13fe5c64..b948e4b1b0 100644
--- a/test/Android.run-test.mk
+++ b/test/Android.run-test.mk
@@ -229,16 +229,10 @@ endif
TEST_ART_BROKEN_NO_RELOCATE_TESTS :=
-# Tests that are broken with GC stress.
-TEST_ART_BROKEN_GCSTRESS_RUN_TESTS :=
-
-ifneq (,$(filter gcstress,$(GC_TYPES)))
- ART_TEST_KNOWN_BROKEN += $(call all-run-test-names,$(TARGET_TYPES),$(RUN_TYPES),$(PREBUILD_TYPES), \
- $(COMPILER_TYPES),$(RELOCATE_TYPES),$(TRACE_TYPES),gcstress,$(JNI_TYPES), \
- $(IMAGE_TYPES), $(PICTEST_TYPES), $(DBEUGGABLE_TYPES), $(TEST_ART_BROKEN_GCSTRESS_RUN_TESTS), $(ALL_ADDRESS_SIZES))
-endif
-
-TEST_ART_BROKEN_GCSTRESS_RUN_TESTS :=
+# 098-ddmc is broken until we restore the old behavior of getRecentAllocation() of DDMS. b/20037135
+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), 098-ddmc, $(ALL_ADDRESS_SIZES))
# 115-native-bridge setup is complicated. Need to implement it correctly for the target.
ART_TEST_KNOWN_BROKEN += $(call all-run-test-names,target,$(RUN_TYPES),$(PREBUILD_TYPES),$(COMPILER_TYPES), \
@@ -259,6 +253,11 @@ ART_TEST_KNOWN_BROKEN += $(call all-run-test-names,$(TARGET_TYPES),$(RUN_TYPES),
$(COMPILER_TYPES),$(RELOCATE_TYPES),$(TRACE_TYPES),$(GC_TYPES),$(JNI_TYPES),$(IMAGE_TYPES), \
$(PICTEST_TYPES),$(DEBUGGABLE_TYPES),131-structural-change,$(ALL_ADDRESS_SIZES))
+# 138-duplicate-classes-check. Turned off temporarily, b/21333911.
+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),138-duplicate-classes-check,$(ALL_ADDRESS_SIZES))
+
# All these tests check that we have sane behavior if we don't have a patchoat or dex2oat.
# Therefore we shouldn't run them in situations where we actually don't have these since they
# explicitly test for them. These all also assume we have an image.
@@ -468,11 +467,6 @@ endif
TEST_ART_BROKEN_HEAP_POISONING_RUN_TESTS :=
-# Test 137-cfi works in 32-bit only until we enable 64-bit ELF files.
-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),137-cfi,64)
-
# 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), \
diff --git a/test/etc/run-test-jar b/test/etc/run-test-jar
index 240ed41ff2..09841bfcec 100755
--- a/test/etc/run-test-jar
+++ b/test/etc/run-test-jar
@@ -296,6 +296,10 @@ if [ "$RELOCATE" = "y" ]; then
else
FLAGS="$FLAGS -Xnorelocate"
COMPILE_FLAGS="${COMPILE_FLAGS} --runtime-arg -Xnorelocate"
+ if [ "$HOST" = "y" ]; then
+ # Increase ulimit to 64MB in case we are running hprof test.
+ ulimit -S 64000 || exit 1
+ fi
fi
if [ "$HOST" = "n" ]; then
diff --git a/test/run-test b/test/run-test
index ed3309923b..ed033217b8 100755
--- a/test/run-test
+++ b/test/run-test
@@ -96,6 +96,7 @@ basic_verify="false"
gc_verify="false"
gc_stress="false"
always_clean="no"
+never_clean="no"
have_dex2oat="yes"
have_patchoat="yes"
have_image="yes"
@@ -270,6 +271,9 @@ while true; do
elif [ "x$1" = "x--always-clean" ]; then
always_clean="yes"
shift
+ elif [ "x$1" = "x--never-clean" ]; then
+ never_clean="yes"
+ shift
elif [ "x$1" = "x--dex2oat-swap" ]; then
run_args="${run_args} --dex2oat-swap"
shift
@@ -472,6 +476,7 @@ if [ "$usage" = "yes" ]; then
echo " --gcstress Run with gc stress testing"
echo " --gcverify Run with gc verification"
echo " --always-clean Delete the test files even if the test fails."
+ echo " --never-clean Keep the test files even if the test succeeds."
echo " --android-root [path] The path on target for the android root. (/system by default)."
echo " --dex2oat-swap Use a dex2oat swap file."
) 1>&2
@@ -668,7 +673,7 @@ fi
) 1>&2
# Clean up test files.
-if [ "$always_clean" = "yes" -o "$good" = "yes" ]; then
+if [ "$always_clean" = "yes" -o "$good" = "yes" ] && [ "$never_clean" = "no" ]; then
cd "$oldwd"
rm -rf "$tmp_dir"
if [ "$target_mode" = "yes" -a "$build_exit" = "0" ]; then