1 /* 2 * Copyright (C) 2018 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 import annotations.BootstrapMethod; 18 import annotations.CalledByIndy; 19 import java.lang.invoke.CallSite; 20 import java.lang.invoke.ConstantCallSite; 21 import java.lang.invoke.MethodHandle; 22 import java.lang.invoke.MethodHandles; 23 import java.lang.invoke.MethodType; 24 25 class TestInvocationKinds extends TestBase { 26 private static int static_field; 27 private double instance_field; 28 lookupStaticFieldGetter( MethodHandles.Lookup lookup, String name, MethodType methodType)29 static CallSite lookupStaticFieldGetter( 30 MethodHandles.Lookup lookup, String name, MethodType methodType) throws Throwable { 31 // methodType = "()LfieldType;" 32 MethodHandle mh = 33 lookup.findStaticGetter(TestInvocationKinds.class, name, methodType.returnType()); 34 return new ConstantCallSite(mh); 35 } 36 37 @CalledByIndy( 38 bootstrapMethod = 39 @BootstrapMethod( 40 enclosingType = TestInvocationKinds.class, 41 name = "lookupStaticFieldSetter" 42 ), 43 fieldOrMethodName = "static_field", 44 returnType = void.class, 45 parameterTypes = {int.class} 46 ) setStaticField(int value)47 private static void setStaticField(int value) { 48 assertNotReached(); 49 } 50 lookupStaticFieldSetter( MethodHandles.Lookup lookup, String name, MethodType methodType)51 static CallSite lookupStaticFieldSetter( 52 MethodHandles.Lookup lookup, String name, MethodType methodType) throws Throwable { 53 // methodType = "(LfieldType;)V" 54 MethodHandle mh = 55 lookup.findStaticSetter( 56 TestInvocationKinds.class, name, methodType.parameterType(0)); 57 return new ConstantCallSite(mh); 58 } 59 60 @CalledByIndy( 61 bootstrapMethod = 62 @BootstrapMethod( 63 enclosingType = TestInvocationKinds.class, 64 name = "lookupStaticFieldGetter" 65 ), 66 fieldOrMethodName = "static_field", 67 returnType = int.class, 68 parameterTypes = {} 69 ) getStaticField()70 private static int getStaticField() { 71 assertNotReached(); 72 return 0; 73 } 74 lookupInstanceFieldSetter( MethodHandles.Lookup lookup, String name, MethodType methodType)75 static CallSite lookupInstanceFieldSetter( 76 MethodHandles.Lookup lookup, String name, MethodType methodType) throws Throwable { 77 // methodType = "(Lreceiver;LfieldType;)V" 78 MethodHandle mh = 79 lookup.findSetter(methodType.parameterType(0), name, methodType.parameterType(1)); 80 return new ConstantCallSite(mh); 81 } 82 83 @CalledByIndy( 84 bootstrapMethod = 85 @BootstrapMethod( 86 enclosingType = TestInvocationKinds.class, 87 name = "lookupInstanceFieldSetter" 88 ), 89 fieldOrMethodName = "instance_field", 90 returnType = void.class, 91 parameterTypes = {TestInvocationKinds.class, double.class} 92 ) setInstanceField(TestInvocationKinds instance, double value)93 private static void setInstanceField(TestInvocationKinds instance, double value) { 94 assertNotReached(); 95 instance.instance_field = Double.NaN; 96 } 97 lookupInstanceFieldGetter( MethodHandles.Lookup lookup, String name, MethodType methodType)98 static CallSite lookupInstanceFieldGetter( 99 MethodHandles.Lookup lookup, String name, MethodType methodType) throws Throwable { 100 // methodType = "(Lreceiver;)LfieldType;" 101 MethodHandle mh = 102 lookup.findGetter(methodType.parameterType(0), name, methodType.returnType()); 103 return new ConstantCallSite(mh); 104 } 105 106 @CalledByIndy( 107 bootstrapMethod = 108 @BootstrapMethod( 109 enclosingType = TestInvocationKinds.class, 110 name = "lookupInstanceFieldGetter" 111 ), 112 fieldOrMethodName = "instance_field", 113 returnType = double.class, 114 parameterTypes = {TestInvocationKinds.class} 115 ) getInstanceField(TestInvocationKinds instance)116 private static double getInstanceField(TestInvocationKinds instance) { 117 assertNotReached(); 118 return Double.NaN; 119 } 120 testStaticFieldAccessors()121 private static void testStaticFieldAccessors() { 122 System.out.println("testStaticFieldAccessors"); 123 setStaticField(3); 124 assertEquals(static_field, 3); 125 setStaticField(4); 126 assertEquals(static_field, 4); 127 assertEquals(static_field, getStaticField()); 128 static_field = Integer.MAX_VALUE; 129 assertEquals(Integer.MAX_VALUE, getStaticField()); 130 } 131 testInstanceFieldAccessors()132 private static void testInstanceFieldAccessors() { 133 System.out.println("testInstanceFieldAccessors"); 134 TestInvocationKinds instance = new TestInvocationKinds(); 135 instance.instance_field = Double.MIN_VALUE; 136 setInstanceField(instance, Math.PI); 137 assertEquals(Math.PI, instance.instance_field); 138 instance.instance_field = Math.E; 139 assertEquals(Math.E, getInstanceField(instance)); 140 } 141 lookupVirtual( MethodHandles.Lookup lookup, String name, MethodType methodType)142 private static CallSite lookupVirtual( 143 MethodHandles.Lookup lookup, String name, MethodType methodType) throws Throwable { 144 // To get the point-of-use and invokedynamic to work the methodType here has the 145 // receiver type as the leading paramter which needs to be dropped for findVirtual(). 146 MethodType mt = methodType.dropParameterTypes(0, 1); 147 MethodHandle mh = lookup.findVirtual(TestInvocationKinds.class, name, mt); 148 return new ConstantCallSite(mh); 149 } 150 151 @CalledByIndy( 152 bootstrapMethod = 153 @BootstrapMethod(enclosingType = TestInvocationKinds.class, name = "lookupVirtual"), 154 fieldOrMethodName = "getMaxIntegerValue", 155 returnType = int.class, 156 parameterTypes = {TestInvocationKinds.class, int.class, int.class} 157 ) maxIntegerValue(TestInvocationKinds receiver, int x, int y)158 private static int maxIntegerValue(TestInvocationKinds receiver, int x, int y) { 159 assertNotReached(); 160 return 0; 161 } 162 getMaxIntegerValue(int x, int y)163 public int getMaxIntegerValue(int x, int y) { 164 return x > y ? x : y; 165 } 166 testInvokeVirtual()167 static void testInvokeVirtual() { 168 System.out.print("testInvokeVirtual => max(77, -3) = "); 169 TestInvocationKinds receiver = new TestInvocationKinds(); 170 int result = maxIntegerValue(receiver, 77, -3); 171 System.out.println(result); 172 } 173 174 static class Widget { 175 int value; 176 Widget(int value)177 public Widget(int value) {} 178 } 179 lookupConstructor( MethodHandles.Lookup lookup, String name, MethodType methodType)180 private static CallSite lookupConstructor( 181 MethodHandles.Lookup lookup, String name, MethodType methodType) throws Throwable { 182 // methodType = (constructorParams);classToBeConstructed 183 Class<?> cls = methodType.returnType(); 184 MethodType constructorMethodType = methodType.changeReturnType(void.class); 185 MethodHandle mh = lookup.findConstructor(cls, constructorMethodType); 186 return new ConstantCallSite(mh); 187 } 188 189 @CalledByIndy( 190 bootstrapMethod = 191 @BootstrapMethod( 192 enclosingType = TestInvocationKinds.class, 193 name = "lookupConstructor" 194 ), 195 fieldOrMethodName = "unused", 196 returnType = Widget.class, 197 parameterTypes = {int.class} 198 ) makeWidget(int v)199 private static Widget makeWidget(int v) { 200 assertNotReached(); 201 return null; 202 } 203 testConstructor()204 static void testConstructor() { 205 System.out.print("testConstructor => "); 206 Widget receiver = makeWidget(3); 207 assertEquals(Widget.class, receiver.getClass()); 208 System.out.println(receiver.getClass()); 209 } 210 test()211 public static void test() { 212 System.out.println(TestInvocationKinds.class.getName()); 213 testStaticFieldAccessors(); 214 testInstanceFieldAccessors(); 215 testInvokeVirtual(); 216 testConstructor(); 217 } 218 } 219