1 /* 2 * Copyright (C) 2018 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 /** 18 * Tests for detecting throwing methods for code sinking. 19 */ 20 public class Main { 21 22 // 23 // Some "runtime library" methods. 24 // 25 doThrow(String par)26 public final void doThrow(String par) { 27 throw new Error("you are null: " + par); 28 } 29 checkNotNullDirect(Object obj, String par)30 public final void checkNotNullDirect(Object obj, String par) { 31 if (obj == null) 32 throw new Error("you are null: " + par); 33 } 34 checkNotNullSplit(Object obj, String par)35 public final void checkNotNullSplit(Object obj, String par) { 36 if (obj == null) 37 doThrow(par); 38 } 39 40 // 41 // Various ways of enforcing non-null parameter. 42 // In all cases, par should be subject to code sinking. 43 // 44 45 /// CHECK-START: void Main.doit1(int[]) code_sinking (before) 46 /// CHECK: begin_block 47 /// CHECK: <<Str:l\d+>> LoadString 48 /// CHECK: <<Tst:z\d+>> Equal 49 /// CHECK: If [<<Tst>>] 50 /// CHECK: end_block 51 /// CHECK: begin_block 52 /// CHECK: InvokeVirtual [{{l\d+}},<<Str>>] 53 /// CHECK: Throw 54 /// CHECK: end_block 55 // 56 /// CHECK-START: void Main.doit1(int[]) code_sinking (after) 57 /// CHECK: begin_block 58 /// CHECK: <<Tst:z\d+>> Equal 59 /// CHECK: If [<<Tst>>] 60 /// CHECK: end_block 61 /// CHECK: begin_block 62 /// CHECK: <<Str:l\d+>> LoadString 63 /// CHECK: InvokeVirtual [{{l\d+}},<<Str>>] 64 /// CHECK: Throw 65 /// CHECK: end_block doit1(int[] a)66 public void doit1(int[] a) { 67 // Being in the boot image means we know the load string cannot throw. Create one that is 68 // unlikely to be there to ensure we handle that case. 69 String par = "stringUnlikelyToBeInBootImage"; 70 if (a == null) 71 throw new Error("you are null: " + par); 72 for (int i = 0; i < a.length; i++) { 73 a[i] = 1; 74 } 75 } 76 77 /// CHECK-START: void Main.doit2(int[]) code_sinking (before) 78 /// CHECK: begin_block 79 /// CHECK: <<Str:l\d+>> LoadString 80 /// CHECK: <<Tst:z\d+>> NotEqual 81 /// CHECK: If [<<Tst>>] 82 /// CHECK: end_block 83 /// CHECK: begin_block 84 /// CHECK: InvokeStaticOrDirect [{{l\d+}},<<Str>>] method_name:Main.doThrow 85 /// CHECK: end_block 86 // 87 /// CHECK-START: void Main.doit2(int[]) code_sinking (after) 88 /// CHECK: begin_block 89 /// CHECK: <<Tst:z\d+>> NotEqual 90 /// CHECK: If [<<Tst>>] 91 /// CHECK: end_block 92 /// CHECK: begin_block 93 /// CHECK: <<Str:l\d+>> LoadString 94 /// CHECK: InvokeStaticOrDirect [{{l\d+}},<<Str>>] method_name:Main.doThrow 95 /// CHECK: end_block doit2(int[] a)96 public void doit2(int[] a) { 97 // Being in the boot image means we know the load string cannot throw. Create one that is 98 // unlikely to be there to ensure we handle that case. 99 String par = "stringUnlikelyToBeInBootImage"; 100 if (a == null) 101 doThrow(par); 102 for (int i = 0; i < a.length; i++) { 103 a[i] = 2; 104 } 105 } 106 107 /// CHECK-START: void Main.doit3(int[]) code_sinking (before) 108 /// CHECK: begin_block 109 /// CHECK: <<Str:l\d+>> LoadString 110 /// CHECK: <<Tst:z\d+>> Equal 111 /// CHECK: If [<<Tst>>] 112 /// CHECK: end_block 113 /// CHECK: begin_block 114 /// CHECK: InvokeVirtual [{{l\d+}},<<Str>>] 115 /// CHECK: Throw 116 /// CHECK: end_block 117 // 118 /// CHECK-START: void Main.doit3(int[]) code_sinking (after) 119 /// CHECK: begin_block 120 /// CHECK: <<Tst:z\d+>> Equal 121 /// CHECK: If [<<Tst>>] 122 /// CHECK: end_block 123 /// CHECK: begin_block 124 /// CHECK: <<Str:l\d+>> LoadString 125 /// CHECK: InvokeVirtual [{{l\d+}},<<Str>>] 126 /// CHECK: Throw 127 /// CHECK: end_block doit3(int[] a)128 public void doit3(int[] a) { 129 // Being in the boot image means we know the load string cannot throw. Create one that is 130 // unlikely to be there to ensure we handle that case. 131 String par = "stringUnlikelyToBeInBootImage"; 132 checkNotNullDirect(a, par); 133 for (int i = 0; i < a.length; i++) { 134 a[i] = 3; 135 } 136 } 137 138 /// CHECK-START: void Main.doit4(int[]) code_sinking (before) 139 /// CHECK: begin_block 140 /// CHECK: <<Str:l\d+>> LoadString 141 /// CHECK: <<Tst:z\d+>> NotEqual 142 /// CHECK: If [<<Tst>>] 143 /// CHECK: end_block 144 /// CHECK: begin_block 145 /// CHECK: InvokeStaticOrDirect [{{l\d+}},<<Str>>] method_name:Main.doThrow 146 /// CHECK: end_block 147 // 148 /// CHECK-START: void Main.doit4(int[]) code_sinking (after) 149 /// CHECK: begin_block 150 /// CHECK: <<Tst:z\d+>> NotEqual 151 /// CHECK: If [<<Tst>>] 152 /// CHECK: end_block 153 /// CHECK: begin_block 154 /// CHECK: <<Str:l\d+>> LoadString 155 /// CHECK: InvokeStaticOrDirect [{{l\d+}},<<Str>>] method_name:Main.doThrow 156 /// CHECK: end_block doit4(int[] a)157 public void doit4(int[] a) { 158 // Being in the boot image means we know the load string cannot throw. Create one that is 159 // unlikely to be there to ensure we handle that case. 160 String par = "stringUnlikelyToBeInBootImage"; 161 checkNotNullSplit(a, par); 162 for (int i = 0; i < a.length; i++) { 163 a[i] = 4; 164 } 165 } 166 167 // 168 // Test driver. 169 // 170 main(String[] args)171 static public void main(String[] args) { 172 int[] a = new int[100]; 173 for (int i = 0; i < 100; i++) { 174 a[i] = 0; 175 } 176 177 Main m = new Main(); 178 179 try { 180 m.doit1(null); 181 System.out.println("should not reach this!"); 182 } catch (Error e) { 183 m.doit1(a); 184 } 185 for (int i = 0; i < 100; i++) { 186 expectEquals(1, a[i]); 187 } 188 189 try { 190 m.doit2(null); 191 System.out.println("should not reach this!"); 192 } catch (Error e) { 193 m.doit2(a); 194 } 195 for (int i = 0; i < 100; i++) { 196 expectEquals(2, a[i]); 197 } 198 199 try { 200 m.doit3(null); 201 System.out.println("should not reach this!"); 202 } catch (Error e) { 203 m.doit3(a); 204 } 205 for (int i = 0; i < 100; i++) { 206 expectEquals(3, a[i]); 207 } 208 209 try { 210 m.doit4(null); 211 System.out.println("should not reach this!"); 212 } catch (Error e) { 213 m.doit4(a); 214 } 215 for (int i = 0; i < 100; i++) { 216 expectEquals(4, a[i]); 217 } 218 219 System.out.println("passed"); 220 } 221 expectEquals(int expected, int result)222 private static void expectEquals(int expected, int result) { 223 if (expected != result) { 224 throw new Error("Expected: " + expected + ", found: " + result); 225 } 226 } 227 } 228