diff options
Diffstat (limited to 'test')
25 files changed, 460 insertions, 86 deletions
diff --git a/test/004-JniTest/src/Main.java b/test/004-JniTest/src/Main.java index dd88db0b7c..ee3a3b9830 100644 --- a/test/004-JniTest/src/Main.java +++ b/test/004-JniTest/src/Main.java @@ -120,7 +120,7 @@ public class Main { private static void testRemoveLocalObject() { removeLocalObject(new Object()); } - + private static native short shortMethod(short s1, short s2, short s3, short s4, short s5, short s6, short s7, short s8, short s9, short s10); diff --git a/test/024-illegal-access/expected.txt b/test/024-illegal-access/expected.txt index 5f951f4939..0ae4a774f3 100644 --- a/test/024-illegal-access/expected.txt +++ b/test/024-illegal-access/expected.txt @@ -1,2 +1,5 @@ Got expected failure 1 Got expected failure 2 +Got expected failure 3 +Got expected failure 4 +Got expected failure 5 diff --git a/test/024-illegal-access/src/Main.java b/test/024-illegal-access/src/Main.java index bde73e9452..84c7114cb4 100644 --- a/test/024-illegal-access/src/Main.java +++ b/test/024-illegal-access/src/Main.java @@ -17,7 +17,7 @@ public class Main { static public void main(String[] args) { try { - PublicAccess.main(); + PublicAccess.accessStaticField(); System.err.println("ERROR: call 1 not expected to succeed"); } catch (VerifyError ve) { // dalvik @@ -28,14 +28,41 @@ public class Main { } try { - CheckInstanceof.main(new Object()); + PublicAccess.accessStaticMethod(); System.err.println("ERROR: call 2 not expected to succeed"); + } catch (IllegalAccessError iae) { + // reference + System.out.println("Got expected failure 2"); + } + + try { + PublicAccess.accessInstanceField(); + System.err.println("ERROR: call 3 not expected to succeed"); } catch (VerifyError ve) { // dalvik - System.out.println("Got expected failure 2"); + System.out.println("Got expected failure 3"); } catch (IllegalAccessError iae) { // reference - System.out.println("Got expected failure 2"); + System.out.println("Got expected failure 3"); + } + + try { + PublicAccess.accessInstanceMethod(); + System.err.println("ERROR: call 4 not expected to succeed"); + } catch (IllegalAccessError iae) { + // reference + System.out.println("Got expected failure 4"); + } + + try { + CheckInstanceof.main(new Object()); + System.err.println("ERROR: call 5 not expected to succeed"); + } catch (VerifyError ve) { + // dalvik + System.out.println("Got expected failure 5"); + } catch (IllegalAccessError iae) { + // reference + System.out.println("Got expected failure 5"); } } } diff --git a/test/024-illegal-access/src/PublicAccess.java b/test/024-illegal-access/src/PublicAccess.java index 4e72cd4dce..e3fef855e2 100644 --- a/test/024-illegal-access/src/PublicAccess.java +++ b/test/024-illegal-access/src/PublicAccess.java @@ -18,8 +18,20 @@ * Some stuff for access checks. */ public class PublicAccess { - public static void main() { - String shouldFail = SemiPrivate.mPrivvy; + public static void accessStaticField() { + String shouldFail = SemiPrivate.mStaticPrivvy; + System.out.println("Got " + shouldFail); + } + public static void accessStaticMethod() { + String shouldFail = SemiPrivate.privvyStaticMethod(); + System.out.println("Got " + shouldFail); + } + public static void accessInstanceField() { + String shouldFail = new SemiPrivate().mInstancePrivvy; + System.out.println("Got " + shouldFail); + } + public static void accessInstanceMethod() { + String shouldFail = new SemiPrivate().privvyInstanceMethod(); System.out.println("Got " + shouldFail); } } diff --git a/test/024-illegal-access/src/SemiPrivate.java b/test/024-illegal-access/src/SemiPrivate.java index 06b16c40b9..62e0d05213 100644 --- a/test/024-illegal-access/src/SemiPrivate.java +++ b/test/024-illegal-access/src/SemiPrivate.java @@ -18,5 +18,15 @@ * Version with package scope access. */ public class SemiPrivate { - /* not private */ static String mPrivvy = "stuff"; + /* not private */ static String mStaticPrivvy = "stuff"; + + /* not private */ static String privvyStaticMethod() { + return "stuff"; + } + + /* not private */ String mInstancePrivvy = "stuff"; + + /* not private */ String privvyInstanceMethod() { + return "stuff"; + } } diff --git a/test/024-illegal-access/src2/SemiPrivate.java b/test/024-illegal-access/src2/SemiPrivate.java index 064265ab37..4f36a07418 100644 --- a/test/024-illegal-access/src2/SemiPrivate.java +++ b/test/024-illegal-access/src2/SemiPrivate.java @@ -18,5 +18,15 @@ * Version with private access. */ public class SemiPrivate { - private static String mPrivvy = "stuff"; + private static String mStaticPrivvy = "stuff"; + + private static String privvyStaticMethod() { + return "stuff"; + } + + private String mInstancePrivvy = "stuff"; + + private String privvyInstanceMethod() { + return "stuff"; + } } diff --git a/test/087-gc-after-link/src/Main.java b/test/087-gc-after-link/src/Main.java index e0a187a3a0..2f6d496f44 100644 --- a/test/087-gc-after-link/src/Main.java +++ b/test/087-gc-after-link/src/Main.java @@ -155,6 +155,12 @@ public class Main { * See if we can GC after a failed load. */ static void testFailLoadAndGc() throws TestFailed { + processFailLoadAndGc(); + Runtime.getRuntime().gc(); + System.out.println("GC complete."); + } + + private static void processFailLoadAndGc() throws TestFailed { try { BrokenDexLoader loader; @@ -170,7 +176,5 @@ public class Main { ite.printStackTrace(); } } - Runtime.getRuntime().gc(); - System.out.println("GC complete."); } } diff --git a/test/088-monitor-verification/smali/NotStructuredOverUnlock.smali b/test/088-monitor-verification/smali/NotStructuredOverUnlock.smali index aa0c2d5a13..0dc492f2b3 100644 --- a/test/088-monitor-verification/smali/NotStructuredOverUnlock.smali +++ b/test/088-monitor-verification/smali/NotStructuredOverUnlock.smali @@ -5,7 +5,7 @@ .method public static run(Ljava/lang/Object;)V .registers 3 - invoke-static {}, LMain;->assertCallerIsInterpreted()V + invoke-static {}, LMain;->assertIsInterpreted()V # Lock twice, but unlock thrice. diff --git a/test/088-monitor-verification/smali/NotStructuredUnderUnlock.smali b/test/088-monitor-verification/smali/NotStructuredUnderUnlock.smali index 2c31fdaa85..df6e168685 100644 --- a/test/088-monitor-verification/smali/NotStructuredUnderUnlock.smali +++ b/test/088-monitor-verification/smali/NotStructuredUnderUnlock.smali @@ -5,7 +5,7 @@ .method public static run(Ljava/lang/Object;)V .registers 3 - invoke-static {}, LMain;->assertCallerIsInterpreted()V + invoke-static {}, LMain;->assertIsInterpreted()V # Lock thrice, but only unlock twice. diff --git a/test/088-monitor-verification/smali/OK.smali b/test/088-monitor-verification/smali/OK.smali index 596798d80c..a43ecb0704 100644 --- a/test/088-monitor-verification/smali/OK.smali +++ b/test/088-monitor-verification/smali/OK.smali @@ -20,7 +20,7 @@ .method public static runNoMonitors(Ljava/lang/Object;Ljava/lang/Object;)V .registers 3 - invoke-static {}, LMain;->assertCallerIsManaged()V + invoke-static {}, LMain;->assertIsManaged()V return-void @@ -29,7 +29,7 @@ .method public static runStraightLine(Ljava/lang/Object;Ljava/lang/Object;)V .registers 3 - invoke-static {}, LMain;->assertCallerIsManaged()V + invoke-static {}, LMain;->assertIsManaged()V monitor-enter v1 # 1 monitor-enter v2 # 2 @@ -44,7 +44,7 @@ .method public static runBalancedJoin(Ljava/lang/Object;Ljava/lang/Object;)V .registers 3 - invoke-static {}, LMain;->assertCallerIsManaged()V + invoke-static {}, LMain;->assertIsManaged()V monitor-enter v1 # 1 diff --git a/test/088-monitor-verification/smali/TooDeep.smali b/test/088-monitor-verification/smali/TooDeep.smali index 1a8f2f06e8..a1e328148d 100644 --- a/test/088-monitor-verification/smali/TooDeep.smali +++ b/test/088-monitor-verification/smali/TooDeep.smali @@ -7,7 +7,7 @@ # Lock depth is 33, which is more than the verifier supports. This should have been punted to # the interpreter. - invoke-static {}, LMain;->assertCallerIsInterpreted()V + invoke-static {}, LMain;->assertIsInterpreted()V monitor-enter v2 # 1 monitor-enter v2 # 2 diff --git a/test/088-monitor-verification/smali/UnbalancedJoin.smali b/test/088-monitor-verification/smali/UnbalancedJoin.smali index da8f7732af..993f32c022 100644 --- a/test/088-monitor-verification/smali/UnbalancedJoin.smali +++ b/test/088-monitor-verification/smali/UnbalancedJoin.smali @@ -5,7 +5,7 @@ .method public static run(Ljava/lang/Object;Ljava/lang/Object;)V .registers 3 - invoke-static {}, LMain;->assertCallerIsInterpreted()V + invoke-static {}, LMain;->assertIsInterpreted()V if-eqz v2, :Lnull diff --git a/test/088-monitor-verification/smali/UnbalancedStraight.smali b/test/088-monitor-verification/smali/UnbalancedStraight.smali index 68edb6c783..cbb8bcc488 100644 --- a/test/088-monitor-verification/smali/UnbalancedStraight.smali +++ b/test/088-monitor-verification/smali/UnbalancedStraight.smali @@ -5,7 +5,7 @@ .method public static run(Ljava/lang/Object;Ljava/lang/Object;)V .registers 3 - invoke-static {}, LMain;->assertCallerIsInterpreted()V + invoke-static {}, LMain;->assertIsInterpreted()V monitor-enter v1 # 1 monitor-enter v2 # 2 diff --git a/test/088-monitor-verification/src/Main.java b/test/088-monitor-verification/src/Main.java index fc5755b06f..218805543e 100644 --- a/test/088-monitor-verification/src/Main.java +++ b/test/088-monitor-verification/src/Main.java @@ -220,7 +220,7 @@ public class Main { // Smali testing code. private static void runSmaliTests() { - if (!hasOatFile() || runtimeIsSoftFail() || isCallerInterpreted()) { + if (!hasOatFile() || runtimeIsSoftFail() || isInterpreted()) { // Skip test, this seems to be a non-compiled code test configuration. return; } @@ -277,9 +277,9 @@ public class Main { } // Helpers for the smali code. - public static native void assertCallerIsInterpreted(); - public static native void assertCallerIsManaged(); + public static native void assertIsInterpreted(); + public static native void assertIsManaged(); public static native boolean hasOatFile(); public static native boolean runtimeIsSoftFail(); - public static native boolean isCallerInterpreted(); + public static native boolean isInterpreted(); } diff --git a/test/449-checker-bce/expected.txt b/test/449-checker-bce/expected.txt index e114c50371..4665d7af8b 100644 --- a/test/449-checker-bce/expected.txt +++ b/test/449-checker-bce/expected.txt @@ -1 +1,2 @@ +JNI_OnLoad called java.lang.ArrayIndexOutOfBoundsException: length=5; index=82 diff --git a/test/449-checker-bce/src/Main.java b/test/449-checker-bce/src/Main.java index f06c250dc7..22829cddc8 100644 --- a/test/449-checker-bce/src/Main.java +++ b/test/449-checker-bce/src/Main.java @@ -265,6 +265,7 @@ public class Main { // A helper into which the actual throwing function should be inlined. static void constantIndexingForward6(int[] array) { + assertIsManaged(); constantIndexing6(array); } @@ -618,13 +619,17 @@ public class Main { static int foo() { try { + assertIsManaged(); // This will cause AIOOBE. constantIndexing2(new int[3]); } catch (ArrayIndexOutOfBoundsException e) { + assertIsManaged(); // This is to ensure that single-frame deoptimization works. + // Will need to be updated if constantIndexing2 is inlined. try { // This will cause AIOOBE. constantIndexingForward6(new int[3]); } catch (ArrayIndexOutOfBoundsException e2) { + assertIsManaged(); return 99; } } @@ -634,13 +639,13 @@ public class Main { int sum; - /// CHECK-START: void Main.foo1(int[], int, int) BCE (before) + /// CHECK-START: void Main.foo1(int[], int, int, boolean) BCE (before) /// CHECK: BoundsCheck /// CHECK: ArraySet /// CHECK-NOT: BoundsCheck /// CHECK: ArrayGet - /// CHECK-START: void Main.foo1(int[], int, int) BCE (after) + /// CHECK-START: void Main.foo1(int[], int, int, boolean) BCE (after) /// CHECK: Phi /// CHECK-NOT: BoundsCheck /// CHECK: ArraySet @@ -657,25 +662,30 @@ public class Main { /// CHECK: Phi /// CHECK: Goto - void foo1(int[] array, int start, int end) { + void foo1(int[] array, int start, int end, boolean expectInterpreter) { // Three HDeoptimize will be added. One for // start >= 0, one for end <= array.length, // and one for null check on array (to hoist null // check and array.length out of loop). for (int i = start ; i < end; i++) { + if (expectInterpreter) { + assertIsInterpreted(); + } else { + assertIsManaged(); + } array[i] = 1; sum += array[i]; } } - /// CHECK-START: void Main.foo2(int[], int, int) BCE (before) + /// CHECK-START: void Main.foo2(int[], int, int, boolean) BCE (before) /// CHECK: BoundsCheck /// CHECK: ArraySet /// CHECK-NOT: BoundsCheck /// CHECK: ArrayGet - /// CHECK-START: void Main.foo2(int[], int, int) BCE (after) + /// CHECK-START: void Main.foo2(int[], int, int, boolean) BCE (after) /// CHECK: Phi /// CHECK-NOT: BoundsCheck /// CHECK: ArraySet @@ -692,25 +702,30 @@ public class Main { /// CHECK: Phi /// CHECK: Goto - void foo2(int[] array, int start, int end) { + void foo2(int[] array, int start, int end, boolean expectInterpreter) { // Three HDeoptimize will be added. One for // start >= 0, one for end <= array.length, // and one for null check on array (to hoist null // check and array.length out of loop). for (int i = start ; i <= end; i++) { + if (expectInterpreter) { + assertIsInterpreted(); + } else { + assertIsManaged(); + } array[i] = 1; sum += array[i]; } } - /// CHECK-START: void Main.foo3(int[], int) BCE (before) + /// CHECK-START: void Main.foo3(int[], int, boolean) BCE (before) /// CHECK: BoundsCheck /// CHECK: ArraySet /// CHECK-NOT: BoundsCheck /// CHECK: ArrayGet - /// CHECK-START: void Main.foo3(int[], int) BCE (after) + /// CHECK-START: void Main.foo3(int[], int, boolean) BCE (after) /// CHECK: Phi /// CHECK-NOT: BoundsCheck /// CHECK: ArraySet @@ -726,24 +741,29 @@ public class Main { /// CHECK: Phi /// CHECK: Goto - void foo3(int[] array, int end) { + void foo3(int[] array, int end, boolean expectInterpreter) { // Two HDeoptimize will be added. One for end < array.length, // and one for null check on array (to hoist null check // and array.length out of loop). for (int i = 3 ; i <= end; i++) { + if (expectInterpreter) { + assertIsInterpreted(); + } else { + assertIsManaged(); + } array[i] = 1; sum += array[i]; } } - /// CHECK-START: void Main.foo4(int[], int) BCE (before) + /// CHECK-START: void Main.foo4(int[], int, boolean) BCE (before) /// CHECK: BoundsCheck /// CHECK: ArraySet /// CHECK-NOT: BoundsCheck /// CHECK: ArrayGet - /// CHECK-START: void Main.foo4(int[], int) BCE (after) + /// CHECK-START: void Main.foo4(int[], int, boolean) BCE (after) /// CHECK: Phi /// CHECK-NOT: BoundsCheck /// CHECK: ArraySet @@ -759,18 +779,23 @@ public class Main { /// CHECK: Phi /// CHECK: Goto - void foo4(int[] array, int end) { + void foo4(int[] array, int end, boolean expectInterpreter) { // Two HDeoptimize will be added. One for end <= array.length, // and one for null check on array (to hoist null check // and array.length out of loop). for (int i = end ; i > 0; i--) { + if (expectInterpreter) { + assertIsInterpreted(); + } else { + assertIsManaged(); + } array[i - 1] = 1; sum += array[i - 1]; } } - /// CHECK-START: void Main.foo5(int[], int) BCE (before) + /// CHECK-START: void Main.foo5(int[], int, boolean) BCE (before) /// CHECK: BoundsCheck /// CHECK: ArraySet /// CHECK: BoundsCheck @@ -780,7 +805,7 @@ public class Main { /// CHECK: BoundsCheck /// CHECK: ArrayGet - /// CHECK-START: void Main.foo5(int[], int) BCE (after) + /// CHECK-START: void Main.foo5(int[], int, boolean) BCE (after) /// CHECK-NOT: BoundsCheck /// CHECK: ArraySet /// CHECK: Phi @@ -800,7 +825,7 @@ public class Main { /// CHECK-NOT: Phi /// CHECK: Goto - void foo5(int[] array, int end) { + void foo5(int[] array, int end, boolean expectInterpreter) { // Bounds check in this loop can be eliminated without deoptimization. for (int i = array.length - 1 ; i >= 0; i--) { array[i] = 1; @@ -808,6 +833,11 @@ public class Main { // One HDeoptimize will be added. // It's for (end - 2 <= array.length - 2). for (int i = end - 2 ; i > 0; i--) { + if (expectInterpreter) { + assertIsInterpreted(); + } else { + assertIsManaged(); + } sum += array[i - 1]; sum += array[i]; sum += array[i + 1]; @@ -815,7 +845,7 @@ public class Main { } - /// CHECK-START: void Main.foo6(int[], int, int) BCE (before) + /// CHECK-START: void Main.foo6(int[], int, int, boolean) BCE (before) /// CHECK: BoundsCheck /// CHECK: ArrayGet /// CHECK: BoundsCheck @@ -829,7 +859,7 @@ public class Main { /// CHECK-NOT: BoundsCheck /// CHECK: ArraySet - /// CHECK-START: void Main.foo6(int[], int, int) BCE (after) + /// CHECK-START: void Main.foo6(int[], int, int, boolean) BCE (after) /// CHECK: Phi /// CHECK-NOT: BoundsCheck /// CHECK: ArrayGet @@ -855,12 +885,17 @@ public class Main { /// CHECK: Goto /// CHECK-NOT: Deoptimize - void foo6(int[] array, int start, int end) { + void foo6(int[] array, int start, int end, boolean expectInterpreter) { // Three HDeoptimize will be added. One for // start >= 2, one for end <= array.length - 3, // and one for null check on array (to hoist null // check and array.length out of loop). for (int i = end; i >= start; i--) { + if (expectInterpreter) { + assertIsInterpreted(); + } else { + assertIsManaged(); + } array[i] = (array[i-2] + array[i-1] + array[i] + array[i+1] + array[i+2]) / 5; } } @@ -948,12 +983,12 @@ public class Main { } - /// CHECK-START: void Main.foo9(int[]) BCE (before) + /// CHECK-START: void Main.foo9(int[], boolean) BCE (before) /// CHECK: NullCheck /// CHECK: BoundsCheck /// CHECK: ArrayGet - /// CHECK-START: void Main.foo9(int[]) BCE (after) + /// CHECK-START: void Main.foo9(int[], boolean) BCE (after) // The loop is guaranteed to be entered. No need to transform the // loop for loop body entry test. /// CHECK: Deoptimize @@ -964,10 +999,15 @@ public class Main { /// CHECK-NOT: BoundsCheck /// CHECK: ArrayGet - void foo9(int[] array) { + void foo9(int[] array, boolean expectInterpreter) { // Two HDeoptimize will be added. One for // 10 <= array.length, and one for null check on array. for (int i = 0 ; i < 10; i++) { + if (expectInterpreter) { + assertIsInterpreted(); + } else { + assertIsManaged(); + } sum += array[i]; } } @@ -999,7 +1039,7 @@ public class Main { static void testUnknownBounds() { boolean caught = false; Main main = new Main(); - main.foo1(new int[10], 0, 10); + main.foo1(new int[10], 0, 10, false); if (main.sum != 10) { System.out.println("foo1 failed!"); } @@ -1007,7 +1047,7 @@ public class Main { caught = false; main = new Main(); try { - main.foo1(new int[10], 0, 11); + main.foo1(new int[10], 0, 11, true); } catch (ArrayIndexOutOfBoundsException e) { caught = true; } @@ -1016,7 +1056,7 @@ public class Main { } main = new Main(); - main.foo2(new int[10], 0, 9); + main.foo2(new int[10], 0, 9, false); if (main.sum != 10) { System.out.println("foo2 failed!"); } @@ -1024,7 +1064,7 @@ public class Main { caught = false; main = new Main(); try { - main.foo2(new int[10], 0, 10); + main.foo2(new int[10], 0, 10, true); } catch (ArrayIndexOutOfBoundsException e) { caught = true; } @@ -1033,7 +1073,7 @@ public class Main { } main = new Main(); - main.foo3(new int[10], 9); + main.foo3(new int[10], 9, false); if (main.sum != 7) { System.out.println("foo3 failed!"); } @@ -1041,7 +1081,7 @@ public class Main { caught = false; main = new Main(); try { - main.foo3(new int[10], 10); + main.foo3(new int[10], 10, true); } catch (ArrayIndexOutOfBoundsException e) { caught = true; } @@ -1050,7 +1090,7 @@ public class Main { } main = new Main(); - main.foo4(new int[10], 10); + main.foo4(new int[10], 10, false); if (main.sum != 10) { System.out.println("foo4 failed!"); } @@ -1058,7 +1098,7 @@ public class Main { caught = false; main = new Main(); try { - main.foo4(new int[10], 11); + main.foo4(new int[10], 11, true); } catch (ArrayIndexOutOfBoundsException e) { caught = true; } @@ -1067,7 +1107,7 @@ public class Main { } main = new Main(); - main.foo5(new int[10], 10); + main.foo5(new int[10], 10, false); if (main.sum != 24) { System.out.println("foo5 failed!"); } @@ -1075,7 +1115,7 @@ public class Main { caught = false; main = new Main(); try { - main.foo5(new int[10], 11); + main.foo5(new int[10], 11, true); } catch (ArrayIndexOutOfBoundsException e) { caught = true; } @@ -1084,11 +1124,11 @@ public class Main { } main = new Main(); - main.foo6(new int[10], 2, 7); + main.foo6(new int[10], 2, 7, false); main = new Main(); int[] array9 = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; - main.foo9(array9); + main.foo9(array9, false); if (main.sum != 45) { System.out.println("foo9 failed!"); } @@ -1104,7 +1144,7 @@ public class Main { caught = false; main = new Main(); try { - main.foo6(new int[10], 2, 8); + main.foo6(new int[10], 2, 8, true); } catch (ArrayIndexOutOfBoundsException e) { caught = true; } @@ -1115,7 +1155,7 @@ public class Main { caught = false; main = new Main(); try { - main.foo6(new int[10], 1, 7); + main.foo6(new int[10], 1, 7, true); } catch (ArrayIndexOutOfBoundsException e) { caught = true; } @@ -1152,6 +1192,15 @@ public class Main { /// CHECK: ParallelMove public static void main(String[] args) { + System.loadLibrary(args[0]); + + if (!compiledWithOptimizing() || + !hasOatFile() || + runtimeIsSoftFail() || + isInterpreted()) { + disableStackFrameAsserts(); + } + sieve(20); int[] array = {5, 2, 3, 7, 0, 1, 6, 4}; @@ -1190,4 +1239,11 @@ public class Main { new Main().testExceptionMessage(); } + public static native boolean compiledWithOptimizing(); + public static native void disableStackFrameAsserts(); + public static native void assertIsManaged(); + public static native void assertIsInterpreted(); + public static native boolean hasOatFile(); + public static native boolean runtimeIsSoftFail(); + public static native boolean isInterpreted(); } diff --git a/test/529-checker-unresolved/expected.txt b/test/529-checker-unresolved/expected.txt index 358048c75b..1e7dbfed2e 100644 --- a/test/529-checker-unresolved/expected.txt +++ b/test/529-checker-unresolved/expected.txt @@ -3,3 +3,5 @@ UnresolvedClass.staticMethod() UnresolvedClass.virtualMethod() UnresolvedClass.interfaceMethod() UnresolvedClass.superMethod() +instanceof ok +checkcast ok diff --git a/test/529-checker-unresolved/src/Main.java b/test/529-checker-unresolved/src/Main.java index 6f047974b3..5219c04c37 100644 --- a/test/529-checker-unresolved/src/Main.java +++ b/test/529-checker-unresolved/src/Main.java @@ -44,13 +44,141 @@ public class Main extends UnresolvedSuperClass { super.superMethod(); } + /// CHECK-START: void Main.callUnresolvedStaticFieldAccess() register (before) + /// CHECK: UnresolvedStaticFieldSet field_type:PrimByte + /// CHECK: UnresolvedStaticFieldSet field_type:PrimChar + /// CHECK: UnresolvedStaticFieldSet field_type:PrimInt + /// CHECK: UnresolvedStaticFieldSet field_type:PrimLong + /// CHECK: UnresolvedStaticFieldSet field_type:PrimFloat + /// CHECK: UnresolvedStaticFieldSet field_type:PrimDouble + /// CHECK: UnresolvedStaticFieldSet field_type:PrimNot + + /// CHECK: UnresolvedStaticFieldGet field_type:PrimByte + /// CHECK: UnresolvedStaticFieldGet field_type:PrimChar + /// CHECK: UnresolvedStaticFieldGet field_type:PrimInt + /// CHECK: UnresolvedStaticFieldGet field_type:PrimLong + /// CHECK: UnresolvedStaticFieldGet field_type:PrimFloat + /// CHECK: UnresolvedStaticFieldGet field_type:PrimDouble + /// CHECK: UnresolvedStaticFieldGet field_type:PrimNot + static public void callUnresolvedStaticFieldAccess() { + Object o = new Object(); + UnresolvedClass.staticByte = (byte)1; + UnresolvedClass.staticChar = '1'; + UnresolvedClass.staticInt = 123456789; + UnresolvedClass.staticLong = 123456789123456789l; + UnresolvedClass.staticFloat = 123456789123456789f; + UnresolvedClass.staticDouble = 123456789123456789d; + UnresolvedClass.staticObject = o; + + expectEquals((byte)1, UnresolvedClass.staticByte); + expectEquals('1', UnresolvedClass.staticChar); + expectEquals(123456789, UnresolvedClass.staticInt); + expectEquals(123456789123456789l, UnresolvedClass.staticLong); + expectEquals(123456789123456789f, UnresolvedClass.staticFloat); + expectEquals(123456789123456789d, UnresolvedClass.staticDouble); + expectEquals(o, UnresolvedClass.staticObject); + } + + /// CHECK-START: void Main.callUnresolvedInstanceFieldAccess(UnresolvedClass) register (before) + /// CHECK: UnresolvedInstanceFieldSet field_type:PrimByte + /// CHECK: UnresolvedInstanceFieldSet field_type:PrimChar + /// CHECK: UnresolvedInstanceFieldSet field_type:PrimInt + /// CHECK: UnresolvedInstanceFieldSet field_type:PrimLong + /// CHECK: UnresolvedInstanceFieldSet field_type:PrimFloat + /// CHECK: UnresolvedInstanceFieldSet field_type:PrimDouble + /// CHECK: UnresolvedInstanceFieldSet field_type:PrimNot + + /// CHECK: UnresolvedInstanceFieldGet field_type:PrimByte + /// CHECK: UnresolvedInstanceFieldGet field_type:PrimChar + /// CHECK: UnresolvedInstanceFieldGet field_type:PrimInt + /// CHECK: UnresolvedInstanceFieldGet field_type:PrimLong + /// CHECK: UnresolvedInstanceFieldGet field_type:PrimFloat + /// CHECK: UnresolvedInstanceFieldGet field_type:PrimDouble + /// CHECK: UnresolvedInstanceFieldGet field_type:PrimNot + static public void callUnresolvedInstanceFieldAccess(UnresolvedClass c) { + Object o = new Object(); + c.instanceByte = (byte)1; + c.instanceChar = '1'; + c.instanceInt = 123456789; + c.instanceLong = 123456789123456789l; + c.instanceFloat = 123456789123456789f; + c.instanceDouble = 123456789123456789d; + c.instanceObject = o; + + expectEquals((byte)1, c.instanceByte); + expectEquals('1', c.instanceChar); + expectEquals(123456789, c.instanceInt); + expectEquals(123456789123456789l, c.instanceLong); + expectEquals(123456789123456789f, c.instanceFloat); + expectEquals(123456789123456789d, c.instanceDouble); + expectEquals(o, c.instanceObject); + } + + static public void testInstanceOf(Object o) { + if (o instanceof UnresolvedSuperClass) { + System.out.println("instanceof ok"); + } + } + + static public UnresolvedSuperClass testCheckCast(Object o) { + UnresolvedSuperClass c = (UnresolvedSuperClass) o; + System.out.println("checkcast ok"); + return c; + } /// CHECK-START: void Main.main(java.lang.String[]) register (before) /// CHECK: InvokeUnresolved invoke_type:direct static public void main(String[] args) { UnresolvedClass c = new UnresolvedClass(); + Main m = new Main(); callInvokeUnresolvedStatic(); callInvokeUnresolvedVirtual(c); callInvokeUnresolvedInterface(c); - callInvokeUnresolvedSuper(new Main()); + callInvokeUnresolvedSuper(m); + callUnresolvedStaticFieldAccess(); + callUnresolvedInstanceFieldAccess(c); + testInstanceOf(m); + testCheckCast(m); + } + + public static void expectEquals(byte expected, byte result) { + if (expected != result) { + throw new Error("Expected: " + expected + ", found: " + result); + } + } + + public static void expectEquals(char expected, char result) { + if (expected != result) { + throw new Error("Expected: " + expected + ", found: " + result); + } + } + + public static void expectEquals(int expected, int result) { + if (expected != result) { + throw new Error("Expected: " + expected + ", found: " + result); + } + } + + public static void expectEquals(long expected, long result) { + if (expected != result) { + throw new Error("Expected: " + expected + ", found: " + result); + } + } + + public static void expectEquals(float expected, float result) { + if (expected != result) { + throw new Error("Expected: " + expected + ", found: " + result); + } + } + + public static void expectEquals(double expected, double result) { + if (expected != result) { + throw new Error("Expected: " + expected + ", found: " + result); + } + } + + public static void expectEquals(Object expected, Object result) { + if (expected != result) { + throw new Error("Expected: " + expected + ", found: " + result); + } } } diff --git a/test/529-checker-unresolved/src/Unresolved.java b/test/529-checker-unresolved/src/Unresolved.java index 5bf92dd331..20ac6e0b89 100644 --- a/test/529-checker-unresolved/src/Unresolved.java +++ b/test/529-checker-unresolved/src/Unresolved.java @@ -40,15 +40,21 @@ class UnresolvedClass extends UnresolvedSuperClass implements UnresolvedInterfac public void interfaceMethod() { System.out.println("UnresolvedClass.interfaceMethod()"); } -} - -final class UnresolvedFinalClass { - public void directMethod() { - System.out.println("UnresolvedFinalClass.directMethod()"); - } -} -class UnresolvedAtRuntime { - public void unresolvedAtRuntime() { } + public static byte staticByte; + public static char staticChar; + public static int staticInt; + public static long staticLong; + public static float staticFloat; + public static double staticDouble; + public static Object staticObject; + + public byte instanceByte; + public char instanceChar; + public int instanceInt; + public long instanceLong; + public float instanceFloat; + public double instanceDouble; + public Object instanceObject; } diff --git a/test/535-deopt-and-inlining/expected.txt b/test/535-deopt-and-inlining/expected.txt new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/test/535-deopt-and-inlining/expected.txt diff --git a/test/535-deopt-and-inlining/info.txt b/test/535-deopt-and-inlining/info.txt new file mode 100644 index 0000000000..717612a1ad --- /dev/null +++ b/test/535-deopt-and-inlining/info.txt @@ -0,0 +1,2 @@ +Stress test for deoptimization and JIT, to ensure the +stack visitor uses the right ArtMethod when deopting. diff --git a/test/535-deopt-and-inlining/src/Main.java b/test/535-deopt-and-inlining/src/Main.java new file mode 100644 index 0000000000..c231bf0e87 --- /dev/null +++ b/test/535-deopt-and-inlining/src/Main.java @@ -0,0 +1,55 @@ +/* + * 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 run() { + // Loop enough to get JIT compilation. + for (int i = 0; i < 10000; ++i) { + doCall(new int[0]); + } + } + + public static void main(String[] args) throws Exception { + run(); + } + + public static void doCall(int[] array) { + try { + deopt(array); + } catch (IndexOutOfBoundsException ioobe) { + // Expected + } + } + + public static void deopt(int[] array) { + // Invoke `deopt` much more than `$inline$deopt` so that only `deopt` gets + // initially JITted. + if (call == 100) { + call = 0; + $inline$deopt(array); + } else { + call++; + } + } + + public static void $inline$deopt(int[] array) { + array[0] = 1; + array[1] = 1; + } + + static int call = 0; +} diff --git a/test/Android.run-test.mk b/test/Android.run-test.mk index 49778cb3a6..db16b97ea6 100644 --- a/test/Android.run-test.mk +++ b/test/Android.run-test.mk @@ -369,6 +369,7 @@ TEST_ART_BROKEN_FALLBACK_RUN_TESTS := # This test dynamically enables tracing to force a deoptimization. This makes the test meaningless # when already tracing, and writes an error message that we do not want to check for. TEST_ART_BROKEN_TRACING_RUN_TESTS := \ + 087-gc-after-link \ 137-cfi \ 141-class-unload \ 802-deoptimization @@ -490,14 +491,6 @@ ifneq (,$(filter optimizing,$(COMPILER_TYPES))) $(IMAGE_TYPES),$(PICTEST_TYPES),$(DEBUGGABLE_TYPES),$(TEST_ART_BROKEN_OPTIMIZING_RUN_TESTS),$(ALL_ADDRESS_SIZES)) endif -# If ART_USE_OPTIMIZING_COMPILER is set to true, then the default core.art has been -# compiled with the optimizing compiler. -ifeq ($(ART_USE_OPTIMIZING_COMPILER),true) - ART_TEST_KNOWN_BROKEN += $(call all-run-test-names,$(TARGET_TYPES),$(RUN_TYPES),$(PREBUILD_TYPES), \ - default,$(RELOCATE_TYPES),$(TRACE_TYPES),$(GC_TYPES),$(JNI_TYPES), \ - $(IMAGE_TYPES),$(PICTEST_TYPES),$(DEBUGGABLE_TYPES),$(TEST_ART_BROKEN_OPTIMIZING_RUN_TESTS),$(ALL_ADDRESS_SIZES)) -endif - TEST_ART_BROKEN_OPTIMIZING_RUN_TESTS := # Tests that should fail when the optimizing compiler compiles them non-debuggable. diff --git a/test/common/runtime_state.cc b/test/common/runtime_state.cc index 042b03bfb6..082c9b3c8d 100644 --- a/test/common/runtime_state.cc +++ b/test/common/runtime_state.cc @@ -66,4 +66,54 @@ extern "C" JNIEXPORT jboolean JNICALL Java_Main_isImageDex2OatEnabled(JNIEnv* en return Runtime::Current()->IsImageDex2OatEnabled(); } +// public static native boolean compiledWithOptimizing(); +// Did we use the optimizing compiler to compile this? + +extern "C" JNIEXPORT jboolean JNICALL Java_Main_compiledWithOptimizing(JNIEnv* env, jclass cls) { + ScopedObjectAccess soa(env); + + mirror::Class* klass = soa.Decode<mirror::Class*>(cls); + const DexFile& dex_file = klass->GetDexFile(); + const OatFile::OatDexFile* oat_dex_file = dex_file.GetOatDexFile(); + if (oat_dex_file == nullptr) { + // Could be JIT, which also uses optimizing, but conservatively say no. + return JNI_FALSE; + } + const OatFile* oat_file = oat_dex_file->GetOatFile(); + CHECK(oat_file != nullptr); + + const char* cmd_line = oat_file->GetOatHeader().GetStoreValueByKey(OatHeader::kDex2OatCmdLineKey); + CHECK(cmd_line != nullptr); // Huh? This should not happen. + + // Check the backend. + constexpr const char* kCompilerBackend = "--compiler-backend="; + const char* backend = strstr(cmd_line, kCompilerBackend); + if (backend != nullptr) { + // If it's set, make sure it's optimizing. + backend += strlen(kCompilerBackend); + if (strncmp(backend, "Optimizing", strlen("Optimizing")) != 0) { + return JNI_FALSE; + } + } + + // Check the filter. + constexpr const char* kCompilerFilter = "--compiler-filter="; + const char* filter = strstr(cmd_line, kCompilerFilter); + if (filter != nullptr) { + // If it's set, make sure it's not interpret-only|verify-none|verify-at-runtime. + // Note: The space filter might have an impact on the test, but ignore that for now. + filter += strlen(kCompilerFilter); + constexpr const char* kInterpretOnly = "interpret-only"; + constexpr const char* kVerifyNone = "verify-none"; + constexpr const char* kVerifyAtRuntime = "verify-at-runtime"; + if (strncmp(filter, kInterpretOnly, strlen(kInterpretOnly)) == 0 || + strncmp(filter, kVerifyNone, strlen(kVerifyNone)) == 0 || + strncmp(filter, kVerifyAtRuntime, strlen(kVerifyAtRuntime)) == 0) { + return JNI_FALSE; + } + } + + return JNI_TRUE; +} + } // namespace art diff --git a/test/common/stack_inspect.cc b/test/common/stack_inspect.cc index d22cf52882..922eae61e2 100644 --- a/test/common/stack_inspect.cc +++ b/test/common/stack_inspect.cc @@ -27,9 +27,20 @@ namespace art { -// public static native boolean isCallerInterpreted(); +static bool asserts_enabled = true; -extern "C" JNIEXPORT jboolean JNICALL Java_Main_isCallerInterpreted(JNIEnv* env, jclass) { +// public static native void disableStackFrameAsserts(); +// Note: to globally disable asserts in unsupported configurations. + +extern "C" JNIEXPORT void JNICALL Java_Main_disableStackFrameAsserts(JNIEnv* env ATTRIBUTE_UNUSED, + jclass cls ATTRIBUTE_UNUSED) { + asserts_enabled = false; +} + + +// public static native boolean isInterpreted(); + +extern "C" JNIEXPORT jboolean JNICALL Java_Main_isInterpreted(JNIEnv* env, jclass) { ScopedObjectAccess soa(env); NthCallerVisitor caller(soa.Self(), 1, false); caller.WalkStack(); @@ -37,16 +48,18 @@ extern "C" JNIEXPORT jboolean JNICALL Java_Main_isCallerInterpreted(JNIEnv* env, return caller.GetCurrentShadowFrame() != nullptr ? JNI_TRUE : JNI_FALSE; } -// public static native void assertCallerIsInterpreted(); +// public static native void assertIsInterpreted(); -extern "C" JNIEXPORT void JNICALL Java_Main_assertCallerIsInterpreted(JNIEnv* env, jclass klass) { - CHECK(Java_Main_isCallerInterpreted(env, klass)); +extern "C" JNIEXPORT void JNICALL Java_Main_assertIsInterpreted(JNIEnv* env, jclass klass) { + if (asserts_enabled) { + CHECK(Java_Main_isInterpreted(env, klass)); + } } -// public static native boolean isCallerManaged(); +// public static native boolean isManaged(); -extern "C" JNIEXPORT jboolean JNICALL Java_Main_isCallerManaged(JNIEnv* env, jclass cls) { +extern "C" JNIEXPORT jboolean JNICALL Java_Main_isManaged(JNIEnv* env, jclass cls) { ScopedObjectAccess soa(env); mirror::Class* klass = soa.Decode<mirror::Class*>(cls); @@ -65,10 +78,12 @@ extern "C" JNIEXPORT jboolean JNICALL Java_Main_isCallerManaged(JNIEnv* env, jcl return caller.GetCurrentShadowFrame() != nullptr ? JNI_FALSE : JNI_TRUE; } -// public static native void assertCallerIsManaged(); +// public static native void assertIsManaged(); -extern "C" JNIEXPORT void JNICALL Java_Main_assertCallerIsManaged(JNIEnv* env, jclass cls) { - CHECK(Java_Main_isCallerManaged(env, cls)); +extern "C" JNIEXPORT void JNICALL Java_Main_assertIsManaged(JNIEnv* env, jclass cls) { + if (asserts_enabled) { + CHECK(Java_Main_isManaged(env, cls)); + } } } // namespace art |