MethodHandles: fix missing nominal type return value conversion

Fixes missing adaption path when a method handle has a nominal type
set from MH.asType().

Bug: 113855305
Test: art/test/run-test --host 956
Change-Id: Id203e5ab6bd5df03fd728944f52f6e267c3a38f3
diff --git a/runtime/method_handles.cc b/runtime/method_handles.cc
index 38bd611..2dc9f67 100644
--- a/runtime/method_handles.cc
+++ b/runtime/method_handles.cc
@@ -419,6 +419,7 @@
 static inline bool MethodHandleInvokeMethod(ArtMethod* called_method,
                                             Handle<mirror::MethodType> callsite_type,
                                             Handle<mirror::MethodType> target_type,
+                                            Handle<mirror::MethodType> nominal_type,
                                             Thread* self,
                                             ShadowFrame& shadow_frame,
                                             const InstructionOperands* const operands,
@@ -543,6 +544,11 @@
     return false;
   }
 
+  if (nominal_type != nullptr) {
+    return ConvertReturnValue(nominal_type, target_type, result) &&
+        ConvertReturnValue(callsite_type, nominal_type, result);
+  }
+
   return ConvertReturnValue(callsite_type, target_type, result);
 }
 
@@ -714,8 +720,9 @@
                                const InstructionOperands* const operands,
                                JValue* result)
   REQUIRES_SHARED(Locks::mutator_lock_) {
-  StackHandleScope<1> hs(self);
+  StackHandleScope<2> hs(self);
   Handle<mirror::MethodType> handle_type(hs.NewHandle(method_handle->GetMethodType()));
+  Handle<mirror::MethodType> nominal_handle_type(hs.NewHandle(method_handle->GetNominalType()));
   const mirror::MethodHandle::Kind handle_kind = method_handle->GetHandleKind();
   DCHECK(IsInvoke(handle_kind));
 
@@ -761,6 +768,7 @@
     return MethodHandleInvokeMethod(called_method,
                                     callsite_type,
                                     handle_type,
+                                    nominal_handle_type,
                                     self,
                                     shadow_frame,
                                     operands,
diff --git a/test/956-methodhandles/src/Main.java b/test/956-methodhandles/src/Main.java
index a54b481..e70c83b 100644
--- a/test/956-methodhandles/src/Main.java
+++ b/test/956-methodhandles/src/Main.java
@@ -95,6 +95,11 @@
     }
   }
 
+  public static class I {
+    public static void someVoidMethod() {
+    }
+  }
+
   public static void main(String[] args) throws Throwable {
     testfindSpecial_invokeSuperBehaviour();
     testfindSpecial_invokeDirectBehaviour();
@@ -635,6 +640,30 @@
       fail();
     } catch (WrongMethodTypeException expected) {
     }
+
+    // Zero / null introduction
+    MethodHandle voidMH = MethodHandles.lookup().findStatic(I.class, "someVoidMethod",
+                                                            MethodType.methodType(void.class));
+    {
+      MethodHandle booleanMH = voidMH.asType(MethodType.methodType(boolean.class));
+      assertEquals(boolean.class, booleanMH.type().returnType());
+      assertEquals(false, booleanMH.invoke());
+    }
+    {
+      MethodHandle intMH = voidMH.asType(MethodType.methodType(int.class));
+      assertEquals(int.class, intMH.type().returnType());
+      assertEquals(0, intMH.invoke());
+    }
+    {
+      MethodHandle longMH = voidMH.asType(MethodType.methodType(long.class));
+      assertEquals(long.class, longMH.type().returnType());
+      assertEquals(0L, longMH.invoke());
+    }
+    {
+      MethodHandle objMH = voidMH.asType(MethodType.methodType(Object.class));
+      assertEquals(Object.class, objMH.type().returnType());
+      assertEquals(null, objMH.invoke());
+    }
   }
 
   public static void assertTrue(boolean value) {