Home | History | Annotate | Download | only in src
      1 /*
      2  * Copyright (C) 2015 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 public class Main {
     18 
     19   public static void assertIntEquals(int expected, int result) {
     20     if (expected != result) {
     21       throw new Error("Expected: " + expected + ", found: " + result);
     22     }
     23   }
     24 
     25   public static void assertStringEquals(String expected, String result) {
     26     if (expected != null ? !expected.equals(result) : result != null) {
     27       throw new Error("Expected: " + expected + ", found: " + result);
     28     }
     29   }
     30 
     31   public static void assertClassEquals(Class<?> expected, Class<?> result) {
     32     if (expected != result) {
     33       throw new Error("Expected: " + expected + ", found: " + result);
     34     }
     35   }
     36 
     37   public static boolean doThrow = false;
     38 
     39   private static int $noinline$foo(int x) {
     40     if (doThrow) { throw new Error(); }
     41     return x;
     42   }
     43 
     44   /// CHECK-START: int Main.testSimple(int) sharpening (before)
     45   /// CHECK:                InvokeStaticOrDirect method_load_kind:RuntimeCall
     46 
     47   /// CHECK-START-ARM: int Main.testSimple(int) sharpening (after)
     48   /// CHECK:                InvokeStaticOrDirect method_load_kind:BssEntry
     49 
     50   /// CHECK-START-ARM64: int Main.testSimple(int) sharpening (after)
     51   /// CHECK:                InvokeStaticOrDirect method_load_kind:BssEntry
     52 
     53   /// CHECK-START-MIPS: int Main.testSimple(int) sharpening (after)
     54   /// CHECK:                InvokeStaticOrDirect method_load_kind:BssEntry
     55 
     56   /// CHECK-START-MIPS64: int Main.testSimple(int) sharpening (after)
     57   /// CHECK:                InvokeStaticOrDirect method_load_kind:BssEntry
     58 
     59   /// CHECK-START-X86: int Main.testSimple(int) sharpening (after)
     60   /// CHECK-NOT:            X86ComputeBaseMethodAddress
     61   /// CHECK:                InvokeStaticOrDirect method_load_kind:BssEntry
     62 
     63   /// CHECK-START-X86_64: int Main.testSimple(int) sharpening (after)
     64   /// CHECK:                InvokeStaticOrDirect method_load_kind:BssEntry
     65 
     66   /// CHECK-START-MIPS: int Main.testSimple(int) pc_relative_fixups_mips (after)
     67   /// CHECK:                MipsComputeBaseMethodAddress
     68   /// CHECK-NOT:            MipsComputeBaseMethodAddress
     69 
     70   /// CHECK-START-X86: int Main.testSimple(int) pc_relative_fixups_x86 (after)
     71   /// CHECK:                X86ComputeBaseMethodAddress
     72   /// CHECK-NOT:            X86ComputeBaseMethodAddress
     73 
     74   public static int testSimple(int x) {
     75     // This call should use PC-relative dex cache array load to retrieve the target method.
     76     return $noinline$foo(x);
     77   }
     78 
     79   /// CHECK-START: int Main.testDiamond(boolean, int) sharpening (before)
     80   /// CHECK:                InvokeStaticOrDirect method_load_kind:RuntimeCall
     81 
     82   /// CHECK-START-ARM: int Main.testDiamond(boolean, int) sharpening (after)
     83   /// CHECK:                InvokeStaticOrDirect method_load_kind:BssEntry
     84   /// CHECK:                InvokeStaticOrDirect method_load_kind:BssEntry
     85 
     86   /// CHECK-START-ARM64: int Main.testDiamond(boolean, int) sharpening (after)
     87   /// CHECK:                InvokeStaticOrDirect method_load_kind:BssEntry
     88   /// CHECK:                InvokeStaticOrDirect method_load_kind:BssEntry
     89 
     90   /// CHECK-START-MIPS: int Main.testDiamond(boolean, int) sharpening (after)
     91   /// CHECK:                InvokeStaticOrDirect method_load_kind:BssEntry
     92   /// CHECK:                InvokeStaticOrDirect method_load_kind:BssEntry
     93 
     94   /// CHECK-START-MIPS64: int Main.testDiamond(boolean, int) sharpening (after)
     95   /// CHECK:                InvokeStaticOrDirect method_load_kind:BssEntry
     96   /// CHECK:                InvokeStaticOrDirect method_load_kind:BssEntry
     97 
     98   /// CHECK-START-X86: int Main.testDiamond(boolean, int) sharpening (after)
     99   /// CHECK-NOT:            X86ComputeBaseMethodAddress
    100   /// CHECK:                InvokeStaticOrDirect method_load_kind:BssEntry
    101   /// CHECK:                InvokeStaticOrDirect method_load_kind:BssEntry
    102 
    103   /// CHECK-START-X86_64: int Main.testDiamond(boolean, int) sharpening (after)
    104   /// CHECK:                InvokeStaticOrDirect method_load_kind:BssEntry
    105   /// CHECK:                InvokeStaticOrDirect method_load_kind:BssEntry
    106 
    107   /// CHECK-START-MIPS: int Main.testDiamond(boolean, int) pc_relative_fixups_mips (after)
    108   /// CHECK:                MipsComputeBaseMethodAddress
    109   /// CHECK-NOT:            MipsComputeBaseMethodAddress
    110 
    111   /// CHECK-START-MIPS: int Main.testDiamond(boolean, int) pc_relative_fixups_mips (after)
    112   /// CHECK:                MipsComputeBaseMethodAddress
    113   /// CHECK-NEXT:           If
    114 
    115   /// CHECK-START-X86: int Main.testDiamond(boolean, int) pc_relative_fixups_x86 (after)
    116   /// CHECK:                X86ComputeBaseMethodAddress
    117   /// CHECK-NOT:            X86ComputeBaseMethodAddress
    118 
    119   /// CHECK-START-X86: int Main.testDiamond(boolean, int) pc_relative_fixups_x86 (after)
    120   /// CHECK:                X86ComputeBaseMethodAddress
    121   /// CHECK-NEXT:           If
    122 
    123   public static int testDiamond(boolean negate, int x) {
    124     // These calls should use PC-relative loads to retrieve the target method.
    125     // PC-relative bases used by MIPS and X86 should be pulled before the If.
    126     if (negate) {
    127       return $noinline$foo(-x);
    128     } else {
    129       return $noinline$foo(x);
    130     }
    131   }
    132 
    133   /// CHECK-START-MIPS: int Main.testLoop(int[], int) pc_relative_fixups_mips (before)
    134   /// CHECK-NOT:            MipsComputeBaseMethodAddress
    135 
    136   /// CHECK-START-MIPS: int Main.testLoop(int[], int) pc_relative_fixups_mips (after)
    137   /// CHECK:                MipsComputeBaseMethodAddress
    138   /// CHECK-NOT:            MipsComputeBaseMethodAddress
    139 
    140   /// CHECK-START-MIPS: int Main.testLoop(int[], int) pc_relative_fixups_mips (after)
    141   /// CHECK:                InvokeStaticOrDirect
    142   /// CHECK-NOT:            InvokeStaticOrDirect
    143 
    144   /// CHECK-START-MIPS: int Main.testLoop(int[], int) pc_relative_fixups_mips (after)
    145   /// CHECK:                ArrayLength
    146   /// CHECK-NEXT:           MipsComputeBaseMethodAddress
    147   /// CHECK-NEXT:           Goto
    148   /// CHECK:                begin_block
    149   /// CHECK:                InvokeStaticOrDirect method_load_kind:BssEntry
    150 
    151   /// CHECK-START-X86: int Main.testLoop(int[], int) pc_relative_fixups_x86 (before)
    152   /// CHECK-NOT:            X86ComputeBaseMethodAddress
    153 
    154   /// CHECK-START-X86: int Main.testLoop(int[], int) pc_relative_fixups_x86 (after)
    155   /// CHECK:                X86ComputeBaseMethodAddress
    156   /// CHECK-NOT:            X86ComputeBaseMethodAddress
    157 
    158   /// CHECK-START-X86: int Main.testLoop(int[], int) pc_relative_fixups_x86 (after)
    159   /// CHECK:                InvokeStaticOrDirect
    160   /// CHECK-NOT:            InvokeStaticOrDirect
    161 
    162   /// CHECK-START-X86: int Main.testLoop(int[], int) pc_relative_fixups_x86 (after)
    163   /// CHECK:                ArrayLength
    164   /// CHECK-NEXT:           X86ComputeBaseMethodAddress
    165   /// CHECK-NEXT:           Goto
    166   /// CHECK:                begin_block
    167   /// CHECK:                InvokeStaticOrDirect method_load_kind:BssEntry
    168 
    169   public static int testLoop(int[] array, int x) {
    170     // PC-relative bases used by MIPS and X86 should be pulled before the loop.
    171     for (int i : array) {
    172       x += $noinline$foo(i);
    173     }
    174     return x;
    175   }
    176 
    177   /// CHECK-START-MIPS: int Main.testLoopWithDiamond(int[], boolean, int) pc_relative_fixups_mips (before)
    178   /// CHECK-NOT:            MipsComputeBaseMethodAddress
    179 
    180   /// CHECK-START-MIPS: int Main.testLoopWithDiamond(int[], boolean, int) pc_relative_fixups_mips (after)
    181   /// CHECK:                If
    182   /// CHECK:                begin_block
    183   /// CHECK:                ArrayLength
    184   /// CHECK-NEXT:           MipsComputeBaseMethodAddress
    185   /// CHECK-NEXT:           Goto
    186 
    187   /// CHECK-START-X86: int Main.testLoopWithDiamond(int[], boolean, int) pc_relative_fixups_x86 (before)
    188   /// CHECK-NOT:            X86ComputeBaseMethodAddress
    189 
    190   /// CHECK-START-X86: int Main.testLoopWithDiamond(int[], boolean, int) pc_relative_fixups_x86 (after)
    191   /// CHECK:                If
    192   /// CHECK:                begin_block
    193   /// CHECK:                ArrayLength
    194   /// CHECK-NEXT:           X86ComputeBaseMethodAddress
    195   /// CHECK-NEXT:           Goto
    196 
    197   public static int testLoopWithDiamond(int[] array, boolean negate, int x) {
    198     // PC-relative bases used by MIPS and X86 should be pulled before the loop
    199     // but not outside the if.
    200     if (array != null) {
    201       for (int i : array) {
    202         if (negate) {
    203           x += $noinline$foo(-i);
    204         } else {
    205           x += $noinline$foo(i);
    206         }
    207       }
    208     }
    209     return x;
    210   }
    211 
    212   /// CHECK-START: java.lang.String Main.$noinline$getBootImageString() sharpening (before)
    213   /// CHECK:                LoadString load_kind:RuntimeCall
    214 
    215   /// CHECK-START-X86: java.lang.String Main.$noinline$getBootImageString() sharpening (after)
    216   // Note: load kind depends on PIC/non-PIC
    217   /// CHECK:                LoadString load_kind:{{BootImageAddress|BssEntry}}
    218 
    219   /// CHECK-START-X86_64: java.lang.String Main.$noinline$getBootImageString() sharpening (after)
    220   // Note: load kind depends on PIC/non-PIC
    221   /// CHECK:                LoadString load_kind:{{BootImageAddress|BssEntry}}
    222 
    223   /// CHECK-START-ARM: java.lang.String Main.$noinline$getBootImageString() sharpening (after)
    224   // Note: load kind depends on PIC/non-PIC
    225   /// CHECK:                LoadString load_kind:{{BootImageAddress|BssEntry}}
    226 
    227   /// CHECK-START-ARM64: java.lang.String Main.$noinline$getBootImageString() sharpening (after)
    228   // Note: load kind depends on PIC/non-PIC
    229   /// CHECK:                LoadString load_kind:{{BootImageAddress|BssEntry}}
    230 
    231   /// CHECK-START-MIPS: java.lang.String Main.$noinline$getBootImageString() sharpening (after)
    232   // Note: load kind depends on PIC/non-PIC
    233   /// CHECK:                LoadString load_kind:{{BootImageAddress|BssEntry}}
    234 
    235   /// CHECK-START-MIPS64: java.lang.String Main.$noinline$getBootImageString() sharpening (after)
    236   // Note: load kind depends on PIC/non-PIC
    237   /// CHECK:                LoadString load_kind:{{BootImageAddress|BssEntry}}
    238 
    239   public static String $noinline$getBootImageString() {
    240     // Prevent inlining to avoid the string comparison being optimized away.
    241     if (doThrow) { throw new Error(); }
    242     // Empty string is known to be in the boot image.
    243     return "";
    244   }
    245 
    246   /// CHECK-START: java.lang.String Main.$noinline$getNonBootImageString() sharpening (before)
    247   /// CHECK:                LoadString load_kind:RuntimeCall
    248 
    249   /// CHECK-START-X86: java.lang.String Main.$noinline$getNonBootImageString() sharpening (after)
    250   /// CHECK:                LoadString load_kind:BssEntry
    251 
    252   /// CHECK-START-X86: java.lang.String Main.$noinline$getNonBootImageString() pc_relative_fixups_x86 (after)
    253   /// CHECK-DAG:            X86ComputeBaseMethodAddress
    254   /// CHECK-DAG:            LoadString load_kind:BssEntry
    255 
    256   /// CHECK-START-X86_64: java.lang.String Main.$noinline$getNonBootImageString() sharpening (after)
    257   /// CHECK:                LoadString load_kind:BssEntry
    258 
    259   /// CHECK-START-ARM: java.lang.String Main.$noinline$getNonBootImageString() sharpening (after)
    260   /// CHECK:                LoadString load_kind:BssEntry
    261 
    262   /// CHECK-START-ARM64: java.lang.String Main.$noinline$getNonBootImageString() sharpening (after)
    263   /// CHECK:                LoadString load_kind:BssEntry
    264 
    265   /// CHECK-START-MIPS: java.lang.String Main.$noinline$getNonBootImageString() sharpening (after)
    266   /// CHECK:                LoadString load_kind:BssEntry
    267 
    268   /// CHECK-START-MIPS64: java.lang.String Main.$noinline$getNonBootImageString() sharpening (after)
    269   /// CHECK:                LoadString load_kind:BssEntry
    270 
    271   public static String $noinline$getNonBootImageString() {
    272     // Prevent inlining to avoid the string comparison being optimized away.
    273     if (doThrow) { throw new Error(); }
    274     // This string is not in the boot image.
    275     return "non-boot-image-string";
    276   }
    277 
    278   /// CHECK-START-X86: java.lang.Class Main.$noinline$getStringClass() sharpening (after)
    279   // Note: load kind depends on PIC/non-PIC
    280   /// CHECK:                LoadClass load_kind:{{BootImageAddress|BssEntry}} class_name:java.lang.String
    281 
    282   /// CHECK-START-X86_64: java.lang.Class Main.$noinline$getStringClass() sharpening (after)
    283   // Note: load kind depends on PIC/non-PIC
    284   /// CHECK:                LoadClass load_kind:{{BootImageAddress|BssEntry}} class_name:java.lang.String
    285 
    286   /// CHECK-START-ARM: java.lang.Class Main.$noinline$getStringClass() sharpening (after)
    287   // Note: load kind depends on PIC/non-PIC
    288   /// CHECK:                LoadClass load_kind:{{BootImageAddress|BssEntry}} class_name:java.lang.String
    289 
    290   /// CHECK-START-ARM64: java.lang.Class Main.$noinline$getStringClass() sharpening (after)
    291   // Note: load kind depends on PIC/non-PIC
    292   /// CHECK:                LoadClass load_kind:{{BootImageAddress|BssEntry}} class_name:java.lang.String
    293 
    294   /// CHECK-START-MIPS: java.lang.Class Main.$noinline$getStringClass() sharpening (after)
    295   // Note: load kind depends on PIC/non-PIC
    296   /// CHECK:                LoadClass load_kind:{{BootImageAddress|BssEntry}} class_name:java.lang.String
    297 
    298   /// CHECK-START-MIPS64: java.lang.Class Main.$noinline$getStringClass() sharpening (after)
    299   // Note: load kind depends on PIC/non-PIC
    300   /// CHECK:                LoadClass load_kind:{{BootImageAddress|BssEntry}} class_name:java.lang.String
    301 
    302   public static Class<?> $noinline$getStringClass() {
    303     // Prevent inlining to avoid the string comparison being optimized away.
    304     if (doThrow) { throw new Error(); }
    305     // String class is known to be in the boot image.
    306     return String.class;
    307   }
    308 
    309   /// CHECK-START-X86: java.lang.Class Main.$noinline$getOtherClass() sharpening (after)
    310   /// CHECK:                LoadClass load_kind:BssEntry class_name:Other
    311 
    312   /// CHECK-START-X86: java.lang.Class Main.$noinline$getOtherClass() pc_relative_fixups_x86 (after)
    313   /// CHECK-DAG:            X86ComputeBaseMethodAddress
    314   /// CHECK-DAG:            LoadClass load_kind:BssEntry class_name:Other
    315 
    316   /// CHECK-START-X86_64: java.lang.Class Main.$noinline$getOtherClass() sharpening (after)
    317   /// CHECK:                LoadClass load_kind:BssEntry class_name:Other
    318 
    319   /// CHECK-START-ARM: java.lang.Class Main.$noinline$getOtherClass() sharpening (after)
    320   /// CHECK:                LoadClass load_kind:BssEntry class_name:Other
    321 
    322   /// CHECK-START-ARM64: java.lang.Class Main.$noinline$getOtherClass() sharpening (after)
    323   /// CHECK:                LoadClass load_kind:BssEntry class_name:Other
    324 
    325   /// CHECK-START-MIPS: java.lang.Class Main.$noinline$getOtherClass() sharpening (after)
    326   /// CHECK:                LoadClass load_kind:BssEntry class_name:Other
    327 
    328   /// CHECK-START-MIPS64: java.lang.Class Main.$noinline$getOtherClass() sharpening (after)
    329   /// CHECK:                LoadClass load_kind:BssEntry class_name:Other
    330 
    331   public static Class<?> $noinline$getOtherClass() {
    332     // Prevent inlining to avoid the string comparison being optimized away.
    333     if (doThrow) { throw new Error(); }
    334     // Other class is not in the boot image.
    335     return Other.class;
    336   }
    337 
    338   public static void main(String[] args) {
    339     assertIntEquals(1, testSimple(1));
    340     assertIntEquals(1, testDiamond(false, 1));
    341     assertIntEquals(-1, testDiamond(true, 1));
    342     assertIntEquals(3, testLoop(new int[]{ 2 }, 1));
    343     assertIntEquals(8, testLoop(new int[]{ 3, 4 }, 1));
    344     assertIntEquals(1, testLoopWithDiamond(null, false, 1));
    345     assertIntEquals(3, testLoopWithDiamond(new int[]{ 2 }, false, 1));
    346     assertIntEquals(-6, testLoopWithDiamond(new int[]{ 3, 4 }, true, 1));
    347     assertStringEquals("", $noinline$getBootImageString());
    348     assertStringEquals("non-boot-image-string", $noinline$getNonBootImageString());
    349     assertClassEquals(String.class, $noinline$getStringClass());
    350     assertClassEquals(Other.class, $noinline$getOtherClass());
    351   }
    352 }
    353 
    354 class Other {
    355 }
    356