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