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