1*795d594fSAndroid Build Coastguard Worker /* 2*795d594fSAndroid Build Coastguard Worker * Copyright (C) 2015 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 public class Main { 18*795d594fSAndroid Build Coastguard Worker 19*795d594fSAndroid Build Coastguard Worker /* 20*795d594fSAndroid Build Coastguard Worker * Ensure an inlined static invoke explicitly triggers the 21*795d594fSAndroid Build Coastguard Worker * initialization check of the called method's declaring class, and 22*795d594fSAndroid Build Coastguard Worker * that the corresponding load class instruction does not get 23*795d594fSAndroid Build Coastguard Worker * removed before register allocation & code generation. 24*795d594fSAndroid Build Coastguard Worker */ 25*795d594fSAndroid Build Coastguard Worker 26*795d594fSAndroid Build Coastguard Worker /// CHECK-START: void Main.invokeStaticInlined() builder (after) 27*795d594fSAndroid Build Coastguard Worker /// CHECK-DAG: <<LoadClass:l\d+>> LoadClass gen_clinit_check:false 28*795d594fSAndroid Build Coastguard Worker /// CHECK-DAG: <<ClinitCheck:l\d+>> ClinitCheck [<<LoadClass>>] 29*795d594fSAndroid Build Coastguard Worker /// CHECK-DAG: InvokeStaticOrDirect [{{([ij]\d+,)?}}<<ClinitCheck>>] 30*795d594fSAndroid Build Coastguard Worker 31*795d594fSAndroid Build Coastguard Worker /// CHECK-START: void Main.invokeStaticInlined() inliner (after) 32*795d594fSAndroid Build Coastguard Worker /// CHECK-DAG: <<LoadClass:l\d+>> LoadClass gen_clinit_check:false 33*795d594fSAndroid Build Coastguard Worker /// CHECK-DAG: <<ClinitCheck:l\d+>> ClinitCheck [<<LoadClass>>] 34*795d594fSAndroid Build Coastguard Worker 35*795d594fSAndroid Build Coastguard Worker /// CHECK-START: void Main.invokeStaticInlined() inliner (after) 36*795d594fSAndroid Build Coastguard Worker /// CHECK-NOT: InvokeStaticOrDirect 37*795d594fSAndroid Build Coastguard Worker 38*795d594fSAndroid Build Coastguard Worker // The following checks ensure the clinit check instruction added by 39*795d594fSAndroid Build Coastguard Worker // the builder is pruned by the PrepareForRegisterAllocation, while 40*795d594fSAndroid Build Coastguard Worker // the load class instruction is preserved. As the control flow 41*795d594fSAndroid Build Coastguard Worker // graph is not dumped after (nor before) this step, we check the 42*795d594fSAndroid Build Coastguard Worker // CFG as it is before the next pass (liveness analysis) instead. 43*795d594fSAndroid Build Coastguard Worker 44*795d594fSAndroid Build Coastguard Worker /// CHECK-START: void Main.invokeStaticInlined() liveness (before) 45*795d594fSAndroid Build Coastguard Worker /// CHECK-DAG: LoadClass gen_clinit_check:true 46*795d594fSAndroid Build Coastguard Worker 47*795d594fSAndroid Build Coastguard Worker /// CHECK-START: void Main.invokeStaticInlined() liveness (before) 48*795d594fSAndroid Build Coastguard Worker /// CHECK-NOT: ClinitCheck 49*795d594fSAndroid Build Coastguard Worker /// CHECK-NOT: InvokeStaticOrDirect 50*795d594fSAndroid Build Coastguard Worker invokeStaticInlined()51*795d594fSAndroid Build Coastguard Worker static void invokeStaticInlined() { 52*795d594fSAndroid Build Coastguard Worker ClassWithClinit1.$opt$inline$StaticMethod(); 53*795d594fSAndroid Build Coastguard Worker } 54*795d594fSAndroid Build Coastguard Worker 55*795d594fSAndroid Build Coastguard Worker static class ClassWithClinit1 { 56*795d594fSAndroid Build Coastguard Worker static { 57*795d594fSAndroid Build Coastguard Worker System.out.println("Main$ClassWithClinit1's static initializer"); 58*795d594fSAndroid Build Coastguard Worker } 59*795d594fSAndroid Build Coastguard Worker $opt$inline$StaticMethod()60*795d594fSAndroid Build Coastguard Worker static void $opt$inline$StaticMethod() { 61*795d594fSAndroid Build Coastguard Worker } 62*795d594fSAndroid Build Coastguard Worker } 63*795d594fSAndroid Build Coastguard Worker 64*795d594fSAndroid Build Coastguard Worker /* 65*795d594fSAndroid Build Coastguard Worker * Ensure a non-inlined static invoke eventually has an implicit 66*795d594fSAndroid Build Coastguard Worker * initialization check of the called method's declaring class. 67*795d594fSAndroid Build Coastguard Worker */ 68*795d594fSAndroid Build Coastguard Worker 69*795d594fSAndroid Build Coastguard Worker /// CHECK-START: void Main.invokeStaticNotInlined() builder (after) 70*795d594fSAndroid Build Coastguard Worker /// CHECK: <<LoadClass:l\d+>> LoadClass gen_clinit_check:false 71*795d594fSAndroid Build Coastguard Worker /// CHECK: <<ClinitCheck:l\d+>> ClinitCheck [<<LoadClass>>] 72*795d594fSAndroid Build Coastguard Worker /// CHECK: InvokeStaticOrDirect [{{([ij]\d+,)?}}<<ClinitCheck>>] 73*795d594fSAndroid Build Coastguard Worker 74*795d594fSAndroid Build Coastguard Worker /// CHECK-START: void Main.invokeStaticNotInlined() inliner (after) 75*795d594fSAndroid Build Coastguard Worker /// CHECK: <<LoadClass:l\d+>> LoadClass gen_clinit_check:false 76*795d594fSAndroid Build Coastguard Worker /// CHECK: <<ClinitCheck:l\d+>> ClinitCheck [<<LoadClass>>] 77*795d594fSAndroid Build Coastguard Worker /// CHECK: InvokeStaticOrDirect [{{([ij]\d+,)?}}<<ClinitCheck>>] 78*795d594fSAndroid Build Coastguard Worker 79*795d594fSAndroid Build Coastguard Worker // The following checks ensure the clinit check and load class 80*795d594fSAndroid Build Coastguard Worker // instructions added by the builder are pruned by the 81*795d594fSAndroid Build Coastguard Worker // PrepareForRegisterAllocation. As the control flow graph is not 82*795d594fSAndroid Build Coastguard Worker // dumped after (nor before) this step, we check the CFG as it is 83*795d594fSAndroid Build Coastguard Worker // before the next pass (liveness analysis) instead. 84*795d594fSAndroid Build Coastguard Worker 85*795d594fSAndroid Build Coastguard Worker /// CHECK-START: void Main.invokeStaticNotInlined() liveness (before) 86*795d594fSAndroid Build Coastguard Worker /// CHECK: InvokeStaticOrDirect clinit_check:implicit 87*795d594fSAndroid Build Coastguard Worker 88*795d594fSAndroid Build Coastguard Worker /// CHECK-START: void Main.invokeStaticNotInlined() liveness (before) 89*795d594fSAndroid Build Coastguard Worker /// CHECK-NOT: LoadClass 90*795d594fSAndroid Build Coastguard Worker /// CHECK-NOT: ClinitCheck 91*795d594fSAndroid Build Coastguard Worker invokeStaticNotInlined()92*795d594fSAndroid Build Coastguard Worker static void invokeStaticNotInlined() { 93*795d594fSAndroid Build Coastguard Worker ClassWithClinit2.$noinline$staticMethod(); 94*795d594fSAndroid Build Coastguard Worker } 95*795d594fSAndroid Build Coastguard Worker 96*795d594fSAndroid Build Coastguard Worker static class ClassWithClinit2 { 97*795d594fSAndroid Build Coastguard Worker static { 98*795d594fSAndroid Build Coastguard Worker System.out.println("Main$ClassWithClinit2's static initializer"); 99*795d594fSAndroid Build Coastguard Worker } 100*795d594fSAndroid Build Coastguard Worker 101*795d594fSAndroid Build Coastguard Worker static boolean staticField = false; 102*795d594fSAndroid Build Coastguard Worker $noinline$staticMethod()103*795d594fSAndroid Build Coastguard Worker static void $noinline$staticMethod() { 104*795d594fSAndroid Build Coastguard Worker } 105*795d594fSAndroid Build Coastguard Worker } 106*795d594fSAndroid Build Coastguard Worker 107*795d594fSAndroid Build Coastguard Worker /* 108*795d594fSAndroid Build Coastguard Worker * Ensure an inlined call from a static method to a static method 109*795d594fSAndroid Build Coastguard Worker * of the same class does not require an explicit clinit check 110*795d594fSAndroid Build Coastguard Worker * (already initialized or initializing in the same thread). 111*795d594fSAndroid Build Coastguard Worker */ 112*795d594fSAndroid Build Coastguard Worker 113*795d594fSAndroid Build Coastguard Worker /// CHECK-START: void Main$ClassWithClinit3Static.invokeStaticInlined() builder (after) 114*795d594fSAndroid Build Coastguard Worker /// CHECK-DAG: InvokeStaticOrDirect 115*795d594fSAndroid Build Coastguard Worker 116*795d594fSAndroid Build Coastguard Worker /// CHECK-START: void Main$ClassWithClinit3Static.invokeStaticInlined() builder (after) 117*795d594fSAndroid Build Coastguard Worker /// CHECK-NOT: LoadClass 118*795d594fSAndroid Build Coastguard Worker /// CHECK-NOT: ClinitCheck 119*795d594fSAndroid Build Coastguard Worker 120*795d594fSAndroid Build Coastguard Worker /// CHECK-START: void Main$ClassWithClinit3Static.invokeStaticInlined() inliner (after) 121*795d594fSAndroid Build Coastguard Worker /// CHECK-NOT: LoadClass 122*795d594fSAndroid Build Coastguard Worker /// CHECK-NOT: ClinitCheck 123*795d594fSAndroid Build Coastguard Worker /// CHECK-NOT: InvokeStaticOrDirect 124*795d594fSAndroid Build Coastguard Worker 125*795d594fSAndroid Build Coastguard Worker static class ClassWithClinit3Static { invokeStaticInlined()126*795d594fSAndroid Build Coastguard Worker static void invokeStaticInlined() { 127*795d594fSAndroid Build Coastguard Worker // The invocation of invokeStaticInlined happens only after a clinit check 128*795d594fSAndroid Build Coastguard Worker // of ClassWithClinit3Static, meaning that the hereinbelow call to 129*795d594fSAndroid Build Coastguard Worker // $opt$inline$StaticMethod does not need another clinit check. 130*795d594fSAndroid Build Coastguard Worker $opt$inline$StaticMethod(); 131*795d594fSAndroid Build Coastguard Worker } 132*795d594fSAndroid Build Coastguard Worker 133*795d594fSAndroid Build Coastguard Worker static { 134*795d594fSAndroid Build Coastguard Worker System.out.println("Main$ClassWithClinit3Static's static initializer"); 135*795d594fSAndroid Build Coastguard Worker } 136*795d594fSAndroid Build Coastguard Worker $opt$inline$StaticMethod()137*795d594fSAndroid Build Coastguard Worker static void $opt$inline$StaticMethod() { 138*795d594fSAndroid Build Coastguard Worker } 139*795d594fSAndroid Build Coastguard Worker } 140*795d594fSAndroid Build Coastguard Worker 141*795d594fSAndroid Build Coastguard Worker /* 142*795d594fSAndroid Build Coastguard Worker * Ensure an inlined call from an instance method to a static method 143*795d594fSAndroid Build Coastguard Worker * of the same class actually requires an explicit clinit check when 144*795d594fSAndroid Build Coastguard Worker * the class has a non-trivial initialization as we could be executing 145*795d594fSAndroid Build Coastguard Worker * the instance method on an escaped object of an erroneous class. b/62478025 146*795d594fSAndroid Build Coastguard Worker */ 147*795d594fSAndroid Build Coastguard Worker 148*795d594fSAndroid Build Coastguard Worker /// CHECK-START: void Main$ClassWithClinit3Instance.invokeStaticInlined() builder (after) 149*795d594fSAndroid Build Coastguard Worker /// CHECK-DAG: LoadClass 150*795d594fSAndroid Build Coastguard Worker /// CHECK-DAG: ClinitCheck 151*795d594fSAndroid Build Coastguard Worker /// CHECK-DAG: InvokeStaticOrDirect 152*795d594fSAndroid Build Coastguard Worker 153*795d594fSAndroid Build Coastguard Worker /// CHECK-START: void Main$ClassWithClinit3Instance.invokeStaticInlined() inliner (after) 154*795d594fSAndroid Build Coastguard Worker /// CHECK-DAG: LoadClass 155*795d594fSAndroid Build Coastguard Worker /// CHECK-DAG: ClinitCheck 156*795d594fSAndroid Build Coastguard Worker 157*795d594fSAndroid Build Coastguard Worker /// CHECK-START: void Main$ClassWithClinit3Instance.invokeStaticInlined() inliner (after) 158*795d594fSAndroid Build Coastguard Worker /// CHECK-NOT: InvokeStaticOrDirect 159*795d594fSAndroid Build Coastguard Worker 160*795d594fSAndroid Build Coastguard Worker static class ClassWithClinit3Instance { invokeStaticInlined()161*795d594fSAndroid Build Coastguard Worker void invokeStaticInlined() { 162*795d594fSAndroid Build Coastguard Worker // ClinitCheck required. 163*795d594fSAndroid Build Coastguard Worker $opt$inline$StaticMethod(); 164*795d594fSAndroid Build Coastguard Worker } 165*795d594fSAndroid Build Coastguard Worker 166*795d594fSAndroid Build Coastguard Worker static { 167*795d594fSAndroid Build Coastguard Worker System.out.println("Main$ClassWithClinit3Instance's static initializer"); 168*795d594fSAndroid Build Coastguard Worker } 169*795d594fSAndroid Build Coastguard Worker $opt$inline$StaticMethod()170*795d594fSAndroid Build Coastguard Worker static void $opt$inline$StaticMethod() { 171*795d594fSAndroid Build Coastguard Worker } 172*795d594fSAndroid Build Coastguard Worker } 173*795d594fSAndroid Build Coastguard Worker 174*795d594fSAndroid Build Coastguard Worker /* 175*795d594fSAndroid Build Coastguard Worker * Ensure a non-inlined call from a static method to a static method 176*795d594fSAndroid Build Coastguard Worker * of the same class does not require an explicit clinit check 177*795d594fSAndroid Build Coastguard Worker * (already initialized or initializing in the same thread). 178*795d594fSAndroid Build Coastguard Worker */ 179*795d594fSAndroid Build Coastguard Worker 180*795d594fSAndroid Build Coastguard Worker /// CHECK-START: void Main$ClassWithClinit4Static.invokeStaticNotInlined() builder (after) 181*795d594fSAndroid Build Coastguard Worker /// CHECK-DAG: InvokeStaticOrDirect 182*795d594fSAndroid Build Coastguard Worker 183*795d594fSAndroid Build Coastguard Worker /// CHECK-START: void Main$ClassWithClinit4Static.invokeStaticNotInlined() builder (after) 184*795d594fSAndroid Build Coastguard Worker /// CHECK-NOT: LoadClass 185*795d594fSAndroid Build Coastguard Worker /// CHECK-NOT: ClinitCheck 186*795d594fSAndroid Build Coastguard Worker 187*795d594fSAndroid Build Coastguard Worker /// CHECK-START: void Main$ClassWithClinit4Static.invokeStaticNotInlined() inliner (after) 188*795d594fSAndroid Build Coastguard Worker /// CHECK-DAG: InvokeStaticOrDirect 189*795d594fSAndroid Build Coastguard Worker 190*795d594fSAndroid Build Coastguard Worker /// CHECK-START: void Main$ClassWithClinit4Static.invokeStaticNotInlined() inliner (after) 191*795d594fSAndroid Build Coastguard Worker /// CHECK-NOT: LoadClass 192*795d594fSAndroid Build Coastguard Worker /// CHECK-NOT: ClinitCheck 193*795d594fSAndroid Build Coastguard Worker 194*795d594fSAndroid Build Coastguard Worker static class ClassWithClinit4Static { invokeStaticNotInlined()195*795d594fSAndroid Build Coastguard Worker static void invokeStaticNotInlined() { 196*795d594fSAndroid Build Coastguard Worker // The invocation of invokeStaticNotInlined triggers the 197*795d594fSAndroid Build Coastguard Worker // initialization of ClassWithClinit4Static, meaning that the 198*795d594fSAndroid Build Coastguard Worker // call to staticMethod below does not need a clinit 199*795d594fSAndroid Build Coastguard Worker // check. 200*795d594fSAndroid Build Coastguard Worker $noinline$staticMethod(); 201*795d594fSAndroid Build Coastguard Worker } 202*795d594fSAndroid Build Coastguard Worker 203*795d594fSAndroid Build Coastguard Worker static { 204*795d594fSAndroid Build Coastguard Worker System.out.println("Main$ClassWithClinit4Static's static initializer"); 205*795d594fSAndroid Build Coastguard Worker } 206*795d594fSAndroid Build Coastguard Worker $noinline$staticMethod()207*795d594fSAndroid Build Coastguard Worker static void $noinline$staticMethod() { 208*795d594fSAndroid Build Coastguard Worker } 209*795d594fSAndroid Build Coastguard Worker } 210*795d594fSAndroid Build Coastguard Worker 211*795d594fSAndroid Build Coastguard Worker /* 212*795d594fSAndroid Build Coastguard Worker * Ensure a non-inlined call from an instance method to a static method 213*795d594fSAndroid Build Coastguard Worker * of the same class actually requires an explicit clinit check when 214*795d594fSAndroid Build Coastguard Worker * the class has a non-trivial initialization as we could be executing 215*795d594fSAndroid Build Coastguard Worker * the instance method on an escaped object of an erroneous class. b/62478025 216*795d594fSAndroid Build Coastguard Worker */ 217*795d594fSAndroid Build Coastguard Worker 218*795d594fSAndroid Build Coastguard Worker /// CHECK-START: void Main$ClassWithClinit4Instance.invokeStaticNotInlined() builder (after) 219*795d594fSAndroid Build Coastguard Worker /// CHECK-DAG: LoadClass 220*795d594fSAndroid Build Coastguard Worker /// CHECK-DAG: ClinitCheck 221*795d594fSAndroid Build Coastguard Worker /// CHECK-DAG: InvokeStaticOrDirect 222*795d594fSAndroid Build Coastguard Worker 223*795d594fSAndroid Build Coastguard Worker /// CHECK-START: void Main$ClassWithClinit4Instance.invokeStaticNotInlined() inliner (after) 224*795d594fSAndroid Build Coastguard Worker /// CHECK-DAG: LoadClass 225*795d594fSAndroid Build Coastguard Worker /// CHECK-DAG: ClinitCheck 226*795d594fSAndroid Build Coastguard Worker /// CHECK-DAG: InvokeStaticOrDirect 227*795d594fSAndroid Build Coastguard Worker 228*795d594fSAndroid Build Coastguard Worker // The following checks ensure the clinit check and load class 229*795d594fSAndroid Build Coastguard Worker // instructions added by the builder are pruned by the 230*795d594fSAndroid Build Coastguard Worker // PrepareForRegisterAllocation. As the control flow graph is not 231*795d594fSAndroid Build Coastguard Worker // dumped after (nor before) this step, we check the CFG as it is 232*795d594fSAndroid Build Coastguard Worker // before the next pass (liveness analysis) instead. 233*795d594fSAndroid Build Coastguard Worker 234*795d594fSAndroid Build Coastguard Worker /// CHECK-START: void Main$ClassWithClinit4Instance.invokeStaticNotInlined() liveness (before) 235*795d594fSAndroid Build Coastguard Worker /// CHECK: InvokeStaticOrDirect clinit_check:implicit 236*795d594fSAndroid Build Coastguard Worker 237*795d594fSAndroid Build Coastguard Worker /// CHECK-START: void Main$ClassWithClinit4Instance.invokeStaticNotInlined() liveness (before) 238*795d594fSAndroid Build Coastguard Worker /// CHECK-NOT: LoadClass 239*795d594fSAndroid Build Coastguard Worker /// CHECK-NOT: ClinitCheck 240*795d594fSAndroid Build Coastguard Worker 241*795d594fSAndroid Build Coastguard Worker static class ClassWithClinit4Instance { invokeStaticNotInlined()242*795d594fSAndroid Build Coastguard Worker void invokeStaticNotInlined() { 243*795d594fSAndroid Build Coastguard Worker // ClinitCheck required. 244*795d594fSAndroid Build Coastguard Worker $noinline$staticMethod(); 245*795d594fSAndroid Build Coastguard Worker } 246*795d594fSAndroid Build Coastguard Worker 247*795d594fSAndroid Build Coastguard Worker static { 248*795d594fSAndroid Build Coastguard Worker System.out.println("Main$ClassWithClinit4Instance's static initializer"); 249*795d594fSAndroid Build Coastguard Worker } 250*795d594fSAndroid Build Coastguard Worker $noinline$staticMethod()251*795d594fSAndroid Build Coastguard Worker static void $noinline$staticMethod() { 252*795d594fSAndroid Build Coastguard Worker } 253*795d594fSAndroid Build Coastguard Worker } 254*795d594fSAndroid Build Coastguard Worker 255*795d594fSAndroid Build Coastguard Worker /* 256*795d594fSAndroid Build Coastguard Worker * We used to remove clinit check for calls to static methods in a superclass. However, this 257*795d594fSAndroid Build Coastguard Worker * is not a valid optimization when instances of erroneous classes can escape, therefore 258*795d594fSAndroid Build Coastguard Worker * we avoid this optimization for classes with non-trivial initialization. b/62478025 259*795d594fSAndroid Build Coastguard Worker */ 260*795d594fSAndroid Build Coastguard Worker 261*795d594fSAndroid Build Coastguard Worker /// CHECK-START: void Main$SubClassOfClassWithClinit5.invokeStaticInlined() builder (after) 262*795d594fSAndroid Build Coastguard Worker /// CHECK-DAG: LoadClass 263*795d594fSAndroid Build Coastguard Worker /// CHECK-DAG: ClinitCheck 264*795d594fSAndroid Build Coastguard Worker /// CHECK-DAG: InvokeStaticOrDirect 265*795d594fSAndroid Build Coastguard Worker 266*795d594fSAndroid Build Coastguard Worker /// CHECK-START: void Main$SubClassOfClassWithClinit5.invokeStaticInlined() inliner (after) 267*795d594fSAndroid Build Coastguard Worker /// CHECK-DAG: LoadClass 268*795d594fSAndroid Build Coastguard Worker /// CHECK-DAG: ClinitCheck 269*795d594fSAndroid Build Coastguard Worker /// CHECK-NOT: InvokeStaticOrDirect 270*795d594fSAndroid Build Coastguard Worker 271*795d594fSAndroid Build Coastguard Worker static class ClassWithClinit5 { $opt$inline$StaticMethod()272*795d594fSAndroid Build Coastguard Worker static void $opt$inline$StaticMethod() { 273*795d594fSAndroid Build Coastguard Worker } 274*795d594fSAndroid Build Coastguard Worker 275*795d594fSAndroid Build Coastguard Worker static { 276*795d594fSAndroid Build Coastguard Worker System.out.println("Main$ClassWithClinit5's static initializer"); 277*795d594fSAndroid Build Coastguard Worker } 278*795d594fSAndroid Build Coastguard Worker } 279*795d594fSAndroid Build Coastguard Worker 280*795d594fSAndroid Build Coastguard Worker static class SubClassOfClassWithClinit5 extends ClassWithClinit5 { invokeStaticInlined()281*795d594fSAndroid Build Coastguard Worker static void invokeStaticInlined() { 282*795d594fSAndroid Build Coastguard Worker ClassWithClinit5.$opt$inline$StaticMethod(); 283*795d594fSAndroid Build Coastguard Worker } 284*795d594fSAndroid Build Coastguard Worker } 285*795d594fSAndroid Build Coastguard Worker 286*795d594fSAndroid Build Coastguard Worker /* 287*795d594fSAndroid Build Coastguard Worker * Ensure an inlined call to a static method whose declaring class is a super class 288*795d594fSAndroid Build Coastguard Worker * of the caller's class does not require an explicit clinit check if the declaring 289*795d594fSAndroid Build Coastguard Worker * class has a trivial initialization. b/62478025 290*795d594fSAndroid Build Coastguard Worker */ 291*795d594fSAndroid Build Coastguard Worker 292*795d594fSAndroid Build Coastguard Worker /// CHECK-START: void Main$SubClassOfClassWithoutClinit5.invokeStaticInlined() builder (after) 293*795d594fSAndroid Build Coastguard Worker /// CHECK-DAG: InvokeStaticOrDirect 294*795d594fSAndroid Build Coastguard Worker 295*795d594fSAndroid Build Coastguard Worker /// CHECK-START: void Main$SubClassOfClassWithoutClinit5.invokeStaticInlined() builder (after) 296*795d594fSAndroid Build Coastguard Worker /// CHECK-NOT: LoadClass 297*795d594fSAndroid Build Coastguard Worker /// CHECK-NOT: ClinitCheck 298*795d594fSAndroid Build Coastguard Worker 299*795d594fSAndroid Build Coastguard Worker /// CHECK-START: void Main$SubClassOfClassWithoutClinit5.invokeStaticInlined() inliner (after) 300*795d594fSAndroid Build Coastguard Worker /// CHECK-NOT: LoadClass 301*795d594fSAndroid Build Coastguard Worker /// CHECK-NOT: ClinitCheck 302*795d594fSAndroid Build Coastguard Worker /// CHECK-NOT: InvokeStaticOrDirect 303*795d594fSAndroid Build Coastguard Worker 304*795d594fSAndroid Build Coastguard Worker static class ClassWithoutClinit5 { // Mimicks ClassWithClinit5 but without the <clinit>. $opt$inline$StaticMethod()305*795d594fSAndroid Build Coastguard Worker static void $opt$inline$StaticMethod() { 306*795d594fSAndroid Build Coastguard Worker } 307*795d594fSAndroid Build Coastguard Worker } 308*795d594fSAndroid Build Coastguard Worker 309*795d594fSAndroid Build Coastguard Worker static class SubClassOfClassWithoutClinit5 extends ClassWithoutClinit5 { 310*795d594fSAndroid Build Coastguard Worker static { 311*795d594fSAndroid Build Coastguard Worker System.out.println("Main$SubClassOfClassWithoutClinit5's static initializer"); 312*795d594fSAndroid Build Coastguard Worker } 313*795d594fSAndroid Build Coastguard Worker invokeStaticInlined()314*795d594fSAndroid Build Coastguard Worker static void invokeStaticInlined() { 315*795d594fSAndroid Build Coastguard Worker ClassWithoutClinit5.$opt$inline$StaticMethod(); 316*795d594fSAndroid Build Coastguard Worker } 317*795d594fSAndroid Build Coastguard Worker } 318*795d594fSAndroid Build Coastguard Worker 319*795d594fSAndroid Build Coastguard Worker /* 320*795d594fSAndroid Build Coastguard Worker * We used to remove clinit check for calls to static methods in a superclass. However, this 321*795d594fSAndroid Build Coastguard Worker * is not a valid optimization when instances of erroneous classes can escape, therefore 322*795d594fSAndroid Build Coastguard Worker * we avoid this optimization for classes with non-trivial initialization. b/62478025 323*795d594fSAndroid Build Coastguard Worker */ 324*795d594fSAndroid Build Coastguard Worker 325*795d594fSAndroid Build Coastguard Worker /// CHECK-START: void Main$SubClassOfClassWithClinit6.invokeStaticNotInlined() builder (after) 326*795d594fSAndroid Build Coastguard Worker /// CHECK-DAG: InvokeStaticOrDirect 327*795d594fSAndroid Build Coastguard Worker 328*795d594fSAndroid Build Coastguard Worker /// CHECK-START: void Main$SubClassOfClassWithClinit6.invokeStaticNotInlined() builder (after) 329*795d594fSAndroid Build Coastguard Worker /// CHECK-DAG: LoadClass 330*795d594fSAndroid Build Coastguard Worker /// CHECK-DAG: ClinitCheck 331*795d594fSAndroid Build Coastguard Worker 332*795d594fSAndroid Build Coastguard Worker /// CHECK-START: void Main$SubClassOfClassWithClinit6.invokeStaticNotInlined() inliner (after) 333*795d594fSAndroid Build Coastguard Worker /// CHECK-DAG: LoadClass 334*795d594fSAndroid Build Coastguard Worker /// CHECK-DAG: ClinitCheck 335*795d594fSAndroid Build Coastguard Worker /// CHECK-DAG: InvokeStaticOrDirect 336*795d594fSAndroid Build Coastguard Worker 337*795d594fSAndroid Build Coastguard Worker static class ClassWithClinit6 { $noinline$staticMethod()338*795d594fSAndroid Build Coastguard Worker static void $noinline$staticMethod() { 339*795d594fSAndroid Build Coastguard Worker } 340*795d594fSAndroid Build Coastguard Worker 341*795d594fSAndroid Build Coastguard Worker static { 342*795d594fSAndroid Build Coastguard Worker System.out.println("Main$ClassWithClinit6's static initializer"); 343*795d594fSAndroid Build Coastguard Worker } 344*795d594fSAndroid Build Coastguard Worker } 345*795d594fSAndroid Build Coastguard Worker 346*795d594fSAndroid Build Coastguard Worker static class SubClassOfClassWithClinit6 extends ClassWithClinit6 { invokeStaticNotInlined()347*795d594fSAndroid Build Coastguard Worker static void invokeStaticNotInlined() { 348*795d594fSAndroid Build Coastguard Worker ClassWithClinit6.$noinline$staticMethod(); 349*795d594fSAndroid Build Coastguard Worker } 350*795d594fSAndroid Build Coastguard Worker } 351*795d594fSAndroid Build Coastguard Worker 352*795d594fSAndroid Build Coastguard Worker /* 353*795d594fSAndroid Build Coastguard Worker * Ensure a non-inlined call to a static method whose declaring class is a super class 354*795d594fSAndroid Build Coastguard Worker * of the caller's class does not require an explicit clinit check if the declaring 355*795d594fSAndroid Build Coastguard Worker * class has a trivial initialization. b/62478025 356*795d594fSAndroid Build Coastguard Worker */ 357*795d594fSAndroid Build Coastguard Worker 358*795d594fSAndroid Build Coastguard Worker /// CHECK-START: void Main$SubClassOfClassWithoutClinit6.invokeStaticNotInlined() builder (after) 359*795d594fSAndroid Build Coastguard Worker /// CHECK-DAG: InvokeStaticOrDirect 360*795d594fSAndroid Build Coastguard Worker 361*795d594fSAndroid Build Coastguard Worker /// CHECK-START: void Main$SubClassOfClassWithoutClinit6.invokeStaticNotInlined() builder (after) 362*795d594fSAndroid Build Coastguard Worker /// CHECK-NOT: LoadClass 363*795d594fSAndroid Build Coastguard Worker /// CHECK-NOT: ClinitCheck 364*795d594fSAndroid Build Coastguard Worker 365*795d594fSAndroid Build Coastguard Worker /// CHECK-START: void Main$SubClassOfClassWithoutClinit6.invokeStaticNotInlined() inliner (after) 366*795d594fSAndroid Build Coastguard Worker /// CHECK-DAG: InvokeStaticOrDirect 367*795d594fSAndroid Build Coastguard Worker 368*795d594fSAndroid Build Coastguard Worker /// CHECK-START: void Main$SubClassOfClassWithoutClinit6.invokeStaticNotInlined() inliner (after) 369*795d594fSAndroid Build Coastguard Worker /// CHECK-NOT: LoadClass 370*795d594fSAndroid Build Coastguard Worker /// CHECK-NOT: ClinitCheck 371*795d594fSAndroid Build Coastguard Worker 372*795d594fSAndroid Build Coastguard Worker static class ClassWithoutClinit6 { // Mimicks ClassWithClinit6 but without the <clinit>. $noinline$staticMethod()373*795d594fSAndroid Build Coastguard Worker static void $noinline$staticMethod() { 374*795d594fSAndroid Build Coastguard Worker } 375*795d594fSAndroid Build Coastguard Worker } 376*795d594fSAndroid Build Coastguard Worker 377*795d594fSAndroid Build Coastguard Worker static class SubClassOfClassWithoutClinit6 extends ClassWithoutClinit6 { 378*795d594fSAndroid Build Coastguard Worker static { 379*795d594fSAndroid Build Coastguard Worker System.out.println("Main$SubClassOfClassWithoutClinit6's static initializer"); 380*795d594fSAndroid Build Coastguard Worker } 381*795d594fSAndroid Build Coastguard Worker invokeStaticNotInlined()382*795d594fSAndroid Build Coastguard Worker static void invokeStaticNotInlined() { 383*795d594fSAndroid Build Coastguard Worker ClassWithoutClinit6.$noinline$staticMethod(); 384*795d594fSAndroid Build Coastguard Worker } 385*795d594fSAndroid Build Coastguard Worker } 386*795d594fSAndroid Build Coastguard Worker 387*795d594fSAndroid Build Coastguard Worker /* 388*795d594fSAndroid Build Coastguard Worker * Verify that if we have a static call immediately after the load class 389*795d594fSAndroid Build Coastguard Worker * we don't do generate a clinit check. 390*795d594fSAndroid Build Coastguard Worker */ 391*795d594fSAndroid Build Coastguard Worker 392*795d594fSAndroid Build Coastguard Worker /// CHECK-START: void Main.noClinitBecauseOfInvokeStatic() liveness (before) 393*795d594fSAndroid Build Coastguard Worker /// CHECK-DAG: <<IntConstant:i\d+>> IntConstant 0 394*795d594fSAndroid Build Coastguard Worker /// CHECK-DAG: <<LoadClass:l\d+>> LoadClass gen_clinit_check:false 395*795d594fSAndroid Build Coastguard Worker /// CHECK-DAG: InvokeStaticOrDirect clinit_check:implicit 396*795d594fSAndroid Build Coastguard Worker /// CHECK-DAG: StaticFieldSet [<<LoadClass>>,<<IntConstant>>] 397*795d594fSAndroid Build Coastguard Worker 398*795d594fSAndroid Build Coastguard Worker /// CHECK-START: void Main.noClinitBecauseOfInvokeStatic() liveness (before) 399*795d594fSAndroid Build Coastguard Worker /// CHECK-NOT: ClinitCheck 400*795d594fSAndroid Build Coastguard Worker noClinitBecauseOfInvokeStatic()401*795d594fSAndroid Build Coastguard Worker static void noClinitBecauseOfInvokeStatic() { 402*795d594fSAndroid Build Coastguard Worker ClassWithClinit2.$noinline$staticMethod(); 403*795d594fSAndroid Build Coastguard Worker ClassWithClinit2.staticField = false; 404*795d594fSAndroid Build Coastguard Worker } 405*795d594fSAndroid Build Coastguard Worker 406*795d594fSAndroid Build Coastguard Worker /* 407*795d594fSAndroid Build Coastguard Worker * Verify that if the static call is after a field access, the load class 408*795d594fSAndroid Build Coastguard Worker * will generate a clinit check. 409*795d594fSAndroid Build Coastguard Worker */ 410*795d594fSAndroid Build Coastguard Worker 411*795d594fSAndroid Build Coastguard Worker /// CHECK-START: void Main.clinitBecauseOfFieldAccess() liveness (before) 412*795d594fSAndroid Build Coastguard Worker /// CHECK-DAG: <<IntConstant:i\d+>> IntConstant 0 413*795d594fSAndroid Build Coastguard Worker /// CHECK-DAG: <<LoadClass:l\d+>> LoadClass gen_clinit_check:true 414*795d594fSAndroid Build Coastguard Worker /// CHECK-DAG: StaticFieldSet [<<LoadClass>>,<<IntConstant>>] 415*795d594fSAndroid Build Coastguard Worker /// CHECK-DAG: InvokeStaticOrDirect clinit_check:none 416*795d594fSAndroid Build Coastguard Worker 417*795d594fSAndroid Build Coastguard Worker /// CHECK-START: void Main.clinitBecauseOfFieldAccess() liveness (before) 418*795d594fSAndroid Build Coastguard Worker /// CHECK-NOT: ClinitCheck clinitBecauseOfFieldAccess()419*795d594fSAndroid Build Coastguard Worker static void clinitBecauseOfFieldAccess() { 420*795d594fSAndroid Build Coastguard Worker ClassWithClinit2.staticField = false; 421*795d594fSAndroid Build Coastguard Worker ClassWithClinit2.$noinline$staticMethod(); 422*795d594fSAndroid Build Coastguard Worker } 423*795d594fSAndroid Build Coastguard Worker 424*795d594fSAndroid Build Coastguard Worker /* 425*795d594fSAndroid Build Coastguard Worker * Verify that LoadClass from const-class is not merged with 426*795d594fSAndroid Build Coastguard Worker * later invoke-static (or it's ClinitCheck). 427*795d594fSAndroid Build Coastguard Worker */ 428*795d594fSAndroid Build Coastguard Worker 429*795d594fSAndroid Build Coastguard Worker /// CHECK-START: void Main.constClassAndInvokeStatic(java.lang.Iterable) liveness (before) 430*795d594fSAndroid Build Coastguard Worker /// CHECK: LoadClass gen_clinit_check:false 431*795d594fSAndroid Build Coastguard Worker /// CHECK: InvokeStaticOrDirect clinit_check:implicit 432*795d594fSAndroid Build Coastguard Worker 433*795d594fSAndroid Build Coastguard Worker /// CHECK-START: void Main.constClassAndInvokeStatic(java.lang.Iterable) liveness (before) 434*795d594fSAndroid Build Coastguard Worker /// CHECK-NOT: ClinitCheck 435*795d594fSAndroid Build Coastguard Worker constClassAndInvokeStatic(Iterable<?> it)436*795d594fSAndroid Build Coastguard Worker static void constClassAndInvokeStatic(Iterable<?> it) { 437*795d594fSAndroid Build Coastguard Worker $opt$inline$ignoreClass(ClassWithClinit7.class); 438*795d594fSAndroid Build Coastguard Worker ClassWithClinit7.$noinline$someStaticMethod(it); 439*795d594fSAndroid Build Coastguard Worker } 440*795d594fSAndroid Build Coastguard Worker $opt$inline$ignoreClass(Class<?> c)441*795d594fSAndroid Build Coastguard Worker static void $opt$inline$ignoreClass(Class<?> c) { 442*795d594fSAndroid Build Coastguard Worker } 443*795d594fSAndroid Build Coastguard Worker 444*795d594fSAndroid Build Coastguard Worker static class ClassWithClinit7 { 445*795d594fSAndroid Build Coastguard Worker static { 446*795d594fSAndroid Build Coastguard Worker System.out.println("Main$ClassWithClinit7's static initializer"); 447*795d594fSAndroid Build Coastguard Worker } 448*795d594fSAndroid Build Coastguard Worker $noinline$someStaticMethod(Iterable<?> it)449*795d594fSAndroid Build Coastguard Worker static void $noinline$someStaticMethod(Iterable<?> it) { 450*795d594fSAndroid Build Coastguard Worker it.iterator(); 451*795d594fSAndroid Build Coastguard Worker } 452*795d594fSAndroid Build Coastguard Worker } 453*795d594fSAndroid Build Coastguard Worker 454*795d594fSAndroid Build Coastguard Worker /* 455*795d594fSAndroid Build Coastguard Worker * Verify that LoadClass from sget is not merged with later invoke-static. 456*795d594fSAndroid Build Coastguard Worker */ 457*795d594fSAndroid Build Coastguard Worker 458*795d594fSAndroid Build Coastguard Worker /// CHECK-START: void Main.sgetAndInvokeStatic(java.lang.Iterable) liveness (before) 459*795d594fSAndroid Build Coastguard Worker /// CHECK: LoadClass gen_clinit_check:true 460*795d594fSAndroid Build Coastguard Worker /// CHECK: InvokeStaticOrDirect clinit_check:none 461*795d594fSAndroid Build Coastguard Worker 462*795d594fSAndroid Build Coastguard Worker /// CHECK-START: void Main.sgetAndInvokeStatic(java.lang.Iterable) liveness (before) 463*795d594fSAndroid Build Coastguard Worker /// CHECK-NOT: ClinitCheck 464*795d594fSAndroid Build Coastguard Worker sgetAndInvokeStatic(Iterable<?> it)465*795d594fSAndroid Build Coastguard Worker static void sgetAndInvokeStatic(Iterable<?> it) { 466*795d594fSAndroid Build Coastguard Worker $opt$inline$ignoreInt(ClassWithClinit8.value); 467*795d594fSAndroid Build Coastguard Worker ClassWithClinit8.$noinline$someStaticMethod(it); 468*795d594fSAndroid Build Coastguard Worker } 469*795d594fSAndroid Build Coastguard Worker $opt$inline$ignoreInt(int i)470*795d594fSAndroid Build Coastguard Worker static void $opt$inline$ignoreInt(int i) { 471*795d594fSAndroid Build Coastguard Worker } 472*795d594fSAndroid Build Coastguard Worker 473*795d594fSAndroid Build Coastguard Worker static class ClassWithClinit8 { 474*795d594fSAndroid Build Coastguard Worker public static int value = 0; 475*795d594fSAndroid Build Coastguard Worker static { 476*795d594fSAndroid Build Coastguard Worker System.out.println("Main$ClassWithClinit8's static initializer"); 477*795d594fSAndroid Build Coastguard Worker } 478*795d594fSAndroid Build Coastguard Worker $noinline$someStaticMethod(Iterable<?> it)479*795d594fSAndroid Build Coastguard Worker static void $noinline$someStaticMethod(Iterable<?> it) { 480*795d594fSAndroid Build Coastguard Worker it.iterator(); 481*795d594fSAndroid Build Coastguard Worker } 482*795d594fSAndroid Build Coastguard Worker } 483*795d594fSAndroid Build Coastguard Worker 484*795d594fSAndroid Build Coastguard Worker /* 485*795d594fSAndroid Build Coastguard Worker * Verify that LoadClass from const-class, ClinitCheck from sget and 486*795d594fSAndroid Build Coastguard Worker * InvokeStaticOrDirect from invoke-static are not merged. 487*795d594fSAndroid Build Coastguard Worker */ 488*795d594fSAndroid Build Coastguard Worker 489*795d594fSAndroid Build Coastguard Worker /// CHECK-START: void Main.constClassSgetAndInvokeStatic(java.lang.Iterable) liveness (before) 490*795d594fSAndroid Build Coastguard Worker /// CHECK: LoadClass gen_clinit_check:false 491*795d594fSAndroid Build Coastguard Worker /// CHECK: ClinitCheck 492*795d594fSAndroid Build Coastguard Worker /// CHECK: InvokeStaticOrDirect clinit_check:none 493*795d594fSAndroid Build Coastguard Worker constClassSgetAndInvokeStatic(Iterable<?> it)494*795d594fSAndroid Build Coastguard Worker static void constClassSgetAndInvokeStatic(Iterable<?> it) { 495*795d594fSAndroid Build Coastguard Worker $opt$inline$ignoreClass(ClassWithClinit9.class); 496*795d594fSAndroid Build Coastguard Worker $opt$inline$ignoreInt(ClassWithClinit9.value); 497*795d594fSAndroid Build Coastguard Worker ClassWithClinit9.$noinline$someStaticMethod(it); 498*795d594fSAndroid Build Coastguard Worker } 499*795d594fSAndroid Build Coastguard Worker 500*795d594fSAndroid Build Coastguard Worker static class ClassWithClinit9 { 501*795d594fSAndroid Build Coastguard Worker public static int value = 0; 502*795d594fSAndroid Build Coastguard Worker static { 503*795d594fSAndroid Build Coastguard Worker System.out.println("Main$ClassWithClinit9's static initializer"); 504*795d594fSAndroid Build Coastguard Worker } 505*795d594fSAndroid Build Coastguard Worker $noinline$someStaticMethod(Iterable<?> it)506*795d594fSAndroid Build Coastguard Worker static void $noinline$someStaticMethod(Iterable<?> it) { 507*795d594fSAndroid Build Coastguard Worker it.iterator(); 508*795d594fSAndroid Build Coastguard Worker } 509*795d594fSAndroid Build Coastguard Worker } 510*795d594fSAndroid Build Coastguard Worker 511*795d594fSAndroid Build Coastguard Worker /* 512*795d594fSAndroid Build Coastguard Worker * Verify that LoadClass from a fully-inlined invoke-static is not merged 513*795d594fSAndroid Build Coastguard Worker * with InvokeStaticOrDirect from a later invoke-static to the same method. 514*795d594fSAndroid Build Coastguard Worker */ 515*795d594fSAndroid Build Coastguard Worker 516*795d594fSAndroid Build Coastguard Worker /// CHECK-START: void Main.inlinedInvokeStaticViaNonStatic(java.lang.Iterable) liveness (before) 517*795d594fSAndroid Build Coastguard Worker /// CHECK: LoadClass gen_clinit_check:true 518*795d594fSAndroid Build Coastguard Worker /// CHECK: InvokeStaticOrDirect clinit_check:none 519*795d594fSAndroid Build Coastguard Worker 520*795d594fSAndroid Build Coastguard Worker /// CHECK-START: void Main.inlinedInvokeStaticViaNonStatic(java.lang.Iterable) liveness (before) 521*795d594fSAndroid Build Coastguard Worker /// CHECK-NOT: ClinitCheck 522*795d594fSAndroid Build Coastguard Worker inlinedInvokeStaticViaNonStatic(Iterable<?> it)523*795d594fSAndroid Build Coastguard Worker static void inlinedInvokeStaticViaNonStatic(Iterable<?> it) { 524*795d594fSAndroid Build Coastguard Worker if (it != null) { 525*795d594fSAndroid Build Coastguard Worker inlinedInvokeStaticViaNonStaticHelper(null); 526*795d594fSAndroid Build Coastguard Worker inlinedInvokeStaticViaNonStaticHelper(it); 527*795d594fSAndroid Build Coastguard Worker } 528*795d594fSAndroid Build Coastguard Worker } 529*795d594fSAndroid Build Coastguard Worker inlinedInvokeStaticViaNonStaticHelper(Iterable<?> it)530*795d594fSAndroid Build Coastguard Worker static void inlinedInvokeStaticViaNonStaticHelper(Iterable<?> it) { 531*795d594fSAndroid Build Coastguard Worker ClassWithClinit10.inlinedForNull(it); 532*795d594fSAndroid Build Coastguard Worker } 533*795d594fSAndroid Build Coastguard Worker 534*795d594fSAndroid Build Coastguard Worker static class ClassWithClinit10 { 535*795d594fSAndroid Build Coastguard Worker public static int value = 0; 536*795d594fSAndroid Build Coastguard Worker static { 537*795d594fSAndroid Build Coastguard Worker System.out.println("Main$ClassWithClinit10's static initializer"); 538*795d594fSAndroid Build Coastguard Worker } 539*795d594fSAndroid Build Coastguard Worker inlinedForNull(Iterable<?> it)540*795d594fSAndroid Build Coastguard Worker static void inlinedForNull(Iterable<?> it) { 541*795d594fSAndroid Build Coastguard Worker if (it != null) { 542*795d594fSAndroid Build Coastguard Worker it.iterator(); 543*795d594fSAndroid Build Coastguard Worker // We're not inlining methods that always throw. 544*795d594fSAndroid Build Coastguard Worker throw new Error(""); 545*795d594fSAndroid Build Coastguard Worker } 546*795d594fSAndroid Build Coastguard Worker } 547*795d594fSAndroid Build Coastguard Worker } 548*795d594fSAndroid Build Coastguard Worker 549*795d594fSAndroid Build Coastguard Worker /* 550*795d594fSAndroid Build Coastguard Worker * Check that the LoadClass from an invoke-static C.foo() doesn't get merged with 551*795d594fSAndroid Build Coastguard Worker * an invoke-static inside C.foo(). This would mess up the stack walk in the 552*795d594fSAndroid Build Coastguard Worker * resolution trampoline where we would have to load C (if C isn't loaded yet) 553*795d594fSAndroid Build Coastguard Worker * which is not permitted there. 554*795d594fSAndroid Build Coastguard Worker * 555*795d594fSAndroid Build Coastguard Worker * Note: In case of failure, we would get an failed assertion during compilation, 556*795d594fSAndroid Build Coastguard Worker * so we wouldn't really get to the checker tests below. 557*795d594fSAndroid Build Coastguard Worker */ 558*795d594fSAndroid Build Coastguard Worker 559*795d594fSAndroid Build Coastguard Worker /// CHECK-START: void Main.inlinedInvokeStaticViaStatic(java.lang.Iterable) liveness (before) 560*795d594fSAndroid Build Coastguard Worker /// CHECK: LoadClass gen_clinit_check:true 561*795d594fSAndroid Build Coastguard Worker /// CHECK: InvokeStaticOrDirect clinit_check:none 562*795d594fSAndroid Build Coastguard Worker 563*795d594fSAndroid Build Coastguard Worker /// CHECK-START: void Main.inlinedInvokeStaticViaStatic(java.lang.Iterable) liveness (before) 564*795d594fSAndroid Build Coastguard Worker /// CHECK-NOT: ClinitCheck 565*795d594fSAndroid Build Coastguard Worker inlinedInvokeStaticViaStatic(Iterable<?> it)566*795d594fSAndroid Build Coastguard Worker static void inlinedInvokeStaticViaStatic(Iterable<?> it) { 567*795d594fSAndroid Build Coastguard Worker if (it != null) { 568*795d594fSAndroid Build Coastguard Worker ClassWithClinit11.callInlinedForNull(it); 569*795d594fSAndroid Build Coastguard Worker } 570*795d594fSAndroid Build Coastguard Worker } 571*795d594fSAndroid Build Coastguard Worker 572*795d594fSAndroid Build Coastguard Worker static class ClassWithClinit11 { 573*795d594fSAndroid Build Coastguard Worker public static int value = 0; 574*795d594fSAndroid Build Coastguard Worker static { 575*795d594fSAndroid Build Coastguard Worker System.out.println("Main$ClassWithClinit11's static initializer"); 576*795d594fSAndroid Build Coastguard Worker } 577*795d594fSAndroid Build Coastguard Worker callInlinedForNull(Iterable<?> it)578*795d594fSAndroid Build Coastguard Worker static void callInlinedForNull(Iterable<?> it) { 579*795d594fSAndroid Build Coastguard Worker inlinedForNull(it); 580*795d594fSAndroid Build Coastguard Worker } 581*795d594fSAndroid Build Coastguard Worker inlinedForNull(Iterable<?> it)582*795d594fSAndroid Build Coastguard Worker static void inlinedForNull(Iterable<?> it) { 583*795d594fSAndroid Build Coastguard Worker it.iterator(); 584*795d594fSAndroid Build Coastguard Worker if (it != null) { 585*795d594fSAndroid Build Coastguard Worker // We're not inlining methods that always throw. 586*795d594fSAndroid Build Coastguard Worker throw new Error(""); 587*795d594fSAndroid Build Coastguard Worker } 588*795d594fSAndroid Build Coastguard Worker } 589*795d594fSAndroid Build Coastguard Worker } 590*795d594fSAndroid Build Coastguard Worker 591*795d594fSAndroid Build Coastguard Worker /* 592*795d594fSAndroid Build Coastguard Worker * A test similar to inlinedInvokeStaticViaStatic() but doing the indirect invoke 593*795d594fSAndroid Build Coastguard Worker * twice with the first one to be fully inlined. 594*795d594fSAndroid Build Coastguard Worker */ 595*795d594fSAndroid Build Coastguard Worker 596*795d594fSAndroid Build Coastguard Worker /// CHECK-START: void Main.inlinedInvokeStaticViaStaticTwice(java.lang.Iterable) liveness (before) 597*795d594fSAndroid Build Coastguard Worker /// CHECK: LoadClass gen_clinit_check:true 598*795d594fSAndroid Build Coastguard Worker /// CHECK: InvokeStaticOrDirect clinit_check:none 599*795d594fSAndroid Build Coastguard Worker 600*795d594fSAndroid Build Coastguard Worker /// CHECK-START: void Main.inlinedInvokeStaticViaStaticTwice(java.lang.Iterable) liveness (before) 601*795d594fSAndroid Build Coastguard Worker /// CHECK-NOT: ClinitCheck 602*795d594fSAndroid Build Coastguard Worker inlinedInvokeStaticViaStaticTwice(Iterable<?> it)603*795d594fSAndroid Build Coastguard Worker static void inlinedInvokeStaticViaStaticTwice(Iterable<?> it) { 604*795d594fSAndroid Build Coastguard Worker if (it != null) { 605*795d594fSAndroid Build Coastguard Worker ClassWithClinit12.callInlinedForNull(null); 606*795d594fSAndroid Build Coastguard Worker ClassWithClinit12.callInlinedForNull(it); 607*795d594fSAndroid Build Coastguard Worker } 608*795d594fSAndroid Build Coastguard Worker } 609*795d594fSAndroid Build Coastguard Worker 610*795d594fSAndroid Build Coastguard Worker static class ClassWithClinit12 { 611*795d594fSAndroid Build Coastguard Worker public static int value = 0; 612*795d594fSAndroid Build Coastguard Worker static { 613*795d594fSAndroid Build Coastguard Worker System.out.println("Main$ClassWithClinit12's static initializer"); 614*795d594fSAndroid Build Coastguard Worker } 615*795d594fSAndroid Build Coastguard Worker callInlinedForNull(Iterable<?> it)616*795d594fSAndroid Build Coastguard Worker static void callInlinedForNull(Iterable<?> it) { 617*795d594fSAndroid Build Coastguard Worker inlinedForNull(it); 618*795d594fSAndroid Build Coastguard Worker } 619*795d594fSAndroid Build Coastguard Worker inlinedForNull(Iterable<?> it)620*795d594fSAndroid Build Coastguard Worker static void inlinedForNull(Iterable<?> it) { 621*795d594fSAndroid Build Coastguard Worker if (it != null) { 622*795d594fSAndroid Build Coastguard Worker // We're not inlining methods that always throw. 623*795d594fSAndroid Build Coastguard Worker throw new Error(""); 624*795d594fSAndroid Build Coastguard Worker } 625*795d594fSAndroid Build Coastguard Worker } 626*795d594fSAndroid Build Coastguard Worker } 627*795d594fSAndroid Build Coastguard Worker 628*795d594fSAndroid Build Coastguard Worker static class ClassWithClinit13 { 629*795d594fSAndroid Build Coastguard Worker static { 630*795d594fSAndroid Build Coastguard Worker System.out.println("Main$ClassWithClinit13's static initializer"); 631*795d594fSAndroid Build Coastguard Worker } 632*795d594fSAndroid Build Coastguard Worker $inline$forwardToGetIterator(Iterable<?> it)633*795d594fSAndroid Build Coastguard Worker public static void $inline$forwardToGetIterator(Iterable<?> it) { 634*795d594fSAndroid Build Coastguard Worker $noinline$getIterator(it); 635*795d594fSAndroid Build Coastguard Worker } 636*795d594fSAndroid Build Coastguard Worker $noinline$getIterator(Iterable<?> it)637*795d594fSAndroid Build Coastguard Worker public static void $noinline$getIterator(Iterable<?> it) { 638*795d594fSAndroid Build Coastguard Worker it.iterator(); 639*795d594fSAndroid Build Coastguard Worker } 640*795d594fSAndroid Build Coastguard Worker } 641*795d594fSAndroid Build Coastguard Worker 642*795d594fSAndroid Build Coastguard Worker // TODO: Write checker statements. $noinline$testInliningAndNewInstance(Iterable<?> it)643*795d594fSAndroid Build Coastguard Worker static Object $noinline$testInliningAndNewInstance(Iterable<?> it) { 644*795d594fSAndroid Build Coastguard Worker ClassWithClinit13.$inline$forwardToGetIterator(it); 645*795d594fSAndroid Build Coastguard Worker return new ClassWithClinit13(); 646*795d594fSAndroid Build Coastguard Worker } 647*795d594fSAndroid Build Coastguard Worker 648*795d594fSAndroid Build Coastguard Worker // TODO: Add a test for the case of a static method whose declaring 649*795d594fSAndroid Build Coastguard Worker // class type index is not available (i.e. when `storage_index` 650*795d594fSAndroid Build Coastguard Worker // equals `dex::kDexNoIndex` in 651*795d594fSAndroid Build Coastguard Worker // art::HGraphBuilder::BuildInvoke). 652*795d594fSAndroid Build Coastguard Worker main(String[] args)653*795d594fSAndroid Build Coastguard Worker public static void main(String[] args) { 654*795d594fSAndroid Build Coastguard Worker invokeStaticInlined(); 655*795d594fSAndroid Build Coastguard Worker invokeStaticNotInlined(); 656*795d594fSAndroid Build Coastguard Worker ClassWithClinit3Static.invokeStaticInlined(); 657*795d594fSAndroid Build Coastguard Worker new ClassWithClinit3Instance().invokeStaticInlined(); 658*795d594fSAndroid Build Coastguard Worker ClassWithClinit4Static.invokeStaticNotInlined(); 659*795d594fSAndroid Build Coastguard Worker new ClassWithClinit4Instance().invokeStaticNotInlined(); 660*795d594fSAndroid Build Coastguard Worker SubClassOfClassWithClinit5.invokeStaticInlined(); 661*795d594fSAndroid Build Coastguard Worker SubClassOfClassWithoutClinit5.invokeStaticInlined(); 662*795d594fSAndroid Build Coastguard Worker SubClassOfClassWithClinit6.invokeStaticNotInlined(); 663*795d594fSAndroid Build Coastguard Worker SubClassOfClassWithoutClinit6.invokeStaticNotInlined(); 664*795d594fSAndroid Build Coastguard Worker Iterable it = new Iterable() { public java.util.Iterator iterator() { return null; } }; 665*795d594fSAndroid Build Coastguard Worker constClassAndInvokeStatic(it); 666*795d594fSAndroid Build Coastguard Worker sgetAndInvokeStatic(it); 667*795d594fSAndroid Build Coastguard Worker constClassSgetAndInvokeStatic(it); 668*795d594fSAndroid Build Coastguard Worker try { 669*795d594fSAndroid Build Coastguard Worker inlinedInvokeStaticViaNonStatic(it); 670*795d594fSAndroid Build Coastguard Worker } catch (Error e) { 671*795d594fSAndroid Build Coastguard Worker // Expected 672*795d594fSAndroid Build Coastguard Worker } 673*795d594fSAndroid Build Coastguard Worker try { 674*795d594fSAndroid Build Coastguard Worker inlinedInvokeStaticViaStatic(it); 675*795d594fSAndroid Build Coastguard Worker } catch (Error e) { 676*795d594fSAndroid Build Coastguard Worker // Expected 677*795d594fSAndroid Build Coastguard Worker } 678*795d594fSAndroid Build Coastguard Worker try{ 679*795d594fSAndroid Build Coastguard Worker inlinedInvokeStaticViaStaticTwice(it); 680*795d594fSAndroid Build Coastguard Worker } catch (Error e) { 681*795d594fSAndroid Build Coastguard Worker // Expected 682*795d594fSAndroid Build Coastguard Worker } 683*795d594fSAndroid Build Coastguard Worker $noinline$testInliningAndNewInstance(it); 684*795d594fSAndroid Build Coastguard Worker } 685*795d594fSAndroid Build Coastguard Worker } 686