| /* |
| * 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 annotations.Constant; |
| 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; |
| import java.util.Arrays; |
| |
| public class TestVariableArityLinkerMethod extends TestBase { |
| private static void printBsmArgs(String method, Object... args) { |
| System.out.print(method); |
| System.out.print("("); |
| for (int i = 0; i < args.length; ++i) { |
| if (i != 0) { |
| System.out.print(", "); |
| } |
| if (args[i] != null && args[i].getClass().isArray()) { |
| Object array = args[i]; |
| if (array.getClass() == int[].class) { |
| System.out.print(Arrays.toString((int[]) array)); |
| } else if (array.getClass() == long[].class) { |
| System.out.print(Arrays.toString((long[]) array)); |
| } else if (array.getClass() == float[].class) { |
| System.out.print(Arrays.toString((float[]) array)); |
| } else if (array.getClass() == double[].class) { |
| System.out.print(Arrays.toString((double[]) array)); |
| } else { |
| System.out.print(Arrays.toString((Object[]) array)); |
| } |
| } else { |
| System.out.print(args[i]); |
| } |
| } |
| System.out.println(");"); |
| } |
| |
| private static CallSite bsmWithStringArray( |
| MethodHandles.Lookup lookup, |
| String methodName, |
| MethodType methodType, |
| String... arityArgs) |
| throws Throwable { |
| printBsmArgs("bsmWithStringArray", lookup, methodName, methodType, arityArgs); |
| MethodHandle mh = lookup.findStatic(lookup.lookupClass(), methodName, methodType); |
| return new ConstantCallSite(mh); |
| } |
| |
| @CalledByIndy( |
| bootstrapMethod = |
| @BootstrapMethod( |
| enclosingType = TestVariableArityLinkerMethod.class, |
| name = "bsmWithStringArray", |
| parameterTypes = { |
| MethodHandles.Lookup.class, |
| String.class, |
| MethodType.class, |
| String[].class |
| } |
| ), |
| fieldOrMethodName = "methodA", |
| constantArgumentsForBootstrapMethod = { |
| @Constant(stringValue = "Aachen"), |
| @Constant(stringValue = "Aalborg"), |
| @Constant(stringValue = "Aalto") |
| } |
| ) |
| private static void methodA() { |
| System.out.println("methodA"); |
| } |
| |
| @CalledByIndy( |
| bootstrapMethod = |
| @BootstrapMethod( |
| enclosingType = TestVariableArityLinkerMethod.class, |
| name = "bsmWithStringArray", |
| parameterTypes = { |
| MethodHandles.Lookup.class, |
| String.class, |
| MethodType.class, |
| String[].class |
| } |
| ), |
| fieldOrMethodName = "methodB", |
| constantArgumentsForBootstrapMethod = {@Constant(stringValue = "barium")} |
| ) |
| private static void methodB() { |
| System.out.println("methodB"); |
| } |
| |
| @CalledByIndy( |
| bootstrapMethod = |
| @BootstrapMethod( |
| enclosingType = TestVariableArityLinkerMethod.class, |
| name = "bsmWithStringArray", |
| parameterTypes = { |
| MethodHandles.Lookup.class, |
| String.class, |
| MethodType.class, |
| String[].class |
| } |
| ), |
| fieldOrMethodName = "methodC" |
| ) |
| private static void methodC() { |
| System.out.println("methodC"); |
| } |
| |
| private static CallSite bsmWithIntAndStringArray( |
| MethodHandles.Lookup lookup, |
| String methodName, |
| MethodType methodType, |
| int extraInt, |
| String... extraArityArgs) |
| throws Throwable { |
| printBsmArgs( |
| "bsmWithIntAndStringArray", |
| lookup, |
| methodName, |
| methodType, |
| extraInt, |
| extraArityArgs); |
| MethodHandle mh = lookup.findStatic(lookup.lookupClass(), methodName, methodType); |
| return new ConstantCallSite(mh); |
| } |
| |
| @CalledByIndy( |
| bootstrapMethod = |
| @BootstrapMethod( |
| enclosingType = TestVariableArityLinkerMethod.class, |
| name = "bsmWithIntAndStringArray", |
| parameterTypes = { |
| MethodHandles.Lookup.class, |
| String.class, |
| MethodType.class, |
| int.class, |
| String[].class |
| } |
| ), |
| fieldOrMethodName = "methodD", |
| constantArgumentsForBootstrapMethod = { |
| @Constant(intValue = 101), |
| @Constant(stringValue = "zoo"), |
| @Constant(stringValue = "zoogene"), |
| @Constant(stringValue = "zoogenic") |
| } |
| ) |
| private static void methodD() { |
| System.out.println("methodD"); |
| } |
| |
| @CalledByIndy( |
| bootstrapMethod = |
| @BootstrapMethod( |
| enclosingType = TestVariableArityLinkerMethod.class, |
| name = "bsmWithIntAndStringArray", |
| parameterTypes = { |
| MethodHandles.Lookup.class, |
| String.class, |
| MethodType.class, |
| int.class, |
| String[].class |
| } |
| ), |
| fieldOrMethodName = "methodE", |
| constantArgumentsForBootstrapMethod = { |
| @Constant(intValue = 102), |
| @Constant(stringValue = "zonic") |
| } |
| ) |
| private static void methodE() { |
| System.out.println("methodE"); |
| } |
| |
| @CalledByIndy( |
| bootstrapMethod = |
| @BootstrapMethod( |
| enclosingType = TestVariableArityLinkerMethod.class, |
| name = "bsmWithIntAndStringArray", |
| parameterTypes = { |
| MethodHandles.Lookup.class, |
| String.class, |
| MethodType.class, |
| int.class, |
| String[].class |
| } |
| ), |
| fieldOrMethodName = "methodF", |
| constantArgumentsForBootstrapMethod = {@Constant(intValue = 103)} |
| ) |
| private static void methodF() { |
| System.out.println("methodF"); |
| } |
| |
| private static CallSite bsmWithLongAndIntArray( |
| MethodHandles.Lookup lookup, |
| String methodName, |
| MethodType methodType, |
| long extraArg, |
| int... arityArgs) |
| throws Throwable { |
| printBsmArgs("bsmWithLongAndIntArray", lookup, methodName, methodType, extraArg, arityArgs); |
| MethodHandle mh = lookup.findStatic(lookup.lookupClass(), methodName, methodType); |
| return new ConstantCallSite(mh); |
| } |
| |
| @CalledByIndy( |
| bootstrapMethod = |
| @BootstrapMethod( |
| enclosingType = TestVariableArityLinkerMethod.class, |
| name = "bsmWithLongAndIntArray", |
| parameterTypes = { |
| MethodHandles.Lookup.class, |
| String.class, |
| MethodType.class, |
| long.class, |
| int[].class |
| } |
| ), |
| fieldOrMethodName = "methodG", |
| constantArgumentsForBootstrapMethod = { |
| @Constant(longValue = 0x123456789abcdefl), |
| @Constant(intValue = +1), |
| @Constant(intValue = -1), |
| @Constant(intValue = +2), |
| @Constant(intValue = -2) |
| } |
| ) |
| private static void methodG() { |
| System.out.println("methodG"); |
| } |
| |
| private static CallSite bsmWithFloatAndLongArray( |
| MethodHandles.Lookup lookup, |
| String methodName, |
| MethodType methodType, |
| float extraArg, |
| long... arityArgs) |
| throws Throwable { |
| printBsmArgs( |
| "bsmWithFloatAndLongArray", lookup, methodName, methodType, extraArg, arityArgs); |
| MethodHandle mh = lookup.findStatic(lookup.lookupClass(), methodName, methodType); |
| return new ConstantCallSite(mh); |
| } |
| |
| @CalledByIndy( |
| bootstrapMethod = |
| @BootstrapMethod( |
| enclosingType = TestVariableArityLinkerMethod.class, |
| name = "bsmWithFloatAndLongArray", |
| parameterTypes = { |
| MethodHandles.Lookup.class, |
| String.class, |
| MethodType.class, |
| float.class, |
| long[].class |
| } |
| ), |
| fieldOrMethodName = "methodH", |
| constantArgumentsForBootstrapMethod = { |
| @Constant(floatValue = (float) -Math.E), |
| @Constant(longValue = 999999999999l), |
| @Constant(longValue = -8888888888888l) |
| } |
| ) |
| private static void methodH() { |
| System.out.println("methodH"); |
| } |
| |
| private static CallSite bsmWithClassAndFloatArray( |
| MethodHandles.Lookup lookup, |
| String methodName, |
| MethodType methodType, |
| Class<?> extraArg, |
| float... arityArgs) |
| throws Throwable { |
| printBsmArgs( |
| "bsmWithClassAndFloatArray", lookup, methodName, methodType, extraArg, arityArgs); |
| MethodHandle mh = lookup.findStatic(lookup.lookupClass(), methodName, methodType); |
| return new ConstantCallSite(mh); |
| } |
| |
| @CalledByIndy( |
| bootstrapMethod = |
| @BootstrapMethod( |
| enclosingType = TestVariableArityLinkerMethod.class, |
| name = "bsmWithClassAndFloatArray", |
| parameterTypes = { |
| MethodHandles.Lookup.class, |
| String.class, |
| MethodType.class, |
| Class.class, |
| float[].class |
| } |
| ), |
| fieldOrMethodName = "methodI", |
| constantArgumentsForBootstrapMethod = { |
| @Constant(classValue = Throwable.class), |
| @Constant(floatValue = Float.MAX_VALUE), |
| @Constant(floatValue = Float.MIN_VALUE), |
| @Constant(floatValue = (float) Math.PI), |
| @Constant(floatValue = (float) -Math.PI) |
| } |
| ) |
| private static void methodI() { |
| System.out.println("methodI"); |
| } |
| |
| private static CallSite bsmWithDoubleArray( |
| MethodHandles.Lookup lookup, |
| String methodName, |
| MethodType methodType, |
| double... arityArgs) |
| throws Throwable { |
| printBsmArgs("bsmWithDoubleArray", lookup, methodName, methodType, arityArgs); |
| MethodHandle mh = lookup.findStatic(lookup.lookupClass(), methodName, methodType); |
| return new ConstantCallSite(mh); |
| } |
| |
| @CalledByIndy( |
| bootstrapMethod = |
| @BootstrapMethod( |
| enclosingType = TestVariableArityLinkerMethod.class, |
| name = "bsmWithDoubleArray", |
| parameterTypes = { |
| MethodHandles.Lookup.class, |
| String.class, |
| MethodType.class, |
| double[].class |
| } |
| ), |
| fieldOrMethodName = "methodJ", |
| constantArgumentsForBootstrapMethod = { |
| @Constant(doubleValue = Double.MAX_VALUE), |
| @Constant(doubleValue = Double.MIN_VALUE), |
| @Constant(doubleValue = Math.E), |
| @Constant(doubleValue = -Math.PI) |
| } |
| ) |
| private static void methodJ() { |
| System.out.println("methodJ"); |
| } |
| |
| private static CallSite bsmWithClassArray( |
| MethodHandles.Lookup lookup, |
| String methodName, |
| MethodType methodType, |
| Class... arityArgs) |
| throws Throwable { |
| printBsmArgs("bsmWithClassArray", lookup, methodName, methodType, arityArgs); |
| MethodHandle mh = lookup.findStatic(lookup.lookupClass(), methodName, methodType); |
| return new ConstantCallSite(mh); |
| } |
| |
| @CalledByIndy( |
| bootstrapMethod = |
| @BootstrapMethod( |
| enclosingType = TestVariableArityLinkerMethod.class, |
| name = "bsmWithClassArray", |
| parameterTypes = { |
| MethodHandles.Lookup.class, |
| String.class, |
| MethodType.class, |
| Class[].class |
| } |
| ), |
| fieldOrMethodName = "methodK", |
| constantArgumentsForBootstrapMethod = { |
| @Constant(classValue = Integer.class), |
| @Constant(classValue = MethodHandles.class), |
| @Constant(classValue = Arrays.class) |
| } |
| ) |
| private static void methodK() { |
| System.out.println("methodK"); |
| } |
| |
| @CalledByIndy( |
| bootstrapMethod = |
| @BootstrapMethod( |
| enclosingType = TestVariableArityLinkerMethod.class, |
| name = "bsmWithIntAndStringArray", |
| parameterTypes = { |
| MethodHandles.Lookup.class, |
| String.class, |
| MethodType.class, |
| int.class, |
| String[].class |
| } |
| ), |
| fieldOrMethodName = "methodO", |
| constantArgumentsForBootstrapMethod = {@Constant(intValue = 103), @Constant(intValue = 104)} |
| ) |
| private static void methodO() { |
| // Arguments are not compatible |
| assertNotReached(); |
| } |
| |
| @CalledByIndy( |
| bootstrapMethod = |
| @BootstrapMethod( |
| enclosingType = TestVariableArityLinkerMethod.class, |
| name = "bsmWithIntAndStringArray", |
| parameterTypes = { |
| MethodHandles.Lookup.class, |
| String.class, |
| MethodType.class, |
| int.class, |
| String[].class |
| } |
| ), |
| fieldOrMethodName = "methodP", |
| constantArgumentsForBootstrapMethod = { |
| @Constant(intValue = 103), |
| @Constant(stringValue = "A"), |
| @Constant(stringValue = "B"), |
| @Constant(intValue = 42) |
| } |
| ) |
| private static void methodP() { |
| // Arguments are not compatible - specifically, the third |
| // component of potential collector array is an integer |
| // argument (42). |
| assertNotReached(); |
| } |
| |
| private static CallSite bsmWithWiderArray( |
| MethodHandles.Lookup lookup, String methodName, MethodType methodType, long[] extraArgs) |
| throws Throwable { |
| printBsmArgs("bsmWithWiderArray", lookup, methodName, methodType, extraArgs); |
| MethodHandle mh = lookup.findStatic(lookup.lookupClass(), methodName, methodType); |
| return new ConstantCallSite(mh); |
| } |
| |
| @CalledByIndy( |
| bootstrapMethod = |
| @BootstrapMethod( |
| enclosingType = TestVariableArityLinkerMethod.class, |
| name = "bsmWithWiderArray", |
| parameterTypes = { |
| MethodHandles.Lookup.class, |
| String.class, |
| MethodType.class, |
| long[].class |
| } |
| ), |
| fieldOrMethodName = "methodQ", |
| constantArgumentsForBootstrapMethod = {@Constant(intValue = 103), @Constant(intValue = 42)} |
| ) |
| private static void methodQ() { |
| assertNotReached(); |
| } |
| |
| private static CallSite bsmWithBoxedArray( |
| MethodHandles.Lookup lookup, |
| String methodName, |
| MethodType methodType, |
| Integer[] extraArgs) |
| throws Throwable { |
| printBsmArgs("bsmWithBoxedArray", lookup, methodName, methodType, extraArgs); |
| MethodHandle mh = lookup.findStatic(lookup.lookupClass(), methodName, methodType); |
| return new ConstantCallSite(mh); |
| } |
| |
| @CalledByIndy( |
| bootstrapMethod = |
| @BootstrapMethod( |
| enclosingType = TestVariableArityLinkerMethod.class, |
| name = "bsmWithBoxedArray", |
| parameterTypes = { |
| MethodHandles.Lookup.class, |
| String.class, |
| MethodType.class, |
| Integer[].class |
| } |
| ), |
| fieldOrMethodName = "methodR", |
| constantArgumentsForBootstrapMethod = { |
| @Constant(intValue = 1030), |
| @Constant(intValue = 420) |
| } |
| ) |
| private static void methodR() { |
| assertNotReached(); |
| } |
| |
| static void test() { |
| // Happy cases |
| for (int i = 0; i < 2; ++i) { |
| methodA(); |
| methodB(); |
| methodC(); |
| } |
| for (int i = 0; i < 2; ++i) { |
| methodD(); |
| methodE(); |
| methodF(); |
| } |
| methodG(); |
| methodH(); |
| methodI(); |
| methodJ(); |
| methodK(); |
| |
| // Broken cases |
| try { |
| // bsm has incompatible static methods. Collector |
| // component type is String, the corresponding static |
| // arguments are int values. |
| methodO(); |
| assertNotReached(); |
| } catch (BootstrapMethodError expected) { |
| System.out.print("methodO => "); |
| System.out.print(expected.getClass()); |
| System.out.print(" => "); |
| System.out.println(expected.getCause().getClass()); |
| } |
| try { |
| // bsm has a trailing String array for the collector array. |
| // There is an int value amongst the String values. |
| methodP(); |
| assertNotReached(); |
| } catch (BootstrapMethodError expected) { |
| System.out.print("methodP => "); |
| System.out.print(expected.getClass()); |
| System.out.print(" => "); |
| System.out.println(expected.getCause().getClass()); |
| } |
| try { |
| // bsm has as trailing long[] element for the collector array. |
| // The corresponding static bsm arguments are of type int. |
| methodQ(); |
| assertNotReached(); |
| } catch (BootstrapMethodError expected) { |
| System.out.print("methodQ => "); |
| System.out.print(expected.getClass()); |
| System.out.print(" => "); |
| System.out.println(expected.getCause().getClass()); |
| } |
| try { |
| // bsm has as trailing Integer[] element for the collector array. |
| // The corresponding static bsm arguments are of type int. |
| methodR(); |
| assertNotReached(); |
| } catch (BootstrapMethodError expected) { |
| System.out.print("methodR => "); |
| System.out.print(expected.getClass()); |
| System.out.print(" => "); |
| System.out.println(expected.getCause().getClass()); |
| } |
| } |
| } |