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