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