blob: 597273c8ecf340035a48c7b25a0923cc5c842e66 [file] [log] [blame]
/*
* 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());
}
}
}