diff options
author | Andreas Gampe <agampe@google.com> | 2014-06-11 21:56:39 +0000 |
---|---|---|
committer | Gerrit Code Review <noreply-gerritcodereview@google.com> | 2014-06-10 22:20:24 +0000 |
commit | 16e1eda5b1fcaf617371072692503714c7a6afe8 (patch) | |
tree | 70de80df0b476bdbd75d26f4624d631c1622f76f /compiler/utils | |
parent | c879aaec949f429c9b029bbbfaa76be8872cef0a (diff) | |
parent | 5408b6ba5d73ac0890683ebd7ddb4151a8ac2721 (diff) | |
download | art-16e1eda5b1fcaf617371072692503714c7a6afe8.zip art-16e1eda5b1fcaf617371072692503714c7a6afe8.tar.gz art-16e1eda5b1fcaf617371072692503714c7a6afe8.tar.bz2 |
Merge "x86_64: Fix issue in JNI compiler"
Diffstat (limited to 'compiler/utils')
-rw-r--r-- | compiler/utils/x86_64/assembler_x86_64.cc | 6 | ||||
-rw-r--r-- | compiler/utils/x86_64/assembler_x86_64.h | 7 | ||||
-rw-r--r-- | compiler/utils/x86_64/assembler_x86_64_test.cc | 118 |
3 files changed, 128 insertions, 3 deletions
diff --git a/compiler/utils/x86_64/assembler_x86_64.cc b/compiler/utils/x86_64/assembler_x86_64.cc index a14551c..b07eed3 100644 --- a/compiler/utils/x86_64/assembler_x86_64.cc +++ b/compiler/utils/x86_64/assembler_x86_64.cc @@ -1650,7 +1650,7 @@ void X86_64Assembler::BuildFrame(size_t frame_size, ManagedRegister method_reg, pushq(spill_regs.at(i).AsX86_64().AsCpuRegister()); } // return address then method on stack - addq(CpuRegister(RSP), Immediate(-frame_size + (spill_regs.size() * kFramePointerSize) + + addq(CpuRegister(RSP), Immediate(-static_cast<int64_t>(frame_size) + (spill_regs.size() * kFramePointerSize) + sizeof(StackReference<mirror::ArtMethod>) /*method*/ + kFramePointerSize /*return address*/)); @@ -1682,7 +1682,7 @@ void X86_64Assembler::BuildFrame(size_t frame_size, ManagedRegister method_reg, void X86_64Assembler::RemoveFrame(size_t frame_size, const std::vector<ManagedRegister>& spill_regs) { CHECK_ALIGNED(frame_size, kStackAlignment); - addq(CpuRegister(RSP), Immediate(frame_size - (spill_regs.size() * kFramePointerSize) - kFramePointerSize)); + addq(CpuRegister(RSP), Immediate(static_cast<int64_t>(frame_size) - (spill_regs.size() * kFramePointerSize) - kFramePointerSize)); for (size_t i = 0; i < spill_regs.size(); ++i) { popq(spill_regs.at(i).AsX86_64().AsCpuRegister()); } @@ -1691,7 +1691,7 @@ void X86_64Assembler::RemoveFrame(size_t frame_size, void X86_64Assembler::IncreaseFrameSize(size_t adjust) { CHECK_ALIGNED(adjust, kStackAlignment); - addq(CpuRegister(RSP), Immediate(-adjust)); + addq(CpuRegister(RSP), Immediate(-static_cast<int64_t>(adjust))); } void X86_64Assembler::DecreaseFrameSize(size_t adjust) { diff --git a/compiler/utils/x86_64/assembler_x86_64.h b/compiler/utils/x86_64/assembler_x86_64.h index 548d379..6276603 100644 --- a/compiler/utils/x86_64/assembler_x86_64.h +++ b/compiler/utils/x86_64/assembler_x86_64.h @@ -29,6 +29,13 @@ namespace art { namespace x86_64 { +// Encodes an immediate value for operands. +// +// Note: Immediates can be 64b on x86-64 for certain instructions, but are often restricted +// to 32b. +// +// Note: As we support cross-compilation, the value type must be int64_t. Please be aware of +// conversion rules in expressions regarding negation, especially size_t on 32b. class Immediate { public: explicit Immediate(int64_t value) : value_(value) {} diff --git a/compiler/utils/x86_64/assembler_x86_64_test.cc b/compiler/utils/x86_64/assembler_x86_64_test.cc index 7201d04..799db9f 100644 --- a/compiler/utils/x86_64/assembler_x86_64_test.cc +++ b/compiler/utils/x86_64/assembler_x86_64_test.cc @@ -200,4 +200,122 @@ TEST_F(AssemblerX86_64Test, SetCC) { DriverFn(&setcc_test_fn, "setcc"); } +static x86_64::X86_64ManagedRegister ManagedFromCpu(x86_64::Register r) { + return x86_64::X86_64ManagedRegister::FromCpuRegister(r); +} + +static x86_64::X86_64ManagedRegister ManagedFromFpu(x86_64::FloatRegister r) { + return x86_64::X86_64ManagedRegister::FromXmmRegister(r); +} + +std::string buildframe_test_fn(x86_64::X86_64Assembler* assembler) { + // TODO: more interesting spill registers / entry spills. + + // Two random spill regs. + std::vector<ManagedRegister> spill_regs; + spill_regs.push_back(ManagedFromCpu(x86_64::R10)); + spill_regs.push_back(ManagedFromCpu(x86_64::RSI)); + + // Three random entry spills. + ManagedRegisterEntrySpills entry_spills; + ManagedRegisterSpill spill(ManagedFromCpu(x86_64::RAX), 8, 0); + entry_spills.push_back(spill); + ManagedRegisterSpill spill2(ManagedFromCpu(x86_64::RBX), 8, 8); + entry_spills.push_back(spill2); + ManagedRegisterSpill spill3(ManagedFromFpu(x86_64::XMM1), 8, 16); + entry_spills.push_back(spill3); + + x86_64::X86_64ManagedRegister method_reg = ManagedFromCpu(x86_64::RDI); + + size_t frame_size = 10 * kStackAlignment; + assembler->BuildFrame(10 * kStackAlignment, method_reg, spill_regs, entry_spills); + + // Construct assembly text counterpart. + std::ostringstream str; + // 1) Push the spill_regs. + str << "pushq %rsi\n"; + str << "pushq %r10\n"; + // 2) Move down the stack pointer. + ssize_t displacement = -static_cast<ssize_t>(frame_size) + spill_regs.size() * 8 + + sizeof(StackReference<mirror::ArtMethod>) + 8; + str << "addq $" << displacement << ", %rsp\n"; + // 3) Make space for method reference, and store it. + str << "subq $4, %rsp\n"; + str << "movl %edi, (%rsp)\n"; + // 4) Entry spills. + str << "movq %rax, " << frame_size + 0 << "(%rsp)\n"; + str << "movq %rbx, " << frame_size + 8 << "(%rsp)\n"; + str << "movsd %xmm1, " << frame_size + 16 << "(%rsp)\n"; + + return str.str(); +} + +TEST_F(AssemblerX86_64Test, BuildFrame) { + DriverFn(&buildframe_test_fn, "BuildFrame"); +} + +std::string removeframe_test_fn(x86_64::X86_64Assembler* assembler) { + // TODO: more interesting spill registers / entry spills. + + // Two random spill regs. + std::vector<ManagedRegister> spill_regs; + spill_regs.push_back(ManagedFromCpu(x86_64::R10)); + spill_regs.push_back(ManagedFromCpu(x86_64::RSI)); + + size_t frame_size = 10 * kStackAlignment; + assembler->RemoveFrame(10 * kStackAlignment, spill_regs); + + // Construct assembly text counterpart. + std::ostringstream str; + // 1) Move up the stack pointer. + ssize_t displacement = static_cast<ssize_t>(frame_size) - spill_regs.size() * 8 - 8; + str << "addq $" << displacement << ", %rsp\n"; + // 2) Pop spill regs. + str << "popq %r10\n"; + str << "popq %rsi\n"; + str << "ret\n"; + + return str.str(); +} + +TEST_F(AssemblerX86_64Test, RemoveFrame) { + DriverFn(&removeframe_test_fn, "RemoveFrame"); +} + +std::string increaseframe_test_fn(x86_64::X86_64Assembler* assembler) { + assembler->IncreaseFrameSize(0U); + assembler->IncreaseFrameSize(kStackAlignment); + assembler->IncreaseFrameSize(10 * kStackAlignment); + + // Construct assembly text counterpart. + std::ostringstream str; + str << "addq $0, %rsp\n"; + str << "addq $-" << kStackAlignment << ", %rsp\n"; + str << "addq $-" << 10 * kStackAlignment << ", %rsp\n"; + + return str.str(); +} + +TEST_F(AssemblerX86_64Test, IncreaseFrame) { + DriverFn(&increaseframe_test_fn, "IncreaseFrame"); +} + +std::string decreaseframe_test_fn(x86_64::X86_64Assembler* assembler) { + assembler->DecreaseFrameSize(0U); + assembler->DecreaseFrameSize(kStackAlignment); + assembler->DecreaseFrameSize(10 * kStackAlignment); + + // Construct assembly text counterpart. + std::ostringstream str; + str << "addq $0, %rsp\n"; + str << "addq $" << kStackAlignment << ", %rsp\n"; + str << "addq $" << 10 * kStackAlignment << ", %rsp\n"; + + return str.str(); +} + +TEST_F(AssemblerX86_64Test, DecreaseFrame) { + DriverFn(&decreaseframe_test_fn, "DecreaseFrame"); +} + } // namespace art |