summaryrefslogtreecommitdiffstats
path: root/compiler/dex
diff options
context:
space:
mode:
authorVladimir Marko <vmarko@google.com>2015-03-27 18:18:36 +0000
committerVladimir Marko <vmarko@google.com>2015-04-02 09:12:07 +0100
commitdc56cc509d8e1718ad321f7a91661dbe85ec8cef (patch)
treee261790925acd817ff470c23610ec2cc8be9f32e /compiler/dex
parentd29c27ff21b8cce7c06a4aff1bd382305df4d381 (diff)
downloadart-dc56cc509d8e1718ad321f7a91661dbe85ec8cef.zip
art-dc56cc509d8e1718ad321f7a91661dbe85ec8cef.tar.gz
art-dc56cc509d8e1718ad321f7a91661dbe85ec8cef.tar.bz2
PC-relative loads from dex cache arrays for x86-64.
Change-Id: I6cfe22c7e69512b3c0f95b073aaa572db74ec189
Diffstat (limited to 'compiler/dex')
-rw-r--r--compiler/dex/quick/x86/call_x86.cc24
-rw-r--r--compiler/dex/quick/x86/codegen_x86.h12
-rwxr-xr-xcompiler/dex/quick/x86/int_x86.cc35
-rwxr-xr-xcompiler/dex/quick/x86/target_x86.cc16
4 files changed, 72 insertions, 15 deletions
diff --git a/compiler/dex/quick/x86/call_x86.cc b/compiler/dex/quick/x86/call_x86.cc
index e81228a..bf7c157 100644
--- a/compiler/dex/quick/x86/call_x86.cc
+++ b/compiler/dex/quick/x86/call_x86.cc
@@ -25,6 +25,7 @@
#include "gc/accounting/card_table.h"
#include "mirror/art_method.h"
#include "mirror/object_array-inl.h"
+#include "utils/dex_cache_arrays_layout-inl.h"
#include "x86_lir.h"
namespace art {
@@ -322,13 +323,13 @@ void X86Mir2Lir::GenImplicitNullCheck(RegStorage reg, int opt_flags) {
* Bit of a hack here - in the absence of a real scheduling pass,
* emit the next instruction in static & direct invoke sequences.
*/
-static int X86NextSDCallInsn(CompilationUnit* cu, CallInfo* info,
- int state, const MethodReference& target_method,
- uint32_t,
- uintptr_t direct_code, uintptr_t direct_method,
- InvokeType type) {
+int X86Mir2Lir::X86NextSDCallInsn(CompilationUnit* cu, CallInfo* info,
+ int state, const MethodReference& target_method,
+ uint32_t,
+ uintptr_t direct_code, uintptr_t direct_method,
+ InvokeType type) {
UNUSED(info, direct_code);
- Mir2Lir* cg = static_cast<Mir2Lir*>(cu->cg.get());
+ X86Mir2Lir* cg = static_cast<X86Mir2Lir*>(cu->cg.get());
if (direct_method != 0) {
switch (state) {
case 0: // Get the current Method* [sets kArg0]
@@ -346,6 +347,17 @@ static int X86NextSDCallInsn(CompilationUnit* cu, CallInfo* info,
default:
return -1;
}
+ } else if (cg->CanUseOpPcRelDexCacheArrayLoad()) {
+ switch (state) {
+ case 0: {
+ CHECK_EQ(cu->dex_file, target_method.dex_file);
+ size_t offset = cg->dex_cache_arrays_layout_.MethodOffset(target_method.dex_method_index);
+ cg->OpPcRelDexCacheArrayLoad(cu->dex_file, offset, cg->TargetReg(kArg0, kRef));
+ break;
+ }
+ default:
+ return -1;
+ }
} else {
RegStorage arg0_ref = cg->TargetReg(kArg0, kRef);
switch (state) {
diff --git a/compiler/dex/quick/x86/codegen_x86.h b/compiler/dex/quick/x86/codegen_x86.h
index 040a8c4..758684e 100644
--- a/compiler/dex/quick/x86/codegen_x86.h
+++ b/compiler/dex/quick/x86/codegen_x86.h
@@ -104,6 +104,9 @@ class X86Mir2Lir : public Mir2Lir {
/// @copydoc Mir2Lir::UnconditionallyMarkGCCard(RegStorage)
void UnconditionallyMarkGCCard(RegStorage tgt_addr_reg) OVERRIDE;
+ bool CanUseOpPcRelDexCacheArrayLoad() const OVERRIDE;
+ void OpPcRelDexCacheArrayLoad(const DexFile* dex_file, int offset, RegStorage r_dest) OVERRIDE;
+
void GenImplicitNullCheck(RegStorage reg, int opt_flags) OVERRIDE;
// Required for target - register utilities.
@@ -952,6 +955,9 @@ class X86Mir2Lir : public Mir2Lir {
// Instructions needing patching with PC relative code addresses.
ArenaVector<LIR*> call_method_insns_;
+ // Instructions needing patching with PC relative code addresses.
+ ArenaVector<LIR*> dex_cache_access_insns_;
+
// Prologue decrement of stack pointer.
LIR* stack_decrement_;
@@ -992,6 +998,12 @@ class X86Mir2Lir : public Mir2Lir {
void SwapBits(RegStorage result_reg, int shift, int32_t value);
void SwapBits64(RegStorage result_reg, int shift, int64_t value);
+ static int X86NextSDCallInsn(CompilationUnit* cu, CallInfo* info,
+ int state, const MethodReference& target_method,
+ uint32_t,
+ uintptr_t direct_code, uintptr_t direct_method,
+ InvokeType type);
+
static const X86EncodingMap EncodingMap[kX86Last];
friend std::ostream& operator<<(std::ostream& os, const X86OpCode& rhs);
diff --git a/compiler/dex/quick/x86/int_x86.cc b/compiler/dex/quick/x86/int_x86.cc
index 4eb626c..5def5c8 100755
--- a/compiler/dex/quick/x86/int_x86.cc
+++ b/compiler/dex/quick/x86/int_x86.cc
@@ -1324,14 +1324,16 @@ bool X86Mir2Lir::GenInlinedReverseBits(CallInfo* info, OpSize size) {
return true;
}
+// When we don't know the proper offset for the value, pick one that will force
+// 4 byte offset. We will fix this up in the assembler or linker later to have
+// the right value.
+static constexpr int kDummy32BitOffset = 256;
+
void X86Mir2Lir::OpPcRelLoad(RegStorage reg, LIR* target) {
if (cu_->target64) {
// We can do this directly using RIP addressing.
- // We don't know the proper offset for the value, so pick one that will force
- // 4 byte offset. We will fix this up in the assembler later to have the right
- // value.
ScopedMemRefType mem_ref_type(this, ResourceMask::kLiteral);
- LIR* res = NewLIR3(kX86Mov32RM, reg.GetReg(), kRIPReg, 256);
+ LIR* res = NewLIR3(kX86Mov32RM, reg.GetReg(), kRIPReg, kDummy32BitOffset);
res->target = target;
res->flags.fixup = kFixupLoad;
return;
@@ -1349,15 +1351,32 @@ void X86Mir2Lir::OpPcRelLoad(RegStorage reg, LIR* target) {
store_method_addr_used_ = true;
// Load the proper value from the literal area.
- // We don't know the proper offset for the value, so pick one that will force
- // 4 byte offset. We will fix this up in the assembler later to have the right
- // value.
ScopedMemRefType mem_ref_type(this, ResourceMask::kLiteral);
- LIR* res = NewLIR3(kX86Mov32RM, reg.GetReg(), reg.GetReg(), 256);
+ LIR* res = NewLIR3(kX86Mov32RM, reg.GetReg(), reg.GetReg(), kDummy32BitOffset);
res->target = target;
res->flags.fixup = kFixupLoad;
}
+bool X86Mir2Lir::CanUseOpPcRelDexCacheArrayLoad() const {
+ // TODO: Implement for 32-bit.
+ return cu_->target64 && dex_cache_arrays_layout_.Valid();
+}
+
+void X86Mir2Lir::OpPcRelDexCacheArrayLoad(const DexFile* dex_file, int offset,
+ RegStorage r_dest) {
+ if (cu_->target64) {
+ LIR* mov = NewLIR3(kX86Mov32RM, r_dest.GetReg(), kRIPReg, kDummy32BitOffset);
+ mov->flags.fixup = kFixupLabel;
+ mov->operands[3] = WrapPointer(dex_file);
+ mov->operands[4] = offset;
+ dex_cache_access_insns_.push_back(mov);
+ } else {
+ // TODO: Implement for 32-bit.
+ LOG(FATAL) << "Unimplemented.";
+ UNREACHABLE();
+ }
+}
+
LIR* X86Mir2Lir::OpVldm(RegStorage r_base, int count) {
UNUSED(r_base, count);
LOG(FATAL) << "Unexpected use of OpVldm for x86";
diff --git a/compiler/dex/quick/x86/target_x86.cc b/compiler/dex/quick/x86/target_x86.cc
index f128eb7..cad82a1 100755
--- a/compiler/dex/quick/x86/target_x86.cc
+++ b/compiler/dex/quick/x86/target_x86.cc
@@ -829,6 +829,7 @@ X86Mir2Lir::X86Mir2Lir(CompilationUnit* cu, MIRGraph* mir_graph, ArenaAllocator*
method_address_insns_(arena->Adapter()),
class_type_address_insns_(arena->Adapter()),
call_method_insns_(arena->Adapter()),
+ dex_cache_access_insns_(arena->Adapter()),
stack_decrement_(nullptr), stack_increment_(nullptr),
const_vectors_(nullptr) {
method_address_insns_.reserve(100);
@@ -1058,6 +1059,9 @@ void X86Mir2Lir::InstallLiteralPools() {
}
}
+ patches_.reserve(method_address_insns_.size() + class_type_address_insns_.size() +
+ call_method_insns_.size() + dex_cache_access_insns_.size());
+
// Handle the fixups for methods.
for (LIR* p : method_address_insns_) {
DCHECK_EQ(p->opcode, kX86Mov32RI);
@@ -1084,7 +1088,6 @@ void X86Mir2Lir::InstallLiteralPools() {
}
// And now the PC-relative calls to methods.
- patches_.reserve(call_method_insns_.size());
for (LIR* p : call_method_insns_) {
DCHECK_EQ(p->opcode, kX86CallI);
uint32_t target_method_idx = p->operands[1];
@@ -1096,6 +1099,17 @@ void X86Mir2Lir::InstallLiteralPools() {
target_dex_file, target_method_idx));
}
+ // PC-relative references to dex cache arrays.
+ for (LIR* p : dex_cache_access_insns_) {
+ DCHECK(p->opcode == kX86Mov32RM);
+ const DexFile* dex_file = UnwrapPointer<DexFile>(p->operands[3]);
+ uint32_t offset = p->operands[4];
+ // The offset to patch is the last 4 bytes of the instruction.
+ int patch_offset = p->offset + p->flags.size - 4;
+ DCHECK(!p->flags.is_nop);
+ patches_.push_back(LinkerPatch::DexCacheArrayPatch(patch_offset, dex_file, p->offset, offset));
+ }
+
// And do the normal processing.
Mir2Lir::InstallLiteralPools();
}