/* * Copyright (C) 2018 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ import annotations.BootstrapMethod; import annotations.CalledByIndy; import java.lang.invoke.CallSite; import java.lang.invoke.ConstantCallSite; import java.lang.invoke.MethodHandle; import java.lang.invoke.MethodHandles; import java.lang.invoke.MethodType; class TestInvocationKinds extends TestBase { private static int static_field; private double instance_field; static CallSite lookupStaticFieldGetter( MethodHandles.Lookup lookup, String name, MethodType methodType) throws Throwable { // methodType = "()LfieldType;" MethodHandle mh = lookup.findStaticGetter(TestInvocationKinds.class, name, methodType.returnType()); return new ConstantCallSite(mh); } @CalledByIndy( bootstrapMethod = @BootstrapMethod( enclosingType = TestInvocationKinds.class, name = "lookupStaticFieldSetter" ), fieldOrMethodName = "static_field", returnType = void.class, parameterTypes = {int.class} ) private static void setStaticField(int value) { assertNotReached(); } static CallSite lookupStaticFieldSetter( MethodHandles.Lookup lookup, String name, MethodType methodType) throws Throwable { // methodType = "(LfieldType;)V" MethodHandle mh = lookup.findStaticSetter( TestInvocationKinds.class, name, methodType.parameterType(0)); return new ConstantCallSite(mh); } @CalledByIndy( bootstrapMethod = @BootstrapMethod( enclosingType = TestInvocationKinds.class, name = "lookupStaticFieldGetter" ), fieldOrMethodName = "static_field", returnType = int.class, parameterTypes = {} ) private static int getStaticField() { assertNotReached(); return 0; } static CallSite lookupInstanceFieldSetter( MethodHandles.Lookup lookup, String name, MethodType methodType) throws Throwable { // methodType = "(Lreceiver;LfieldType;)V" MethodHandle mh = lookup.findSetter(methodType.parameterType(0), name, methodType.parameterType(1)); return new ConstantCallSite(mh); } @CalledByIndy( bootstrapMethod = @BootstrapMethod( enclosingType = TestInvocationKinds.class, name = "lookupInstanceFieldSetter" ), fieldOrMethodName = "instance_field", returnType = void.class, parameterTypes = {TestInvocationKinds.class, double.class} ) private static void setInstanceField(TestInvocationKinds instance, double value) { assertNotReached(); instance.instance_field = Double.NaN; } static CallSite lookupInstanceFieldGetter( MethodHandles.Lookup lookup, String name, MethodType methodType) throws Throwable { // methodType = "(Lreceiver;)LfieldType;" MethodHandle mh = lookup.findGetter(methodType.parameterType(0), name, methodType.returnType()); return new ConstantCallSite(mh); } @CalledByIndy( bootstrapMethod = @BootstrapMethod( enclosingType = TestInvocationKinds.class, name = "lookupInstanceFieldGetter" ), fieldOrMethodName = "instance_field", returnType = double.class, parameterTypes = {TestInvocationKinds.class} ) private static double getInstanceField(TestInvocationKinds instance) { assertNotReached(); return Double.NaN; } private static void testStaticFieldAccessors() { System.out.println("testStaticFieldAccessors"); setStaticField(3); assertEquals(static_field, 3); setStaticField(4); assertEquals(static_field, 4); assertEquals(static_field, getStaticField()); static_field = Integer.MAX_VALUE; assertEquals(Integer.MAX_VALUE, getStaticField()); } private static void testInstanceFieldAccessors() { System.out.println("testInstanceFieldAccessors"); TestInvocationKinds instance = new TestInvocationKinds(); instance.instance_field = Double.MIN_VALUE; setInstanceField(instance, Math.PI); assertEquals(Math.PI, instance.instance_field); instance.instance_field = Math.E; assertEquals(Math.E, getInstanceField(instance)); } private static CallSite lookupVirtual( MethodHandles.Lookup lookup, String name, MethodType methodType) throws Throwable { // To get the point-of-use and invokedynamic to work the methodType here has the // receiver type as the leading paramter which needs to be dropped for findVirtual(). MethodType mt = methodType.dropParameterTypes(0, 1); MethodHandle mh = lookup.findVirtual(TestInvocationKinds.class, name, mt); return new ConstantCallSite(mh); } @CalledByIndy( bootstrapMethod = @BootstrapMethod(enclosingType = TestInvocationKinds.class, name = "lookupVirtual"), fieldOrMethodName = "getMaxIntegerValue", returnType = int.class, parameterTypes = {TestInvocationKinds.class, int.class, int.class} ) private static int maxIntegerValue(TestInvocationKinds receiver, int x, int y) { assertNotReached(); return 0; } public int getMaxIntegerValue(int x, int y) { return x > y ? x : y; } static void testInvokeVirtual() { System.out.print("testInvokeVirtual => max(77, -3) = "); TestInvocationKinds receiver = new TestInvocationKinds(); int result = maxIntegerValue(receiver, 77, -3); System.out.println(result); } static class Widget { int value; public Widget(int value) {} } private static CallSite lookupConstructor( MethodHandles.Lookup lookup, String name, MethodType methodType) throws Throwable { // methodType = (constructorParams);classToBeConstructed Class cls = methodType.returnType(); MethodType constructorMethodType = methodType.changeReturnType(void.class); MethodHandle mh = lookup.findConstructor(cls, constructorMethodType); return new ConstantCallSite(mh); } @CalledByIndy( bootstrapMethod = @BootstrapMethod( enclosingType = TestInvocationKinds.class, name = "lookupConstructor" ), fieldOrMethodName = "unused", returnType = Widget.class, parameterTypes = {int.class} ) private static Widget makeWidget(int v) { assertNotReached(); return null; } static void testConstructor() { System.out.print("testConstructor => "); Widget receiver = makeWidget(3); assertEquals(Widget.class, receiver.getClass()); System.out.println(receiver.getClass()); } public static void test() { System.out.println(TestInvocationKinds.class.getName()); testStaticFieldAccessors(); testInstanceFieldAccessors(); testInvokeVirtual(); testConstructor(); } }