Main.java revision 4c0eb42259d790fddcd9978b66328dbb3ab65615
14c0eb42259d790fddcd9978b66328dbb3ab65615Roland Levillain/* 24c0eb42259d790fddcd9978b66328dbb3ab65615Roland Levillain * Copyright (C) 2015 The Android Open Source Project 34c0eb42259d790fddcd9978b66328dbb3ab65615Roland Levillain * 44c0eb42259d790fddcd9978b66328dbb3ab65615Roland Levillain * Licensed under the Apache License, Version 2.0 (the "License"); 54c0eb42259d790fddcd9978b66328dbb3ab65615Roland Levillain * you may not use this file except in compliance with the License. 64c0eb42259d790fddcd9978b66328dbb3ab65615Roland Levillain * You may obtain a copy of the License at 74c0eb42259d790fddcd9978b66328dbb3ab65615Roland Levillain * 84c0eb42259d790fddcd9978b66328dbb3ab65615Roland Levillain * http://www.apache.org/licenses/LICENSE-2.0 94c0eb42259d790fddcd9978b66328dbb3ab65615Roland Levillain * 104c0eb42259d790fddcd9978b66328dbb3ab65615Roland Levillain * Unless required by applicable law or agreed to in writing, software 114c0eb42259d790fddcd9978b66328dbb3ab65615Roland Levillain * distributed under the License is distributed on an "AS IS" BASIS, 124c0eb42259d790fddcd9978b66328dbb3ab65615Roland Levillain * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 134c0eb42259d790fddcd9978b66328dbb3ab65615Roland Levillain * See the License for the specific language governing permissions and 144c0eb42259d790fddcd9978b66328dbb3ab65615Roland Levillain * limitations under the License. 154c0eb42259d790fddcd9978b66328dbb3ab65615Roland Levillain */ 164c0eb42259d790fddcd9978b66328dbb3ab65615Roland Levillain 174c0eb42259d790fddcd9978b66328dbb3ab65615Roland Levillainpublic class Main { 184c0eb42259d790fddcd9978b66328dbb3ab65615Roland Levillain 194c0eb42259d790fddcd9978b66328dbb3ab65615Roland Levillain /* 204c0eb42259d790fddcd9978b66328dbb3ab65615Roland Levillain * Ensure an inlined static invoke explicitly triggers the 214c0eb42259d790fddcd9978b66328dbb3ab65615Roland Levillain * initialization check of the called method's declaring class, and 224c0eb42259d790fddcd9978b66328dbb3ab65615Roland Levillain * that the corresponding load class instruction does not get 234c0eb42259d790fddcd9978b66328dbb3ab65615Roland Levillain * removed before register allocation & code generation. 244c0eb42259d790fddcd9978b66328dbb3ab65615Roland Levillain */ 254c0eb42259d790fddcd9978b66328dbb3ab65615Roland Levillain 264c0eb42259d790fddcd9978b66328dbb3ab65615Roland Levillain // CHECK-START: void Main.invokeStaticInlined() builder (after) 274c0eb42259d790fddcd9978b66328dbb3ab65615Roland Levillain // CHECK-DAG: [[LoadClass:l\d+]] LoadClass 284c0eb42259d790fddcd9978b66328dbb3ab65615Roland Levillain // CHECK-DAG: [[ClinitCheck:l\d+]] ClinitCheck [ [[LoadClass]] ] 294c0eb42259d790fddcd9978b66328dbb3ab65615Roland Levillain // CHECK-DAG: InvokeStaticOrDirect [ [[ClinitCheck]] ] 304c0eb42259d790fddcd9978b66328dbb3ab65615Roland Levillain 314c0eb42259d790fddcd9978b66328dbb3ab65615Roland Levillain // CHECK-START: void Main.invokeStaticInlined() inliner (after) 324c0eb42259d790fddcd9978b66328dbb3ab65615Roland Levillain // CHECK-DAG: [[LoadClass:l\d+]] LoadClass 334c0eb42259d790fddcd9978b66328dbb3ab65615Roland Levillain // CHECK-DAG: [[ClinitCheck:l\d+]] ClinitCheck [ [[LoadClass]] ] 344c0eb42259d790fddcd9978b66328dbb3ab65615Roland Levillain 354c0eb42259d790fddcd9978b66328dbb3ab65615Roland Levillain // CHECK-START: void Main.invokeStaticInlined() inliner (after) 364c0eb42259d790fddcd9978b66328dbb3ab65615Roland Levillain // CHECK-NOT: InvokeStaticOrDirect 374c0eb42259d790fddcd9978b66328dbb3ab65615Roland Levillain 384c0eb42259d790fddcd9978b66328dbb3ab65615Roland Levillain // The following checks ensure the clinit check instruction added by 394c0eb42259d790fddcd9978b66328dbb3ab65615Roland Levillain // the builder is pruned by the PrepareForRegisterAllocation, while 404c0eb42259d790fddcd9978b66328dbb3ab65615Roland Levillain // the load class instruction is preserved. As the control flow 414c0eb42259d790fddcd9978b66328dbb3ab65615Roland Levillain // graph is not dumped after (nor before) this step, we check the 424c0eb42259d790fddcd9978b66328dbb3ab65615Roland Levillain // CFG as it is before the next pass (liveness analysis) instead. 434c0eb42259d790fddcd9978b66328dbb3ab65615Roland Levillain 444c0eb42259d790fddcd9978b66328dbb3ab65615Roland Levillain // CHECK-START: void Main.invokeStaticInlined() liveness (before) 454c0eb42259d790fddcd9978b66328dbb3ab65615Roland Levillain // CHECK-DAG: LoadClass 464c0eb42259d790fddcd9978b66328dbb3ab65615Roland Levillain 474c0eb42259d790fddcd9978b66328dbb3ab65615Roland Levillain // CHECK-START: void Main.invokeStaticInlined() liveness (before) 484c0eb42259d790fddcd9978b66328dbb3ab65615Roland Levillain // CHECK-NOT: ClinitCheck 494c0eb42259d790fddcd9978b66328dbb3ab65615Roland Levillain // CHECK-NOT: InvokeStaticOrDirect 504c0eb42259d790fddcd9978b66328dbb3ab65615Roland Levillain 514c0eb42259d790fddcd9978b66328dbb3ab65615Roland Levillain static void invokeStaticInlined() { 524c0eb42259d790fddcd9978b66328dbb3ab65615Roland Levillain ClassWithClinit1.$opt$inline$StaticMethod(); 534c0eb42259d790fddcd9978b66328dbb3ab65615Roland Levillain } 544c0eb42259d790fddcd9978b66328dbb3ab65615Roland Levillain 554c0eb42259d790fddcd9978b66328dbb3ab65615Roland Levillain static class ClassWithClinit1 { 564c0eb42259d790fddcd9978b66328dbb3ab65615Roland Levillain static { 574c0eb42259d790fddcd9978b66328dbb3ab65615Roland Levillain System.out.println("Main$ClassWithClinit1's static initializer"); 584c0eb42259d790fddcd9978b66328dbb3ab65615Roland Levillain } 594c0eb42259d790fddcd9978b66328dbb3ab65615Roland Levillain 604c0eb42259d790fddcd9978b66328dbb3ab65615Roland Levillain static void $opt$inline$StaticMethod() { 614c0eb42259d790fddcd9978b66328dbb3ab65615Roland Levillain } 624c0eb42259d790fddcd9978b66328dbb3ab65615Roland Levillain } 634c0eb42259d790fddcd9978b66328dbb3ab65615Roland Levillain 644c0eb42259d790fddcd9978b66328dbb3ab65615Roland Levillain /* 654c0eb42259d790fddcd9978b66328dbb3ab65615Roland Levillain * Ensure a non-inlined static invoke eventually has an implicit 664c0eb42259d790fddcd9978b66328dbb3ab65615Roland Levillain * initialization check of the called method's declaring class. 674c0eb42259d790fddcd9978b66328dbb3ab65615Roland Levillain */ 684c0eb42259d790fddcd9978b66328dbb3ab65615Roland Levillain 694c0eb42259d790fddcd9978b66328dbb3ab65615Roland Levillain // CHECK-START: void Main.invokeStaticNotInlined() builder (after) 704c0eb42259d790fddcd9978b66328dbb3ab65615Roland Levillain // CHECK-DAG: [[LoadClass:l\d+]] LoadClass 714c0eb42259d790fddcd9978b66328dbb3ab65615Roland Levillain // CHECK-DAG: [[ClinitCheck:l\d+]] ClinitCheck [ [[LoadClass]] ] 724c0eb42259d790fddcd9978b66328dbb3ab65615Roland Levillain // CHECK-DAG: InvokeStaticOrDirect [ [[ClinitCheck]] ] 734c0eb42259d790fddcd9978b66328dbb3ab65615Roland Levillain 744c0eb42259d790fddcd9978b66328dbb3ab65615Roland Levillain // CHECK-START: void Main.invokeStaticNotInlined() inliner (after) 754c0eb42259d790fddcd9978b66328dbb3ab65615Roland Levillain // CHECK-DAG: [[LoadClass:l\d+]] LoadClass 764c0eb42259d790fddcd9978b66328dbb3ab65615Roland Levillain // CHECK-DAG: [[ClinitCheck:l\d+]] ClinitCheck [ [[LoadClass]] ] 774c0eb42259d790fddcd9978b66328dbb3ab65615Roland Levillain // CHECK-DAG: InvokeStaticOrDirect [ [[ClinitCheck]] ] 784c0eb42259d790fddcd9978b66328dbb3ab65615Roland Levillain 794c0eb42259d790fddcd9978b66328dbb3ab65615Roland Levillain // The following checks ensure the clinit check and load class 804c0eb42259d790fddcd9978b66328dbb3ab65615Roland Levillain // instructions added by the builder are pruned by the 814c0eb42259d790fddcd9978b66328dbb3ab65615Roland Levillain // PrepareForRegisterAllocation. As the control flow graph is not 824c0eb42259d790fddcd9978b66328dbb3ab65615Roland Levillain // dumped after (nor before) this step, we check the CFG as it is 834c0eb42259d790fddcd9978b66328dbb3ab65615Roland Levillain // before the next pass (liveness analysis) instead. 844c0eb42259d790fddcd9978b66328dbb3ab65615Roland Levillain 854c0eb42259d790fddcd9978b66328dbb3ab65615Roland Levillain // CHECK-START: void Main.invokeStaticNotInlined() liveness (before) 864c0eb42259d790fddcd9978b66328dbb3ab65615Roland Levillain // CHECK-DAG: InvokeStaticOrDirect 874c0eb42259d790fddcd9978b66328dbb3ab65615Roland Levillain 884c0eb42259d790fddcd9978b66328dbb3ab65615Roland Levillain // CHECK-START: void Main.invokeStaticNotInlined() liveness (before) 894c0eb42259d790fddcd9978b66328dbb3ab65615Roland Levillain // CHECK-NOT: LoadClass 904c0eb42259d790fddcd9978b66328dbb3ab65615Roland Levillain // CHECK-NOT: ClinitCheck 914c0eb42259d790fddcd9978b66328dbb3ab65615Roland Levillain 924c0eb42259d790fddcd9978b66328dbb3ab65615Roland Levillain static void invokeStaticNotInlined() { 934c0eb42259d790fddcd9978b66328dbb3ab65615Roland Levillain ClassWithClinit2.staticMethod(); 944c0eb42259d790fddcd9978b66328dbb3ab65615Roland Levillain } 954c0eb42259d790fddcd9978b66328dbb3ab65615Roland Levillain 964c0eb42259d790fddcd9978b66328dbb3ab65615Roland Levillain static class ClassWithClinit2 { 974c0eb42259d790fddcd9978b66328dbb3ab65615Roland Levillain static { 984c0eb42259d790fddcd9978b66328dbb3ab65615Roland Levillain System.out.println("Main$ClassWithClinit2's static initializer"); 994c0eb42259d790fddcd9978b66328dbb3ab65615Roland Levillain } 1004c0eb42259d790fddcd9978b66328dbb3ab65615Roland Levillain 1014c0eb42259d790fddcd9978b66328dbb3ab65615Roland Levillain static boolean doThrow = false; 1024c0eb42259d790fddcd9978b66328dbb3ab65615Roland Levillain 1034c0eb42259d790fddcd9978b66328dbb3ab65615Roland Levillain static void staticMethod() { 1044c0eb42259d790fddcd9978b66328dbb3ab65615Roland Levillain if (doThrow) { 1054c0eb42259d790fddcd9978b66328dbb3ab65615Roland Levillain // Try defeating inlining. 1064c0eb42259d790fddcd9978b66328dbb3ab65615Roland Levillain throw new Error(); 1074c0eb42259d790fddcd9978b66328dbb3ab65615Roland Levillain } 1084c0eb42259d790fddcd9978b66328dbb3ab65615Roland Levillain } 1094c0eb42259d790fddcd9978b66328dbb3ab65615Roland Levillain } 1104c0eb42259d790fddcd9978b66328dbb3ab65615Roland Levillain 1114c0eb42259d790fddcd9978b66328dbb3ab65615Roland Levillain /* 1124c0eb42259d790fddcd9978b66328dbb3ab65615Roland Levillain * Ensure an inlined call to a static method whose declaring class 1134c0eb42259d790fddcd9978b66328dbb3ab65615Roland Levillain * is statically known to have been initialized does not require an 1144c0eb42259d790fddcd9978b66328dbb3ab65615Roland Levillain * explicit clinit check. 1154c0eb42259d790fddcd9978b66328dbb3ab65615Roland Levillain */ 1164c0eb42259d790fddcd9978b66328dbb3ab65615Roland Levillain 1174c0eb42259d790fddcd9978b66328dbb3ab65615Roland Levillain // CHECK-START: void Main$ClassWithClinit3.invokeStaticInlined() builder (after) 1184c0eb42259d790fddcd9978b66328dbb3ab65615Roland Levillain // CHECK-DAG: InvokeStaticOrDirect 1194c0eb42259d790fddcd9978b66328dbb3ab65615Roland Levillain 1204c0eb42259d790fddcd9978b66328dbb3ab65615Roland Levillain // CHECK-START: void Main$ClassWithClinit3.invokeStaticInlined() builder (after) 1214c0eb42259d790fddcd9978b66328dbb3ab65615Roland Levillain // CHECK-NOT: LoadClass 1224c0eb42259d790fddcd9978b66328dbb3ab65615Roland Levillain // CHECK-NOT: ClinitCheck 1234c0eb42259d790fddcd9978b66328dbb3ab65615Roland Levillain 1244c0eb42259d790fddcd9978b66328dbb3ab65615Roland Levillain // CHECK-START: void Main$ClassWithClinit3.invokeStaticInlined() inliner (after) 1254c0eb42259d790fddcd9978b66328dbb3ab65615Roland Levillain // CHECK-NOT: LoadClass 1264c0eb42259d790fddcd9978b66328dbb3ab65615Roland Levillain // CHECK-NOT: ClinitCheck 1274c0eb42259d790fddcd9978b66328dbb3ab65615Roland Levillain // CHECK-NOT: InvokeStaticOrDirect 1284c0eb42259d790fddcd9978b66328dbb3ab65615Roland Levillain 1294c0eb42259d790fddcd9978b66328dbb3ab65615Roland Levillain static class ClassWithClinit3 { 1304c0eb42259d790fddcd9978b66328dbb3ab65615Roland Levillain static void invokeStaticInlined() { 1314c0eb42259d790fddcd9978b66328dbb3ab65615Roland Levillain // The invocation of invokeStaticInlined triggers the 1324c0eb42259d790fddcd9978b66328dbb3ab65615Roland Levillain // initialization of ClassWithClinit3, meaning that the 1334c0eb42259d790fddcd9978b66328dbb3ab65615Roland Levillain // hereinbelow call to $opt$inline$StaticMethod does not need a 1344c0eb42259d790fddcd9978b66328dbb3ab65615Roland Levillain // clinit check. 1354c0eb42259d790fddcd9978b66328dbb3ab65615Roland Levillain $opt$inline$StaticMethod(); 1364c0eb42259d790fddcd9978b66328dbb3ab65615Roland Levillain } 1374c0eb42259d790fddcd9978b66328dbb3ab65615Roland Levillain 1384c0eb42259d790fddcd9978b66328dbb3ab65615Roland Levillain static { 1394c0eb42259d790fddcd9978b66328dbb3ab65615Roland Levillain System.out.println("Main$ClassWithClinit3's static initializer"); 1404c0eb42259d790fddcd9978b66328dbb3ab65615Roland Levillain } 1414c0eb42259d790fddcd9978b66328dbb3ab65615Roland Levillain 1424c0eb42259d790fddcd9978b66328dbb3ab65615Roland Levillain static void $opt$inline$StaticMethod() { 1434c0eb42259d790fddcd9978b66328dbb3ab65615Roland Levillain } 1444c0eb42259d790fddcd9978b66328dbb3ab65615Roland Levillain } 1454c0eb42259d790fddcd9978b66328dbb3ab65615Roland Levillain 1464c0eb42259d790fddcd9978b66328dbb3ab65615Roland Levillain /* 1474c0eb42259d790fddcd9978b66328dbb3ab65615Roland Levillain * Ensure an non-inlined call to a static method whose declaring 1484c0eb42259d790fddcd9978b66328dbb3ab65615Roland Levillain * class is statically known to have been initialized does not 1494c0eb42259d790fddcd9978b66328dbb3ab65615Roland Levillain * require an explicit clinit check. 1504c0eb42259d790fddcd9978b66328dbb3ab65615Roland Levillain */ 1514c0eb42259d790fddcd9978b66328dbb3ab65615Roland Levillain 1524c0eb42259d790fddcd9978b66328dbb3ab65615Roland Levillain // CHECK-START: void Main$ClassWithClinit4.invokeStaticNotInlined() builder (after) 1534c0eb42259d790fddcd9978b66328dbb3ab65615Roland Levillain // CHECK-DAG: InvokeStaticOrDirect 1544c0eb42259d790fddcd9978b66328dbb3ab65615Roland Levillain 1554c0eb42259d790fddcd9978b66328dbb3ab65615Roland Levillain // CHECK-START: void Main$ClassWithClinit4.invokeStaticNotInlined() builder (after) 1564c0eb42259d790fddcd9978b66328dbb3ab65615Roland Levillain // CHECK-NOT: LoadClass 1574c0eb42259d790fddcd9978b66328dbb3ab65615Roland Levillain // CHECK-NOT: ClinitCheck 1584c0eb42259d790fddcd9978b66328dbb3ab65615Roland Levillain 1594c0eb42259d790fddcd9978b66328dbb3ab65615Roland Levillain // CHECK-START: void Main$ClassWithClinit4.invokeStaticNotInlined() inliner (after) 1604c0eb42259d790fddcd9978b66328dbb3ab65615Roland Levillain // CHECK-DAG: InvokeStaticOrDirect 1614c0eb42259d790fddcd9978b66328dbb3ab65615Roland Levillain 1624c0eb42259d790fddcd9978b66328dbb3ab65615Roland Levillain // CHECK-START: void Main$ClassWithClinit4.invokeStaticNotInlined() inliner (after) 1634c0eb42259d790fddcd9978b66328dbb3ab65615Roland Levillain // CHECK-NOT: LoadClass 1644c0eb42259d790fddcd9978b66328dbb3ab65615Roland Levillain // CHECK-NOT: ClinitCheck 1654c0eb42259d790fddcd9978b66328dbb3ab65615Roland Levillain 1664c0eb42259d790fddcd9978b66328dbb3ab65615Roland Levillain static class ClassWithClinit4 { 1674c0eb42259d790fddcd9978b66328dbb3ab65615Roland Levillain static void invokeStaticNotInlined() { 1684c0eb42259d790fddcd9978b66328dbb3ab65615Roland Levillain // The invocation of invokeStaticNotInlined triggers the 1694c0eb42259d790fddcd9978b66328dbb3ab65615Roland Levillain // initialization of ClassWithClinit4, meaning that the 1704c0eb42259d790fddcd9978b66328dbb3ab65615Roland Levillain // hereinbelow call to staticMethod does not need a clinit 1714c0eb42259d790fddcd9978b66328dbb3ab65615Roland Levillain // check. 1724c0eb42259d790fddcd9978b66328dbb3ab65615Roland Levillain staticMethod(); 1734c0eb42259d790fddcd9978b66328dbb3ab65615Roland Levillain } 1744c0eb42259d790fddcd9978b66328dbb3ab65615Roland Levillain 1754c0eb42259d790fddcd9978b66328dbb3ab65615Roland Levillain static { 1764c0eb42259d790fddcd9978b66328dbb3ab65615Roland Levillain System.out.println("Main$ClassWithClinit4's static initializer"); 1774c0eb42259d790fddcd9978b66328dbb3ab65615Roland Levillain } 1784c0eb42259d790fddcd9978b66328dbb3ab65615Roland Levillain 1794c0eb42259d790fddcd9978b66328dbb3ab65615Roland Levillain static boolean doThrow = false; 1804c0eb42259d790fddcd9978b66328dbb3ab65615Roland Levillain 1814c0eb42259d790fddcd9978b66328dbb3ab65615Roland Levillain static void staticMethod() { 1824c0eb42259d790fddcd9978b66328dbb3ab65615Roland Levillain if (doThrow) { 1834c0eb42259d790fddcd9978b66328dbb3ab65615Roland Levillain // Try defeating inlining. 1844c0eb42259d790fddcd9978b66328dbb3ab65615Roland Levillain throw new Error(); 1854c0eb42259d790fddcd9978b66328dbb3ab65615Roland Levillain } 1864c0eb42259d790fddcd9978b66328dbb3ab65615Roland Levillain } 1874c0eb42259d790fddcd9978b66328dbb3ab65615Roland Levillain } 1884c0eb42259d790fddcd9978b66328dbb3ab65615Roland Levillain 1894c0eb42259d790fddcd9978b66328dbb3ab65615Roland Levillain // TODO: Add a test for the case of a static method whose declaring 1904c0eb42259d790fddcd9978b66328dbb3ab65615Roland Levillain // class type index is not available (i.e. when `storage_index` 1914c0eb42259d790fddcd9978b66328dbb3ab65615Roland Levillain // equals `DexFile::kDexNoIndex` in 1924c0eb42259d790fddcd9978b66328dbb3ab65615Roland Levillain // art::HGraphBuilder::BuildInvoke). 1934c0eb42259d790fddcd9978b66328dbb3ab65615Roland Levillain 1944c0eb42259d790fddcd9978b66328dbb3ab65615Roland Levillain public static void main(String[] args) { 1954c0eb42259d790fddcd9978b66328dbb3ab65615Roland Levillain invokeStaticInlined(); 1964c0eb42259d790fddcd9978b66328dbb3ab65615Roland Levillain invokeStaticNotInlined(); 1974c0eb42259d790fddcd9978b66328dbb3ab65615Roland Levillain ClassWithClinit3.invokeStaticInlined(); 1984c0eb42259d790fddcd9978b66328dbb3ab65615Roland Levillain ClassWithClinit4.invokeStaticNotInlined(); 1994c0eb42259d790fddcd9978b66328dbb3ab65615Roland Levillain } 2004c0eb42259d790fddcd9978b66328dbb3ab65615Roland Levillain} 201