| Index: runtime/vm/assembler_x64.cc
|
| diff --git a/runtime/vm/assembler_x64.cc b/runtime/vm/assembler_x64.cc
|
| index e39d8b21aecfb658f2ee652343ffeb8c386218f4..523f29f9ca8fdc3cc7229e3fe75c955c6445f283 100644
|
| --- a/runtime/vm/assembler_x64.cc
|
| +++ b/runtime/vm/assembler_x64.cc
|
| @@ -93,25 +93,20 @@ void Assembler::call(const ExternalLabel* label) {
|
|
|
| void Assembler::CallPatchable(const StubEntry& stub_entry) {
|
| ASSERT(constant_pool_allowed());
|
| - const Code& target = Code::Handle(stub_entry.code());
|
| intptr_t call_start = buffer_.GetPosition();
|
| const int32_t offset = ObjectPool::element_offset(
|
| - object_pool_wrapper_.FindObject(target, kPatchable));
|
| - LoadWordFromPoolOffset(CODE_REG, offset - kHeapObjectTag);
|
| - movq(TMP, FieldAddress(CODE_REG, Code::entry_point_offset()));
|
| - call(TMP);
|
| + object_pool_wrapper_.FindExternalLabel(&stub_entry.label(), kPatchable));
|
| + call(Address::AddressBaseImm32(PP, offset - kHeapObjectTag));
|
| ASSERT((buffer_.GetPosition() - call_start) == kCallExternalLabelSize);
|
| }
|
|
|
|
|
| void Assembler::Call(const StubEntry& stub_entry) {
|
| ASSERT(constant_pool_allowed());
|
| - const Code& target = Code::Handle(stub_entry.code());
|
| const int32_t offset = ObjectPool::element_offset(
|
| - object_pool_wrapper_.FindObject(target, kNotPatchable));
|
| - LoadWordFromPoolOffset(CODE_REG, offset - kHeapObjectTag);
|
| - movq(TMP, FieldAddress(CODE_REG, Code::entry_point_offset()));
|
| - call(TMP);
|
| + object_pool_wrapper_.FindExternalLabel(&stub_entry.label(),
|
| + kNotPatchable));
|
| + call(Address::AddressBaseImm32(PP, offset - kHeapObjectTag));
|
| }
|
|
|
|
|
| @@ -2548,12 +2543,11 @@ void Assembler::j(Condition condition, Label* label, bool near) {
|
| }
|
|
|
|
|
| -void Assembler::J(Condition condition,
|
| - const StubEntry& stub_entry,
|
| +void Assembler::J(Condition condition, const StubEntry& stub_entry,
|
| Register pp) {
|
| Label no_jump;
|
| // Negate condition.
|
| - j(static_cast<Condition>(condition ^ 1), &no_jump, kNearJump);
|
| + j(static_cast<Condition>(condition ^ 1), &no_jump, Assembler::kNearJump);
|
| Jmp(stub_entry, pp);
|
| Bind(&no_jump);
|
| }
|
| @@ -2614,25 +2608,28 @@ void Assembler::jmp(const ExternalLabel* label) {
|
| }
|
|
|
|
|
| +void Assembler::jmp(const StubEntry& stub_entry) {
|
| + jmp(&stub_entry.label());
|
| +}
|
| +
|
| +
|
| void Assembler::JmpPatchable(const StubEntry& stub_entry, Register pp) {
|
| ASSERT((pp != PP) || constant_pool_allowed());
|
| - const Code& target = Code::Handle(stub_entry.code());
|
| + intptr_t call_start = buffer_.GetPosition();
|
| const int32_t offset = ObjectPool::element_offset(
|
| - object_pool_wrapper_.FindObject(target, kPatchable));
|
| - movq(CODE_REG, Address::AddressBaseImm32(pp, offset - kHeapObjectTag));
|
| - movq(TMP, FieldAddress(CODE_REG, Code::entry_point_offset()));
|
| - jmp(TMP);
|
| + object_pool_wrapper_.FindExternalLabel(&stub_entry.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 StubEntry& stub_entry, Register pp) {
|
| ASSERT((pp != PP) || constant_pool_allowed());
|
| - const Code& target = Code::Handle(stub_entry.code());
|
| const int32_t offset = ObjectPool::element_offset(
|
| - object_pool_wrapper_.FindObject(target, kNotPatchable));
|
| - movq(CODE_REG, FieldAddress(pp, offset));
|
| - movq(TMP, FieldAddress(CODE_REG, Code::entry_point_offset()));
|
| - jmp(TMP);
|
| + object_pool_wrapper_.FindExternalLabel(&stub_entry.label(),
|
| + kNotPatchable));
|
| + jmp(Address(pp, offset - kHeapObjectTag));
|
| }
|
|
|
|
|
| @@ -3080,12 +3077,8 @@ void Assembler::StoreIntoObject(Register object,
|
| if (object != RDX) {
|
| movq(RDX, object);
|
| }
|
| - pushq(CODE_REG);
|
| - movq(CODE_REG, Address(THR, Thread::update_store_buffer_code_offset()));
|
| movq(TMP, Address(THR, Thread::update_store_buffer_entry_point_offset()));
|
| call(TMP);
|
| -
|
| - popq(CODE_REG);
|
| if (value != RDX) popq(RDX);
|
| Bind(&done);
|
| }
|
| @@ -3386,30 +3379,27 @@ void Assembler::CallRuntime(const RuntimeEntry& entry,
|
| }
|
|
|
|
|
| -void Assembler::RestoreCodePointer() {
|
| - movq(CODE_REG, Address(RBP, kPcMarkerSlotFromFp * kWordSize));
|
| -}
|
| -
|
| -
|
| void Assembler::LoadPoolPointer(Register pp) {
|
| // Load new pool pointer.
|
| - CheckCodePointer();
|
| - movq(pp, FieldAddress(CODE_REG, Code::object_pool_offset()));
|
| + const intptr_t kRIPRelativeMovqSize = 7;
|
| + const intptr_t entry_to_rip_offset = CodeSize() + kRIPRelativeMovqSize;
|
| + const intptr_t object_pool_pc_dist =
|
| + Instructions::HeaderSize() - Instructions::object_pool_offset();
|
| + movq(pp, Address::AddressRIPRelative(
|
| + -entry_to_rip_offset - object_pool_pc_dist));
|
| + ASSERT(CodeSize() == entry_to_rip_offset);
|
| set_constant_pool_allowed(pp == PP);
|
| }
|
|
|
|
|
| -void Assembler::EnterDartFrame(intptr_t frame_size, Register new_pp) {
|
| - CheckCodePointer();
|
| +void Assembler::EnterDartFrame(intptr_t frame_size,
|
| + Register new_pp,
|
| + Register pc_marker_override) {
|
| ASSERT(!constant_pool_allowed());
|
| EnterFrame(0);
|
| - pushq(CODE_REG);
|
| + pushq(pc_marker_override);
|
| pushq(PP);
|
| - if (new_pp == kNoRegister) {
|
| - LoadPoolPointer(PP);
|
| - } else {
|
| - movq(PP, new_pp);
|
| - }
|
| + movq(PP, new_pp);
|
| set_constant_pool_allowed(true);
|
| if (frame_size != 0) {
|
| subq(RSP, Immediate(frame_size));
|
| @@ -3417,57 +3407,30 @@ void Assembler::EnterDartFrame(intptr_t frame_size, Register new_pp) {
|
| }
|
|
|
|
|
| -void Assembler::LeaveDartFrame(RestorePP restore_pp) {
|
| +void Assembler::LeaveDartFrame() {
|
| + set_constant_pool_allowed(false);
|
| // Restore caller's PP register that was pushed in EnterDartFrame.
|
| - if (restore_pp == kRestoreCallerPP) {
|
| - movq(PP, Address(RBP, (kSavedCallerPpSlotFromFp * kWordSize)));
|
| - set_constant_pool_allowed(false);
|
| - }
|
| + movq(PP, Address(RBP, (kSavedCallerPpSlotFromFp * kWordSize)));
|
| LeaveFrame();
|
| }
|
|
|
|
|
| -void Assembler::CheckCodePointer() {
|
| -#ifdef DEBUG
|
| - Label cid_ok, instructions_ok;
|
| - pushq(RAX);
|
| - LoadClassId(RAX, CODE_REG);
|
| - cmpq(RAX, Immediate(kCodeCid));
|
| - j(EQUAL, &cid_ok);
|
| - int3();
|
| - Bind(&cid_ok);
|
| - {
|
| - const intptr_t kRIPRelativeLeaqSize = 7;
|
| - const intptr_t header_to_entry_offset =
|
| - (Instructions::HeaderSize() - kHeapObjectTag);
|
| - const intptr_t header_to_rip_offset =
|
| - CodeSize() + kRIPRelativeLeaqSize + header_to_entry_offset;
|
| - leaq(RAX, Address::AddressRIPRelative(-header_to_rip_offset));
|
| - ASSERT(CodeSize() == (header_to_rip_offset - header_to_entry_offset));
|
| - }
|
| - cmpq(RAX, FieldAddress(CODE_REG, Code::saved_instructions_offset()));
|
| - j(EQUAL, &instructions_ok);
|
| - int3();
|
| - Bind(&instructions_ok);
|
| - popq(RAX);
|
| -#endif
|
| -}
|
| -
|
| -
|
| // On entry to a function compiled for OSR, the caller's frame pointer, the
|
| // stack locals, and any copied parameters are already in place. The frame
|
| // pointer is already set up. The PC marker is not correct for the
|
| // optimized function and there may be extra space for spill slots to
|
| // allocate.
|
| -void Assembler::EnterOsrFrame(intptr_t extra_size) {
|
| +void Assembler::EnterOsrFrame(intptr_t extra_size,
|
| + Register new_pp,
|
| + Register pc_marker_override) {
|
| ASSERT(!constant_pool_allowed());
|
| if (prologue_offset_ == -1) {
|
| Comment("PrologueOffset = %" Pd "", CodeSize());
|
| prologue_offset_ = CodeSize();
|
| }
|
| - RestoreCodePointer();
|
| - LoadPoolPointer();
|
| -
|
| + movq(Address(RBP, kPcMarkerSlotFromFp * kWordSize), pc_marker_override);
|
| + movq(PP, new_pp);
|
| + set_constant_pool_allowed(true);
|
| if (extra_size != 0) {
|
| subq(RSP, Immediate(extra_size));
|
| }
|
| @@ -3475,7 +3438,11 @@ void Assembler::EnterOsrFrame(intptr_t extra_size) {
|
|
|
|
|
| void Assembler::EnterStubFrame() {
|
| - EnterDartFrame(0, kNoRegister);
|
| + set_constant_pool_allowed(false);
|
| + EnterFrame(0);
|
| + pushq(Immediate(0)); // Push 0 in the saved PC area for stub frames.
|
| + pushq(PP); // Save caller's pool pointer
|
| + LoadPoolPointer();
|
| }
|
|
|
|
|
|
|