1/* 2 * Copyright (C) 2016 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 17class Test1 { 18 int[] iarr; 19} 20 21class Test2 { 22 float[] farr; 23} 24 25public class Main { 26 public static Object[] getObjectArray() { return null; } 27 public static long[] getLongArray() { return null; } 28 public static Object getNull() { return null; } 29 public static Test1 getNullTest1() { return null; } 30 public static Test2 getNullTest2() { return null; } 31 32 public static void main(String[] args) { 33 try { 34 foo(); 35 throw new Error("Expected NullPointerException"); 36 } catch (NullPointerException e) { 37 // Expected. 38 } 39 try { 40 bar(); 41 throw new Error("Expected NullPointerException"); 42 } catch (NullPointerException e) { 43 // Expected. 44 } 45 try { 46 test1(); 47 throw new Error("Expected NullPointerException"); 48 } catch (NullPointerException e) { 49 // Expected. 50 } 51 } 52 53 /// CHECK-START: void Main.foo() load_store_elimination (after) 54 /// CHECK-DAG: <<Null:l\d+>> NullConstant 55 /// CHECK-DAG: <<Check:l\d+>> NullCheck [<<Null>>] 56 /// CHECK-DAG: <<Get1:j\d+>> ArrayGet [<<Check>>,{{i\d+}}] 57 /// CHECK-DAG: <<Get2:l\d+>> ArrayGet [<<Check>>,{{i\d+}}] 58 public static void foo() { 59 longField = getLongArray()[0]; 60 objectField = getObjectArray()[0]; 61 } 62 63 /// CHECK-START: void Main.bar() load_store_elimination (after) 64 /// CHECK-DAG: <<Null:l\d+>> NullConstant 65 /// CHECK-DAG: <<BoundType:l\d+>> BoundType [<<Null>>] 66 /// CHECK-DAG: <<CheckL:l\d+>> NullCheck [<<BoundType>>] 67 /// CHECK-DAG: <<GetL0:l\d+>> ArrayGet [<<CheckL>>,{{i\d+}}] 68 /// CHECK-DAG: <<GetL1:l\d+>> ArrayGet [<<CheckL>>,{{i\d+}}] 69 /// CHECK-DAG: <<GetL2:l\d+>> ArrayGet [<<CheckL>>,{{i\d+}}] 70 /// CHECK-DAG: <<GetL3:l\d+>> ArrayGet [<<CheckL>>,{{i\d+}}] 71 /// CHECK-DAG: <<CheckJ:l\d+>> NullCheck [<<Null>>] 72 /// CHECK-DAG: <<GetJ0:j\d+>> ArrayGet [<<CheckJ>>,{{i\d+}}] 73 /// CHECK-DAG: <<GetJ1:j\d+>> ArrayGet [<<CheckJ>>,{{i\d+}}] 74 /// CHECK-DAG: <<GetJ2:j\d+>> ArrayGet [<<CheckJ>>,{{i\d+}}] 75 /// CHECK-DAG: <<GetJ3:j\d+>> ArrayGet [<<CheckJ>>,{{i\d+}}] 76 public static void bar() { 77 // We create multiple accesses that will lead the bounds check 78 // elimination pass to add a HDeoptimize. Not having the bounds check helped 79 // the load store elimination think it could merge two ArrayGet with different 80 // types. 81 String[] array = (String[])getNull(); 82 objectField = array[0]; 83 objectField = array[1]; 84 objectField = array[2]; 85 objectField = array[3]; 86 long[] longArray = getLongArray(); 87 longField = longArray[0]; 88 longField = longArray[1]; 89 longField = longArray[2]; 90 longField = longArray[3]; 91 } 92 93 /// CHECK-START: float Main.test1() load_store_elimination (after) 94 /// CHECK-DAG: <<Null:l\d+>> NullConstant 95 /// CHECK-DAG: <<Check1:l\d+>> NullCheck [<<Null>>] 96 /// CHECK-DAG: <<FieldGet1:l\d+>> InstanceFieldGet [<<Check1>>] field_name:Test1.iarr 97 /// CHECK-DAG: <<Check2:l\d+>> NullCheck [<<FieldGet1>>] 98 /// CHECK-DAG: <<ArrayGet1:i\d+>> ArrayGet [<<Check2>>,{{i\d+}}] 99 /// CHECK-DAG: <<ArrayGet2:f\d+>> ArrayGet [<<Check2>>,{{i\d+}}] 100 /// CHECK-DAG: Return [<<ArrayGet2>>] 101 public static float test1() { 102 Test1 test1 = getNullTest1(); 103 Test2 test2 = getNullTest2();; 104 int[] iarr = test1.iarr; 105 float[] farr = test2.farr; 106 iarr[0] = iarr[1]; 107 return farr[0]; 108 } 109 110 public static long longField; 111 public static Object objectField; 112} 113