570 lines
20 KiB
Java
570 lines
20 KiB
Java
/*
|
|
* 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());
|
|
}
|
|
}
|
|
}
|