summaryrefslogtreecommitdiff
path: root/test/2277-methodhandle-invokeexact/src
diff options
context:
space:
mode:
author Almaz Mingaleev <mingaleev@google.com> 2024-11-07 10:01:49 +0000
committer Almaz Mingaleev <mingaleev@google.com> 2024-11-12 14:27:31 +0000
commit3051a5e03f32ca7aaae6041025ec60f90d41e34c (patch)
tree6d253e5c533e032ef1a43a914410d32f7e31081a /test/2277-methodhandle-invokeexact/src
parent20cdc427d5f5875c2d58f9fde775957ad2e28cfd (diff)
Remove now unnecessary checks from invokeExact intrinsic.
Also rewrote tests to make sure that MethodHandle-s created via const-method-handle and Java API behave identically. They can be slightly different even if lookup is done in the same class for the same method as const-method-handle can target copied methods. Bug: 297147201 Test: ./art/test/testrunner/testrunner.py -b --host --64 Test: ./art/test/testrunner/testrunner.py -b --jvm Change-Id: I69cdf2c44f2838ee0e57eaa2e93a6ed5276c39fb
Diffstat (limited to 'test/2277-methodhandle-invokeexact/src')
-rw-r--r--test/2277-methodhandle-invokeexact/src/A.java52
-rw-r--r--test/2277-methodhandle-invokeexact/src/AbstractInvokeExactTest.java270
-rw-r--r--test/2277-methodhandle-invokeexact/src/B.java21
-rw-r--r--test/2277-methodhandle-invokeexact/src/Bar.java22
-rw-r--r--test/2277-methodhandle-invokeexact/src/ConstMethodHandleTest.java532
-rw-r--r--test/2277-methodhandle-invokeexact/src/Foo.java27
-rw-r--r--test/2277-methodhandle-invokeexact/src/FooBar.java21
-rw-r--r--test/2277-methodhandle-invokeexact/src/FooBarImpl.java22
-rw-r--r--test/2277-methodhandle-invokeexact/src/I.java29
-rw-r--r--test/2277-methodhandle-invokeexact/src/JavaApiTest.java351
-rw-r--r--test/2277-methodhandle-invokeexact/src/Main.java544
-rw-r--r--test/2277-methodhandle-invokeexact/src/MyRuntimeException.java17
-rw-r--r--test/2277-methodhandle-invokeexact/src/Sums.java78
13 files changed, 1464 insertions, 522 deletions
diff --git a/test/2277-methodhandle-invokeexact/src/A.java b/test/2277-methodhandle-invokeexact/src/A.java
new file mode 100644
index 0000000000..b6fc317cb0
--- /dev/null
+++ b/test/2277-methodhandle-invokeexact/src/A.java
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2024 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.
+ */
+
+public class A extends B implements I {
+ public int field;
+ public void voidMethod() {
+ AbstractInvokeExactTest.STATUS = "A.voidMethod";
+ }
+
+ @Override
+ public void overrideMe() {
+ AbstractInvokeExactTest.STATUS = "A.overrideMe";
+ }
+
+ public void throwException() {
+ AbstractInvokeExactTest.STATUS = "A.throwException";
+ throw new MyRuntimeException();
+ }
+
+ public double returnDouble() {
+ return 42.0d;
+ }
+
+ public int returnInt() {
+ return 42;
+ }
+
+ private int privateReturnInt() {
+ return 1042;
+ }
+
+ public static String staticMethod(A a) {
+ return "staticMethod";
+ }
+
+ public static double staticMethod() {
+ return 41.0d;
+ }
+}
diff --git a/test/2277-methodhandle-invokeexact/src/AbstractInvokeExactTest.java b/test/2277-methodhandle-invokeexact/src/AbstractInvokeExactTest.java
new file mode 100644
index 0000000000..569bff61b2
--- /dev/null
+++ b/test/2277-methodhandle-invokeexact/src/AbstractInvokeExactTest.java
@@ -0,0 +1,270 @@
+/*
+ * Copyright (C) 2024 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 java.lang.invoke.MethodHandle;
+import java.lang.invoke.WrongMethodTypeException;
+import java.util.Objects;
+
+public abstract class AbstractInvokeExactTest {
+
+ public static String STATUS = "";
+
+ public final void runAll() throws Throwable {
+ STATUS = "";
+ Multi.$noinline$testMHFromMain(optionalGet());
+ $noinline$privateMethods();
+ $noinline$testNoArgsCalls();
+ $noinline$nullchecks();
+ $noinline$testWithArgs();
+ $noinline$interfaceChecks();
+ $noinline$abstractClass();
+ }
+
+ // There is no privateLookupIn for const-method-handle.
+ abstract void $noinline$privateMethods() throws Throwable;
+
+ private void $noinline$testNoArgsCalls() throws Throwable {
+ voidMethod().invokeExact(new A());
+ assertEquals("A.voidMethod", STATUS);
+
+ int returnedInt = (int) returnInt().invokeExact(new A());
+ assertEquals(42, returnedInt);
+
+ double returnedDouble = (double) returnDouble().invokeExact(new A());
+ assertEquals(42.0d, returnedDouble);
+ try {
+ interfaceDefaultMethod().invokeExact(new A());
+ unreachable("MethodHandle's type is (Main$I)V, but callsite is (Main$A)V");
+ } catch (WrongMethodTypeException expected) {}
+
+ interfaceDefaultMethod().invokeExact((I) new A());
+ assertEquals("I.defaultMethod", STATUS);
+
+ overwrittenInterfaceDefaultMethod().invokeExact((I) new A());
+ assertEquals("A.overrideMe", STATUS);
+
+
+ try {
+ exceptionThrowingMethod().invokeExact(new A());
+ unreachable("Target method always throws");
+ } catch (MyRuntimeException expected) {
+ assertEquals("A.throwException", STATUS);
+ }
+
+ try {
+ returnInt().invokeExact(new A());
+ unreachable("MethodHandle's type is (Main$A)I, but callsite type is (Main$A)V");
+ } catch (WrongMethodTypeException expected) {}
+
+ String returnedString = (String) staticMethod().invokeExact(new A());
+ assertEquals("staticMethod", returnedString);
+ }
+
+ private void $noinline$nullchecks() throws Throwable {
+ try {
+ voidMethod().invokeExact((A) null);
+ unreachable("Receiver is null, should throw NPE");
+ } catch (NullPointerException expected) {}
+
+ try {
+ voidMethod().invokeExact((Main) null);
+ unreachable("Should throw WMTE: input is of wrong type");
+ } catch (WrongMethodTypeException expected) {}
+
+ try {
+ interfaceDefaultMethod().invokeExact((I) null);
+ unreachable("Receiver is null, should throw NPE");
+ } catch (NullPointerException expected) {}
+
+ try {
+ interfaceDefaultMethod().invokeExact((A) null);
+ unreachable("Should throw WMTE: input is of wrong type");
+ } catch (WrongMethodTypeException expected) {}
+
+ try {
+ MethodHandle mh = $noinline$nullMethodHandle();
+ mh.invokeExact();
+ unreachable("MethodHandle object is null, should throw NPE");
+ } catch (NullPointerException expected) {}
+ }
+
+ private static MethodHandle $noinline$nullMethodHandle() {
+ return null;
+ }
+
+ private void $noinline$testWithArgs() throws Throwable {
+ int sum = (int) sumI().invokeExact(new Sums(), 1);
+ assertEquals(1, sum);
+
+ sum = (int) sum2I().invokeExact(new Sums(), 1, 2);
+ assertEquals(3, sum);
+
+ sum = (int) sum3I().invokeExact(new Sums(), 1, 2, 3);
+ assertEquals(6, sum);
+
+ sum = (int) sum4I().invokeExact(new Sums(), 1, 2, 3, 4);
+ assertEquals(10, sum);
+
+ sum = (int) sum5I().invokeExact(new Sums(), 1, 2, 3, 4, 5);
+ assertEquals(15, sum);
+
+ sum = (int) sum6I().invokeExact(new Sums(), 1, 2, 3, 4, 5, 6);
+ assertEquals(21, sum);
+
+ sum = (int) sum7I().invokeExact(new Sums(), 1, 2, 3, 4, 5, 6, 7);
+ assertEquals(28, sum);
+
+ sum = (int) sum8I().invokeExact(new Sums(), 1, 2, 3, 4, 5, 6, 7, 8);
+ assertEquals(36, sum);
+
+ sum = (int) sum9I().invokeExact(new Sums(), 1, 2, 3, 4, 5, 6, 7, 8, 9);
+ assertEquals(45, sum);
+
+ sum = (int) sum10I().invokeExact(new Sums(), 1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
+ assertEquals(55, sum);
+
+ long lsum = (long) sumIJ().invokeExact(new Sums(), 1, 2L);
+ assertEquals(3L, lsum);
+
+ lsum = (long) sum2IJ().invokeExact(new Sums(), 1, 2L, 3, 4L);
+ assertEquals(10L, lsum);
+
+ lsum = (long) sum3IJ().invokeExact(new Sums(), 1, 2L, 3, 4L, 5, 6L);
+ assertEquals(21L, lsum);
+
+ lsum = (long) sum4IJ().invokeExact(new Sums(), 1, 2L, 3, 4L, 5, 6L, 7, 8L);
+ assertEquals(36L, lsum);
+
+ lsum = (long) sum5IJ().invokeExact(new Sums(), 1, 2L, 3, 4L, 5, 6L, 7, 8L, 9, 10L);
+ assertEquals(55L, lsum);
+ }
+
+ private void $noinline$interfaceChecks() throws Throwable {
+ FooBarImpl instance = new FooBarImpl();
+
+ String result = null;
+ result = (String) fooNonDefault().invokeExact((Foo) instance);
+ assertEquals("FooBarImpl.nonDefault", result);
+
+ result = (String) fooBarImplNonDefault().invokeExact(instance);
+ assertEquals("FooBarImpl.nonDefault", result);
+
+ result = (String) barDefault().invokeExact((Bar) instance);
+ assertEquals("Bar.defaultToOverride", result);
+
+ result = (String) fooDefault().invokeExact((Foo) instance);
+ assertEquals("Bar.defaultToOverride", result);
+
+ result = (String) fooBarImplDefault().invokeExact(instance);
+ assertEquals("Bar.defaultToOverride", result);
+
+ result = (String) fooNonOverriddenDefault().invokeExact((Foo) instance);
+ assertEquals("Foo.nonOverriddenDefault", result);
+
+ result = (String) barNonOverriddenDefault().invokeExact((Bar) instance);
+ assertEquals("Foo.nonOverriddenDefault", result);
+ }
+
+ private void $noinline$abstractClass() throws Throwable {
+ FooBarImpl instance = new FooBarImpl();
+
+ String result = null;
+ result = (String) fooBarDefinedInAbstract().invokeExact((FooBar) instance);
+ assertEquals("FooBar.definedInAbstract", result);
+
+ result = (String) fooBarImplDefinedInAbstract().invokeExact(instance);
+ assertEquals("FooBar.definedInAbstract", result);
+
+ FooBar fooBar = new FooBar() {
+ @Override
+ public String nonDefault() {
+ return "anonymous.nonDefault";
+ }
+ };
+
+ result = (String) fooBarDefinedInAbstract().invokeExact(fooBar);
+ assertEquals("FooBar.definedInAbstract", result);
+
+ result = (String) fooBarNonDefault().invokeExact(fooBar);
+ assertEquals("anonymous.nonDefault", result);
+ }
+
+ static void assertEquals(Object expected, Object actual) {
+ if (!Objects.equals(expected, actual)) {
+ throw new AssertionError("Expected: " + expected + ", got: " + actual);
+ }
+ }
+
+ private static void assertEquals(int expected, int actual) {
+ if (expected != actual) {
+ throw new AssertionError("Expected: " + expected + ", got: " + actual);
+ }
+ }
+
+ private static void assertEquals(long expected, long actual) {
+ if (expected != actual) {
+ throw new AssertionError("Expected: " + expected + ", got: " + actual);
+ }
+ }
+
+ private static void assertEquals(double expected, double actual) {
+ if (expected != actual) {
+ throw new AssertionError("Expected: " + expected + ", got: " + actual);
+ }
+ }
+
+ static void unreachable(String msg) {
+ throw new AssertionError("Unexpectedly reached this point, but shouldn't: " + msg);
+ }
+
+ public abstract MethodHandle optionalGet();
+
+ public abstract MethodHandle voidMethod();
+ public abstract MethodHandle returnInt();
+ public abstract MethodHandle returnDouble();
+ public abstract MethodHandle interfaceDefaultMethod();
+ public abstract MethodHandle overwrittenInterfaceDefaultMethod();
+ public abstract MethodHandle exceptionThrowingMethod();
+ public abstract MethodHandle staticMethod();
+
+ public abstract MethodHandle sumI();
+ public abstract MethodHandle sum2I();
+ public abstract MethodHandle sum3I();
+ public abstract MethodHandle sum4I();
+ public abstract MethodHandle sum5I();
+ public abstract MethodHandle sum6I();
+ public abstract MethodHandle sum7I();
+ public abstract MethodHandle sum8I();
+ public abstract MethodHandle sum9I();
+ public abstract MethodHandle sum10I();
+ public abstract MethodHandle sumIJ();
+ public abstract MethodHandle sum2IJ();
+ public abstract MethodHandle sum3IJ();
+ public abstract MethodHandle sum4IJ();
+ public abstract MethodHandle sum5IJ();
+
+ public abstract MethodHandle fooNonDefault();
+ public abstract MethodHandle fooBarImplNonDefault();
+ public abstract MethodHandle barDefault();
+ public abstract MethodHandle fooDefault();
+ public abstract MethodHandle fooBarImplDefault();
+ public abstract MethodHandle fooNonOverriddenDefault();
+ public abstract MethodHandle barNonOverriddenDefault();
+
+ public abstract MethodHandle fooBarDefinedInAbstract();
+ public abstract MethodHandle fooBarImplDefinedInAbstract();
+ public abstract MethodHandle fooBarNonDefault();
+}
diff --git a/test/2277-methodhandle-invokeexact/src/B.java b/test/2277-methodhandle-invokeexact/src/B.java
new file mode 100644
index 0000000000..f398f8ed8e
--- /dev/null
+++ b/test/2277-methodhandle-invokeexact/src/B.java
@@ -0,0 +1,21 @@
+/*
+ * Copyright (C) 2024 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.
+ */
+
+public class B {
+ private int privateReturnInt() {
+ return 9999;
+ }
+}
diff --git a/test/2277-methodhandle-invokeexact/src/Bar.java b/test/2277-methodhandle-invokeexact/src/Bar.java
new file mode 100644
index 0000000000..b278cd8c52
--- /dev/null
+++ b/test/2277-methodhandle-invokeexact/src/Bar.java
@@ -0,0 +1,22 @@
+/*
+ * Copyright (C) 2024 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.
+ */
+
+interface Bar extends Foo {
+ @Override
+ default String defaultToOverride() {
+ return "Bar.defaultToOverride";
+ }
+}
diff --git a/test/2277-methodhandle-invokeexact/src/ConstMethodHandleTest.java b/test/2277-methodhandle-invokeexact/src/ConstMethodHandleTest.java
new file mode 100644
index 0000000000..38b7eeb10f
--- /dev/null
+++ b/test/2277-methodhandle-invokeexact/src/ConstMethodHandleTest.java
@@ -0,0 +1,532 @@
+/*
+ * Copyright (C) 2024 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.ConstantMethodHandle;
+
+import java.lang.invoke.MethodHandle;
+
+public class ConstMethodHandleTest extends AbstractInvokeExactTest {
+
+ @Override
+ void $noinline$privateMethods() throws Throwable {
+ // TODO(b/378051428): can't create const-method-handle targeting private methods of
+ // inner classes.
+ }
+
+ @ConstantMethodHandle(
+ kind = ConstantMethodHandle.INVOKE_VIRTUAL,
+ owner = "java/util/Optional",
+ fieldOrMethodName = "get",
+ descriptor = "()Ljava/lang/Object;")
+ private static MethodHandle constOptionalGet() {
+ unreachable("should be replaced by const-method-handle");
+ return null;
+ }
+
+ @Override
+ public MethodHandle optionalGet() {
+ return constOptionalGet();
+ }
+
+ @ConstantMethodHandle(
+ kind = ConstantMethodHandle.INVOKE_VIRTUAL,
+ owner = "A",
+ fieldOrMethodName = "voidMethod",
+ descriptor = "()V")
+ private static MethodHandle constVoidMethod() {
+ unreachable("should be replaced by const-method-handle");
+ return null;
+ }
+
+ @Override
+ public MethodHandle voidMethod() {
+ return constVoidMethod();
+ }
+
+ @ConstantMethodHandle(
+ kind = ConstantMethodHandle.INVOKE_VIRTUAL,
+ owner = "A",
+ fieldOrMethodName = "returnInt",
+ descriptor = "()I")
+ private static MethodHandle constReturnInt() {
+ unreachable("should be replaced by const-method-handle");
+ return null;
+ }
+
+ @Override
+ public MethodHandle returnInt() {
+ return constReturnInt();
+ }
+
+ @ConstantMethodHandle(
+ kind = ConstantMethodHandle.INVOKE_VIRTUAL,
+ owner = "A",
+ fieldOrMethodName = "returnDouble",
+ descriptor = "()D")
+ private static MethodHandle constReturnDouble() {
+ unreachable("should be replaced by const-method-handle");
+ return null;
+ }
+
+ @Override
+ public MethodHandle returnDouble() {
+ return constReturnDouble();
+ }
+
+ @ConstantMethodHandle(
+ kind = ConstantMethodHandle.INVOKE_INTERFACE,
+ owner = "I",
+ fieldOrMethodName = "defaultMethod",
+ descriptor = "()V",
+ ownerIsInterface = true)
+ private static MethodHandle constInterfaceDefaultMethod() {
+ unreachable("should be replaced by const-method-handle");
+ return null;
+ }
+
+ @Override
+ public MethodHandle interfaceDefaultMethod() {
+ return constInterfaceDefaultMethod();
+ }
+
+ @ConstantMethodHandle(
+ kind = ConstantMethodHandle.INVOKE_INTERFACE,
+ owner = "I",
+ fieldOrMethodName = "overrideMe",
+ descriptor = "()V",
+ ownerIsInterface = true)
+ private static MethodHandle constOverwrittenInterfaceDefaultMethod() {
+ unreachable("should be replaced by const-method-handle");
+ return null;
+ }
+
+ @Override
+ public MethodHandle overwrittenInterfaceDefaultMethod() {
+ return constOverwrittenInterfaceDefaultMethod();
+ }
+
+ @ConstantMethodHandle(
+ kind = ConstantMethodHandle.INVOKE_VIRTUAL,
+ owner = "A",
+ fieldOrMethodName = "throwException",
+ descriptor = "()V")
+ private static MethodHandle constExceptionThrowingMethod() {
+ unreachable("should be replaced by const-method-handle");
+ return null;
+ }
+
+ @Override
+ public MethodHandle exceptionThrowingMethod() {
+ return constExceptionThrowingMethod();
+ }
+
+ @ConstantMethodHandle(
+ kind = ConstantMethodHandle.INVOKE_STATIC,
+ owner = "A",
+ fieldOrMethodName = "staticMethod",
+ descriptor = "(LA;)Ljava/lang/String;")
+ private static MethodHandle constStaticMethod() {
+ unreachable("should be replaced by const-method-handle");
+ return null;
+ }
+
+ @Override
+ public MethodHandle staticMethod() {
+ return constStaticMethod();
+ }
+
+ @ConstantMethodHandle(
+ kind = ConstantMethodHandle.INVOKE_VIRTUAL,
+ owner = "Sums",
+ fieldOrMethodName = "sum",
+ descriptor = "(I)I")
+ private static MethodHandle constSumI() {
+ unreachable("should be replaced by const-method-handle");
+ return null;
+ }
+
+ @Override
+ public MethodHandle sumI() {
+ return constSumI();
+ }
+
+ @ConstantMethodHandle(
+ kind = ConstantMethodHandle.INVOKE_VIRTUAL,
+ owner = "Sums",
+ fieldOrMethodName = "sum",
+ descriptor = "(II)I")
+ private static MethodHandle constSum2I() {
+ unreachable("should be replaced by const-method-handle");
+ return null;
+ }
+
+ @Override
+ public MethodHandle sum2I() {
+ return constSum2I();
+ }
+
+ @ConstantMethodHandle(
+ kind = ConstantMethodHandle.INVOKE_VIRTUAL,
+ owner = "Sums",
+ fieldOrMethodName = "sum",
+ descriptor = "(III)I")
+ private static MethodHandle constSum3I() {
+ unreachable("should be replaced by const-method-handle");
+ return null;
+ }
+
+ @Override
+ public MethodHandle sum3I() {
+ return constSum3I();
+ }
+
+ @ConstantMethodHandle(
+ kind = ConstantMethodHandle.INVOKE_VIRTUAL,
+ owner = "Sums",
+ fieldOrMethodName = "sum",
+ descriptor = "(IIII)I")
+ private static MethodHandle constSum4I() {
+ unreachable("should be replaced by const-method-handle");
+ return null;
+ }
+
+ @Override
+ public MethodHandle sum4I() {
+ return constSum4I();
+ }
+
+ @ConstantMethodHandle(
+ kind = ConstantMethodHandle.INVOKE_VIRTUAL,
+ owner = "Sums",
+ fieldOrMethodName = "sum",
+ descriptor = "(IIIII)I")
+ private static MethodHandle constSum5I() {
+ unreachable("should be replaced by const-method-handle");
+ return null;
+ }
+
+ @Override
+ public MethodHandle sum5I() {
+ return constSum5I();
+ }
+
+ @ConstantMethodHandle(
+ kind = ConstantMethodHandle.INVOKE_VIRTUAL,
+ owner = "Sums",
+ fieldOrMethodName = "sum",
+ descriptor = "(IIIIII)I")
+ private static MethodHandle constSum6I() {
+ unreachable("should be replaced by const-method-handle");
+ return null;
+ }
+
+ @Override
+ public MethodHandle sum6I() {
+ return constSum6I();
+ }
+
+ @ConstantMethodHandle(
+ kind = ConstantMethodHandle.INVOKE_VIRTUAL,
+ owner = "Sums",
+ fieldOrMethodName = "sum",
+ descriptor = "(IIIIIII)I")
+ private static MethodHandle constSum7I() {
+ unreachable("should be replaced by const-method-handle");
+ return null;
+ }
+
+ @Override
+ public MethodHandle sum7I() {
+ return constSum7I();
+ }
+
+ @ConstantMethodHandle(
+ kind = ConstantMethodHandle.INVOKE_VIRTUAL,
+ owner = "Sums",
+ fieldOrMethodName = "sum",
+ descriptor = "(IIIIIIII)I")
+ private static MethodHandle constSum8I() {
+ unreachable("should be replaced by const-method-handle");
+ return null;
+ }
+
+ @Override
+ public MethodHandle sum8I() {
+ return constSum8I();
+ }
+
+ @ConstantMethodHandle(
+ kind = ConstantMethodHandle.INVOKE_VIRTUAL,
+ owner = "Sums",
+ fieldOrMethodName = "sum",
+ descriptor = "(IIIIIIIII)I")
+ private static MethodHandle constSum9I() {
+ unreachable("should be replaced by const-method-handle");
+ return null;
+ }
+
+ @Override
+ public MethodHandle sum9I() {
+ return constSum9I();
+ }
+
+ @ConstantMethodHandle(
+ kind = ConstantMethodHandle.INVOKE_VIRTUAL,
+ owner = "Sums",
+ fieldOrMethodName = "sum",
+ descriptor = "(IIIIIIIIII)I")
+ private static MethodHandle constSum10I() {
+ unreachable("should be replaced by const-method-handle");
+ return null;
+ }
+
+ @Override
+ public MethodHandle sum10I() {
+ return constSum10I();
+ }
+
+ @ConstantMethodHandle(
+ kind = ConstantMethodHandle.INVOKE_VIRTUAL,
+ owner = "Sums",
+ fieldOrMethodName = "sum",
+ descriptor = "(IJ)J")
+ private static MethodHandle constSumIJ() {
+ unreachable("should be replaced by const-method-handle");
+ return null;
+ }
+
+ @Override
+ public MethodHandle sumIJ() {
+ return constSumIJ();
+ }
+
+ @ConstantMethodHandle(
+ kind = ConstantMethodHandle.INVOKE_VIRTUAL,
+ owner = "Sums",
+ fieldOrMethodName = "sum",
+ descriptor = "(IJIJ)J")
+ private static MethodHandle constSum2IJ() {
+ unreachable("should be replaced by const-method-handle");
+ return null;
+ }
+
+ @Override
+ public MethodHandle sum2IJ() {
+ return constSum2IJ();
+ }
+
+ @ConstantMethodHandle(
+ kind = ConstantMethodHandle.INVOKE_VIRTUAL,
+ owner = "Sums",
+ fieldOrMethodName = "sum",
+ descriptor = "(IJIJIJ)J")
+ private static MethodHandle constSum3IJ() {
+ unreachable("should be replaced by const-method-handle");
+ return null;
+ }
+
+ @Override
+ public MethodHandle sum3IJ() {
+ return constSum3IJ();
+ }
+
+ @ConstantMethodHandle(
+ kind = ConstantMethodHandle.INVOKE_VIRTUAL,
+ owner = "Sums",
+ fieldOrMethodName = "sum",
+ descriptor = "(IJIJIJIJ)J")
+ private static MethodHandle constSum4IJ() {
+ unreachable("should be replaced by const-method-handle");
+ return null;
+ }
+
+ @Override
+ public MethodHandle sum4IJ() {
+ return constSum4IJ();
+ }
+
+
+ @ConstantMethodHandle(
+ kind = ConstantMethodHandle.INVOKE_VIRTUAL,
+ owner = "Sums",
+ fieldOrMethodName = "sum",
+ descriptor = "(IJIJIJIJIJ)J")
+ private static MethodHandle constSum5IJ() {
+ unreachable("should be replaced by const-method-handle");
+ return null;
+ }
+
+ @Override
+ public MethodHandle sum5IJ() {
+ return constSum5IJ();
+ }
+
+ @ConstantMethodHandle(
+ kind = ConstantMethodHandle.INVOKE_INTERFACE,
+ owner = "Foo",
+ fieldOrMethodName = "nonDefault",
+ descriptor = "()Ljava/lang/String;",
+ ownerIsInterface = true)
+ private static MethodHandle constFooNonDefault() {
+ unreachable("should be replaced by const-method-handle");
+ return null;
+ }
+
+ @Override
+ public MethodHandle fooNonDefault() {
+ return constFooNonDefault();
+ }
+
+ @ConstantMethodHandle(
+ kind = ConstantMethodHandle.INVOKE_VIRTUAL,
+ owner = "FooBarImpl",
+ fieldOrMethodName = "nonDefault",
+ descriptor = "()Ljava/lang/String;")
+ private static MethodHandle constFooBarImplNonDefault() {
+ unreachable("should be replaced by const-method-handle");
+ return null;
+ }
+
+ @Override
+ public MethodHandle fooBarImplNonDefault() {
+ return constFooBarImplNonDefault();
+ }
+
+ @ConstantMethodHandle(
+ kind = ConstantMethodHandle.INVOKE_INTERFACE,
+ owner = "Bar",
+ fieldOrMethodName = "defaultToOverride",
+ descriptor = "()Ljava/lang/String;",
+ ownerIsInterface = true)
+ private static MethodHandle constBarDefault() {
+ unreachable("should be replaced by const-method-handle");
+ return null;
+ }
+
+ @Override
+ public MethodHandle barDefault() {
+ return constBarDefault();
+ }
+
+ @ConstantMethodHandle(
+ kind = ConstantMethodHandle.INVOKE_INTERFACE,
+ owner = "Foo",
+ fieldOrMethodName = "defaultToOverride",
+ descriptor = "()Ljava/lang/String;",
+ ownerIsInterface = true)
+ private static MethodHandle constFooDefault() {
+ unreachable("should be replaced by const-method-handle");
+ return null;
+ }
+
+ @Override
+ public MethodHandle fooDefault() {
+ return constFooDefault();
+ }
+
+ @ConstantMethodHandle(
+ kind = ConstantMethodHandle.INVOKE_VIRTUAL,
+ owner = "FooBarImpl",
+ fieldOrMethodName = "defaultToOverride",
+ descriptor = "()Ljava/lang/String;")
+ private static MethodHandle constFooBarImplDefault() {
+ unreachable("should be replaced by const-method-handle");
+ return null;
+ }
+
+ @Override
+ public MethodHandle fooBarImplDefault() {
+ return constFooBarImplDefault();
+ }
+
+ @ConstantMethodHandle(
+ kind = ConstantMethodHandle.INVOKE_INTERFACE,
+ owner = "Foo",
+ fieldOrMethodName = "nonOverriddenDefault",
+ descriptor = "()Ljava/lang/String;",
+ ownerIsInterface = true)
+ private static MethodHandle constFooNonOverriddenDefault() {
+ unreachable("should be replaced by const-method-handle");
+ return null;
+ }
+
+ @Override
+ public MethodHandle fooNonOverriddenDefault() {
+ return constFooNonOverriddenDefault();
+ }
+
+ @ConstantMethodHandle(
+ kind = ConstantMethodHandle.INVOKE_INTERFACE,
+ owner = "Bar",
+ fieldOrMethodName = "nonOverriddenDefault",
+ descriptor = "()Ljava/lang/String;",
+ ownerIsInterface = true)
+ private static MethodHandle constBarNonOverriddenDefault() {
+ unreachable("should be replaced by const-method-handle");
+ return null;
+ }
+
+ @Override
+ public MethodHandle barNonOverriddenDefault() {
+ return constBarNonOverriddenDefault();
+ }
+
+ @ConstantMethodHandle(
+ kind = ConstantMethodHandle.INVOKE_VIRTUAL,
+ owner = "FooBar",
+ fieldOrMethodName = "definedInAbstract",
+ descriptor = "()Ljava/lang/String;")
+ private static MethodHandle constFooBarDefinedInAbstract() {
+ unreachable("should be replaced by const-method-handle");
+ return null;
+ }
+
+ @Override
+ public MethodHandle fooBarDefinedInAbstract() {
+ return constFooBarDefinedInAbstract();
+ }
+
+ @ConstantMethodHandle(
+ kind = ConstantMethodHandle.INVOKE_VIRTUAL,
+ owner = "FooBarImpl",
+ fieldOrMethodName = "definedInAbstract",
+ descriptor = "()Ljava/lang/String;")
+ private static MethodHandle constFooBarImplDefinedInAbstract() {
+ unreachable("should be replaced by const-method-handle");
+ return null;
+ }
+
+ @Override
+ public MethodHandle fooBarImplDefinedInAbstract() {
+ return constFooBarImplDefinedInAbstract();
+ }
+
+ @ConstantMethodHandle(
+ kind = ConstantMethodHandle.INVOKE_VIRTUAL,
+ owner = "FooBar",
+ fieldOrMethodName = "nonDefault",
+ descriptor = "()Ljava/lang/String;")
+ private static MethodHandle constFooBarNonDefault() {
+ unreachable("should be replaced by const-method-handle");
+ return null;
+ }
+
+ @Override
+ public MethodHandle fooBarNonDefault() {
+ return constFooBarNonDefault();
+ }
+
+}
diff --git a/test/2277-methodhandle-invokeexact/src/Foo.java b/test/2277-methodhandle-invokeexact/src/Foo.java
new file mode 100644
index 0000000000..2a79b2175d
--- /dev/null
+++ b/test/2277-methodhandle-invokeexact/src/Foo.java
@@ -0,0 +1,27 @@
+/*
+ * Copyright (C) 2024 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.
+ */
+
+interface Foo {
+ default String defaultToOverride() {
+ return "Foo.defaultToOverride";
+ }
+
+ default String nonOverriddenDefault() {
+ return "Foo.nonOverriddenDefault";
+ }
+
+ String nonDefault();
+}
diff --git a/test/2277-methodhandle-invokeexact/src/FooBar.java b/test/2277-methodhandle-invokeexact/src/FooBar.java
new file mode 100644
index 0000000000..46372e0f8e
--- /dev/null
+++ b/test/2277-methodhandle-invokeexact/src/FooBar.java
@@ -0,0 +1,21 @@
+/*
+ * Copyright (C) 2024 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.
+ */
+
+abstract class FooBar implements Foo, Bar {
+ public String definedInAbstract() {
+ return "FooBar.definedInAbstract";
+ }
+}
diff --git a/test/2277-methodhandle-invokeexact/src/FooBarImpl.java b/test/2277-methodhandle-invokeexact/src/FooBarImpl.java
new file mode 100644
index 0000000000..19d9a0ae64
--- /dev/null
+++ b/test/2277-methodhandle-invokeexact/src/FooBarImpl.java
@@ -0,0 +1,22 @@
+/*
+ * Copyright (C) 2024 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.
+ */
+
+class FooBarImpl extends FooBar {
+ @Override
+ public String nonDefault() {
+ return "FooBarImpl.nonDefault";
+ }
+}
diff --git a/test/2277-methodhandle-invokeexact/src/I.java b/test/2277-methodhandle-invokeexact/src/I.java
new file mode 100644
index 0000000000..eeb41ce2a9
--- /dev/null
+++ b/test/2277-methodhandle-invokeexact/src/I.java
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2024 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.
+ */
+
+public interface I {
+ public default void defaultMethod() {
+ AbstractInvokeExactTest.STATUS = "I.defaultMethod";
+ }
+
+ public default void overrideMe() {
+ throw new RuntimeException("should be overwritten");
+ }
+
+ private String innerPrivateMethod() {
+ return "boo";
+ }
+}
diff --git a/test/2277-methodhandle-invokeexact/src/JavaApiTest.java b/test/2277-methodhandle-invokeexact/src/JavaApiTest.java
new file mode 100644
index 0000000000..77b4bc0c73
--- /dev/null
+++ b/test/2277-methodhandle-invokeexact/src/JavaApiTest.java
@@ -0,0 +1,351 @@
+/*
+ * Copyright (C) 2024 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 static java.lang.invoke.MethodType.methodType;
+
+import java.lang.invoke.MethodHandle;
+import java.lang.invoke.MethodHandles;
+import java.util.Arrays;
+import java.util.Optional;
+
+public class JavaApiTest extends AbstractInvokeExactTest {
+
+ private static final MethodHandle OPTIONAL_GET;
+
+ private static final MethodHandle VOID_METHOD;
+ private static final MethodHandle RETURN_INT;
+ private static final MethodHandle RETURN_DOUBLE;
+ private static final MethodHandle PRIVATE_INTERFACE_METHOD;
+ private static final MethodHandle B_PRIVATE_RETURN_INT;
+ private static final MethodHandle A_PRIVATE_RETURN_INT;
+ private static final MethodHandle STATIC_METHOD;
+ private static final MethodHandle EXCEPTION_THROWING_METHOD;
+ private static final MethodHandle INTERFACE_DEFAULT_METHOD;
+ private static final MethodHandle OVERWRITTEN_INTERFACE_DEFAULT_METHOD;
+
+ private static final MethodHandle SUM_I;
+ private static final MethodHandle SUM_2I;
+ private static final MethodHandle SUM_3I;
+ private static final MethodHandle SUM_4I;
+ private static final MethodHandle SUM_5I;
+ private static final MethodHandle SUM_6I;
+ private static final MethodHandle SUM_7I;
+ private static final MethodHandle SUM_8I;
+ private static final MethodHandle SUM_9I;
+ private static final MethodHandle SUM_10I;
+
+ private static final MethodHandle SUM_IJ;
+ private static final MethodHandle SUM_2IJ;
+ private static final MethodHandle SUM_3IJ;
+ private static final MethodHandle SUM_4IJ;
+ private static final MethodHandle SUM_5IJ;
+
+ private static final MethodHandle FOO_NONDEFAULT;
+ private static final MethodHandle FOOBARIMPL_NONDEFAULT;
+ private static final MethodHandle FOO_DEFAULT;
+ private static final MethodHandle BAR_DEFAULT;
+ private static final MethodHandle FOOBAR_DEFINEDINABSTRACT;
+ private static final MethodHandle FOOBAR_NONDEFAULT;
+ private static final MethodHandle FOOBARIMPL_DEFINEDINABSTRACT;
+ private static final MethodHandle FOOBARIMPL_DEFAULT;
+ private static final MethodHandle FOO_NONOVERRIDDEN_DEFAULT;
+ private static final MethodHandle BAR_NONOVERRIDDEN_DEFAULT;
+
+ static {
+ try {
+ OPTIONAL_GET = MethodHandles.lookup()
+ .findVirtual(Optional.class, "get", methodType(Object.class));
+
+ VOID_METHOD = MethodHandles.lookup()
+ .findVirtual(A.class, "voidMethod", methodType(void.class));
+ RETURN_DOUBLE = MethodHandles.lookup()
+ .findVirtual(A.class, "returnDouble", methodType(double.class));
+ RETURN_INT = MethodHandles.lookup()
+ .findVirtual(A.class, "returnInt", methodType(int.class));
+ PRIVATE_INTERFACE_METHOD = MethodHandles.privateLookupIn(I.class, MethodHandles.lookup())
+ .findVirtual(I.class, "innerPrivateMethod", methodType(String.class));
+ A_PRIVATE_RETURN_INT = MethodHandles.privateLookupIn(A.class, MethodHandles.lookup())
+ .findVirtual(A.class, "privateReturnInt", methodType(int.class));
+ B_PRIVATE_RETURN_INT = MethodHandles.privateLookupIn(B.class, MethodHandles.lookup())
+ .findVirtual(B.class, "privateReturnInt", methodType(int.class));
+ STATIC_METHOD = MethodHandles.lookup()
+ .findStatic(A.class, "staticMethod", methodType(String.class, A.class));
+ EXCEPTION_THROWING_METHOD = MethodHandles.lookup()
+ .findVirtual(A.class, "throwException", methodType(void.class));
+ INTERFACE_DEFAULT_METHOD = MethodHandles.lookup()
+ .findVirtual(I.class, "defaultMethod", methodType(void.class));
+ OVERWRITTEN_INTERFACE_DEFAULT_METHOD = MethodHandles.lookup()
+ .findVirtual(I.class, "overrideMe", methodType(void.class));
+
+ SUM_I = MethodHandles.lookup()
+ .findVirtual(Sums.class, "sum", methodType(int.class, repeat(1, int.class)));
+ SUM_2I = MethodHandles.lookup()
+ .findVirtual(Sums.class, "sum", methodType(int.class, repeat(2, int.class)));
+ SUM_3I = MethodHandles.lookup()
+ .findVirtual(Sums.class, "sum", methodType(int.class, repeat(3, int.class)));
+ SUM_4I = MethodHandles.lookup()
+ .findVirtual(Sums.class, "sum", methodType(int.class, repeat(4, int.class)));
+ SUM_5I = MethodHandles.lookup()
+ .findVirtual(Sums.class, "sum", methodType(int.class, repeat(5, int.class)));
+ SUM_6I = MethodHandles.lookup()
+ .findVirtual(Sums.class, "sum", methodType(int.class, repeat(6, int.class)));
+ SUM_7I = MethodHandles.lookup()
+ .findVirtual(Sums.class, "sum", methodType(int.class, repeat(7, int.class)));
+ SUM_8I = MethodHandles.lookup()
+ .findVirtual(Sums.class, "sum", methodType(int.class, repeat(8, int.class)));
+ SUM_9I = MethodHandles.lookup()
+ .findVirtual(Sums.class, "sum", methodType(int.class, repeat(9, int.class)));
+ SUM_10I = MethodHandles.lookup()
+ .findVirtual(Sums.class, "sum", methodType(int.class, repeat(10, int.class)));
+
+ SUM_IJ = MethodHandles.lookup()
+ .findVirtual(Sums.class, "sum", methodType(long.class, int.class, long.class));
+ SUM_2IJ = MethodHandles.lookup()
+ .findVirtual(Sums.class,
+ "sum",
+ methodType(long.class, repeat(2, int.class, long.class)));
+ SUM_3IJ = MethodHandles.lookup()
+ .findVirtual(Sums.class,
+ "sum",
+ methodType(long.class, repeat(3, int.class, long.class)));
+ SUM_4IJ = MethodHandles.lookup()
+ .findVirtual(Sums.class,
+ "sum",
+ methodType(long.class, repeat(4, int.class, long.class)));
+ SUM_5IJ = MethodHandles.lookup()
+ .findVirtual(Sums.class,
+ "sum",
+ methodType(long.class, repeat(5, int.class, long.class)));
+
+ FOO_NONDEFAULT = MethodHandles.lookup()
+ .findVirtual(Foo.class, "nonDefault", methodType(String.class));
+ FOOBARIMPL_NONDEFAULT = MethodHandles.lookup()
+ .findVirtual(FooBarImpl.class, "nonDefault", methodType(String.class));
+ FOO_DEFAULT = MethodHandles.lookup()
+ .findVirtual(Foo.class, "defaultToOverride", methodType(String.class));
+ BAR_DEFAULT = MethodHandles.lookup()
+ .findVirtual(Bar.class, "defaultToOverride", methodType(String.class));
+ FOOBAR_DEFINEDINABSTRACT = MethodHandles.lookup()
+ .findVirtual(FooBar.class, "definedInAbstract", methodType(String.class));
+ FOOBAR_NONDEFAULT = MethodHandles.lookup()
+ .findVirtual(FooBar.class, "nonDefault", methodType(String.class));
+ FOOBARIMPL_DEFINEDINABSTRACT = MethodHandles.lookup()
+ .findVirtual(FooBarImpl.class, "definedInAbstract", methodType(String.class));
+ FOOBARIMPL_DEFAULT = MethodHandles.lookup()
+ .findVirtual(FooBarImpl.class, "defaultToOverride", methodType(String.class));
+ FOO_NONOVERRIDDEN_DEFAULT = MethodHandles.lookup()
+ .findVirtual(Foo.class, "nonOverriddenDefault", methodType(String.class));
+ BAR_NONOVERRIDDEN_DEFAULT = MethodHandles.lookup()
+ .findVirtual(Bar.class, "nonOverriddenDefault", methodType(String.class));
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ private static Class<?>[] repeat(int times, Class<?> clazz) {
+ Class<?>[] classes = new Class<?>[times];
+ Arrays.fill(classes, clazz);
+ return classes;
+ }
+
+ private static Class<?>[] repeat(int times, Class<?> first, Class<?> second) {
+ Class<?>[] classes = new Class<?>[times * 2];
+ for (int i = 0; i < 2 * times;) {
+ classes[i++] = first;
+ classes[i++] = second;
+ }
+ return classes;
+ }
+
+ @Override
+ void $noinline$privateMethods() throws Throwable {
+ assertEquals("boo", (String) PRIVATE_INTERFACE_METHOD.invokeExact((I) new A()));
+
+ int privateIntA = (int) A_PRIVATE_RETURN_INT.invokeExact(new A());
+ assertEquals(1042, privateIntA);
+
+ int privateIntB = (int) B_PRIVATE_RETURN_INT.invokeExact(new B());
+ assertEquals(9999, privateIntB);
+
+ privateIntB = (int) B_PRIVATE_RETURN_INT.invokeExact((B) new A());
+ assertEquals(9999, privateIntB);
+ }
+
+ @Override
+ public MethodHandle voidMethod() {
+ return VOID_METHOD;
+ }
+
+ @Override
+ public MethodHandle returnDouble() {
+ return RETURN_DOUBLE;
+ }
+
+ @Override
+ public MethodHandle returnInt() {
+ return RETURN_INT;
+ }
+
+ @Override
+ public MethodHandle interfaceDefaultMethod() {
+ return INTERFACE_DEFAULT_METHOD;
+ }
+
+ @Override
+ public MethodHandle overwrittenInterfaceDefaultMethod() {
+ return OVERWRITTEN_INTERFACE_DEFAULT_METHOD;
+ }
+
+ @Override
+ public MethodHandle exceptionThrowingMethod() {
+ return EXCEPTION_THROWING_METHOD;
+ }
+
+ @Override
+ public MethodHandle staticMethod() {
+ return STATIC_METHOD;
+ }
+
+ @Override
+ public MethodHandle sumI() {
+ return SUM_I;
+ }
+
+ @Override
+ public MethodHandle sum2I() {
+ return SUM_2I;
+ }
+
+ @Override
+ public MethodHandle sum3I() {
+ return SUM_3I;
+ }
+
+ @Override
+ public MethodHandle sum4I() {
+ return SUM_4I;
+ }
+
+ @Override
+ public MethodHandle sum5I() {
+ return SUM_5I;
+ }
+
+ @Override
+ public MethodHandle sum6I() {
+ return SUM_6I;
+ }
+
+ @Override
+ public MethodHandle sum7I() {
+ return SUM_7I;
+ }
+
+ @Override
+ public MethodHandle sum8I() {
+ return SUM_8I;
+ }
+
+ @Override
+ public MethodHandle sum9I() {
+ return SUM_9I;
+ }
+
+ @Override
+ public MethodHandle sum10I() {
+ return SUM_10I;
+ }
+
+ @Override
+ public MethodHandle sumIJ() {
+ return SUM_IJ;
+ }
+
+ @Override
+ public MethodHandle sum2IJ() {
+ return SUM_2IJ;
+ }
+
+ @Override
+ public MethodHandle sum3IJ() {
+ return SUM_3IJ;
+ }
+
+ @Override
+ public MethodHandle sum4IJ() {
+ return SUM_4IJ;
+ }
+
+ @Override
+ public MethodHandle sum5IJ() {
+ return SUM_5IJ;
+ }
+
+ @Override
+ public MethodHandle fooNonDefault() {
+ return FOO_NONDEFAULT;
+ }
+
+ @Override
+ public MethodHandle fooBarImplNonDefault() {
+ return FOOBARIMPL_NONDEFAULT;
+ }
+
+ @Override
+ public MethodHandle barDefault() {
+ return BAR_DEFAULT;
+ }
+
+ @Override
+ public MethodHandle fooDefault() {
+ return FOO_DEFAULT;
+ }
+
+ @Override
+ public MethodHandle fooBarImplDefault() {
+ return FOOBARIMPL_DEFAULT;
+ }
+
+ @Override
+ public MethodHandle fooNonOverriddenDefault() {
+ return FOO_NONOVERRIDDEN_DEFAULT;
+ }
+
+ @Override
+ public MethodHandle barNonOverriddenDefault() {
+ return BAR_NONOVERRIDDEN_DEFAULT;
+ }
+
+ @Override
+ public MethodHandle fooBarDefinedInAbstract() {
+ return FOOBAR_DEFINEDINABSTRACT;
+ }
+
+ @Override
+ public MethodHandle fooBarImplDefinedInAbstract() {
+ return FOOBARIMPL_DEFINEDINABSTRACT;
+ }
+
+ @Override
+ public MethodHandle fooBarNonDefault() {
+ return FOOBAR_NONDEFAULT;
+ }
+
+ @Override
+ public MethodHandle optionalGet() {
+ return OPTIONAL_GET;
+ }
+}
diff --git a/test/2277-methodhandle-invokeexact/src/Main.java b/test/2277-methodhandle-invokeexact/src/Main.java
index a34e5eef60..5d4bfad519 100644
--- a/test/2277-methodhandle-invokeexact/src/Main.java
+++ b/test/2277-methodhandle-invokeexact/src/Main.java
@@ -14,539 +14,39 @@
* limitations under the License.
*/
- import static java.lang.invoke.MethodType.methodType;
-
-import java.lang.invoke.MethodHandles;
import java.lang.invoke.MethodHandle;
import java.lang.invoke.WrongMethodTypeException;
-import java.util.Arrays;
import java.util.Objects;
import java.util.Optional;
public class Main {
- private static String STATUS = "";
-
- public static void main(String[] args) throws Throwable {
- $noinline$testNoArgsCalls();
- $noinline$testMethodHandleFromOtherDex();
- Multi.$noinline$testMHFromMain(OPTIONAL_GET);
- $noinline$testWithArgs();
- $noinline$nullchecks();
- $noinline$interfaceChecks();
- $noinline$abstractClass();
- }
-
- private static void $noinline$nullchecks() throws Throwable {
- try {
- VOID_METHOD.invokeExact((A) null);
- unreachable("Receiver is null, should throw NPE");
- } catch (NullPointerException expected) {}
-
- try {
- VOID_METHOD.invokeExact((Main) null);
- unreachable("Should throw WMTE: input is of wrong type");
- } catch (WrongMethodTypeException expected) {}
-
- try {
- INTERFACE_DEFAULT_METHOD.invokeExact((I) null);
- unreachable("Receiver is null, should throw NPE");
- } catch (NullPointerException expected) {}
-
- try {
- INTERFACE_DEFAULT_METHOD.invokeExact((A) null);
- unreachable("Should throw WMTE: input is of wrong type");
- } catch (WrongMethodTypeException expected) {}
-
- try {
- MethodHandle mh = null;
- mh.invokeExact();
- unreachable("MethodHandle object is null, should throw NPE");
- } catch (NullPointerException expected) {}
- }
-
- private static void $noinline$testMethodHandleFromOtherDex() throws Throwable {
- MethodHandle mh = Multi.$noinline$getMethodHandle();
- Optional<String> nonEmpty = Optional.<String>of("hello");
- Object returnedObject = mh.invokeExact(nonEmpty);
- assertEquals("hello", returnedObject);
-
- try {
- mh.invokeExact(nonEmpty);
- unreachable("mh.type() is (Optional)Object, but callsite is (Optional)V");
- } catch (WrongMethodTypeException expected) {}
- }
-
- private static void $noinline$testNoArgsCalls() throws Throwable {
- VOID_METHOD.invokeExact(new A());
- assertEquals("A.voidMethod", STATUS);
-
- int returnedInt = (int) RETURN_INT.invokeExact(new A());
- assertEquals(42, returnedInt);
-
- double returnedDouble = (double) RETURN_DOUBLE.invokeExact(new A());
- assertEquals(42.0d, returnedDouble);
-
- try {
- INTERFACE_DEFAULT_METHOD.invokeExact(new A());
- unreachable("MethodHandle's type is (Main$I)V, but callsite is (Main$A)V");
- } catch (WrongMethodTypeException expected) {}
-
- INTERFACE_DEFAULT_METHOD.invokeExact((I) new A());
- assertEquals("I.defaultMethod", STATUS);
-
- OVERWRITTEN_INTERFACE_DEFAULT_METHOD.invokeExact((I) new A());
- assertEquals("A.overrideMe", STATUS);
-
- assertEquals("boo", (String) PRIVATE_INTERFACE_METHOD.invokeExact((I) new A()));
-
- int privateIntA = (int) A_PRIVATE_RETURN_INT.invokeExact(new A());
- assertEquals(1042, privateIntA);
-
- int privateIntB = (int) B_PRIVATE_RETURN_INT.invokeExact(new B());
- assertEquals(9999, privateIntB);
-
- privateIntB = (int) B_PRIVATE_RETURN_INT.invokeExact((B) new A());
- assertEquals(9999, privateIntB);
-
- try {
- EXCEPTION_THROWING_METHOD.invokeExact(new A());
- unreachable("Target method always throws");
- } catch (MyRuntimeException expected) {
- assertEquals("A.throwException", STATUS);
- }
-
- try {
- RETURN_INT.invokeExact(new A());
- unreachable("MethodHandle's type is (Main$A)I, but callsite type is (Main$A)V");
- } catch (WrongMethodTypeException expected) {}
-
- String returnedString = (String) STATIC_METHOD.invokeExact(new A());
- assertEquals("staticMethod", returnedString);
- }
-
- private static void $noinline$testWithArgs() throws Throwable {
- int sum = (int) SUM_I.invokeExact(new Sums(), 1);
- assertEquals(1, sum);
-
- sum = (int) SUM_2I.invokeExact(new Sums(), 1, 2);
- assertEquals(3, sum);
-
- sum = (int) SUM_3I.invokeExact(new Sums(), 1, 2, 3);
- assertEquals(6, sum);
-
- sum = (int) SUM_4I.invokeExact(new Sums(), 1, 2, 3, 4);
- assertEquals(10, sum);
+ public static void main(String[] args) throws Throwable {
+ $noinline$testMethodHandleFromOtherDex();
- sum = (int) SUM_5I.invokeExact(new Sums(), 1, 2, 3, 4, 5);
- assertEquals(15, sum);
+ new ConstMethodHandleTest().runAll();
+ new JavaApiTest().runAll();
+ }
- sum = (int) SUM_6I.invokeExact(new Sums(), 1, 2, 3, 4, 5, 6);
- assertEquals(21, sum);
+ private static void $noinline$testMethodHandleFromOtherDex() throws Throwable {
+ MethodHandle mh = Multi.$noinline$getMethodHandle();
+ Optional<String> nonEmpty = Optional.<String>of("hello");
+ Object returnedObject = mh.invokeExact(nonEmpty);
+ assertEquals("hello", returnedObject);
- sum = (int) SUM_7I.invokeExact(new Sums(), 1, 2, 3, 4, 5, 6, 7);
- assertEquals(28, sum);
-
- sum = (int) SUM_8I.invokeExact(new Sums(), 1, 2, 3, 4, 5, 6, 7, 8);
- assertEquals(36, sum);
-
- sum = (int) SUM_9I.invokeExact(new Sums(), 1, 2, 3, 4, 5, 6, 7, 8, 9);
- assertEquals(45, sum);
-
- sum = (int) SUM_10I.invokeExact(new Sums(), 1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
- assertEquals(55, sum);
-
- long lsum = (long) SUM_IJ.invokeExact(new Sums(), 1, 2L);
- assertEquals(3L, lsum);
-
- lsum = (long) SUM_2IJ.invokeExact(new Sums(), 1, 2L, 3, 4L);
- assertEquals(10L, lsum);
-
- lsum = (long) SUM_3IJ.invokeExact(new Sums(), 1, 2L, 3, 4L, 5, 6L);
- assertEquals(21L, lsum);
-
- lsum = (long) SUM_4IJ.invokeExact(new Sums(), 1, 2L, 3, 4L, 5, 6L, 7, 8L);
- assertEquals(36L, lsum);
-
- lsum = (long) SUM_5IJ.invokeExact(new Sums(), 1, 2L, 3, 4L, 5, 6L, 7, 8L, 9, 10L);
- assertEquals(55L, lsum);
- }
-
- private static void $noinline$interfaceChecks() throws Throwable {
- FooBarImpl instance = new FooBarImpl();
-
- String result = null;
- result = (String) FOO_NONDEFAULT.invokeExact((Foo) instance);
- assertEquals("FooBarImpl.nonDefault", result);
-
- result = (String) FOOBARIMPL_NONDEFAULT.invokeExact(instance);
- assertEquals("FooBarImpl.nonDefault", result);
-
- result = (String) BAR_DEFAULT.invokeExact((Bar) instance);
- assertEquals("Bar.defaultToOverride", result);
-
- result = (String) FOO_DEFAULT.invokeExact((Foo) instance);
- assertEquals("Bar.defaultToOverride", result);
-
- result = (String) FOOBARIMPL_DEFAULT.invokeExact(instance);
- assertEquals("Bar.defaultToOverride", result);
-
- result = (String) FOO_NONOVERRIDDEN_DEFAULT.invokeExact((Foo) instance);
- assertEquals("Foo.nonOverriddenDefault", result);
-
- result = (String) BAR_NONOVERRIDDEN_DEFAULT.invokeExact((Bar) instance);
- assertEquals("Foo.nonOverriddenDefault", result);
- }
-
- private static void $noinline$abstractClass() throws Throwable {
- FooBarImpl instance = new FooBarImpl();
-
- String result = null;
- result = (String) FOOBAR_DEFINEDINABSTRACT.invokeExact((FooBar) instance);
- assertEquals("FooBar.definedInAbstract", result);
-
- result = (String) FOOBARIMPL_DEFINEDINABSTRACT.invokeExact(instance);
- assertEquals("FooBar.definedInAbstract", result);
-
- FooBar fooBar = new FooBar() {
- @Override
- public String nonDefault() {
- return "anonymous.nonDefault";
- }
- };
-
- result = (String) FOOBAR_DEFINEDINABSTRACT.invokeExact(fooBar);
- assertEquals("FooBar.definedInAbstract", result);
-
- result = (String) FOOBAR_NONDEFAULT.invokeExact(fooBar);
- assertEquals("anonymous.nonDefault", result);
- }
-
- private static void assertEquals(Object expected, Object actual) {
- if (!Objects.equals(expected, actual)) {
- throw new AssertionError("Expected: " + expected + ", got: " + actual);
- }
- }
-
- private static void assertEquals(int expected, int actual) {
- if (expected != actual) {
- throw new AssertionError("Expected: " + expected + ", got: " + actual);
- }
- }
+ try {
+ mh.invokeExact(nonEmpty);
+ unreachable("mh.type() is (Optional)Object, but callsite is (Optional)V");
+ } catch (WrongMethodTypeException expected) {}
+ }
- private static void assertEquals(long expected, long actual) {
- if (expected != actual) {
- throw new AssertionError("Expected: " + expected + ", got: " + actual);
- }
+ private static void assertEquals(Object expected, Object actual) {
+ if (!Objects.equals(expected, actual)) {
+ throw new AssertionError("Expected: " + expected + ", got: " + actual);
}
+ }
- private static void assertEquals(double expected, double actual) {
- if (expected != actual) {
- throw new AssertionError("Expected: " + expected + ", got: " + actual);
- }
- }
-
- private static void unreachable(String msg) {
- throw new AssertionError("Unexpectedly reached this point, but shouldn't: " + msg);
- }
-
- private static final MethodHandle VOID_METHOD;
- private static final MethodHandle RETURN_DOUBLE;
- private static final MethodHandle RETURN_INT;
- private static final MethodHandle PRIVATE_INTERFACE_METHOD;
- private static final MethodHandle B_PRIVATE_RETURN_INT;
- private static final MethodHandle A_PRIVATE_RETURN_INT;
- private static final MethodHandle STATIC_METHOD;
- private static final MethodHandle EXCEPTION_THROWING_METHOD;
- private static final MethodHandle INTERFACE_DEFAULT_METHOD;
- private static final MethodHandle OVERWRITTEN_INTERFACE_DEFAULT_METHOD;
- private static final MethodHandle OPTIONAL_GET;
-
- private static final MethodHandle SUM_I;
- private static final MethodHandle SUM_2I;
- private static final MethodHandle SUM_3I;
- private static final MethodHandle SUM_4I;
- private static final MethodHandle SUM_5I;
- private static final MethodHandle SUM_6I;
- private static final MethodHandle SUM_7I;
- private static final MethodHandle SUM_8I;
- private static final MethodHandle SUM_9I;
- private static final MethodHandle SUM_10I;
-
- private static final MethodHandle SUM_IJ;
- private static final MethodHandle SUM_2IJ;
- private static final MethodHandle SUM_3IJ;
- private static final MethodHandle SUM_4IJ;
- private static final MethodHandle SUM_5IJ;
-
- private static final MethodHandle FOO_NONDEFAULT;
- private static final MethodHandle FOOBARIMPL_NONDEFAULT;
- private static final MethodHandle FOO_DEFAULT;
- private static final MethodHandle BAR_DEFAULT;
- private static final MethodHandle FOOBAR_DEFINEDINABSTRACT;
- private static final MethodHandle FOOBAR_NONDEFAULT;
- private static final MethodHandle FOOBARIMPL_DEFINEDINABSTRACT;
- private static final MethodHandle FOOBARIMPL_DEFAULT;
- private static final MethodHandle FOO_NONOVERRIDDEN_DEFAULT;
- private static final MethodHandle BAR_NONOVERRIDDEN_DEFAULT;
-
- static {
- try {
- VOID_METHOD = MethodHandles.lookup()
- .findVirtual(A.class, "voidMethod", methodType(void.class));
- RETURN_DOUBLE = MethodHandles.lookup()
- .findVirtual(A.class, "returnDouble", methodType(double.class));
- RETURN_INT = MethodHandles.lookup()
- .findVirtual(A.class, "returnInt", methodType(int.class));
- PRIVATE_INTERFACE_METHOD = MethodHandles.privateLookupIn(I.class, MethodHandles.lookup())
- .findVirtual(I.class, "innerPrivateMethod", methodType(String.class));
- A_PRIVATE_RETURN_INT = MethodHandles.privateLookupIn(A.class, MethodHandles.lookup())
- .findVirtual(A.class, "privateReturnInt", methodType(int.class));
- B_PRIVATE_RETURN_INT = MethodHandles.privateLookupIn(B.class, MethodHandles.lookup())
- .findVirtual(B.class, "privateReturnInt", methodType(int.class));
- STATIC_METHOD = MethodHandles.lookup()
- .findStatic(A.class, "staticMethod", methodType(String.class, A.class));
- EXCEPTION_THROWING_METHOD = MethodHandles.lookup()
- .findVirtual(A.class, "throwException", methodType(void.class));
- INTERFACE_DEFAULT_METHOD = MethodHandles.lookup()
- .findVirtual(I.class, "defaultMethod", methodType(void.class));
- OVERWRITTEN_INTERFACE_DEFAULT_METHOD = MethodHandles.lookup()
- .findVirtual(I.class, "overrideMe", methodType(void.class));
- OPTIONAL_GET = MethodHandles.lookup()
- .findVirtual(Optional.class, "get", methodType(Object.class));
-
- SUM_I = MethodHandles.lookup()
- .findVirtual(Sums.class, "sum", methodType(int.class, repeat(1, int.class)));
- SUM_2I = MethodHandles.lookup()
- .findVirtual(Sums.class, "sum", methodType(int.class, repeat(2, int.class)));
- SUM_3I = MethodHandles.lookup()
- .findVirtual(Sums.class, "sum", methodType(int.class, repeat(3, int.class)));
- SUM_4I = MethodHandles.lookup()
- .findVirtual(Sums.class, "sum", methodType(int.class, repeat(4, int.class)));
- SUM_5I = MethodHandles.lookup()
- .findVirtual(Sums.class, "sum", methodType(int.class, repeat(5, int.class)));
- SUM_6I = MethodHandles.lookup()
- .findVirtual(Sums.class, "sum", methodType(int.class, repeat(6, int.class)));
- SUM_7I = MethodHandles.lookup()
- .findVirtual(Sums.class, "sum", methodType(int.class, repeat(7, int.class)));
- SUM_8I = MethodHandles.lookup()
- .findVirtual(Sums.class, "sum", methodType(int.class, repeat(8, int.class)));
- SUM_9I = MethodHandles.lookup()
- .findVirtual(Sums.class, "sum", methodType(int.class, repeat(9, int.class)));
- SUM_10I = MethodHandles.lookup()
- .findVirtual(Sums.class, "sum", methodType(int.class, repeat(10, int.class)));
-
- SUM_IJ = MethodHandles.lookup()
- .findVirtual(Sums.class, "sum", methodType(long.class, int.class, long.class));
- SUM_2IJ = MethodHandles.lookup()
- .findVirtual(Sums.class,
- "sum",
- methodType(long.class, repeat(2, int.class, long.class)));
- SUM_3IJ = MethodHandles.lookup()
- .findVirtual(Sums.class,
- "sum",
- methodType(long.class, repeat(3, int.class, long.class)));
- SUM_4IJ = MethodHandles.lookup()
- .findVirtual(Sums.class,
- "sum",
- methodType(long.class, repeat(4, int.class, long.class)));
- SUM_5IJ = MethodHandles.lookup()
- .findVirtual(Sums.class,
- "sum",
- methodType(long.class, repeat(5, int.class, long.class)));
-
- FOO_NONDEFAULT = MethodHandles.lookup()
- .findVirtual(Foo.class, "nonDefault", methodType(String.class));
- FOOBARIMPL_NONDEFAULT = MethodHandles.lookup()
- .findVirtual(FooBarImpl.class, "nonDefault", methodType(String.class));
- FOO_DEFAULT = MethodHandles.lookup()
- .findVirtual(Foo.class, "defaultToOverride", methodType(String.class));
- BAR_DEFAULT = MethodHandles.lookup()
- .findVirtual(Bar.class, "defaultToOverride", methodType(String.class));
- FOOBAR_DEFINEDINABSTRACT = MethodHandles.lookup()
- .findVirtual(FooBar.class, "definedInAbstract", methodType(String.class));
- FOOBAR_NONDEFAULT = MethodHandles.lookup()
- .findVirtual(FooBar.class, "nonDefault", methodType(String.class));
- FOOBARIMPL_DEFINEDINABSTRACT = MethodHandles.lookup()
- .findVirtual(FooBarImpl.class, "definedInAbstract", methodType(String.class));
- FOOBARIMPL_DEFAULT = MethodHandles.lookup()
- .findVirtual(FooBarImpl.class, "defaultToOverride", methodType(String.class));
- FOO_NONOVERRIDDEN_DEFAULT = MethodHandles.lookup()
- .findVirtual(Foo.class, "nonOverriddenDefault", methodType(String.class));
- BAR_NONOVERRIDDEN_DEFAULT = MethodHandles.lookup()
- .findVirtual(Bar.class, "nonOverriddenDefault", methodType(String.class));
- } catch (Exception e) {
- throw new RuntimeException(e);
- }
- }
-
- private static Class<?>[] repeat(int times, Class<?> clazz) {
- Class<?>[] classes = new Class<?>[times];
- Arrays.fill(classes, clazz);
- return classes;
- }
-
- private static Class<?>[] repeat(int times, Class<?> first, Class<?> second) {
- Class<?>[] classes = new Class<?>[times * 2];
- for (int i = 0; i < 2 * times;) {
- classes[i++] = first;
- classes[i++] = second;
- }
- return classes;
- }
-
- static interface Foo {
- default String defaultToOverride() {
- return "Foo.defaultToOverride";
- }
-
- default String nonOverriddenDefault() {
- return "Foo.nonOverriddenDefault";
- }
-
- String nonDefault();
- }
-
- static interface Bar extends Foo {
- @Override
- default String defaultToOverride() {
- return "Bar.defaultToOverride";
- }
- }
-
- static abstract class FooBar implements Foo, Bar {
- public String definedInAbstract() {
- return "FooBar.definedInAbstract";
- }
- }
-
- static class FooBarImpl extends FooBar {
- @Override
- public String nonDefault() {
- return "FooBarImpl.nonDefault";
- }
- }
-
- static class MyRuntimeException extends RuntimeException {}
-
- static interface I {
- public default void defaultMethod() {
- STATUS = "I.defaultMethod";
- }
-
- public default void overrideMe() {
- throw new RuntimeException("should be overwritten");
- }
-
- private String innerPrivateMethod() {
- return "boo";
- }
- }
-
- static class A extends B implements I {
- public int field;
- public void voidMethod() {
- STATUS = "A.voidMethod";
- }
-
- @Override
- public void overrideMe() {
- STATUS = "A.overrideMe";
- }
-
- public void throwException() {
- STATUS = "A.throwException";
- throw new MyRuntimeException();
- }
-
- public double returnDouble() {
- return 42.0d;
- }
-
- public int returnInt() {
- return 42;
- }
-
- private int privateReturnInt() {
- return 1042;
- }
-
- public static String staticMethod(A a) {
- return "staticMethod";
- }
-
- public static double staticMethod() {
- return 41.0d;
- }
- }
-
- static class B {
- private int privateReturnInt() {
- return 9999;
- }
- }
-
- static class Sums {
- public int sum(int a) {
- return a;
- }
-
- public int sum(int a1, int a2) {
- return a1 + a2;
- }
-
- public int sum(int a1, int a2, int a3) {
- return a1 + a2 + a3;
- }
-
- public int sum(int a1, int a2, int a3, int a4) {
- return a1 + a2 + a3 + a4;
- }
-
- public int sum(int a1, int a2, int a3, int a4, int a5) {
- return a1 + a2 + a3 + a4 + a5;
- }
-
- public int sum(int a1, int a2, int a3, int a4, int a5, int a6) {
- return a1 + a2 + a3 + a4 + a5 + a6;
- }
-
- public int sum(int a1, int a2, int a3, int a4, int a5, int a6, int a7) {
- return a1 + a2 + a3 + a4 + a5 + a6 + a7;
- }
-
- public int sum(int a1, int a2, int a3, int a4, int a5, int a6, int a7, int a8) {
- return a1 + a2 + a3 + a4 + a5 + a6 + a7 + a8;
- }
-
- public int sum(int a1, int a2, int a3, int a4, int a5, int a6, int a7, int a8, int a9) {
- return a1 + a2 + a3 + a4 + a5 + a6 + a7 + a8 + a9;
- }
-
- public int sum(int a1, int a2, int a3, int a4, int a5, int a6, int a7, int a8, int a9,
- int a10) {
- return a1 + a2 + a3 + a4 + a5 + a6 + a7 + a8 + a9 + a10;
- }
-
- public long sum(int a1, long a2) {
- return a1 + a2;
- }
-
- public long sum(int a1, long a2, int a3, long a4) {
- return a1 + a2 + a3 + a4;
- }
-
- public long sum(int a1, long a2, int a3, long a4, int a5, long a6) {
- return a1 + a2 + a3 + a4 + a5 + a6;
- }
-
- public long sum(int a1, long a2, int a3, long a4, int a5, long a6, int a7, long a8) {
- return a1 + a2 + a3 + a4 + a5 + a6 + a7 + a8;
- }
-
- public long sum(int a1, long a2, int a3, long a4, int a5, long a6, int a7, long a8, int a9,
- long a10) {
- return a1 + a2 + a3 + a4 + a5 + a6 + a7 + a8 + a9 + a10;
- }
- }
+ private static void unreachable(String msg) {
+ throw new AssertionError("Unexpectedly reached this point, but shouldn't: " + msg);
+ }
}
diff --git a/test/2277-methodhandle-invokeexact/src/MyRuntimeException.java b/test/2277-methodhandle-invokeexact/src/MyRuntimeException.java
new file mode 100644
index 0000000000..623843d4e6
--- /dev/null
+++ b/test/2277-methodhandle-invokeexact/src/MyRuntimeException.java
@@ -0,0 +1,17 @@
+/*
+ * Copyright (C) 2024 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.
+ */
+
+public class MyRuntimeException extends RuntimeException {}
diff --git a/test/2277-methodhandle-invokeexact/src/Sums.java b/test/2277-methodhandle-invokeexact/src/Sums.java
new file mode 100644
index 0000000000..cb5d852d9d
--- /dev/null
+++ b/test/2277-methodhandle-invokeexact/src/Sums.java
@@ -0,0 +1,78 @@
+/*
+ * Copyright (C) 2024 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.
+ */
+public class Sums {
+ public int sum(int a) {
+ return a;
+ }
+
+ public int sum(int a1, int a2) {
+ return a1 + a2;
+ }
+
+ public int sum(int a1, int a2, int a3) {
+ return a1 + a2 + a3;
+ }
+
+ public int sum(int a1, int a2, int a3, int a4) {
+ return a1 + a2 + a3 + a4;
+ }
+
+ public int sum(int a1, int a2, int a3, int a4, int a5) {
+ return a1 + a2 + a3 + a4 + a5;
+ }
+
+ public int sum(int a1, int a2, int a3, int a4, int a5, int a6) {
+ return a1 + a2 + a3 + a4 + a5 + a6;
+ }
+
+ public int sum(int a1, int a2, int a3, int a4, int a5, int a6, int a7) {
+ return a1 + a2 + a3 + a4 + a5 + a6 + a7;
+ }
+
+ public int sum(int a1, int a2, int a3, int a4, int a5, int a6, int a7, int a8) {
+ return a1 + a2 + a3 + a4 + a5 + a6 + a7 + a8;
+ }
+
+ public int sum(int a1, int a2, int a3, int a4, int a5, int a6, int a7, int a8, int a9) {
+ return a1 + a2 + a3 + a4 + a5 + a6 + a7 + a8 + a9;
+ }
+
+ public int sum(int a1, int a2, int a3, int a4, int a5, int a6, int a7, int a8, int a9,
+ int a10) {
+ return a1 + a2 + a3 + a4 + a5 + a6 + a7 + a8 + a9 + a10;
+ }
+
+ public long sum(int a1, long a2) {
+ return a1 + a2;
+ }
+
+ public long sum(int a1, long a2, int a3, long a4) {
+ return a1 + a2 + a3 + a4;
+ }
+
+ public long sum(int a1, long a2, int a3, long a4, int a5, long a6) {
+ return a1 + a2 + a3 + a4 + a5 + a6;
+ }
+
+ public long sum(int a1, long a2, int a3, long a4, int a5, long a6, int a7, long a8) {
+ return a1 + a2 + a3 + a4 + a5 + a6 + a7 + a8;
+ }
+
+ public long sum(int a1, long a2, int a3, long a4, int a5, long a6, int a7, long a8, int a9,
+ long a10) {
+ return a1 + a2 + a3 + a4 + a5 + a6 + a7 + a8 + a9 + a10;
+ }
+}