blob: 09ebff16c241327fef3527dbf2af7cdd51aa2fcf [file] [log] [blame]
Nicolas Geoffray03971632016-03-17 10:44:24 +00001/*
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
Igor Murashkin11ffec22017-06-27 15:36:23 -070017import java.lang.reflect.Method;
18import java.lang.reflect.InvocationTargetException;
19
Nicolas Geoffraybb2c93b2016-05-04 14:00:12 +010020class Test1 {
21 int[] iarr;
22}
23
24class Test2 {
25 float[] farr;
26}
27
Nicolas Geoffray03971632016-03-17 10:44:24 +000028public class Main {
29 public static Object[] getObjectArray() { return null; }
30 public static long[] getLongArray() { return null; }
Nicolas Geoffrayb1d91572016-03-18 16:25:38 +000031 public static Object getNull() { return null; }
Nicolas Geoffraybb2c93b2016-05-04 14:00:12 +010032 public static Test1 getNullTest1() { return null; }
33 public static Test2 getNullTest2() { return null; }
Nicolas Geoffray03971632016-03-17 10:44:24 +000034
Igor Murashkin11ffec22017-06-27 15:36:23 -070035 public static void $noinline$runSmaliTest(String name) throws Throwable {
36 try {
37 Class<?> c = Class.forName("SmaliTests");
38 Method m = c.getMethod(name);
39 m.invoke(null);
40 } catch (InvocationTargetException ex) {
41 throw ex.getCause(); // re-raise expected exception.
42 } catch (Exception ex) {
43 throw new Error(ex);
44 }
45 }
46
Nicolas Geoffray03971632016-03-17 10:44:24 +000047 public static void main(String[] args) {
48 try {
49 foo();
50 throw new Error("Expected NullPointerException");
51 } catch (NullPointerException e) {
52 // Expected.
53 }
Nicolas Geoffraybb2c93b2016-05-04 14:00:12 +010054 try {
55 bar();
56 throw new Error("Expected NullPointerException");
57 } catch (NullPointerException e) {
58 // Expected.
59 }
60 try {
Igor Murashkin11ffec22017-06-27 15:36:23 -070061 $noinline$runSmaliTest("bar");
62 throw new Error("Expected NullPointerException");
63 } catch (NullPointerException e) {
64 // Expected.
65 } catch (Throwable t) {
66 throw new Error("Unexpected Throwable", t);
67 }
68
69 try {
Nicolas Geoffraybb2c93b2016-05-04 14:00:12 +010070 test1();
71 throw new Error("Expected NullPointerException");
72 } catch (NullPointerException e) {
73 // Expected.
74 }
Nicolas Geoffray03971632016-03-17 10:44:24 +000075 }
76
77 /// CHECK-START: void Main.foo() load_store_elimination (after)
Nicolas Geoffraybb2c93b2016-05-04 14:00:12 +010078 /// CHECK-DAG: <<Null:l\d+>> NullConstant
79 /// CHECK-DAG: <<Check:l\d+>> NullCheck [<<Null>>]
80 /// CHECK-DAG: <<Get1:j\d+>> ArrayGet [<<Check>>,{{i\d+}}]
81 /// CHECK-DAG: <<Get2:l\d+>> ArrayGet [<<Check>>,{{i\d+}}]
Nicolas Geoffray03971632016-03-17 10:44:24 +000082 public static void foo() {
83 longField = getLongArray()[0];
84 objectField = getObjectArray()[0];
85 }
86
Nicolas Geoffrayb1d91572016-03-18 16:25:38 +000087 /// CHECK-START: void Main.bar() load_store_elimination (after)
88 /// CHECK-DAG: <<Null:l\d+>> NullConstant
Igor Murashkin11ffec22017-06-27 15:36:23 -070089 /// CHECK-DAG: <<BoundFirst:l\d+>> BoundType [<<Null>>]
90 /// CHECK-DAG: <<BoundType:l\d+>> BoundType [<<BoundFirst>>]
Nicolas Geoffrayb1d91572016-03-18 16:25:38 +000091 /// CHECK-DAG: <<CheckL:l\d+>> NullCheck [<<BoundType>>]
92 /// CHECK-DAG: <<GetL0:l\d+>> ArrayGet [<<CheckL>>,{{i\d+}}]
93 /// CHECK-DAG: <<GetL1:l\d+>> ArrayGet [<<CheckL>>,{{i\d+}}]
94 /// CHECK-DAG: <<GetL2:l\d+>> ArrayGet [<<CheckL>>,{{i\d+}}]
95 /// CHECK-DAG: <<GetL3:l\d+>> ArrayGet [<<CheckL>>,{{i\d+}}]
96 /// CHECK-DAG: <<CheckJ:l\d+>> NullCheck [<<Null>>]
97 /// CHECK-DAG: <<GetJ0:j\d+>> ArrayGet [<<CheckJ>>,{{i\d+}}]
98 /// CHECK-DAG: <<GetJ1:j\d+>> ArrayGet [<<CheckJ>>,{{i\d+}}]
99 /// CHECK-DAG: <<GetJ2:j\d+>> ArrayGet [<<CheckJ>>,{{i\d+}}]
100 /// CHECK-DAG: <<GetJ3:j\d+>> ArrayGet [<<CheckJ>>,{{i\d+}}]
101 public static void bar() {
102 // We create multiple accesses that will lead the bounds check
103 // elimination pass to add a HDeoptimize. Not having the bounds check helped
104 // the load store elimination think it could merge two ArrayGet with different
105 // types.
Nicolas Geoffraybb2c93b2016-05-04 14:00:12 +0100106 String[] array = (String[])getNull();
Nicolas Geoffrayb1d91572016-03-18 16:25:38 +0000107 objectField = array[0];
108 objectField = array[1];
109 objectField = array[2];
110 objectField = array[3];
111 long[] longArray = getLongArray();
112 longField = longArray[0];
113 longField = longArray[1];
114 longField = longArray[2];
115 longField = longArray[3];
116 }
117
Nicolas Geoffraybb2c93b2016-05-04 14:00:12 +0100118 /// CHECK-START: float Main.test1() load_store_elimination (after)
119 /// CHECK-DAG: <<Null:l\d+>> NullConstant
120 /// CHECK-DAG: <<Check1:l\d+>> NullCheck [<<Null>>]
121 /// CHECK-DAG: <<FieldGet1:l\d+>> InstanceFieldGet [<<Check1>>] field_name:Test1.iarr
122 /// CHECK-DAG: <<Check2:l\d+>> NullCheck [<<FieldGet1>>]
123 /// CHECK-DAG: <<ArrayGet1:i\d+>> ArrayGet [<<Check2>>,{{i\d+}}]
124 /// CHECK-DAG: <<ArrayGet2:f\d+>> ArrayGet [<<Check2>>,{{i\d+}}]
125 /// CHECK-DAG: Return [<<ArrayGet2>>]
126 public static float test1() {
127 Test1 test1 = getNullTest1();
Mathieu Chartier6beced42016-11-15 15:51:31 -0800128 Test2 test2 = getNullTest2();
Nicolas Geoffraybb2c93b2016-05-04 14:00:12 +0100129 int[] iarr = test1.iarr;
130 float[] farr = test2.farr;
131 iarr[0] = iarr[1];
132 return farr[0];
133 }
134
Nicolas Geoffray03971632016-03-17 10:44:24 +0000135 public static long longField;
136 public static Object objectField;
137}