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