1*795d594fSAndroid Build Coastguard Worker /* 2*795d594fSAndroid Build Coastguard Worker * Copyright (C) 2016 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 import java.lang.reflect.InvocationTargetException; 19*795d594fSAndroid Build Coastguard Worker 20*795d594fSAndroid Build Coastguard Worker class Test1 { 21*795d594fSAndroid Build Coastguard Worker int[] iarr; 22*795d594fSAndroid Build Coastguard Worker } 23*795d594fSAndroid Build Coastguard Worker 24*795d594fSAndroid Build Coastguard Worker class Test2 { 25*795d594fSAndroid Build Coastguard Worker float[] farr; 26*795d594fSAndroid Build Coastguard Worker } 27*795d594fSAndroid Build Coastguard Worker 28*795d594fSAndroid Build Coastguard Worker public class Main { getObjectArray()29*795d594fSAndroid Build Coastguard Worker public static Object[] getObjectArray() { return null; } getLongArray()30*795d594fSAndroid Build Coastguard Worker public static long[] getLongArray() { return null; } getNull()31*795d594fSAndroid Build Coastguard Worker public static Object getNull() { return null; } getNullTest1()32*795d594fSAndroid Build Coastguard Worker public static Test1 getNullTest1() { return null; } getNullTest2()33*795d594fSAndroid Build Coastguard Worker public static Test2 getNullTest2() { return null; } 34*795d594fSAndroid Build Coastguard Worker $noinline$runSmaliTest(String name)35*795d594fSAndroid Build Coastguard Worker public static void $noinline$runSmaliTest(String name) throws Throwable { 36*795d594fSAndroid Build Coastguard Worker try { 37*795d594fSAndroid Build Coastguard Worker Class<?> c = Class.forName("SmaliTests"); 38*795d594fSAndroid Build Coastguard Worker Method m = c.getMethod(name); 39*795d594fSAndroid Build Coastguard Worker m.invoke(null); 40*795d594fSAndroid Build Coastguard Worker } catch (InvocationTargetException ex) { 41*795d594fSAndroid Build Coastguard Worker throw ex.getCause(); // re-raise expected exception. 42*795d594fSAndroid Build Coastguard Worker } catch (Exception ex) { 43*795d594fSAndroid Build Coastguard Worker throw new Error(ex); 44*795d594fSAndroid Build Coastguard Worker } 45*795d594fSAndroid Build Coastguard Worker } 46*795d594fSAndroid Build Coastguard Worker main(String[] args)47*795d594fSAndroid Build Coastguard Worker public static void main(String[] args) { 48*795d594fSAndroid Build Coastguard Worker try { 49*795d594fSAndroid Build Coastguard Worker foo(); 50*795d594fSAndroid Build Coastguard Worker throw new Error("Expected NullPointerException"); 51*795d594fSAndroid Build Coastguard Worker } catch (NullPointerException e) { 52*795d594fSAndroid Build Coastguard Worker // Expected. 53*795d594fSAndroid Build Coastguard Worker } 54*795d594fSAndroid Build Coastguard Worker try { 55*795d594fSAndroid Build Coastguard Worker bar(); 56*795d594fSAndroid Build Coastguard Worker throw new Error("Expected NullPointerException"); 57*795d594fSAndroid Build Coastguard Worker } catch (NullPointerException e) { 58*795d594fSAndroid Build Coastguard Worker // Expected. 59*795d594fSAndroid Build Coastguard Worker } 60*795d594fSAndroid Build Coastguard Worker try { 61*795d594fSAndroid Build Coastguard Worker $noinline$runSmaliTest("bar"); 62*795d594fSAndroid Build Coastguard Worker throw new Error("Expected NullPointerException"); 63*795d594fSAndroid Build Coastguard Worker } catch (NullPointerException e) { 64*795d594fSAndroid Build Coastguard Worker // Expected. 65*795d594fSAndroid Build Coastguard Worker } catch (Throwable t) { 66*795d594fSAndroid Build Coastguard Worker throw new Error("Unexpected Throwable", t); 67*795d594fSAndroid Build Coastguard Worker } 68*795d594fSAndroid Build Coastguard Worker try { 69*795d594fSAndroid Build Coastguard Worker $noinline$runSmaliTest("bar2"); 70*795d594fSAndroid Build Coastguard Worker throw new Error("Expected NullPointerException"); 71*795d594fSAndroid Build Coastguard Worker } catch (NullPointerException e) { 72*795d594fSAndroid Build Coastguard Worker // Expected. 73*795d594fSAndroid Build Coastguard Worker } catch (Throwable t) { 74*795d594fSAndroid Build Coastguard Worker throw new Error("Unexpected Throwable", t); 75*795d594fSAndroid Build Coastguard Worker } 76*795d594fSAndroid Build Coastguard Worker 77*795d594fSAndroid Build Coastguard Worker try { 78*795d594fSAndroid Build Coastguard Worker test1(); 79*795d594fSAndroid Build Coastguard Worker throw new Error("Expected NullPointerException"); 80*795d594fSAndroid Build Coastguard Worker } catch (NullPointerException e) { 81*795d594fSAndroid Build Coastguard Worker // Expected. 82*795d594fSAndroid Build Coastguard Worker } 83*795d594fSAndroid Build Coastguard Worker } 84*795d594fSAndroid Build Coastguard Worker 85*795d594fSAndroid Build Coastguard Worker /// CHECK-START: void Main.foo() load_store_elimination (after) 86*795d594fSAndroid Build Coastguard Worker /// CHECK-DAG: <<Null:l\d+>> NullConstant 87*795d594fSAndroid Build Coastguard Worker /// CHECK-DAG: <<Check:l\d+>> NullCheck [<<Null>>] 88*795d594fSAndroid Build Coastguard Worker /// CHECK-DAG: <<Get1:j\d+>> ArrayGet [<<Check>>,{{i\d+}}] 89*795d594fSAndroid Build Coastguard Worker /// CHECK-DAG: <<Get2:l\d+>> ArrayGet [<<Check>>,{{i\d+}}] foo()90*795d594fSAndroid Build Coastguard Worker public static void foo() { 91*795d594fSAndroid Build Coastguard Worker longField = getLongArray()[0]; 92*795d594fSAndroid Build Coastguard Worker objectField = getObjectArray()[0]; 93*795d594fSAndroid Build Coastguard Worker } 94*795d594fSAndroid Build Coastguard Worker 95*795d594fSAndroid Build Coastguard Worker /// CHECK-START: void Main.bar() load_store_elimination (after) 96*795d594fSAndroid Build Coastguard Worker /// CHECK-DAG: <<Null:l\d+>> NullConstant 97*795d594fSAndroid Build Coastguard Worker /// CHECK-DAG: BoundType [<<Null>>] 98*795d594fSAndroid Build Coastguard Worker /// CHECK-DAG: <<CheckL:l\d+>> NullCheck 99*795d594fSAndroid Build Coastguard Worker /// CHECK-DAG: <<GetL0:l\d+>> ArrayGet [<<CheckL>>,{{i\d+}}] 100*795d594fSAndroid Build Coastguard Worker /// CHECK-DAG: <<GetL1:l\d+>> ArrayGet [<<CheckL>>,{{i\d+}}] 101*795d594fSAndroid Build Coastguard Worker /// CHECK-DAG: <<GetL2:l\d+>> ArrayGet [<<CheckL>>,{{i\d+}}] 102*795d594fSAndroid Build Coastguard Worker /// CHECK-DAG: <<GetL3:l\d+>> ArrayGet [<<CheckL>>,{{i\d+}}] 103*795d594fSAndroid Build Coastguard Worker /// CHECK-DAG: <<CheckJ:l\d+>> NullCheck [<<Null>>] 104*795d594fSAndroid Build Coastguard Worker /// CHECK-DAG: <<GetJ0:j\d+>> ArrayGet [<<CheckJ>>,{{i\d+}}] 105*795d594fSAndroid Build Coastguard Worker /// CHECK-DAG: <<GetJ1:j\d+>> ArrayGet [<<CheckJ>>,{{i\d+}}] 106*795d594fSAndroid Build Coastguard Worker /// CHECK-DAG: <<GetJ2:j\d+>> ArrayGet [<<CheckJ>>,{{i\d+}}] 107*795d594fSAndroid Build Coastguard Worker /// CHECK-DAG: <<GetJ3:j\d+>> ArrayGet [<<CheckJ>>,{{i\d+}}] bar()108*795d594fSAndroid Build Coastguard Worker public static void bar() { 109*795d594fSAndroid Build Coastguard Worker // We create multiple accesses that will lead the bounds check 110*795d594fSAndroid Build Coastguard Worker // elimination pass to add a HDeoptimize. Not having the bounds check 111*795d594fSAndroid Build Coastguard Worker // makes the ArrayGets look almost the same if it were not for the type! 112*795d594fSAndroid Build Coastguard Worker String[] array = (String[])getNull(); 113*795d594fSAndroid Build Coastguard Worker objectField = array[0]; 114*795d594fSAndroid Build Coastguard Worker objectField = array[1]; 115*795d594fSAndroid Build Coastguard Worker objectField = array[2]; 116*795d594fSAndroid Build Coastguard Worker objectField = array[3]; 117*795d594fSAndroid Build Coastguard Worker long[] longArray = getLongArray(); 118*795d594fSAndroid Build Coastguard Worker longField = longArray[0]; 119*795d594fSAndroid Build Coastguard Worker longField = longArray[1]; 120*795d594fSAndroid Build Coastguard Worker longField = longArray[2]; 121*795d594fSAndroid Build Coastguard Worker longField = longArray[3]; 122*795d594fSAndroid Build Coastguard Worker } 123*795d594fSAndroid Build Coastguard Worker 124*795d594fSAndroid Build Coastguard Worker /// CHECK-START: float Main.test1() load_store_elimination (after) 125*795d594fSAndroid Build Coastguard Worker /// CHECK-DAG: <<Null:l\d+>> NullConstant 126*795d594fSAndroid Build Coastguard Worker /// CHECK-DAG: <<Check1:l\d+>> NullCheck [<<Null>>] 127*795d594fSAndroid Build Coastguard Worker /// CHECK-DAG: <<FieldGet1:l\d+>> InstanceFieldGet [<<Check1>>] field_name:Test1.iarr 128*795d594fSAndroid Build Coastguard Worker /// CHECK-DAG: <<Check2:l\d+>> NullCheck [<<FieldGet1>>] 129*795d594fSAndroid Build Coastguard Worker /// CHECK-DAG: <<ArrayGet1:i\d+>> ArrayGet [<<Check2>>,{{i\d+}}] 130*795d594fSAndroid Build Coastguard Worker /// CHECK-DAG: <<ArrayGet2:f\d+>> ArrayGet [<<Check2>>,{{i\d+}}] 131*795d594fSAndroid Build Coastguard Worker /// CHECK-DAG: Return [<<ArrayGet2>>] test1()132*795d594fSAndroid Build Coastguard Worker public static float test1() { 133*795d594fSAndroid Build Coastguard Worker Test1 test1 = getNullTest1(); 134*795d594fSAndroid Build Coastguard Worker Test2 test2 = getNullTest2(); 135*795d594fSAndroid Build Coastguard Worker int[] iarr = test1.iarr; 136*795d594fSAndroid Build Coastguard Worker float[] farr = test2.farr; 137*795d594fSAndroid Build Coastguard Worker iarr[0] = iarr[1]; 138*795d594fSAndroid Build Coastguard Worker return farr[0]; 139*795d594fSAndroid Build Coastguard Worker } 140*795d594fSAndroid Build Coastguard Worker 141*795d594fSAndroid Build Coastguard Worker public static long longField; 142*795d594fSAndroid Build Coastguard Worker public static Object objectField; 143*795d594fSAndroid Build Coastguard Worker } 144