summaryrefslogtreecommitdiff
path: root/test
diff options
context:
space:
mode:
Diffstat (limited to 'test')
-rw-r--r--test/952-invoke-custom/expected.txt64
-rw-r--r--test/952-invoke-custom/src/Main.java11
-rw-r--r--test/952-invoke-custom/src/TestBadBootstrapArguments.java583
-rw-r--r--test/952-invoke-custom/src/TestDynamicBootstrapArguments.java92
-rw-r--r--test/952-invoke-custom/src/TestInvocationKinds.java1
-rw-r--r--test/952-invoke-custom/src/TestVariableArityLinkerMethod.java569
-rw-r--r--test/knownfailures.json1
7 files changed, 1313 insertions, 8 deletions
diff --git a/test/952-invoke-custom/expected.txt b/test/952-invoke-custom/expected.txt
index 767cc7e734..7e8ffa6f41 100644
--- a/test/952-invoke-custom/expected.txt
+++ b/test/952-invoke-custom/expected.txt
@@ -18,3 +18,67 @@ testStaticFieldAccessors
testInstanceFieldAccessors
testInvokeVirtual => max(77, -3) = 77
testConstructor => class TestInvocationKinds$Widget
+TestDynamicArguments
+bsm
+0, One, 3.141592653589793
+bsm
+1, Two, 2.718281828459045
+bsm
+2, Three, 0.0
+0, One, 3.141592653589793
+1, Two, 2.718281828459045
+2, Three, 0.0
+TestBadBootstrapArguments
+bsm(class TestBadBootstrapArguments, happy, ()void, -1, very)
+happy
+invokeWrongParameterTypes => class java.lang.NoSuchMethodError
+invokeMissingParameterTypes => class java.lang.NoSuchMethodError
+invokeExtraArguments => class java.lang.BootstrapMethodError => class java.lang.invoke.WrongMethodTypeException
+invokeWrongArguments => class java.lang.BootstrapMethodError => class java.lang.ClassCastException
+invokeWrongArguments => class java.lang.BootstrapMethodError => class java.lang.ClassCastException
+invokeWrongArgumentsAgain => class java.lang.BootstrapMethodError => class java.lang.ClassCastException
+invokeNarrowArguments => class java.lang.BootstrapMethodError => class java.lang.ClassCastException
+bsmDJ(..., 1.7976931348623157E308, 2147483647)
+wideningArguments
+bsmDoubleLong(..., 1.7976931348623157E308, 9223372036854775807)
+boxingArguments
+invokeWideningBoxingArguments => class java.lang.BootstrapMethodError => class java.lang.ClassCastException
+bsm returning void value.
+invokeVoidReturnType() => class java.lang.BootstrapMethodError => class java.lang.ClassCastException
+bsm returning Object value.
+invokeObjectReturnType() => class java.lang.BootstrapMethodError => class java.lang.ClassCastException
+bsm returning Integer value.
+invokeIntegerReturnType() => class java.lang.BootstrapMethodError => class java.lang.ClassCastException
+Hello!
+bsmWithStringArray(TestVariableArityLinkerMethod, methodA, ()void, [Aachen, Aalborg, Aalto]);
+methodA
+bsmWithStringArray(TestVariableArityLinkerMethod, methodB, ()void, [barium]);
+methodB
+bsmWithStringArray(TestVariableArityLinkerMethod, methodC, ()void, []);
+methodC
+methodA
+methodB
+methodC
+bsmWithIntAndStringArray(TestVariableArityLinkerMethod, methodD, ()void, 101, [zoo, zoogene, zoogenic]);
+methodD
+bsmWithIntAndStringArray(TestVariableArityLinkerMethod, methodE, ()void, 102, [zonic]);
+methodE
+bsmWithIntAndStringArray(TestVariableArityLinkerMethod, methodF, ()void, 103, []);
+methodF
+methodD
+methodE
+methodF
+bsmWithLongAndIntArray(TestVariableArityLinkerMethod, methodG, ()void, 81985529216486895, [1, -1, 2, -2]);
+methodG
+bsmWithFloatAndLongArray(TestVariableArityLinkerMethod, methodH, ()void, -2.7182817, [999999999999, -8888888888888]);
+methodH
+bsmWithClassAndFloatArray(TestVariableArityLinkerMethod, methodI, ()void, class java.lang.Throwable, [3.4028235E38, 1.4E-45, 3.1415927, -3.1415927]);
+methodI
+bsmWithDoubleArray(TestVariableArityLinkerMethod, methodJ, ()void, [1.7976931348623157E308, 4.9E-324, 2.718281828459045, -3.141592653589793]);
+methodJ
+bsmWithClassArray(TestVariableArityLinkerMethod, methodK, ()void, [class java.lang.Integer, class java.lang.invoke.MethodHandles, class java.util.Arrays]);
+methodK
+methodO => class java.lang.BootstrapMethodError => class java.lang.ClassCastException
+methodP => class java.lang.BootstrapMethodError => class java.lang.ClassCastException
+methodQ => class java.lang.BootstrapMethodError => class java.lang.invoke.WrongMethodTypeException
+methodR => class java.lang.BootstrapMethodError => class java.lang.invoke.WrongMethodTypeException
diff --git a/test/952-invoke-custom/src/Main.java b/test/952-invoke-custom/src/Main.java
index 0b1c1fffe5..d2250a9647 100644
--- a/test/952-invoke-custom/src/Main.java
+++ b/test/952-invoke-custom/src/Main.java
@@ -74,18 +74,15 @@ public class Main extends TestBase {
TestLinkerMethodMinimalArguments.FAILURE_TYPE_NONE, 10, 13);
}
- private static void TestInvokeCustomWithConcurrentThreads() throws Throwable {
- // This is a concurrency test that attempts to run invoke-custom on the same
- // call site.
- TestInvokeCustomWithConcurrentThreads.test();
- }
-
public static void main(String[] args) throws Throwable {
TestUninitializedCallSite();
TestLinkerMethodMinimalArguments();
TestLinkerMethodMultipleArgumentTypes();
TestLinkerUnrelatedBSM.test();
- TestInvokeCustomWithConcurrentThreads();
+ TestInvokeCustomWithConcurrentThreads.test();
TestInvocationKinds.test();
+ TestDynamicBootstrapArguments.test();
+ TestBadBootstrapArguments.test();
+ TestVariableArityLinkerMethod.test();
}
}
diff --git a/test/952-invoke-custom/src/TestBadBootstrapArguments.java b/test/952-invoke-custom/src/TestBadBootstrapArguments.java
new file mode 100644
index 0000000000..25d8b59eaa
--- /dev/null
+++ b/test/952-invoke-custom/src/TestBadBootstrapArguments.java
@@ -0,0 +1,583 @@
+/*
+ * 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.lang.invoke.WrongMethodTypeException;
+
+public class TestBadBootstrapArguments extends TestBase {
+ private static CallSite bsm(
+ MethodHandles.Lookup lookup,
+ String methodName,
+ MethodType methodType,
+ int extraInt,
+ String extraString)
+ throws Throwable {
+ System.out.print("bsm(");
+ System.out.print(lookup.lookupClass());
+ System.out.print(", ");
+ System.out.print(methodName);
+ System.out.print(", ");
+ System.out.print(methodType);
+ System.out.print(", ");
+ System.out.print(extraInt);
+ System.out.print(", ");
+ System.out.print(extraString);
+ System.out.println(")");
+ MethodHandle mh = lookup.findStatic(lookup.lookupClass(), methodName, methodType);
+ return new ConstantCallSite(mh);
+ }
+
+ @CalledByIndy(
+ bootstrapMethod =
+ @BootstrapMethod(
+ enclosingType = TestBadBootstrapArguments.class,
+ name = "bsm",
+ parameterTypes = {
+ MethodHandles.Lookup.class,
+ String.class,
+ MethodType.class,
+ int.class,
+ String.class
+ }
+ ),
+ fieldOrMethodName = "happy",
+ constantArgumentsForBootstrapMethod = {
+ @Constant(intValue = -1),
+ @Constant(stringValue = "very")
+ }
+ )
+ private static void invokeHappy() {
+ assertNotReached();
+ }
+
+ private static void happy() {
+ System.out.println("happy");
+ }
+
+ // BootstrapMethod.parameterTypes != parameterTypesOf(constantArgumentsForBootstrapMethod)
+ @CalledByIndy(
+ bootstrapMethod =
+ @BootstrapMethod(
+ enclosingType = TestBadBootstrapArguments.class,
+ name = "bsm",
+ parameterTypes = {
+ MethodHandles.Lookup.class,
+ String.class,
+ MethodType.class,
+ int.class,
+ double.class
+ }
+ ),
+ fieldOrMethodName = "wrongParameterTypes",
+ constantArgumentsForBootstrapMethod = {
+ @Constant(intValue = -1),
+ @Constant(stringValue = "very")
+ }
+ )
+ private static void invokeWrongParameterTypes() throws NoSuchMethodError {
+ assertNotReached();
+ }
+
+ private static void wrongParameterTypes() {
+ System.out.println("wrongParameterTypes");
+ }
+
+ // BootstrapMethod.parameterTypes != parameterTypesOf(constantArgumentsForBootstrapMethod)
+ // (missing constantArgumentTypes))
+ @CalledByIndy(
+ bootstrapMethod =
+ @BootstrapMethod(
+ enclosingType = TestBadBootstrapArguments.class,
+ name = "bsm",
+ parameterTypes = {
+ MethodHandles.Lookup.class,
+ String.class,
+ MethodType.class,
+ int.class,
+ double.class
+ }
+ ),
+ fieldOrMethodName = "missingParameterTypes",
+ constantArgumentsForBootstrapMethod = {}
+ )
+ private static void invokeMissingParameterTypes() throws NoSuchMethodError {
+ assertNotReached();
+ }
+
+ private static void missingParameterTypes() {
+ System.out.println("missingParameterTypes");
+ }
+
+ // BootstrapMethod.parameterTypes != parameterTypesOf(constantArgumentsForBootstrapMethod):
+ // extra constant present
+ @CalledByIndy(
+ bootstrapMethod =
+ @BootstrapMethod(
+ enclosingType = TestBadBootstrapArguments.class,
+ name = "bsm",
+ parameterTypes = {
+ MethodHandles.Lookup.class,
+ String.class,
+ MethodType.class,
+ int.class,
+ String.class
+ }
+ ),
+ fieldOrMethodName = "extraArguments",
+ constantArgumentsForBootstrapMethod = {
+ @Constant(intValue = 1),
+ @Constant(stringValue = "2"),
+ @Constant(intValue = 3)
+ }
+ )
+ private static void invokeExtraArguments() {
+ assertNotReached();
+ }
+
+ private static void extraArguments() {
+ System.out.println("extraArguments");
+ }
+
+ // constantArgumentTypes do not correspond to expected parameter types
+ @CalledByIndy(
+ bootstrapMethod =
+ @BootstrapMethod(
+ enclosingType = TestBadBootstrapArguments.class,
+ name = "bsm",
+ parameterTypes = {
+ MethodHandles.Lookup.class,
+ String.class,
+ MethodType.class,
+ int.class,
+ String.class
+ }
+ ),
+ fieldOrMethodName = "wrongArguments",
+ constantArgumentsForBootstrapMethod = {
+ @Constant(stringValue = "1"),
+ @Constant(doubleValue = Math.PI)
+ }
+ )
+ private static void invokeWrongArguments() {
+ assertNotReached();
+ }
+
+ private static void wrongArguments() {
+ System.out.println("wrongArguments");
+ }
+
+ // constantArgumentTypes do not correspond to expected parameter types
+ @CalledByIndy(
+ bootstrapMethod =
+ @BootstrapMethod(
+ enclosingType = TestBadBootstrapArguments.class,
+ name = "bsm",
+ parameterTypes = {
+ MethodHandles.Lookup.class,
+ String.class,
+ MethodType.class,
+ int.class,
+ String.class
+ }
+ ),
+ fieldOrMethodName = "wrongArgumentsAgain",
+ constantArgumentsForBootstrapMethod = {
+ @Constant(doubleValue = Math.PI),
+ @Constant(stringValue = "pie")
+ }
+ )
+ private static void invokeWrongArgumentsAgain() {
+ assertNotReached();
+ }
+
+ private static void wrongArgumentsAgain() {
+ System.out.println("wrongArgumentsAgain");
+ }
+
+ // Primitive argument types not supported {Z, B, C, S}.
+ private static CallSite bsmZBCS(
+ MethodHandles.Lookup lookup,
+ String methodName,
+ MethodType methodType,
+ boolean extraArg0,
+ byte extraArg1,
+ char extraArg2,
+ short extraArg3)
+ throws Throwable {
+ assertNotReached();
+ return null;
+ }
+
+ // Arguments are narrower than supported.
+ @CalledByIndy(
+ bootstrapMethod =
+ @BootstrapMethod(
+ enclosingType = TestBadBootstrapArguments.class,
+ name = "bsmZBCS",
+ parameterTypes = {
+ MethodHandles.Lookup.class,
+ String.class,
+ MethodType.class,
+ boolean.class,
+ byte.class,
+ char.class,
+ short.class
+ }
+ ),
+ fieldOrMethodName = "narrowArguments",
+ constantArgumentsForBootstrapMethod = {
+ @Constant(booleanValue = true),
+ @Constant(byteValue = Byte.MAX_VALUE),
+ @Constant(charValue = 'A'),
+ @Constant(shortValue = Short.MIN_VALUE)
+ }
+ )
+ private static void invokeNarrowArguments() {
+ assertNotReached();
+ }
+
+ private static void narrowArguments() {
+ assertNotReached();
+ }
+
+ private static CallSite bsmDJ(
+ MethodHandles.Lookup lookup,
+ String methodName,
+ MethodType methodType,
+ double extraArg0,
+ long extraArg1)
+ throws Throwable {
+ System.out.print("bsmDJ(..., ");
+ System.out.print(extraArg0);
+ System.out.print(", ");
+ System.out.print(extraArg1);
+ System.out.println(")");
+ MethodHandle mh = lookup.findStatic(lookup.lookupClass(), methodName, methodType);
+ return new ConstantCallSite(mh);
+ }
+
+ // Arguments need widening to parameter types.
+ @CalledByIndy(
+ bootstrapMethod =
+ @BootstrapMethod(
+ enclosingType = TestBadBootstrapArguments.class,
+ name = "bsmDJ",
+ parameterTypes = {
+ MethodHandles.Lookup.class,
+ String.class,
+ MethodType.class,
+ double.class,
+ long.class
+ }
+ ),
+ fieldOrMethodName = "wideningArguments",
+ constantArgumentsForBootstrapMethod = {
+ @Constant(doubleValue = Double.MAX_VALUE),
+ @Constant(intValue = Integer.MAX_VALUE)
+ }
+ )
+ private static void invokeWideningArguments() {
+ assertNotReached();
+ }
+
+ private static void wideningArguments() {
+ System.out.println("wideningArguments");
+ }
+
+ private static CallSite bsmDoubleLong(
+ MethodHandles.Lookup lookup,
+ String methodName,
+ MethodType methodType,
+ Double extraArg0,
+ Long extraArg1)
+ throws Throwable {
+ System.out.print("bsmDoubleLong(..., ");
+ System.out.print(extraArg0);
+ System.out.print(", ");
+ System.out.print(extraArg1);
+ System.out.println(")");
+ MethodHandle mh = lookup.findStatic(lookup.lookupClass(), methodName, methodType);
+ return new ConstantCallSite(mh);
+ }
+
+ // Arguments need boxing to parameter types
+ @CalledByIndy(
+ bootstrapMethod =
+ @BootstrapMethod(
+ enclosingType = TestBadBootstrapArguments.class,
+ name = "bsmDoubleLong",
+ parameterTypes = {
+ MethodHandles.Lookup.class,
+ String.class,
+ MethodType.class,
+ Double.class,
+ Long.class
+ }
+ ),
+ fieldOrMethodName = "boxingArguments",
+ constantArgumentsForBootstrapMethod = {
+ @Constant(doubleValue = Double.MAX_VALUE),
+ @Constant(longValue = Long.MAX_VALUE)
+ }
+ )
+ private static void invokeBoxingArguments() {
+ assertNotReached();
+ }
+
+ private static void boxingArguments() {
+ System.out.println("boxingArguments");
+ }
+
+ // Arguments need widening and boxing to parameter types
+ @CalledByIndy(
+ bootstrapMethod =
+ @BootstrapMethod(
+ enclosingType = TestBadBootstrapArguments.class,
+ name = "bsmDoubleLong",
+ parameterTypes = {
+ MethodHandles.Lookup.class,
+ String.class,
+ MethodType.class,
+ Double.class,
+ Long.class
+ }
+ ),
+ fieldOrMethodName = "wideningBoxingArguments",
+ constantArgumentsForBootstrapMethod = {
+ @Constant(floatValue = Float.MAX_VALUE),
+ @Constant(longValue = Integer.MAX_VALUE)
+ }
+ )
+ private static void invokeWideningBoxingArguments() {
+ assertNotReached();
+ }
+
+ private static void wideningBoxingArguments() {
+ System.out.println("wideningBoxingArguments");
+ }
+
+ static void bsmReturningVoid(MethodHandles.Lookup lookup, String name, MethodType type) {
+ System.out.println("bsm returning void value.");
+ }
+
+ @CalledByIndy(
+ bootstrapMethod =
+ @BootstrapMethod(
+ enclosingType = TestBadBootstrapArguments.class,
+ name = "bsmReturningVoid",
+ parameterTypes = {MethodHandles.Lookup.class, String.class, MethodType.class},
+ returnType = void.class
+ ),
+ fieldOrMethodName = "voidReturnType"
+ )
+ private static void invokeVoidReturnType() {
+ assertNotReached();
+ }
+
+ private static void voidReturnType() {
+ assertNotReached();
+ }
+
+ static Object bsmReturningObject(MethodHandles.Lookup lookup, String name, MethodType type) {
+ System.out.println("bsm returning Object value.");
+ return new Object();
+ }
+
+ @CalledByIndy(
+ bootstrapMethod =
+ @BootstrapMethod(
+ enclosingType = TestBadBootstrapArguments.class,
+ name = "bsmReturningObject",
+ parameterTypes = {MethodHandles.Lookup.class, String.class, MethodType.class},
+ returnType = Object.class
+ ),
+ fieldOrMethodName = "ObjectReturnType"
+ )
+ private static void invokeObjectReturnType() {
+ assertNotReached();
+ }
+
+ private static void objectReturnType() {
+ assertNotReached();
+ }
+
+ static Integer bsmReturningInteger(MethodHandles.Lookup lookup, String name, MethodType type) {
+ System.out.println("bsm returning Integer value.");
+ return Integer.valueOf(3);
+ }
+
+ @CalledByIndy(
+ bootstrapMethod =
+ @BootstrapMethod(
+ enclosingType = TestBadBootstrapArguments.class,
+ name = "bsmReturningInteger",
+ parameterTypes = {MethodHandles.Lookup.class, String.class, MethodType.class},
+ returnType = Integer.class
+ ),
+ fieldOrMethodName = "integerReturnType"
+ )
+ private static void invokeIntegerReturnType() {
+ assertNotReached();
+ }
+
+ private static void integerReturnType() {
+ assertNotReached();
+ }
+
+ static class TestersConstantCallSite extends ConstantCallSite {
+ public TestersConstantCallSite(MethodHandle mh) {
+ super(mh);
+ }
+ }
+
+ static TestersConstantCallSite bsmReturningTestersConstantCallsite(
+ MethodHandles.Lookup lookup, String name, MethodType type) throws Throwable {
+ return new TestersConstantCallSite(lookup.findStatic(lookup.lookupClass(), name, type));
+ }
+
+ @CalledByIndy(
+ bootstrapMethod =
+ @BootstrapMethod(
+ enclosingType = TestBadBootstrapArguments.class,
+ name = "bsmReturningTestersConstantCallsite",
+ parameterTypes = {MethodHandles.Lookup.class, String.class, MethodType.class},
+ returnType = TestersConstantCallSite.class
+ ),
+ fieldOrMethodName = "sayHello"
+ )
+ private static void invokeViaCustomCallSiteClass() {
+ assertNotReached();
+ }
+
+ private static void sayHello() {
+ System.out.println("Hello!");
+ }
+
+ static void test() {
+ System.out.println("TestBadBootstrapArguments");
+ invokeHappy();
+ try {
+ invokeWrongParameterTypes();
+ assertNotReached();
+ } catch (NoSuchMethodError expected) {
+ System.out.print("invokeWrongParameterTypes => ");
+ System.out.println(expected.getClass());
+ }
+ try {
+ invokeMissingParameterTypes();
+ assertNotReached();
+ } catch (NoSuchMethodError expected) {
+ System.out.print("invokeMissingParameterTypes => ");
+ System.out.println(expected.getClass());
+ }
+ try {
+ invokeExtraArguments();
+ assertNotReached();
+ } catch (BootstrapMethodError expected) {
+ assertEquals(WrongMethodTypeException.class, expected.getCause().getClass());
+ System.out.print("invokeExtraArguments => ");
+ System.out.print(expected.getClass());
+ System.out.print(" => ");
+ System.out.println(expected.getCause().getClass());
+ }
+ try {
+ invokeWrongArguments();
+ assertNotReached();
+ } catch (BootstrapMethodError expected) {
+ assertEquals(ClassCastException.class, expected.getCause().getClass());
+ System.out.print("invokeWrongArguments => ");
+ System.out.print(expected.getClass());
+ System.out.print(" => ");
+ System.out.println(expected.getCause().getClass());
+ }
+ try {
+ invokeWrongArguments();
+ assertNotReached();
+ } catch (BootstrapMethodError expected) {
+ assertEquals(ClassCastException.class, expected.getCause().getClass());
+ System.out.print("invokeWrongArguments => ");
+ System.out.print(expected.getClass());
+ System.out.print(" => ");
+ System.out.println(expected.getCause().getClass());
+ }
+ try {
+ invokeWrongArgumentsAgain();
+ assertNotReached();
+ } catch (BootstrapMethodError expected) {
+ assertEquals(ClassCastException.class, expected.getCause().getClass());
+ System.out.print("invokeWrongArgumentsAgain => ");
+ System.out.print(expected.getClass());
+ System.out.print(" => ");
+ System.out.println(expected.getCause().getClass());
+ }
+ try {
+ invokeNarrowArguments();
+ assertNotReached();
+ } catch (BootstrapMethodError expected) {
+ assertEquals(ClassCastException.class, expected.getCause().getClass());
+ System.out.print("invokeNarrowArguments => ");
+ System.out.print(expected.getClass());
+ System.out.print(" => ");
+ System.out.println(expected.getCause().getClass());
+ }
+ invokeWideningArguments();
+ invokeBoxingArguments();
+ try {
+ invokeWideningBoxingArguments();
+ assertNotReached();
+ } catch (BootstrapMethodError expected) {
+ System.out.print("invokeWideningBoxingArguments => ");
+ System.out.print(expected.getClass());
+ System.out.print(" => ");
+ System.out.println(expected.getCause().getClass());
+ }
+ try {
+ invokeVoidReturnType();
+ assertNotReached();
+ } catch (BootstrapMethodError expected) {
+ System.out.print("invokeVoidReturnType() => ");
+ System.out.print(expected.getClass());
+ System.out.print(" => ");
+ System.out.println(expected.getCause().getClass());
+ }
+ try {
+ invokeObjectReturnType();
+ assertNotReached();
+ } catch (BootstrapMethodError expected) {
+ System.out.print("invokeObjectReturnType() => ");
+ System.out.print(expected.getClass());
+ System.out.print(" => ");
+ System.out.println(expected.getCause().getClass());
+ }
+ try {
+ invokeIntegerReturnType();
+ assertNotReached();
+ } catch (BootstrapMethodError expected) {
+ System.out.print("invokeIntegerReturnType() => ");
+ System.out.print(expected.getClass());
+ System.out.print(" => ");
+ System.out.println(expected.getCause().getClass());
+ }
+ invokeViaCustomCallSiteClass();
+ }
+}
diff --git a/test/952-invoke-custom/src/TestDynamicBootstrapArguments.java b/test/952-invoke-custom/src/TestDynamicBootstrapArguments.java
new file mode 100644
index 0000000000..782feca6da
--- /dev/null
+++ b/test/952-invoke-custom/src/TestDynamicBootstrapArguments.java
@@ -0,0 +1,92 @@
+/*
+ * 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;
+
+class TestDynamicBootstrapArguments extends TestBase {
+ private static int bsmCalls = 0;
+
+ static CallSite bsm(
+ MethodHandles.Lookup lookup,
+ String name,
+ MethodType methodType,
+ String otherNameComponent,
+ long nameSuffix)
+ throws Throwable {
+ bsmCalls = bsmCalls + 1;
+ Class<?> definingClass = TestDynamicBootstrapArguments.class;
+ String methodName = name + otherNameComponent + nameSuffix;
+ MethodHandle mh = lookup.findStatic(definingClass, methodName, methodType);
+ System.out.println("bsm");
+ return new ConstantCallSite(mh);
+ }
+
+ @CalledByIndy(
+ bootstrapMethod =
+ @BootstrapMethod(
+ enclosingType = TestDynamicBootstrapArguments.class,
+ name = "bsm",
+ parameterTypes = {
+ MethodHandles.Lookup.class,
+ String.class,
+ MethodType.class,
+ String.class,
+ long.class
+ }
+ ),
+ fieldOrMethodName = "target",
+ returnType = int.class,
+ parameterTypes = {int.class, String.class, double.class},
+ constantArgumentsForBootstrapMethod = {
+ @Constant(stringValue = "A"),
+ @Constant(longValue = 100000000l)
+ }
+ )
+ private static int testDynamic(int i, String s, Double d) {
+ assertNotReached();
+ return 0;
+ }
+
+ private static int targetA100000000(int i, String s, Double d) {
+ System.out.print(i);
+ System.out.print(", ");
+ System.out.print(s);
+ System.out.print(", ");
+ System.out.println(d);
+ return i;
+ }
+
+ static void testCallSites() {
+ assertEquals(0, testDynamic(0, "One", Math.PI));
+ assertEquals(1, testDynamic(1, "Two", Math.E));
+ assertEquals(2, testDynamic(2, "Three", 0.0));
+ }
+
+ static void test() {
+ System.out.println("TestDynamicArguments");
+ testCallSites();
+ assertEquals(3, bsmCalls);
+ testCallSites();
+ assertEquals(3, bsmCalls);
+ }
+}
diff --git a/test/952-invoke-custom/src/TestInvocationKinds.java b/test/952-invoke-custom/src/TestInvocationKinds.java
index 7b88c18c66..f743bef158 100644
--- a/test/952-invoke-custom/src/TestInvocationKinds.java
+++ b/test/952-invoke-custom/src/TestInvocationKinds.java
@@ -173,6 +173,7 @@ class TestInvocationKinds extends TestBase {
static class Widget {
int value;
+
public Widget(int value) {}
}
diff --git a/test/952-invoke-custom/src/TestVariableArityLinkerMethod.java b/test/952-invoke-custom/src/TestVariableArityLinkerMethod.java
new file mode 100644
index 0000000000..597273c8ec
--- /dev/null
+++ b/test/952-invoke-custom/src/TestVariableArityLinkerMethod.java
@@ -0,0 +1,569 @@
+/*
+ * 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());
+ }
+ }
+}
diff --git a/test/knownfailures.json b/test/knownfailures.json
index 5fb78191ef..b2f579d3b9 100644
--- a/test/knownfailures.json
+++ b/test/knownfailures.json
@@ -934,7 +934,6 @@
"946-obsolete-throw",
"948-change-annotations",
"950-redefine-intrinsic",
- "952-invoke-custom",
"954-invoke-polymorphic-verifier",
"955-methodhandles-smali",
"956-methodhandles",