diff options
author | 2015-09-21 11:36:30 -0700 | |
---|---|---|
committer | 2016-01-12 15:40:31 -0800 | |
commit | 705ad49f353d3f90d8b63625aca2c2035bacdbef (patch) | |
tree | ac70af53158a80bc35c057aefae11428281df9ac /compiler | |
parent | fae1db92d8433d0f75258c190bcf2c940731f036 (diff) |
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
Diffstat (limited to 'compiler')
-rw-r--r-- | compiler/dex/quick/quick_compiler.cc | 32 | ||||
-rw-r--r-- | compiler/dex/quick/quick_compiler.h | 3 |
2 files changed, 33 insertions, 2 deletions
diff --git a/compiler/dex/quick/quick_compiler.cc b/compiler/dex/quick/quick_compiler.cc index 3260a7a050..ebc9a2c9ea 100644 --- a/compiler/dex/quick/quick_compiler.cc +++ b/compiler/dex/quick/quick_compiler.cc @@ -520,7 +520,12 @@ static bool CanCompileShorty(const char* shorty, InstructionSet instruction_set) // 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 @@ static bool SkipScanningUnsupportedOpcodes(InstructionSet instruction_set) { } } +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 @@ bool QuickCompiler::CanCompileMethod(uint32_t method_idx, const DexFile& dex_fil << 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) diff --git a/compiler/dex/quick/quick_compiler.h b/compiler/dex/quick/quick_compiler.h index d512b256cd..55f45f1ab0 100644 --- a/compiler/dex/quick/quick_compiler.h +++ b/compiler/dex/quick/quick_compiler.h @@ -18,6 +18,7 @@ #define ART_COMPILER_DEX_QUICK_QUICK_COMPILER_H_ #include "compiler.h" +#include "dex/mir_graph.h" namespace art { @@ -74,6 +75,8 @@ class QuickCompiler : public Compiler { explicit QuickCompiler(CompilerDriver* driver); private: + bool CanCompileInstruction(const MIR* mir, const DexFile& dex_file) const; + std::unique_ptr<PassManager> pre_opt_pass_manager_; std::unique_ptr<PassManager> post_opt_pass_manager_; DISALLOW_COPY_AND_ASSIGN(QuickCompiler); |