MethodHandles: Support and tests for invokeWithArguments.
Tracks libcore change a8cf0bffdb9e9cf031efd0d3c8b5645d45963562.
Test: make test-art-host
Change-Id: I65fbf3a82b629585324c477bdce6dabd63ae408e
diff --git a/runtime/class_linker_test.cc b/runtime/class_linker_test.cc
index 7b6c0dc..c311542 100644
--- a/runtime/class_linker_test.cc
+++ b/runtime/class_linker_test.cc
@@ -743,6 +743,8 @@
MethodHandleImplOffsets() : CheckOffsets<mirror::MethodHandleImpl>(
false, "Ljava/lang/invoke/MethodHandle;") {
addOffset(OFFSETOF_MEMBER(mirror::MethodHandleImpl, art_field_or_method_), "artFieldOrMethod");
+ addOffset(OFFSETOF_MEMBER(mirror::MethodHandleImpl, cached_spread_invoker_),
+ "cachedSpreadInvoker");
addOffset(OFFSETOF_MEMBER(mirror::MethodHandleImpl, handle_kind_), "handleKind");
addOffset(OFFSETOF_MEMBER(mirror::MethodHandleImpl, nominal_type_), "nominalType");
addOffset(OFFSETOF_MEMBER(mirror::MethodHandleImpl, method_type_), "type");
diff --git a/runtime/mirror/method_handle_impl.h b/runtime/mirror/method_handle_impl.h
index abe999a..2f26a22 100644
--- a/runtime/mirror/method_handle_impl.h
+++ b/runtime/mirror/method_handle_impl.h
@@ -84,10 +84,12 @@
static mirror::Class* StaticClass() REQUIRES_SHARED(Locks::mutator_lock_);
private:
+ // NOTE: cached_spread_invoker_ isn't used by the runtime.
+ HeapReference<mirror::MethodHandle> cached_spread_invoker_;
HeapReference<mirror::MethodType> nominal_type_;
HeapReference<mirror::MethodType> method_type_;
- uint64_t art_field_or_method_;
uint32_t handle_kind_;
+ uint64_t art_field_or_method_;
private:
static MemberOffset NominalTypeOffset() {
diff --git a/test/957-methodhandle-transforms/expected.txt b/test/957-methodhandle-transforms/expected.txt
index 154051f..383ccd9 100644
--- a/test/957-methodhandle-transforms/expected.txt
+++ b/test/957-methodhandle-transforms/expected.txt
@@ -47,3 +47,6 @@
a: a, b:1.0, c: 2.0, d: 3.0
a: a, b:1.0, c: 2.0
a: a, b:1.0, c: 2.0
+a: a, b:b, c: c
+a: a, b:b, c: c
+a: a, b:43
diff --git a/test/957-methodhandle-transforms/src/Main.java b/test/957-methodhandle-transforms/src/Main.java
index 3271108..d0bd816 100644
--- a/test/957-methodhandle-transforms/src/Main.java
+++ b/test/957-methodhandle-transforms/src/Main.java
@@ -36,6 +36,7 @@
testInvokers();
testSpreaders_reference();
testSpreaders_primitive();
+ testInvokeWithArguments();
}
public static void testThrowException() throws Throwable {
@@ -1223,6 +1224,34 @@
assertEquals(51, ret);
}
+ public static void testInvokeWithArguments() throws Throwable {
+ MethodType methodType = MethodType.methodType(int.class,
+ new Class<?>[] { String.class, String.class, String.class });
+ MethodHandle handle = MethodHandles.lookup().findStatic(
+ Main.class, "spreadReferences", methodType);
+
+ Object ret = handle.invokeWithArguments(new Object[] { "a", "b", "c"});
+ assertEquals(42, (int) ret);
+ handle.invokeWithArguments(new String[] { "a", "b", "c" });
+ assertEquals(42, (int) ret);
+
+ // Pass in an array that's too small. Should throw an IAE.
+ try {
+ handle.invokeWithArguments(new Object[] { "a", "b" });
+ fail();
+ } catch (IllegalArgumentException expected) {
+ }
+
+ // Test implicit unboxing.
+ MethodType methodType2 = MethodType.methodType(int.class,
+ new Class<?>[] { String.class, int.class });
+ MethodHandle handle2 = MethodHandles.lookup().findStatic(
+ Main.class, "spreadReferences_Unbox", methodType2);
+
+ ret = (int) handle2.invokeWithArguments(new Object[] { "a", 43 });
+ assertEquals(43, (int) ret);
+ }
+
public static void fail() {
System.out.println("FAIL");
Thread.dumpStack();