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