diff options
Diffstat (limited to 'compiler/dex/quick/mips/call_mips.cc')
-rw-r--r-- | compiler/dex/quick/mips/call_mips.cc | 82 |
1 files changed, 82 insertions, 0 deletions
diff --git a/compiler/dex/quick/mips/call_mips.cc b/compiler/dex/quick/mips/call_mips.cc index 51a8c981fb..ed92e82049 100644 --- a/compiler/dex/quick/mips/call_mips.cc +++ b/compiler/dex/quick/mips/call_mips.cc @@ -22,6 +22,8 @@ #include "entrypoints/quick/quick_entrypoints.h" #include "gc/accounting/card_table.h" #include "mips_lir.h" +#include "mirror/art_method.h" +#include "mirror/object_array-inl.h" namespace art { @@ -319,4 +321,84 @@ void MipsMir2Lir::GenSpecialExitSequence() { OpReg(kOpBx, rs_rRA); } +/* + * Bit of a hack here - in the absence of a real scheduling pass, + * emit the next instruction in static & direct invoke sequences. + */ +static int NextSDCallInsn(CompilationUnit* cu, CallInfo* info ATTRIBUTE_UNUSED, + int state, const MethodReference& target_method, + uint32_t, + uintptr_t direct_code, uintptr_t direct_method, + InvokeType type) { + Mir2Lir* cg = static_cast<Mir2Lir*>(cu->cg.get()); + if (direct_code != 0 && direct_method != 0) { + switch (state) { + case 0: // Get the current Method* [sets kArg0] + if (direct_code != static_cast<uintptr_t>(-1)) { + cg->LoadConstant(cg->TargetPtrReg(kInvokeTgt), direct_code); + } else { + cg->LoadCodeAddress(target_method, type, kInvokeTgt); + } + if (direct_method != static_cast<uintptr_t>(-1)) { + cg->LoadConstant(cg->TargetReg(kArg0, kRef), direct_method); + } else { + cg->LoadMethodAddress(target_method, type, kArg0); + } + break; + default: + return -1; + } + } else { + RegStorage arg0_ref = cg->TargetReg(kArg0, kRef); + switch (state) { + case 0: // Get the current Method* [sets kArg0] + // TUNING: we can save a reg copy if Method* has been promoted. + cg->LoadCurrMethodDirect(arg0_ref); + break; + case 1: // Get method->dex_cache_resolved_methods_ + cg->LoadRefDisp(arg0_ref, + mirror::ArtMethod::DexCacheResolvedMethodsOffset().Int32Value(), + arg0_ref, + kNotVolatile); + // Set up direct code if known. + if (direct_code != 0) { + if (direct_code != static_cast<uintptr_t>(-1)) { + cg->LoadConstant(cg->TargetPtrReg(kInvokeTgt), direct_code); + } else { + CHECK_LT(target_method.dex_method_index, target_method.dex_file->NumMethodIds()); + cg->LoadCodeAddress(target_method, type, kInvokeTgt); + } + } + break; + case 2: // Grab target method* + CHECK_EQ(cu->dex_file, target_method.dex_file); + cg->LoadRefDisp(arg0_ref, + mirror::ObjectArray<mirror::Object>:: + OffsetOfElement(target_method.dex_method_index).Int32Value(), + arg0_ref, + kNotVolatile); + break; + case 3: // Grab the code from the method* + if (direct_code == 0) { + int32_t offset = mirror::ArtMethod::EntryPointFromQuickCompiledCodeOffset( + InstructionSetPointerSize(cu->instruction_set)).Int32Value(); + // Get the compiled code address [use *alt_from or kArg0, set kInvokeTgt] + cg->LoadWordDisp(arg0_ref, offset, cg->TargetPtrReg(kInvokeTgt)); + } + break; + default: + return -1; + } + } + return state + 1; +} + +NextCallInsn MipsMir2Lir::GetNextSDCallInsn() { + return NextSDCallInsn; +} + +LIR* MipsMir2Lir::GenCallInsn(const MirMethodLoweringInfo& method_info ATTRIBUTE_UNUSED) { + return OpReg(kOpBlx, TargetPtrReg(kInvokeTgt)); +} + } // namespace art |