diff --git a/runtime/vm/assembler_x64.cc b/runtime/vm/assembler_x64.cc index ed84202ab86..45a169a3c8f 100644 --- a/runtime/vm/assembler_x64.cc +++ b/runtime/vm/assembler_x64.cc @@ -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)); } diff --git a/runtime/vm/assembler_x64.h b/runtime/vm/assembler_x64.h index b468162b3dd..09ac0bf0fee 100644 --- a/runtime/vm/assembler_x64.h +++ b/runtime/vm/assembler_x64.h @@ -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); diff --git a/runtime/vm/assembler_x64_test.cc b/runtime/vm/assembler_x64_test.cc index a62341ed8dd..8ad42ffc290 100644 --- a/runtime/vm/assembler_x64_test.cc +++ b/runtime/vm/assembler_x64_test.cc @@ -1808,6 +1808,20 @@ ASSEMBLER_TEST_RUN(JumpSimpleLeaf, test) { } +ASSEMBLER_TEST_GENERATE(JumpIndirect, assembler) { + ExternalLabel call1(reinterpret_cast(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(test->entry())(&temp)); +} + + ASSEMBLER_TEST_GENERATE(SingleFPMoves, assembler) { __ movq(RAX, Immediate(bit_cast(234.0f))); __ movd(XMM0, RAX); diff --git a/runtime/vm/instructions_x64.cc b/runtime/vm/instructions_x64.cc index f01afbbe5bc..a531e66fadc 100644 --- a/runtime/vm/instructions_x64.cc +++ b/runtime/vm/instructions_x64.cc @@ -37,28 +37,6 @@ bool InstructionPattern::TestBytesWith(const int* data, int num_bytes) const { } -uword CallPattern::TargetAddress() const { - ASSERT(IsValid()); - return *reinterpret_cast(start() + 2); -} - - -void CallPattern::SetTargetAddress(uword target) const { - ASSERT(IsValid()); - *reinterpret_cast(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; } diff --git a/runtime/vm/instructions_x64.h b/runtime/vm/instructions_x64.h index ced627cab80..9e02313cee1 100644 --- a/runtime/vm/instructions_x64.h +++ b/runtime/vm/instructions_x64.h @@ -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_; diff --git a/runtime/vm/instructions_x64_test.cc b/runtime/vm/instructions_x64_test.cc index 0e8ee09a1f6..b9e3eb237e3 100644 --- a/runtime/vm/instructions_x64_test.cc +++ b/runtime/vm/instructions_x64_test.cc @@ -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;