xref: /aosp_15_r20/art/test/510-checker-try-catch/src/Main.java (revision 795d594fd825385562da6b089ea9b2033f3abf5a)
1*795d594fSAndroid Build Coastguard Worker /*
2*795d594fSAndroid Build Coastguard Worker  * Copyright (C) 2015 The Android Open Source Project
3*795d594fSAndroid Build Coastguard Worker  *
4*795d594fSAndroid Build Coastguard Worker  * Licensed under the Apache License, Version 2.0 (the "License");
5*795d594fSAndroid Build Coastguard Worker  * you may not use this file except in compliance with the License.
6*795d594fSAndroid Build Coastguard Worker  * You may obtain a copy of the License at
7*795d594fSAndroid Build Coastguard Worker  *
8*795d594fSAndroid Build Coastguard Worker  *      http://www.apache.org/licenses/LICENSE-2.0
9*795d594fSAndroid Build Coastguard Worker  *
10*795d594fSAndroid Build Coastguard Worker  * Unless required by applicable law or agreed to in writing, software
11*795d594fSAndroid Build Coastguard Worker  * distributed under the License is distributed on an "AS IS" BASIS,
12*795d594fSAndroid Build Coastguard Worker  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*795d594fSAndroid Build Coastguard Worker  * See the License for the specific language governing permissions and
14*795d594fSAndroid Build Coastguard Worker  * limitations under the License.
15*795d594fSAndroid Build Coastguard Worker  */
16*795d594fSAndroid Build Coastguard Worker 
17*795d594fSAndroid Build Coastguard Worker import java.lang.reflect.Method;
18*795d594fSAndroid Build Coastguard Worker 
19*795d594fSAndroid Build Coastguard Worker public class Main {
20*795d594fSAndroid Build Coastguard Worker   public enum TestPath {
21*795d594fSAndroid Build Coastguard Worker     ExceptionalFlow1(true, false, 3),
22*795d594fSAndroid Build Coastguard Worker     ExceptionalFlow2(false, true, 8),
23*795d594fSAndroid Build Coastguard Worker     NormalFlow(false, false, 42);
24*795d594fSAndroid Build Coastguard Worker 
TestPath(boolean arg1, boolean arg2, int expected)25*795d594fSAndroid Build Coastguard Worker     TestPath(boolean arg1, boolean arg2, int expected) {
26*795d594fSAndroid Build Coastguard Worker       this.arg1 = arg1;
27*795d594fSAndroid Build Coastguard Worker       this.arg2 = arg2;
28*795d594fSAndroid Build Coastguard Worker       this.expected = expected;
29*795d594fSAndroid Build Coastguard Worker     }
30*795d594fSAndroid Build Coastguard Worker 
31*795d594fSAndroid Build Coastguard Worker     public boolean arg1;
32*795d594fSAndroid Build Coastguard Worker     public boolean arg2;
33*795d594fSAndroid Build Coastguard Worker     public int expected;
34*795d594fSAndroid Build Coastguard Worker   }
35*795d594fSAndroid Build Coastguard Worker 
36*795d594fSAndroid Build Coastguard Worker   // Test that IntermediateAddress instruction is not alive across BoundsCheck which can throw to
37*795d594fSAndroid Build Coastguard Worker   // a catch block.
38*795d594fSAndroid Build Coastguard Worker   //
39*795d594fSAndroid Build Coastguard Worker   /// CHECK-START-{ARM,ARM64}: void Main.boundsCheckAndCatch(int, int[], int[]) GVN$after_arch (before)
40*795d594fSAndroid Build Coastguard Worker   /// CHECK-DAG: <<Const0:i\d+>>       IntConstant 0
41*795d594fSAndroid Build Coastguard Worker   /// CHECK-DAG: <<Const1:i\d+>>       IntConstant 1
42*795d594fSAndroid Build Coastguard Worker   /// CHECK-DAG: <<Const2:i\d+>>       IntConstant 2
43*795d594fSAndroid Build Coastguard Worker   /// CHECK-DAG: <<Offset:i\d+>>       IntConstant 12
44*795d594fSAndroid Build Coastguard Worker   /// CHECK-DAG: <<IndexParam:i\d+>>   ParameterValue
45*795d594fSAndroid Build Coastguard Worker   /// CHECK-DAG: <<ArrayA:l\d+>>       ParameterValue
46*795d594fSAndroid Build Coastguard Worker   /// CHECK-DAG: <<ArrayB:l\d+>>       ParameterValue
47*795d594fSAndroid Build Coastguard Worker   //
48*795d594fSAndroid Build Coastguard Worker   /// CHECK-DAG: <<NullCh1:l\d+>>      NullCheck [<<ArrayA>>]
49*795d594fSAndroid Build Coastguard Worker   /// CHECK-DAG: <<LengthA:i\d+>>      ArrayLength
50*795d594fSAndroid Build Coastguard Worker   /// CHECK-DAG: <<BoundsCh1:i\d+>>    BoundsCheck [<<IndexParam>>,<<LengthA>>]
51*795d594fSAndroid Build Coastguard Worker   /// CHECK-DAG:                       TryBoundary
52*795d594fSAndroid Build Coastguard Worker   //
53*795d594fSAndroid Build Coastguard Worker   /// CHECK-DAG: <<IntAddr1:i\d+>>     IntermediateAddress [<<NullCh1>>,<<Offset>>]
54*795d594fSAndroid Build Coastguard Worker   /// CHECK-DAG:                       ArraySet [<<IntAddr1>>,<<BoundsCh1>>,<<Const2>>]
55*795d594fSAndroid Build Coastguard Worker   /// CHECK-DAG: <<NullChB:l\d+>>      NullCheck [<<ArrayB>>]
56*795d594fSAndroid Build Coastguard Worker   /// CHECK-DAG: <<LengthB:i\d+>>      ArrayLength
57*795d594fSAndroid Build Coastguard Worker   /// CHECK-DAG: <<BoundsChB:i\d+>>    BoundsCheck [<<Const0>>,<<LengthB>>]
58*795d594fSAndroid Build Coastguard Worker   /// CHECK-DAG: <<GetB:i\d+>>         ArrayGet [<<NullChB>>,<<BoundsChB>>]
59*795d594fSAndroid Build Coastguard Worker   /// CHECK-DAG: <<ZeroCheck:i\d+>>    DivZeroCheck [<<IndexParam>>]
60*795d594fSAndroid Build Coastguard Worker   /// CHECK-DAG: <<Div:i\d+>>          Div [<<GetB>>,<<ZeroCheck>>]
61*795d594fSAndroid Build Coastguard Worker   /// CHECK-DAG: <<Xplus1:i\d+>>       Add [<<IndexParam>>,<<Const1>>]
62*795d594fSAndroid Build Coastguard Worker   /// CHECK-DAG: <<BoundsCh2:i\d+>>    BoundsCheck [<<Xplus1>>,<<LengthA>>]
63*795d594fSAndroid Build Coastguard Worker   /// CHECK-DAG: <<IntAddr2:i\d+>>     IntermediateAddress [<<NullCh1>>,<<Offset>>]
64*795d594fSAndroid Build Coastguard Worker   /// CHECK-DAG:                       ArraySet [<<IntAddr2>>,<<BoundsCh2>>,<<Div>>]
65*795d594fSAndroid Build Coastguard Worker   /// CHECK-DAG:                       TryBoundary
66*795d594fSAndroid Build Coastguard Worker   //
67*795d594fSAndroid Build Coastguard Worker   /// CHECK-DAG:                       ClearException
68*795d594fSAndroid Build Coastguard Worker   /// CHECK-DAG: <<IntAddr3:i\d+>>     IntermediateAddress [<<NullCh1>>,<<Offset>>]
69*795d594fSAndroid Build Coastguard Worker   /// CHECK-DAG:                       ArraySet [<<IntAddr3>>,<<BoundsCh1>>,<<Const1>>]
70*795d594fSAndroid Build Coastguard Worker   //
71*795d594fSAndroid Build Coastguard Worker   /// CHECK-NOT:                       NullCheck
72*795d594fSAndroid Build Coastguard Worker   /// CHECK-NOT:                       IntermediateAddress
73*795d594fSAndroid Build Coastguard Worker 
74*795d594fSAndroid Build Coastguard Worker   /// CHECK-START-{ARM,ARM64}: void Main.boundsCheckAndCatch(int, int[], int[]) GVN$after_arch (after)
75*795d594fSAndroid Build Coastguard Worker   /// CHECK-DAG: <<Const0:i\d+>>       IntConstant 0
76*795d594fSAndroid Build Coastguard Worker   /// CHECK-DAG: <<Const1:i\d+>>       IntConstant 1
77*795d594fSAndroid Build Coastguard Worker   /// CHECK-DAG: <<Const2:i\d+>>       IntConstant 2
78*795d594fSAndroid Build Coastguard Worker   /// CHECK-DAG: <<Offset:i\d+>>       IntConstant 12
79*795d594fSAndroid Build Coastguard Worker   /// CHECK-DAG: <<IndexParam:i\d+>>   ParameterValue
80*795d594fSAndroid Build Coastguard Worker   /// CHECK-DAG: <<ArrayA:l\d+>>       ParameterValue
81*795d594fSAndroid Build Coastguard Worker   /// CHECK-DAG: <<ArrayB:l\d+>>       ParameterValue
82*795d594fSAndroid Build Coastguard Worker   //
83*795d594fSAndroid Build Coastguard Worker   /// CHECK-DAG: <<NullCh1:l\d+>>      NullCheck [<<ArrayA>>]
84*795d594fSAndroid Build Coastguard Worker   /// CHECK-DAG: <<LengthA:i\d+>>      ArrayLength
85*795d594fSAndroid Build Coastguard Worker   /// CHECK-DAG: <<BoundsCh1:i\d+>>    BoundsCheck [<<IndexParam>>,<<LengthA>>]
86*795d594fSAndroid Build Coastguard Worker   /// CHECK-DAG:                       TryBoundary
87*795d594fSAndroid Build Coastguard Worker   //
88*795d594fSAndroid Build Coastguard Worker   /// CHECK-DAG: <<IntAddr1:i\d+>>     IntermediateAddress [<<NullCh1>>,<<Offset>>]
89*795d594fSAndroid Build Coastguard Worker   /// CHECK-DAG:                       ArraySet [<<IntAddr1>>,<<BoundsCh1>>,<<Const2>>]
90*795d594fSAndroid Build Coastguard Worker   /// CHECK-DAG: <<NullChB:l\d+>>      NullCheck [<<ArrayB>>]
91*795d594fSAndroid Build Coastguard Worker   /// CHECK-DAG: <<LengthB:i\d+>>      ArrayLength
92*795d594fSAndroid Build Coastguard Worker   /// CHECK-DAG: <<BoundsChB:i\d+>>    BoundsCheck [<<Const0>>,<<LengthB>>]
93*795d594fSAndroid Build Coastguard Worker   /// CHECK-DAG: <<GetB:i\d+>>         ArrayGet [<<NullChB>>,<<BoundsChB>>]
94*795d594fSAndroid Build Coastguard Worker   /// CHECK-DAG: <<ZeroCheck:i\d+>>    DivZeroCheck [<<IndexParam>>]
95*795d594fSAndroid Build Coastguard Worker   /// CHECK-DAG: <<Div:i\d+>>          Div [<<GetB>>,<<ZeroCheck>>]
96*795d594fSAndroid Build Coastguard Worker   /// CHECK-DAG: <<Xplus1:i\d+>>       Add [<<IndexParam>>,<<Const1>>]
97*795d594fSAndroid Build Coastguard Worker   /// CHECK-DAG: <<BoundsCh2:i\d+>>    BoundsCheck [<<Xplus1>>,<<LengthA>>]
98*795d594fSAndroid Build Coastguard Worker   /// CHECK-DAG:                       ArraySet [<<IntAddr1>>,<<BoundsCh2>>,<<Div>>]
99*795d594fSAndroid Build Coastguard Worker   /// CHECK-DAG:                       TryBoundary
100*795d594fSAndroid Build Coastguard Worker   //
101*795d594fSAndroid Build Coastguard Worker   /// CHECK-DAG:                       ClearException
102*795d594fSAndroid Build Coastguard Worker   /// CHECK-DAG: <<IntAddr3:i\d+>>     IntermediateAddress [<<NullCh1>>,<<Offset>>]
103*795d594fSAndroid Build Coastguard Worker   /// CHECK-DAG:                       ArraySet [<<IntAddr3>>,<<BoundsCh1>>,<<Const1>>]
104*795d594fSAndroid Build Coastguard Worker   //
105*795d594fSAndroid Build Coastguard Worker   /// CHECK-NOT:                       NullCheck
106*795d594fSAndroid Build Coastguard Worker   /// CHECK-NOT:                       IntermediateAddress
107*795d594fSAndroid Build Coastguard Worker 
108*795d594fSAndroid Build Coastguard Worker   //  Make sure that BoundsCheck, DivZeroCheck and NullCheck don't stop IntermediateAddress sharing.
boundsCheckAndCatch(int x, int[] a, int[] b)109*795d594fSAndroid Build Coastguard Worker   public static void boundsCheckAndCatch(int x, int[] a, int[] b) {
110*795d594fSAndroid Build Coastguard Worker     // This a[x] = 1 will be eliminated by LSE, but its related instructions (e.g. NullCheck and
111*795d594fSAndroid Build Coastguard Worker     // BoundsCheck) will remain.
112*795d594fSAndroid Build Coastguard Worker     a[x] = 1;
113*795d594fSAndroid Build Coastguard Worker     try {
114*795d594fSAndroid Build Coastguard Worker       a[x] = 2;
115*795d594fSAndroid Build Coastguard Worker       a[x + 1] = b[0] / x;
116*795d594fSAndroid Build Coastguard Worker     } catch (Exception e) {
117*795d594fSAndroid Build Coastguard Worker       a[x] = 1;
118*795d594fSAndroid Build Coastguard Worker     }
119*795d594fSAndroid Build Coastguard Worker   }
120*795d594fSAndroid Build Coastguard Worker 
expectEquals(int expected, int result)121*795d594fSAndroid Build Coastguard Worker   private static void expectEquals(int expected, int result) {
122*795d594fSAndroid Build Coastguard Worker     if (expected != result) {
123*795d594fSAndroid Build Coastguard Worker       throw new Error("Expected: " + expected + ", found: " + result);
124*795d594fSAndroid Build Coastguard Worker     }
125*795d594fSAndroid Build Coastguard Worker   }
126*795d594fSAndroid Build Coastguard Worker 
127*795d594fSAndroid Build Coastguard Worker   public final static int ARRAY_SIZE = 128;
128*795d594fSAndroid Build Coastguard Worker 
testBoundsCheckAndCatch()129*795d594fSAndroid Build Coastguard Worker   public static void testBoundsCheckAndCatch() {
130*795d594fSAndroid Build Coastguard Worker     int[] a = new int[ARRAY_SIZE];
131*795d594fSAndroid Build Coastguard Worker     int[] b = new int[ARRAY_SIZE];
132*795d594fSAndroid Build Coastguard Worker 
133*795d594fSAndroid Build Coastguard Worker     int index = ARRAY_SIZE - 2;
134*795d594fSAndroid Build Coastguard Worker     boundsCheckAndCatch(index, a, b);
135*795d594fSAndroid Build Coastguard Worker     expectEquals(2, a[index]);
136*795d594fSAndroid Build Coastguard Worker 
137*795d594fSAndroid Build Coastguard Worker     index = ARRAY_SIZE - 1;
138*795d594fSAndroid Build Coastguard Worker     boundsCheckAndCatch(index, a, b);
139*795d594fSAndroid Build Coastguard Worker     expectEquals(1, a[index]);
140*795d594fSAndroid Build Coastguard Worker   }
141*795d594fSAndroid Build Coastguard Worker 
testMethod(String method)142*795d594fSAndroid Build Coastguard Worker   public static void testMethod(String method) throws Exception {
143*795d594fSAndroid Build Coastguard Worker     Class<?> c = Class.forName("Runtime");
144*795d594fSAndroid Build Coastguard Worker     Method m = c.getMethod(method, boolean.class, boolean.class);
145*795d594fSAndroid Build Coastguard Worker 
146*795d594fSAndroid Build Coastguard Worker     for (TestPath path : TestPath.values()) {
147*795d594fSAndroid Build Coastguard Worker       Object[] arguments = new Object[] { path.arg1, path.arg2 };
148*795d594fSAndroid Build Coastguard Worker       int actual = (Integer) m.invoke(null, arguments);
149*795d594fSAndroid Build Coastguard Worker 
150*795d594fSAndroid Build Coastguard Worker       if (actual != path.expected) {
151*795d594fSAndroid Build Coastguard Worker         throw new Error("Method: \"" + method + "\", path: " + path + ", " +
152*795d594fSAndroid Build Coastguard Worker                         "expected: " + path.expected + ", actual: " + actual);
153*795d594fSAndroid Build Coastguard Worker       }
154*795d594fSAndroid Build Coastguard Worker     }
155*795d594fSAndroid Build Coastguard Worker   }
156*795d594fSAndroid Build Coastguard Worker 
testIntAddressCatch()157*795d594fSAndroid Build Coastguard Worker   public static void testIntAddressCatch()  throws Exception {
158*795d594fSAndroid Build Coastguard Worker     int[] a = new int[3];
159*795d594fSAndroid Build Coastguard Worker 
160*795d594fSAndroid Build Coastguard Worker     Class<?> c = Class.forName("Runtime");
161*795d594fSAndroid Build Coastguard Worker     Method m = c.getMethod("testIntAddressCatch", int.class,  Class.forName("[I"));
162*795d594fSAndroid Build Coastguard Worker     m.invoke(null, 0, a);
163*795d594fSAndroid Build Coastguard Worker   }
164*795d594fSAndroid Build Coastguard Worker 
main(String[] args)165*795d594fSAndroid Build Coastguard Worker   public static void main(String[] args) throws Exception {
166*795d594fSAndroid Build Coastguard Worker     testMethod("testUseAfterCatch_int");
167*795d594fSAndroid Build Coastguard Worker     testMethod("testUseAfterCatch_long");
168*795d594fSAndroid Build Coastguard Worker     testMethod("testUseAfterCatch_float");
169*795d594fSAndroid Build Coastguard Worker     testMethod("testUseAfterCatch_double");
170*795d594fSAndroid Build Coastguard Worker     testMethod("testCatchPhi_const");
171*795d594fSAndroid Build Coastguard Worker     testMethod("testCatchPhi_int");
172*795d594fSAndroid Build Coastguard Worker     testMethod("testCatchPhi_long");
173*795d594fSAndroid Build Coastguard Worker     testMethod("testCatchPhi_float");
174*795d594fSAndroid Build Coastguard Worker     testMethod("testCatchPhi_double");
175*795d594fSAndroid Build Coastguard Worker     testMethod("testCatchPhi_singleSlot");
176*795d594fSAndroid Build Coastguard Worker     testMethod("testCatchPhi_doubleSlot");
177*795d594fSAndroid Build Coastguard Worker 
178*795d594fSAndroid Build Coastguard Worker     testBoundsCheckAndCatch();
179*795d594fSAndroid Build Coastguard Worker     testIntAddressCatch();
180*795d594fSAndroid Build Coastguard Worker   }
181*795d594fSAndroid Build Coastguard Worker }
182