Home | History | Annotate | Download | only in smali
      1 # Copyright 2016 The Android Open Source Project
      2 #
      3 # Licensed under the Apache License, Version 2.0 (the "License");
      4 # you may not use this file except in compliance with the License.
      5 # You may obtain a copy of the License at
      6 #
      7 #      http://www.apache.org/licenses/LICENSE-2.0
      8 #
      9 # Unless required by applicable law or agreed to in writing, software
     10 # distributed under the License is distributed on an "AS IS" BASIS,
     11 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     12 # See the License for the specific language governing permissions and
     13 # limitations under the License.
     14 
     15 .class LMain;
     16 .super Ljava/lang/Object;
     17 
     18 # MethodHandle Main.getHandleForVirtual(Class<?> defc, String name, MethodType type);
     19 #
     20 # Returns a handle to a virtual method on |defc| named name with type |type| using
     21 # the public lookup object.
     22 .method public static getHandleForVirtual(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/MethodHandle;
     23 .registers 5
     24 
     25     # Get a reference to the public lookup object (MethodHandles.publicLookup()).
     26     invoke-static {}, Ljava/lang/invoke/MethodHandles;->publicLookup()Ljava/lang/invoke/MethodHandles$Lookup;
     27     move-result-object v0
     28 
     29     # Call Lookup.findVirtual(defc, name, type);
     30     invoke-virtual {v0, p0, p1, p2}, Ljava/lang/invoke/MethodHandles$Lookup;->findVirtual(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/MethodHandle;
     31     move-result-object v1
     32     return-object v1
     33 .end method
     34 
     35 # MethodHandle Main.getHandleForStatic(Class<?> defc, String name, MethodType type);
     36 #
     37 # Returns a handle to a static method on |defc| named name with type |type| using
     38 # the public lookup object.
     39 .method public static getHandleForStatic(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/MethodHandle;
     40 .registers 5
     41 
     42     # Get a reference to the public lookup object (MethodHandles.publicLookup()).
     43     invoke-static {}, Ljava/lang/invoke/MethodHandles;->publicLookup()Ljava/lang/invoke/MethodHandles$Lookup;
     44     move-result-object v0
     45 
     46     # Call Lookup.findStatic(defc, name, type);
     47     invoke-virtual {v0, p0, p1, p2}, Ljava/lang/invoke/MethodHandles$Lookup;->findStatic(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/MethodHandle;
     48     move-result-object v1
     49     return-object v1
     50 .end method
     51 
     52 # Returns a method handle to String java.lang.String.concat(String);
     53 .method public static getStringConcatHandle()Ljava/lang/invoke/MethodHandle;
     54 .registers 3
     55     const-string v0, "concat"
     56     invoke-virtual {v0}, Ljava/lang/Object;->getClass()Ljava/lang/Class;
     57     move-result-object v1
     58 
     59     # Call MethodType.methodType(rtype=String.class, ptype[0] = String.class)
     60     invoke-static {v1, v1}, Ljava/lang/invoke/MethodType;->methodType(Ljava/lang/Class;Ljava/lang/Class;)Ljava/lang/invoke/MethodType;
     61     move-result-object v2
     62 
     63     # Call Main.getHandleForVirtual(String.class, "concat", methodType);
     64     invoke-static {v1, v0, v2}, LMain;->getHandleForVirtual(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/MethodHandle;
     65     move-result-object v0
     66     return-object v0
     67 .end method
     68 
     69 # Returns a method handle to boolean java.lang.Long.compareTo(java.lang.Long other).
     70 .method public static getLongCompareToHandle()Ljava/lang/invoke/MethodHandle;
     71 .registers 4
     72     new-instance v0, Ljava/lang/Long;
     73     const-wide v1, 0
     74     invoke-direct {v0, v1, v2}, Ljava/lang/Long;-><init>(J)V
     75     invoke-virtual {v0}, Ljava/lang/Object;->getClass()Ljava/lang/Class;
     76     move-result-object v0
     77 
     78     # set v0 to Integer.TYPE aka. int.class
     79     sget-object v1, Ljava/lang/Integer;->TYPE:Ljava/lang/Class;
     80 
     81     # Call MethodType.methodType(rtype=int.class, ptype[0] = Long.class)
     82     invoke-static {v1, v0}, Ljava/lang/invoke/MethodType;->methodType(Ljava/lang/Class;Ljava/lang/Class;)Ljava/lang/invoke/MethodType;
     83     move-result-object v2
     84 
     85     const-string v3, "compareTo"
     86     # Call Main.getHandleForVirtual(Long.class, "compareTo", methodType);
     87     invoke-static {v0, v3, v2}, LMain;->getHandleForVirtual(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/MethodHandle;
     88     move-result-object v0
     89     return-object v0
     90 .end method
     91 
     92 # Returns a method handle to static String java.lang.String.valueOf(Object);
     93 .method public static getStringValueOfObjectHandle()Ljava/lang/invoke/MethodHandle;
     94 .registers 4
     95     # set v0 to java.lang.Object.class
     96     new-instance v0, Ljava/lang/Object;
     97     invoke-direct {v0}, Ljava/lang/Object;-><init>()V
     98     invoke-virtual {v0}, Ljava/lang/Object;->getClass()Ljava/lang/Class;
     99     move-result-object v0
    100 
    101     # set v1 to the name of the method ("valueOf") and v2 to java.lang.String.class;
    102     const-string v1, "valueOf"
    103     invoke-virtual {v1}, Ljava/lang/Object;->getClass()Ljava/lang/Class;
    104     move-result-object v2
    105 
    106     # Call MethodType.methodType(rtype=String.class, ptype[0]=Object.class)
    107     invoke-static {v2, v0}, Ljava/lang/invoke/MethodType;->methodType(Ljava/lang/Class;Ljava/lang/Class;)Ljava/lang/invoke/MethodType;
    108     move-result-object v3
    109 
    110     # Call Main.getHandleForStatic(String.class, "valueOf", methodType);
    111     invoke-static {v2, v1, v3}, LMain;->getHandleForStatic(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/MethodHandle;
    112     move-result-object v0
    113     return-object v0
    114 .end method
    115 
    116 # Returns a method handle to static String java.lang.String.valueOf(String);
    117 .method public static getStringValueOfLongHandle()Ljava/lang/invoke/MethodHandle;
    118 .registers 4
    119     # set v0 to Long.TYPE aka. long.class
    120     sget-object v0, Ljava/lang/Long;->TYPE:Ljava/lang/Class;
    121 
    122     # set v1 to the name of the method ("valueOf") and v2 to java.lang.String.class;
    123     const-string v1, "valueOf"
    124     invoke-virtual {v1}, Ljava/lang/Object;->getClass()Ljava/lang/Class;
    125     move-result-object v2
    126 
    127     # Call MethodType.methodType(rtype=String.class, ptype[0]=Long.class)
    128     invoke-static {v2, v0}, Ljava/lang/invoke/MethodType;->methodType(Ljava/lang/Class;Ljava/lang/Class;)Ljava/lang/invoke/MethodType;
    129     move-result-object v3
    130 
    131     # Call Main.getHandleForStatic(String.class, "valueOf", methodType);
    132     invoke-static {v2, v1, v3}, LMain;->getHandleForStatic(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/MethodHandle;
    133     move-result-object v0
    134     return-object v0
    135 .end method
    136 
    137 .method public static main([Ljava/lang/String;)V
    138 .registers 5
    139 
    140     # Test case 1: Exercise String.concat(String, String) which is a virtual method.
    141     invoke-static {}, LMain;->getStringConcatHandle()Ljava/lang/invoke/MethodHandle;
    142     move-result-object v0
    143     const-string v1, "[String1]"
    144     const-string v2, "+[String2]"
    145     invoke-polymorphic {v0, v1, v2}, Ljava/lang/invoke/MethodHandle;->invokeExact([Ljava/lang/Object;)Ljava/lang/Object;, (Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;
    146     move-result-object v3
    147     sget-object v4, Ljava/lang/System;->out:Ljava/io/PrintStream;
    148     invoke-virtual {v4, v3}, Ljava/io/PrintStream;->println(Ljava/lang/String;)V
    149 
    150     # Test case 2: Exercise String.valueOf(Object);
    151     invoke-static {}, LMain;->getStringValueOfObjectHandle()Ljava/lang/invoke/MethodHandle;
    152     move-result-object v0
    153     const-string v1, "[String1]"
    154     invoke-polymorphic {v0, v1}, Ljava/lang/invoke/MethodHandle;->invokeExact([Ljava/lang/Object;)Ljava/lang/Object;, (Ljava/lang/Object;)Ljava/lang/String;
    155     move-result-object v3
    156     sget-object v4, Ljava/lang/System;->out:Ljava/io/PrintStream;
    157     invoke-virtual {v4, v3}, Ljava/io/PrintStream;->println(Ljava/lang/String;)V
    158 
    159     # Test case 3: Exercise String.concat(String, String) with an inexact invoke.
    160     # Note that the callsite type here is String type(Object, Object); so the runtime
    161     # will generate dynamic type checks for the input arguments.
    162     invoke-static {}, LMain;->getStringConcatHandle()Ljava/lang/invoke/MethodHandle;
    163     move-result-object v0
    164     const-string v1, "[String1]"
    165     const-string v2, "+[String2]"
    166     invoke-polymorphic {v0, v1, v2}, Ljava/lang/invoke/MethodHandle;->invoke([Ljava/lang/Object;)Ljava/lang/Object;, (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/String;
    167     move-result-object v3
    168     sget-object v4, Ljava/lang/System;->out:Ljava/io/PrintStream;
    169     invoke-virtual {v4, v3}, Ljava/io/PrintStream;->println(Ljava/lang/String;)V
    170 
    171     # Test case 4: Exercise String.valueOf(long);
    172     #
    173     # We exercise it with various types of unboxing / widening conversions
    174     invoke-static {}, LMain;->getStringValueOfLongHandle()Ljava/lang/invoke/MethodHandle;
    175     move-result-object v0
    176 
    177     # First use a long, this is an invokeExact because the callsite type matches
    178     # the function type precisely.
    179     const-wide v1, 42
    180     invoke-polymorphic {v0, v1, v2}, Ljava/lang/invoke/MethodHandle;->invokeExact([Ljava/lang/Object;)Ljava/lang/Object;, (J)Ljava/lang/String;
    181     move-result-object v3
    182     sget-object v4, Ljava/lang/System;->out:Ljava/io/PrintStream;
    183     invoke-virtual {v4, v3}, Ljava/io/PrintStream;->println(Ljava/lang/String;)V
    184 
    185     # Then use an int, should perform a widening conversion.
    186     const v1, 40
    187     invoke-polymorphic {v0, v1}, Ljava/lang/invoke/MethodHandle;->invoke([Ljava/lang/Object;)Ljava/lang/Object;, (I)Ljava/lang/String;
    188     move-result-object v3
    189     sget-object v4, Ljava/lang/System;->out:Ljava/io/PrintStream;
    190     invoke-virtual {v4, v3}, Ljava/io/PrintStream;->println(Ljava/lang/String;)V
    191 
    192     # Then use a java/lang/Long; - should perform an unboxing conversion.
    193     new-instance v1, Ljava/lang/Long;
    194     const-wide v2, 43
    195     invoke-direct {v1, v2, v3}, Ljava/lang/Long;-><init>(J)V
    196     invoke-polymorphic {v0, v1}, Ljava/lang/invoke/MethodHandle;->invoke([Ljava/lang/Object;)Ljava/lang/Object;, (Ljava/lang/Long;)Ljava/lang/String;
    197     move-result-object v3
    198     sget-object v4, Ljava/lang/System;->out:Ljava/io/PrintStream;
    199     invoke-virtual {v4, v3}, Ljava/io/PrintStream;->println(Ljava/lang/String;)V
    200 
    201     # Then use a java/lang/Integer; - should perform an unboxing in addition to a widening conversion.
    202     new-instance v1, Ljava/lang/Integer;
    203     const v2, 44
    204     invoke-direct {v1, v2}, Ljava/lang/Integer;-><init>(I)V
    205     invoke-polymorphic {v0, v1}, Ljava/lang/invoke/MethodHandle;->invoke([Ljava/lang/Object;)Ljava/lang/Object;, (Ljava/lang/Integer;)Ljava/lang/String;
    206     move-result-object v3
    207     sget-object v4, Ljava/lang/System;->out:Ljava/io/PrintStream;
    208     invoke-virtual {v4, v3}, Ljava/io/PrintStream;->println(Ljava/lang/String;)V
    209 
    210     # Test case 5: Exercise int Long.compareTo(Long)
    211     invoke-static {}, LMain;->getLongCompareToHandle()Ljava/lang/invoke/MethodHandle;
    212     move-result-object v0
    213     new-instance v1, Ljava/lang/Long;
    214     const-wide v2, 43
    215     invoke-direct {v1, v2, v3}, Ljava/lang/Long;-><init>(J)V
    216 
    217     # At this point, v0 is our MethodHandle and v1 is the instance we're going to call compareTo on.
    218 
    219     # Call compareTo(Long) - this is invokeExact semantics.
    220     invoke-polymorphic {v0, v1, v1}, Ljava/lang/invoke/MethodHandle;->invoke([Ljava/lang/Object;)Ljava/lang/Object;, (Ljava/lang/Long;Ljava/lang/Long;)I
    221     move-result v3
    222     sget-object v4, Ljava/lang/System;->out:Ljava/io/PrintStream;
    223     invoke-virtual {v4, v3}, Ljava/io/PrintStream;->println(I)V
    224 
    225     # Call compareTo(long) - this is an implicit box.
    226     const-wide v2, 44
    227     invoke-polymorphic {v0, v1, v2, v3}, Ljava/lang/invoke/MethodHandle;->invoke([Ljava/lang/Object;)Ljava/lang/Object;, (Ljava/lang/Long;J)I
    228     move-result v3
    229     sget-object v4, Ljava/lang/System;->out:Ljava/io/PrintStream;
    230     invoke-virtual {v4, v3}, Ljava/io/PrintStream;->println(I)V
    231 
    232     # Call compareTo(int) - this is an implicit box.
    233 # This throws WrongMethodTypeException as it's a two step conversion int->long->Long or int->Integer->Long.
    234 #    const v2, 40
    235 #    invoke-polymorphic {v0, v1, v2}, Ljava/lang/invoke/MethodHandle;->invoke([Ljava/lang/Object;)Ljava/lang/Object;, (Ljava/lang/Long;I)I
    236 #    move-result v3
    237 #    sget-object v4, Ljava/lang/System;->out:Ljava/io/PrintStream;
    238 #    invoke-virtual {v4, v3}, Ljava/io/PrintStream;->print(I)V
    239 
    240     return-void
    241 .end method
    242