diff options
author | Vladimir Marko <vmarko@google.com> | 2015-04-08 20:51:48 +0100 |
---|---|---|
committer | Vladimir Marko <vmarko@google.com> | 2015-04-09 10:10:39 +0100 |
commit | 1961b609bfefaedb71cee3651c4f931cc3e7393d (patch) | |
tree | 16e98169664ea3cca7f317c1cece67d440dacb6f /compiler/dex/quick/x86/call_x86.cc | |
parent | 1576be32be4a99a1cffdaaf209a3cd67e8b2f88a (diff) | |
download | android_art-1961b609bfefaedb71cee3651c4f931cc3e7393d.tar.gz android_art-1961b609bfefaedb71cee3651c4f931cc3e7393d.tar.bz2 android_art-1961b609bfefaedb71cee3651c4f931cc3e7393d.zip |
Quick: PC-relative loads from dex cache arrays on x86.
Rewrite all PC-relative addressing on x86 and implement
PC-relative loads from dex cache arrays. Don't adjust the
base to point to the start of the method, let it point to
the anchor, i.e. the target of the "call +0" insn.
Change-Id: Ic22544a8bc0c5e49eb00a75154dc8f3ead816989
Diffstat (limited to 'compiler/dex/quick/x86/call_x86.cc')
-rw-r--r-- | compiler/dex/quick/x86/call_x86.cc | 40 |
1 files changed, 16 insertions, 24 deletions
diff --git a/compiler/dex/quick/x86/call_x86.cc b/compiler/dex/quick/x86/call_x86.cc index 18fae17d70..3041458d6d 100644 --- a/compiler/dex/quick/x86/call_x86.cc +++ b/compiler/dex/quick/x86/call_x86.cc @@ -97,29 +97,23 @@ void X86Mir2Lir::GenLargePackedSwitch(MIR* mir, DexOffset table_offset, RegLocat // Add the offset from the table to the table base. OpRegReg(kOpAdd, addr_for_jump, table_base); + tab_rec->anchor = nullptr; // Unused for x86-64. } else { - // Materialize a pointer to the switch table. - RegStorage start_of_method_reg; - if (base_of_code_ != nullptr) { - // We can use the saved value. - RegLocation rl_method = mir_graph_->GetRegLocation(base_of_code_->s_reg_low); - rl_method = LoadValue(rl_method, kCoreReg); - start_of_method_reg = rl_method.reg; - store_method_addr_used_ = true; - } else { - start_of_method_reg = AllocTempRef(); - NewLIR1(kX86StartOfMethod, start_of_method_reg.GetReg()); - } + // Get the PC to a register and get the anchor. + LIR* anchor; + RegStorage r_pc = GetPcAndAnchor(&anchor); + // Load the displacement from the switch table. addr_for_jump = AllocTemp(); - NewLIR5(kX86PcRelLoadRA, addr_for_jump.GetReg(), start_of_method_reg.GetReg(), keyReg.GetReg(), + NewLIR5(kX86PcRelLoadRA, addr_for_jump.GetReg(), r_pc.GetReg(), keyReg.GetReg(), 2, WrapPointer(tab_rec)); - // Add displacement to start of method. - OpRegReg(kOpAdd, addr_for_jump, start_of_method_reg); + // Add displacement and r_pc to get the address. + OpRegReg(kOpAdd, addr_for_jump, r_pc); + tab_rec->anchor = anchor; } // ..and go! - tab_rec->anchor = NewLIR1(kX86JmpR, addr_for_jump.GetReg()); + NewLIR1(kX86JmpR, addr_for_jump.GetReg()); /* branch_over target here */ LIR* target = NewLIR0(kPseudoTargetLabel); @@ -235,14 +229,12 @@ void X86Mir2Lir::GenEntrySequence(RegLocation* ArgLocs, RegLocation rl_method) { FlushIns(ArgLocs, rl_method); - if (base_of_code_ != nullptr) { - RegStorage method_start = TargetPtrReg(kArg0); - // We have been asked to save the address of the method start for later use. - setup_method_address_[0] = NewLIR1(kX86StartOfMethod, method_start.GetReg()); - int displacement = SRegOffset(base_of_code_->s_reg_low); - // Native pointer - must be natural word size. - setup_method_address_[1] = StoreBaseDisp(rs_rSP, displacement, method_start, - cu_->target64 ? k64 : k32, kNotVolatile); + // We can promote the PC of an anchor for PC-relative addressing to a register + // if it's used at least twice. Without investigating where we should lazily + // load the reference, we conveniently load it after flushing inputs. + if (pc_rel_base_reg_.Valid()) { + DCHECK(!cu_->target64); + setup_pc_rel_base_reg_ = OpLoadPc(pc_rel_base_reg_); } FreeTemp(arg0); |