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   public static boolean $inline$classTypeTest(Object o) {
     19     return o instanceof SubMain;
     20   }
     21 
     22   public static boolean $inline$interfaceTypeTest(Object o) {
     23     return o instanceof Itf;
     24   }
     25 
     26   public static SubMain subMain;
     27   public static Main mainField;
     28   public static Unrelated unrelatedField;
     29   public static FinalUnrelated finalUnrelatedField;
     30 
     31   /// CHECK-START: boolean Main.classTypeTestNull() register (after)
     32   /// CHECK-DAG: <<Const:i\d+>> IntConstant 0
     33   /// CHECK-DAG:                Return [<<Const>>]
     34   public static boolean classTypeTestNull() {
     35     return $inline$classTypeTest(null);
     36   }
     37 
     38   /// CHECK-START: boolean Main.classTypeTestExactMain() register (after)
     39   /// CHECK-DAG: <<Const:i\d+>> IntConstant 0
     40   /// CHECK-DAG:                Return [<<Const>>]
     41   public static boolean classTypeTestExactMain() {
     42     return $inline$classTypeTest(new Main());
     43   }
     44 
     45   /// CHECK-START: boolean Main.classTypeTestExactSubMain() register (after)
     46   /// CHECK-DAG: <<Const:i\d+>> IntConstant 1
     47   /// CHECK-DAG:                Return [<<Const>>]
     48   public static boolean classTypeTestExactSubMain() {
     49     return $inline$classTypeTest(new SubMain());
     50   }
     51 
     52   /// CHECK-START: boolean Main.classTypeTestSubMainOrNull() register (after)
     53   /// CHECK-DAG: <<Value:z\d+>> NotEqual
     54   /// CHECK-DAG:                Return [<<Value>>]
     55   public static boolean classTypeTestSubMainOrNull() {
     56     return $inline$classTypeTest(subMain);
     57   }
     58 
     59   /// CHECK-START: boolean Main.classTypeTestMainOrNull() register (after)
     60   /// CHECK-DAG: <<Value:z\d+>> InstanceOf
     61   /// CHECK-DAG:                Return [<<Value>>]
     62   public static boolean classTypeTestMainOrNull() {
     63     return $inline$classTypeTest(mainField);
     64   }
     65 
     66   /// CHECK-START: boolean Main.classTypeTestUnrelated() register (after)
     67   /// CHECK-DAG: <<Const:i\d+>> IntConstant 0
     68   /// CHECK-DAG:                Return [<<Const>>]
     69   public static boolean classTypeTestUnrelated() {
     70     return $inline$classTypeTest(unrelatedField);
     71   }
     72 
     73   /// CHECK-START: boolean Main.classTypeTestFinalUnrelated() register (after)
     74   /// CHECK-DAG: <<Const:i\d+>> IntConstant 0
     75   /// CHECK-DAG:                Return [<<Const>>]
     76   public static boolean classTypeTestFinalUnrelated() {
     77     return $inline$classTypeTest(finalUnrelatedField);
     78   }
     79 
     80   /// CHECK-START: boolean Main.interfaceTypeTestNull() register (after)
     81   /// CHECK-DAG: <<Const:i\d+>> IntConstant 0
     82   /// CHECK-DAG:                Return [<<Const>>]
     83   public static boolean interfaceTypeTestNull() {
     84     return $inline$interfaceTypeTest(null);
     85   }
     86 
     87   /// CHECK-START: boolean Main.interfaceTypeTestExactMain() register (after)
     88   /// CHECK-DAG: <<Const:i\d+>> IntConstant 0
     89   /// CHECK-DAG:                Return [<<Const>>]
     90   public static boolean interfaceTypeTestExactMain() {
     91     return $inline$interfaceTypeTest(new Main());
     92   }
     93 
     94   /// CHECK-START: boolean Main.interfaceTypeTestExactSubMain() register (after)
     95   /// CHECK-DAG: <<Const:i\d+>> IntConstant 1
     96   /// CHECK-DAG:                Return [<<Const>>]
     97   public static boolean interfaceTypeTestExactSubMain() {
     98     return $inline$interfaceTypeTest(new SubMain());
     99   }
    100 
    101   /// CHECK-START: boolean Main.interfaceTypeTestSubMainOrNull() register (after)
    102   /// CHECK-DAG: <<Value:z\d+>> NotEqual
    103   /// CHECK-DAG:                Return [<<Value>>]
    104   public static boolean interfaceTypeTestSubMainOrNull() {
    105     return $inline$interfaceTypeTest(subMain);
    106   }
    107 
    108   /// CHECK-START: boolean Main.interfaceTypeTestMainOrNull() register (after)
    109   /// CHECK-DAG: <<Value:z\d+>> InstanceOf
    110   /// CHECK-DAG:                Return [<<Value>>]
    111   public static boolean interfaceTypeTestMainOrNull() {
    112     return $inline$interfaceTypeTest(mainField);
    113   }
    114 
    115   /// CHECK-START: boolean Main.interfaceTypeTestUnrelated() register (after)
    116   /// CHECK-DAG: <<Value:z\d+>> InstanceOf
    117   /// CHECK-DAG:                Return [<<Value>>]
    118   public static boolean interfaceTypeTestUnrelated() {
    119     // This method is the main difference between doing an instanceof on an interface
    120     // or a class. We have to keep the instanceof in case a subclass of Unrelated
    121     // implements the interface.
    122     return $inline$interfaceTypeTest(unrelatedField);
    123   }
    124 
    125   /// CHECK-START: boolean Main.interfaceTypeTestFinalUnrelated() register (after)
    126   /// CHECK-DAG: <<Const:i\d+>> IntConstant 0
    127   /// CHECK-DAG:                Return [<<Const>>]
    128   public static boolean interfaceTypeTestFinalUnrelated() {
    129     return $inline$interfaceTypeTest(finalUnrelatedField);
    130   }
    131 
    132   // Check that we remove the LoadClass instruction from the graph.
    133   /// CHECK-START: boolean Main.knownTestWithLoadedClass() register (after)
    134   /// CHECK-NOT: LoadClass
    135   public static boolean knownTestWithLoadedClass() {
    136     return new String() instanceof String;
    137   }
    138 
    139   // Check that we do not remove the LoadClass instruction from the graph.
    140   /// CHECK-START: boolean Main.knownTestWithUnloadedClass() register (after)
    141   /// CHECK: <<Const:i\d+>> IntConstant 0
    142   /// CHECK:                LoadClass
    143   /// CHECK:                Return [<<Const>>]
    144   public static boolean knownTestWithUnloadedClass() {
    145     return $inline$returnUnrelated() instanceof String;
    146   }
    147 
    148   public static Object $inline$returnUnrelated() {
    149     return new Unrelated();
    150   }
    151 
    152   public static void expect(boolean expected, boolean actual) {
    153     if (expected != actual) {
    154       throw new Error("Unexpected result");
    155     }
    156   }
    157 
    158   public static void main(String[] args) {
    159     expect(false, classTypeTestNull());
    160     expect(false, classTypeTestExactMain());
    161     expect(true, classTypeTestExactSubMain());
    162 
    163     subMain = null;
    164     expect(false, classTypeTestSubMainOrNull());
    165     subMain = new SubMain();
    166     expect(true, classTypeTestSubMainOrNull());
    167 
    168     mainField = null;
    169     expect(false, classTypeTestMainOrNull());
    170     mainField = new Main();
    171     expect(false, classTypeTestMainOrNull());
    172     mainField = new SubMain();
    173     expect(true, classTypeTestMainOrNull());
    174 
    175     unrelatedField = null;
    176     expect(false, classTypeTestUnrelated());
    177     unrelatedField = new Unrelated();
    178     expect(false, classTypeTestUnrelated());
    179 
    180     finalUnrelatedField = null;
    181     expect(false, classTypeTestFinalUnrelated());
    182     finalUnrelatedField = new FinalUnrelated();
    183     expect(false, classTypeTestFinalUnrelated());
    184 
    185     expect(false, interfaceTypeTestNull());
    186     expect(false, interfaceTypeTestExactMain());
    187     expect(true, interfaceTypeTestExactSubMain());
    188 
    189     subMain = null;
    190     expect(false, interfaceTypeTestSubMainOrNull());
    191     subMain = new SubMain();
    192     expect(true, interfaceTypeTestSubMainOrNull());
    193 
    194     mainField = null;
    195     expect(false, interfaceTypeTestMainOrNull());
    196     mainField = new Main();
    197     expect(false, interfaceTypeTestMainOrNull());
    198     mainField = new SubMain();
    199     expect(true, interfaceTypeTestMainOrNull());
    200 
    201     unrelatedField = null;
    202     expect(false, interfaceTypeTestUnrelated());
    203     unrelatedField = new Unrelated();
    204     expect(false, interfaceTypeTestUnrelated());
    205 
    206     finalUnrelatedField = null;
    207     expect(false, interfaceTypeTestFinalUnrelated());
    208     finalUnrelatedField = new FinalUnrelated();
    209     expect(false, interfaceTypeTestFinalUnrelated());
    210   }
    211 }
    212 
    213 interface Itf {
    214 }
    215 
    216 class SubMain extends Main implements Itf {
    217 }
    218 
    219 class Unrelated {
    220 }
    221 
    222 final class FinalUnrelated {
    223 }
    224