Home | History | Annotate | Download | only in src
      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 
     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     )
     47     private static void setStaticField(int value) {
     48         assertNotReached();
     49     }
     50 
     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     )
     70     private static int getStaticField() {
     71         assertNotReached();
     72         return 0;
     73     }
     74 
     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     )
     93     private static void setInstanceField(TestInvocationKinds instance, double value) {
     94         assertNotReached();
     95         instance.instance_field = Double.NaN;
     96     }
     97 
     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     )
    116     private static double getInstanceField(TestInvocationKinds instance) {
    117         assertNotReached();
    118         return Double.NaN;
    119     }
    120 
    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 
    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 
    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     )
    158     private static int maxIntegerValue(TestInvocationKinds receiver, int x, int y) {
    159         assertNotReached();
    160         return 0;
    161     }
    162 
    163     public int getMaxIntegerValue(int x, int y) {
    164         return x > y ? x : y;
    165     }
    166 
    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         public Widget(int value) {}
    177     }
    178 
    179     private static CallSite lookupConstructor(
    180             MethodHandles.Lookup lookup, String name, MethodType methodType) throws Throwable {
    181         // methodType = (constructorParams);classToBeConstructed
    182         Class<?> cls = methodType.returnType();
    183         MethodType constructorMethodType = methodType.changeReturnType(void.class);
    184         MethodHandle mh = lookup.findConstructor(cls, constructorMethodType);
    185         return new ConstantCallSite(mh);
    186     }
    187 
    188     @CalledByIndy(
    189         bootstrapMethod =
    190                 @BootstrapMethod(
    191                     enclosingType = TestInvocationKinds.class,
    192                     name = "lookupConstructor"
    193                 ),
    194         fieldOrMethodName = "unused",
    195         returnType = Widget.class,
    196         parameterTypes = {int.class}
    197     )
    198     private static Widget makeWidget(int v) {
    199         assertNotReached();
    200         return null;
    201     }
    202 
    203     static void testConstructor() {
    204         System.out.print("testConstructor => ");
    205         Widget receiver = makeWidget(3);
    206         assertEquals(Widget.class, receiver.getClass());
    207         System.out.println(receiver.getClass());
    208     }
    209 
    210     public static void test() {
    211         System.out.println(TestInvocationKinds.class.getName());
    212         testStaticFieldAccessors();
    213         testInstanceFieldAccessors();
    214         testInvokeVirtual();
    215         testConstructor();
    216     }
    217 }
    218