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/compiler/dex/quick/quick_compiler.cc b/compiler/dex/quick/quick_compiler.cc
index 3260a7a..ebc9a2c 100644
--- a/compiler/dex/quick/quick_compiler.cc
+++ b/compiler/dex/quick/quick_compiler.cc
@@ -520,7 +520,12 @@
 // In the rare cases we compile experimental opcodes, the runtime has an option to enable it,
 // which will force scanning for any unsupported opcodes.
 static bool SkipScanningUnsupportedOpcodes(InstructionSet instruction_set) {
-  if (UNLIKELY(kUnsupportedOpcodesSize[instruction_set] == 0U)) {
+  Runtime* runtime = Runtime::Current();
+  if (UNLIKELY(runtime->AreExperimentalFlagsEnabled(ExperimentalFlags::kDefaultMethods))) {
+    // Always need to scan opcodes if we have default methods since invoke-super for interface
+    // methods is never going to be supported in the quick compiler.
+    return false;
+  } else if (UNLIKELY(kUnsupportedOpcodesSize[instruction_set] == 0U)) {
     // All opcodes are supported no matter what. Usually not the case
     // since experimental opcodes are not implemented in the quick compiler.
     return true;
@@ -538,8 +543,28 @@
   }
 }
 
+bool QuickCompiler::CanCompileInstruction(const MIR* mir,
+                                          const DexFile& dex_file) const {
+  switch (mir->dalvikInsn.opcode) {
+    // Quick compiler won't support new instruction semantics to invoke-super into an interface
+    // method
+    case Instruction::INVOKE_SUPER:  // Fall-through
+    case Instruction::INVOKE_SUPER_RANGE: {
+      DCHECK(mir->dalvikInsn.IsInvoke());
+      uint32_t invoke_method_idx = mir->dalvikInsn.vB;
+      const DexFile::MethodId& method_id = dex_file.GetMethodId(invoke_method_idx);
+      const DexFile::ClassDef* class_def = dex_file.FindClassDef(method_id.class_idx_);
+      // False if we are an interface i.e. !(java_access_flags & kAccInterface)
+      return class_def != nullptr && ((class_def->GetJavaAccessFlags() & kAccInterface) == 0);
+    }
+    default:
+      return true;
+  }
+}
+
 // Skip the method that we do not support currently.
-bool QuickCompiler::CanCompileMethod(uint32_t method_idx, const DexFile& dex_file,
+bool QuickCompiler::CanCompileMethod(uint32_t method_idx,
+                                     const DexFile& dex_file,
                                      CompilationUnit* cu) const {
   // This is a limitation in mir_graph. See MirGraph::SetNumSSARegs.
   if (cu->mir_graph->GetNumOfCodeAndTempVRs() > kMaxAllowedDalvikRegisters) {
@@ -580,6 +605,9 @@
               << MIRGraph::extended_mir_op_names_[opcode - kMirOpFirst];
         }
         return false;
+      } else if (!CanCompileInstruction(mir, dex_file)) {
+        VLOG(compiler) << "Cannot compile dalvik opcode : " << mir->dalvikInsn.opcode;
+        return false;
       }
       // Check if it invokes a prototype that we cannot support.
       if (std::find(kInvokeOpcodes, kInvokeOpcodes + arraysize(kInvokeOpcodes), opcode)