VM: Emit compacter code for x64 branches to external labels.
Use jmp [PP + 0xiiii] instead of movq TMP, [PP + 0xiiii] jmp TMP Also, remove some unused code from x64 assembler. R=zra@google.com Review URL: https://codereview.chromium.org//869533003 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart@43094 260f80e4-7a28-3924-810f-c04153c831b5
This commit is contained in:
@@ -8,6 +8,7 @@
|
||||
#include "vm/assembler.h"
|
||||
#include "vm/cpu.h"
|
||||
#include "vm/heap.h"
|
||||
#include "vm/instructions.h"
|
||||
#include "vm/locations.h"
|
||||
#include "vm/memory_region.h"
|
||||
#include "vm/runtime_entry.h"
|
||||
@@ -2558,6 +2559,14 @@ void Assembler::jmp(Register reg) {
|
||||
}
|
||||
|
||||
|
||||
void Assembler::jmp(const Address& dst) {
|
||||
AssemblerBuffer::EnsureCapacity ensured(&buffer_);
|
||||
EmitOperandREX(4, dst, REX_NONE);
|
||||
EmitUint8(0xFF);
|
||||
EmitOperand(4, dst);
|
||||
}
|
||||
|
||||
|
||||
void Assembler::jmp(Label* label, bool near) {
|
||||
AssemblerBuffer::EnsureCapacity ensured(&buffer_);
|
||||
if (VerifiedMemory::enabled()) {
|
||||
@@ -2599,15 +2608,18 @@ void Assembler::jmp(const ExternalLabel* label) {
|
||||
void Assembler::JmpPatchable(const ExternalLabel* label, Register pp) {
|
||||
ASSERT(allow_constant_pool());
|
||||
intptr_t call_start = buffer_.GetPosition();
|
||||
LoadExternalLabel(TMP, label, kPatchable, pp);
|
||||
jmp(TMP);
|
||||
ASSERT((buffer_.GetPosition() - call_start) == kJmpExternalLabelSize);
|
||||
const int32_t offset =
|
||||
Array::element_offset(FindExternalLabel(label, kPatchable));
|
||||
// Patchable jumps always use a 32-bit immediate encoding.
|
||||
jmp(Address::AddressBaseImm32(pp, offset - kHeapObjectTag));
|
||||
ASSERT((buffer_.GetPosition() - call_start) == JumpPattern::kLengthInBytes);
|
||||
}
|
||||
|
||||
|
||||
void Assembler::Jmp(const ExternalLabel* label, Register pp) {
|
||||
LoadExternalLabel(TMP, label, kNotPatchable, pp);
|
||||
jmp(TMP);
|
||||
const int32_t offset =
|
||||
Array::element_offset(FindExternalLabel(label, kNotPatchable));
|
||||
jmp(Address(pp, offset - kHeapObjectTag));
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -353,7 +353,6 @@ class Assembler : public ValueObject {
|
||||
void call(const ExternalLabel* label);
|
||||
|
||||
static const intptr_t kCallExternalLabelSize = 7;
|
||||
static const intptr_t kJmpExternalLabelSize = 10;
|
||||
|
||||
void pushq(Register reg);
|
||||
void pushq(const Address& address);
|
||||
@@ -669,6 +668,7 @@ class Assembler : public ValueObject {
|
||||
void j(Condition condition, const ExternalLabel* label);
|
||||
|
||||
void jmp(Register reg);
|
||||
void jmp(const Address& address);
|
||||
// Note: verified_mem mode forces far jumps.
|
||||
void jmp(Label* label, bool near = kFarJump);
|
||||
void jmp(const ExternalLabel* label);
|
||||
|
||||
@@ -1808,6 +1808,20 @@ ASSEMBLER_TEST_RUN(JumpSimpleLeaf, test) {
|
||||
}
|
||||
|
||||
|
||||
ASSEMBLER_TEST_GENERATE(JumpIndirect, assembler) {
|
||||
ExternalLabel call1(reinterpret_cast<uword>(LeafReturn42));
|
||||
__ movq(Address(CallingConventions::kArg1Reg, 0), Immediate(call1.address()));
|
||||
__ jmp(Address(CallingConventions::kArg1Reg, 0));
|
||||
}
|
||||
|
||||
|
||||
ASSEMBLER_TEST_RUN(JumpIndirect, test) {
|
||||
uword temp = 0;
|
||||
typedef int (*JumpIndirect)(uword*);
|
||||
EXPECT_EQ(42, reinterpret_cast<JumpIndirect>(test->entry())(&temp));
|
||||
}
|
||||
|
||||
|
||||
ASSEMBLER_TEST_GENERATE(SingleFPMoves, assembler) {
|
||||
__ movq(RAX, Immediate(bit_cast<int32_t, float>(234.0f)));
|
||||
__ movd(XMM0, RAX);
|
||||
|
||||
@@ -37,28 +37,6 @@ bool InstructionPattern::TestBytesWith(const int* data, int num_bytes) const {
|
||||
}
|
||||
|
||||
|
||||
uword CallPattern::TargetAddress() const {
|
||||
ASSERT(IsValid());
|
||||
return *reinterpret_cast<uword*>(start() + 2);
|
||||
}
|
||||
|
||||
|
||||
void CallPattern::SetTargetAddress(uword target) const {
|
||||
ASSERT(IsValid());
|
||||
*reinterpret_cast<uword*>(start() + 2) = target;
|
||||
CPU::FlushICache(start() + 2, kWordSize);
|
||||
}
|
||||
|
||||
|
||||
const int* CallPattern::pattern() const {
|
||||
// movq $target, TMP
|
||||
// callq *TMP
|
||||
static const int kCallPattern[kLengthInBytes] =
|
||||
{0x49, 0xBB, -1, -1, -1, -1, -1, -1, -1, -1, 0x41, 0xFF, 0xD3};
|
||||
return kCallPattern;
|
||||
}
|
||||
|
||||
|
||||
uword JumpPattern::TargetAddress() const {
|
||||
ASSERT(IsValid());
|
||||
int index = InstructionPattern::IndexFromPPLoad(start() + 3);
|
||||
@@ -76,10 +54,9 @@ void JumpPattern::SetTargetAddress(uword target) const {
|
||||
|
||||
|
||||
const int* JumpPattern::pattern() const {
|
||||
// 00: 4d 8b 9d imm32 mov R11, [R13 + off]
|
||||
// 07: 41 ff e3 jmpq R11
|
||||
// 07: 41 ff a7 imm32 jmpq [reg + off]
|
||||
static const int kJumpPattern[kLengthInBytes] =
|
||||
{0x4D, 0x8B, -1, -1, -1, -1, -1, 0x41, 0xFF, 0xE3};
|
||||
{0x41, 0xFF, -1, -1, -1, -1, -1};
|
||||
return kJumpPattern;
|
||||
}
|
||||
|
||||
|
||||
@@ -56,29 +56,6 @@ class InstructionPattern : public ValueObject {
|
||||
};
|
||||
|
||||
|
||||
class CallPattern : public InstructionPattern {
|
||||
public:
|
||||
CallPattern(uword pc, const Code& code)
|
||||
: InstructionPattern(pc),
|
||||
code_(code) {}
|
||||
static int InstructionLength() {
|
||||
return kLengthInBytes;
|
||||
}
|
||||
uword TargetAddress() const;
|
||||
void SetTargetAddress(uword new_target) const;
|
||||
virtual int pattern_length_in_bytes() const {
|
||||
return kLengthInBytes;
|
||||
}
|
||||
|
||||
private:
|
||||
static const int kLengthInBytes = 13;
|
||||
virtual const int* pattern() const;
|
||||
const Code& code_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(CallPattern);
|
||||
};
|
||||
|
||||
|
||||
class JumpPattern : public InstructionPattern {
|
||||
public:
|
||||
JumpPattern(uword pc, const Code& code)
|
||||
@@ -93,8 +70,8 @@ class JumpPattern : public InstructionPattern {
|
||||
return kLengthInBytes;
|
||||
}
|
||||
|
||||
static const int kLengthInBytes = 7;
|
||||
private:
|
||||
static const int kLengthInBytes = 10;
|
||||
virtual const int* pattern() const;
|
||||
const Array& object_pool_;
|
||||
|
||||
|
||||
@@ -21,14 +21,6 @@ ASSEMBLER_TEST_GENERATE(Call, assembler) {
|
||||
}
|
||||
|
||||
|
||||
ASSEMBLER_TEST_RUN(Call, test) {
|
||||
StubCode* stub_code = Isolate::Current()->stub_code();
|
||||
CallPattern call(test->entry(), test->code());
|
||||
EXPECT_EQ(stub_code->InvokeDartCodeLabel().address(),
|
||||
call.TargetAddress());
|
||||
}
|
||||
|
||||
|
||||
static intptr_t prologue_code_size = -1;
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user