Support directly invoking interface default methods

With the Java 8 Language one is allowed to directly call default
interface methods of interfaces one (directly) implements through the
use of the super keyword. We support this behavior through the
invoke-super opcode with the target being an interface.

We add 3 tests for this behavior.

Currently only supports slow-path interpreter.

Invoke-super is currently extremely slow.

Bug: 24618811

Change-Id: I7e06e17326f7dbae0116bd7dfefca151f0092bd2
diff --git a/runtime/verifier/method_verifier.cc b/runtime/verifier/method_verifier.cc
index d75587b..1c95648 100644
--- a/runtime/verifier/method_verifier.cc
+++ b/runtime/verifier/method_verifier.cc
@@ -3639,8 +3639,9 @@
   return *common_super;
 }
 
+// TODO Maybe I should just add a METHOD_SUPER to MethodType?
 ArtMethod* MethodVerifier::ResolveMethodAndCheckAccess(
-    uint32_t dex_method_idx, MethodType method_type) {
+    uint32_t dex_method_idx, MethodType method_type, bool is_super) {
   const DexFile::MethodId& method_id = dex_file_->GetMethodId(dex_method_idx);
   const RegType& klass_type = ResolveClassAndCheckAccess(method_id.class_idx_);
   if (klass_type.IsConflict()) {
@@ -3667,6 +3668,8 @@
       res_method = klass->FindDirectMethod(name, signature, pointer_size);
     } else if (method_type == METHOD_INTERFACE) {
       res_method = klass->FindInterfaceMethod(name, signature, pointer_size);
+    } else if (is_super && klass->IsInterface()) {
+      res_method = klass->FindInterfaceMethod(name, signature, pointer_size);
     } else {
       res_method = klass->FindVirtualMethod(name, signature, pointer_size);
     }
@@ -3939,7 +3942,7 @@
   // we're making.
   const uint32_t method_idx = (is_range) ? inst->VRegB_3rc() : inst->VRegB_35c();
 
-  ArtMethod* res_method = ResolveMethodAndCheckAccess(method_idx, method_type);
+  ArtMethod* res_method = ResolveMethodAndCheckAccess(method_idx, method_type, is_super);
   if (res_method == nullptr) {  // error or class is unresolved
     // Check what we can statically.
     if (!have_pending_hard_failure_) {
@@ -3949,24 +3952,32 @@
   }
 
   // If we're using invoke-super(method), make sure that the executing method's class' superclass
-  // has a vtable entry for the target method.
+  // has a vtable entry for the target method. Or the target is on a interface.
   if (is_super) {
     DCHECK(method_type == METHOD_VIRTUAL);
-    const RegType& super = GetDeclaringClass().GetSuperClass(&reg_types_);
-    if (super.IsUnresolvedTypes()) {
-      Fail(VERIFY_ERROR_NO_METHOD) << "unknown super class in invoke-super from "
-                                   << PrettyMethod(dex_method_idx_, *dex_file_)
-                                   << " to super " << PrettyMethod(res_method);
-      return nullptr;
-    }
-    mirror::Class* super_klass = super.GetClass();
-    if (res_method->GetMethodIndex() >= super_klass->GetVTableLength()) {
-      Fail(VERIFY_ERROR_NO_METHOD) << "invalid invoke-super from "
-                                   << PrettyMethod(dex_method_idx_, *dex_file_)
-                                   << " to super " << super
-                                   << "." << res_method->GetName()
-                                   << res_method->GetSignature();
-      return nullptr;
+    if (res_method->GetDeclaringClass()->IsInterface()) {
+      // TODO Fill in this part. Verify what we can...
+      if (Runtime::Current()->IsAotCompiler()) {
+        Fail(VERIFY_ERROR_FORCE_INTERPRETER) << "Currently we only allow invoke-super in "
+                                             << "interpreter when using interface methods";
+      }
+    } else {
+      const RegType& super = GetDeclaringClass().GetSuperClass(&reg_types_);
+      if (super.IsUnresolvedTypes()) {
+        Fail(VERIFY_ERROR_NO_METHOD) << "unknown super class in invoke-super from "
+                                    << PrettyMethod(dex_method_idx_, *dex_file_)
+                                    << " to super " << PrettyMethod(res_method);
+        return nullptr;
+      }
+      mirror::Class* super_klass = super.GetClass();
+      if (res_method->GetMethodIndex() >= super_klass->GetVTableLength()) {
+        Fail(VERIFY_ERROR_NO_METHOD) << "invalid invoke-super from "
+                                    << PrettyMethod(dex_method_idx_, *dex_file_)
+                                    << " to super " << super
+                                    << "." << res_method->GetName()
+                                    << res_method->GetSignature();
+        return nullptr;
+      }
     }
   }
 
diff --git a/runtime/verifier/method_verifier.h b/runtime/verifier/method_verifier.h
index 79db576..ec0a8f9 100644
--- a/runtime/verifier/method_verifier.h
+++ b/runtime/verifier/method_verifier.h
@@ -654,7 +654,7 @@
    * the referrer can access the resolved method.
    * Does not throw exceptions.
    */
-  ArtMethod* ResolveMethodAndCheckAccess(uint32_t method_idx, MethodType method_type)
+  ArtMethod* ResolveMethodAndCheckAccess(uint32_t method_idx, MethodType method_type, bool is_super)
       SHARED_REQUIRES(Locks::mutator_lock_);
 
   /*
diff --git a/runtime/verifier/reg_type.h b/runtime/verifier/reg_type.h
index 80b751c..7c7981e 100644
--- a/runtime/verifier/reg_type.h
+++ b/runtime/verifier/reg_type.h
@@ -246,28 +246,18 @@
   }
 
   /*
-   * A basic Join operation on classes. For a pair of types S and T the Join,
-   *written S v T = J, is
-   * S <: J, T <: J and for-all U such that S <: U, T <: U then J <: U. That is
-   *J is the parent of
-   * S and T such that there isn't a parent of both S and T that isn't also the
-   *parent of J (ie J
+   * A basic Join operation on classes. For a pair of types S and T the Join, written S v T = J, is
+   * S <: J, T <: J and for-all U such that S <: U, T <: U then J <: U. That is J is the parent of
+   * S and T such that there isn't a parent of both S and T that isn't also the parent of J (ie J
    * is the deepest (lowest upper bound) parent of S and T).
    *
-   * This operation applies for regular classes and arrays, however, for
-   *interface types there
-   * needn't be a partial ordering on the types. We could solve the problem of a
-   *lack of a partial
-   * order by introducing sets of types, however, the only operation permissible
-   *on an interface is
-   * invoke-interface. In the tradition of Java verifiers [1] we defer the
-   *verification of interface
-   * types until an invoke-interface call on the interface typed reference at
-   *runtime and allow
-   * the perversion of Object being assignable to an interface type (note,
-   *however, that we don't
-   * allow assignment of Object or Interface to any concrete class and are
-   *therefore type safe).
+   * This operation applies for regular classes and arrays, however, for interface types there
+   * needn't be a partial ordering on the types. We could solve the problem of a lack of a partial
+   * order by introducing sets of types, however, the only operation permissible on an interface is
+   * invoke-interface. In the tradition of Java verifiers [1] we defer the verification of interface
+   * types until an invoke-interface call on the interface typed reference at runtime and allow
+   * the perversion of Object being assignable to an interface type (note, however, that we don't
+   * allow assignment of Object or Interface to any concrete class and are therefore type safe).
    *
    * [1] Java bytecode verification: algorithms and formalizations, Xavier Leroy
    */