MethodHandles: Implement MethodHandle.asType.

Tracks libcore change 16fa583fb5ee489.

Test: make test-art-host
Bug: 30550796

Change-Id: I2457b563f67a183c4eebf94ddbe74cc55f772ee0
diff --git a/runtime/interpreter/interpreter_common.cc b/runtime/interpreter/interpreter_common.cc
index 1a99100..e607d4d 100644
--- a/runtime/interpreter/interpreter_common.cc
+++ b/runtime/interpreter/interpreter_common.cc
@@ -833,9 +833,23 @@
   const MethodHandleKind handle_kind = method_handle->GetHandleKind();
   Handle<mirror::MethodType> handle_type(hs.NewHandle(method_handle->GetMethodType()));
   CHECK(handle_type.Get() != nullptr);
-  if (UNLIKELY(is_invoke_exact && !callsite_type->IsExactMatch(handle_type.Get()))) {
-    ThrowWrongMethodTypeException(handle_type.Get(), callsite_type.Get());
-    return false;
+  if (is_invoke_exact) {
+    // We need to check the nominal type of the handle in addition to the
+    // real type. The "nominal" type is present when MethodHandle.asType is
+    // called any handle, and results in the declared type of the handle
+    // changing.
+    ObjPtr<mirror::MethodType> nominal_type(method_handle->GetNominalType());
+    ObjPtr<mirror::MethodType> check_type(nullptr);
+    if (LIKELY(nominal_type.Ptr() == nullptr)) {
+      check_type.Assign(handle_type.Get());
+    } else {
+      check_type.Assign(nominal_type.Ptr());
+    }
+
+    if (UNLIKELY(!callsite_type->IsExactMatch(check_type.Ptr()))) {
+      ThrowWrongMethodTypeException(check_type.Ptr(), callsite_type.Get());
+      return false;
+    }
   }
 
   uint32_t arg[Instruction::kMaxVarArgRegs] = {};