MethodHandles: Implement invoker / exactInvoker.

Accompanies libcore commit 0a72753297b45d08ca33cf7e87888f5fee87f69e.

- Adds callsiteType field to mirror::EmulatedStackFrame.
- Adds unit tests for MethodHandles.invoker /
  MethodHandles.exactInvoker.

Test: art/test/run-test --host 957
Change-Id: Ia27742c80de560a5b38f792bfa97664678cec8ae
diff --git a/runtime/class_linker_test.cc b/runtime/class_linker_test.cc
index 42108d8..80505d1 100644
--- a/runtime/class_linker_test.cc
+++ b/runtime/class_linker_test.cc
@@ -757,6 +757,7 @@
 struct EmulatedStackFrameOffsets : public CheckOffsets<mirror::EmulatedStackFrame> {
   EmulatedStackFrameOffsets() : CheckOffsets<mirror::EmulatedStackFrame>(
       false, "Ldalvik/system/EmulatedStackFrame;") {
+    addOffset(OFFSETOF_MEMBER(mirror::EmulatedStackFrame, callsite_type_), "callsiteType");
     addOffset(OFFSETOF_MEMBER(mirror::EmulatedStackFrame, references_), "references");
     addOffset(OFFSETOF_MEMBER(mirror::EmulatedStackFrame, stack_frame_), "stackFrame");
     addOffset(OFFSETOF_MEMBER(mirror::EmulatedStackFrame, type_), "type");
diff --git a/runtime/mirror/emulated_stack_frame.cc b/runtime/mirror/emulated_stack_frame.cc
index d607040..978cc32 100644
--- a/runtime/mirror/emulated_stack_frame.cc
+++ b/runtime/mirror/emulated_stack_frame.cc
@@ -195,6 +195,7 @@
   // Step 5: Construct the EmulatedStackFrame object.
   Handle<EmulatedStackFrame> sf(hs.NewHandle(
       ObjPtr<EmulatedStackFrame>::DownCast(StaticClass()->AllocObject(self))));
+  sf->SetFieldObject<false>(CallsiteTypeOffset(), caller_type.Get());
   sf->SetFieldObject<false>(TypeOffset(), callee_type.Get());
   sf->SetFieldObject<false>(ReferencesOffset(), references.Get());
   sf->SetFieldObject<false>(StackFrameOffset(), stack_frame.Get());
diff --git a/runtime/mirror/emulated_stack_frame.h b/runtime/mirror/emulated_stack_frame.h
index d83a536..ddd84a1 100644
--- a/runtime/mirror/emulated_stack_frame.h
+++ b/runtime/mirror/emulated_stack_frame.h
@@ -81,6 +81,10 @@
         OFFSET_OF_OBJECT_MEMBER(EmulatedStackFrame, stack_frame_));
   }
 
+  static MemberOffset CallsiteTypeOffset() {
+    return MemberOffset(OFFSETOF_MEMBER(EmulatedStackFrame, callsite_type_));
+  }
+
   static MemberOffset TypeOffset() {
     return MemberOffset(OFFSETOF_MEMBER(EmulatedStackFrame, type_));
   }
@@ -93,6 +97,7 @@
     return MemberOffset(OFFSETOF_MEMBER(EmulatedStackFrame, stack_frame_));
   }
 
+  HeapReference<mirror::MethodType> callsite_type_;
   HeapReference<mirror::ObjectArray<mirror::Object>> references_;
   HeapReference<mirror::ByteArray> stack_frame_;
   HeapReference<mirror::MethodType> type_;
diff --git a/test/957-methodhandle-transforms/src/Main.java b/test/957-methodhandle-transforms/src/Main.java
index 5806509..c0d3b58 100644
--- a/test/957-methodhandle-transforms/src/Main.java
+++ b/test/957-methodhandle-transforms/src/Main.java
@@ -33,6 +33,7 @@
     testBindTo();
     testFilterReturnValue();
     testPermuteArguments();
+    testInvokers();
   }
 
   public static void testThrowException() throws Throwable {
@@ -888,6 +889,38 @@
     }
   }
 
+  private static Object returnBar() {
+    return "bar";
+  }
+
+  public static void testInvokers() throws Throwable {
+    final MethodType targetType = MethodType.methodType(String.class, String.class);
+    final MethodHandle target = MethodHandles.lookup().findVirtual(
+        String.class, "concat", targetType);
+
+    MethodHandle invoker = MethodHandles.invoker(target.type());
+    assertEquals("barbar", (String) invoker.invoke(target, "bar", "bar"));
+    assertEquals("barbar", (String) invoker.invoke(target, (Object) returnBar(), "bar"));
+    try {
+      String foo = (String) invoker.invoke(target, "bar", "bar", 24);
+      fail();
+    } catch (WrongMethodTypeException expected) {
+    }
+
+    MethodHandle exactInvoker = MethodHandles.exactInvoker(target.type());
+    assertEquals("barbar", (String) exactInvoker.invoke(target, "bar", "bar"));
+    try {
+      String foo = (String) exactInvoker.invoke(target, (Object) returnBar(), "bar");
+      fail();
+    } catch (WrongMethodTypeException expected) {
+    }
+    try {
+      String foo = (String) exactInvoker.invoke(target, "bar", "bar", 24);
+      fail();
+    } catch (WrongMethodTypeException expected) {
+    }
+  }
+
   public static void fail() {
     System.out.println("FAIL");
     Thread.dumpStack();