Revert "Revert "Interpreter: Add support for direct handle invokes on methods.""

This reverts commit cfa61ad52077df66a448b84c360b12bc6f0e3f51.

Test flakiness in 956-methodhandles is fixed by
d08e39b6f02368aaa668b5aae6b6077b3eb44d9c.

Test: make test-art-host

Change-Id: I56e02e9a5bbc2b992cf746a92fd95ea77d32456c
diff --git a/runtime/interpreter/interpreter_common.cc b/runtime/interpreter/interpreter_common.cc
index 09d1167..b71236b 100644
--- a/runtime/interpreter/interpreter_common.cc
+++ b/runtime/interpreter/interpreter_common.cc
@@ -667,11 +667,39 @@
         return false;
       }
     } else if (handle_kind == kInvokeDirect) {
-      // TODO(narayan) : We need to handle the case where the target method is a
-      // constructor here. Also the case where we don't want to dynamically
-      // dispatch based on the type of the receiver.
-      UNIMPLEMENTED(FATAL) << "Direct invokes are not implemented yet.";
-      return false;
+      if (called_method->IsConstructor()) {
+        // TODO(narayan) : We need to handle the case where the target method is a
+        // constructor here.
+        UNIMPLEMENTED(FATAL) << "Direct invokes for constructors are not implemented yet.";
+        return false;
+      }
+
+      // Nothing special to do in the case where we're not dealing with a
+      // constructor. It's a private method, and we've already access checked at
+      // the point of creating the handle.
+    } else if (handle_kind == kInvokeSuper) {
+      mirror::Class* declaring_class = called_method->GetDeclaringClass();
+
+      // Note that we're not dynamically dispatching on the type of the receiver
+      // here. We use the static type of the "receiver" object that we've
+      // recorded in the method handle's type, which will be the same as the
+      // special caller that was specified at the point of lookup.
+      mirror::Class* referrer_class = handle_type->GetPTypes()->Get(0);
+      if (!declaring_class->IsInterface()) {
+        mirror::Class* super_class = referrer_class->GetSuperClass();
+        uint16_t vtable_index = called_method->GetMethodIndex();
+        DCHECK(super_class != nullptr);
+        DCHECK(super_class->HasVTable());
+        // Note that super_class is a super of referrer_class and called_method
+        // will always be declared by super_class (or one of its super classes).
+        DCHECK_LT(vtable_index, super_class->GetVTableLength());
+        called_method = super_class->GetVTableEntry(vtable_index, kRuntimePointerSize);
+      } else {
+        called_method = referrer_class->FindVirtualMethodForInterfaceSuper(
+            called_method, kRuntimePointerSize);
+      }
+
+      CHECK(called_method != nullptr);
     }
 
     // NOTE: handle_kind == kInvokeStatic needs no special treatment here. We