OLD | NEW |
---|---|
1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file |
2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
4 | 4 |
5 #include "vm/globals.h" // NOLINT | 5 #include "vm/globals.h" // NOLINT |
6 #if defined(TARGET_ARCH_X64) | 6 #if defined(TARGET_ARCH_X64) |
7 | 7 |
8 #include "vm/assembler.h" | 8 #include "vm/assembler.h" |
9 #include "vm/cpu.h" | 9 #include "vm/cpu.h" |
10 #include "vm/heap.h" | 10 #include "vm/heap.h" |
(...skipping 26 matching lines...) Expand all Loading... | |
37 | 37 |
38 index = object_pool_wrapper_.AddObject(Bool::True()); | 38 index = object_pool_wrapper_.AddObject(Bool::True()); |
39 ASSERT(index == 1); | 39 ASSERT(index == 1); |
40 | 40 |
41 index = object_pool_wrapper_.AddObject(Bool::False()); | 41 index = object_pool_wrapper_.AddObject(Bool::False()); |
42 ASSERT(index == 2); | 42 ASSERT(index == 2); |
43 | 43 |
44 const Smi& vacant = Smi::Handle(Smi::New(0xfa >> kSmiTagShift)); | 44 const Smi& vacant = Smi::Handle(Smi::New(0xfa >> kSmiTagShift)); |
45 StubCode* stub_code = isolate->stub_code(); | 45 StubCode* stub_code = isolate->stub_code(); |
46 if (stub_code->UpdateStoreBuffer_entry() != NULL) { | 46 if (stub_code->UpdateStoreBuffer_entry() != NULL) { |
47 object_pool_wrapper_.AddExternalLabel( | 47 object_pool_wrapper_.AddObject( |
48 &stub_code->UpdateStoreBufferLabel(), kNotPatchable); | 48 Code::Handle(stub_code->UpdateStoreBufferCode()), kNotPatchable); |
srdjan
2015/06/18 21:29:46
Code::Handle(isolate,
Florian Schneider
2015/06/29 14:50:24
Done.
| |
49 } else { | 49 } else { |
50 object_pool_wrapper_.AddObject(vacant); | 50 object_pool_wrapper_.AddObject(vacant); |
51 } | 51 } |
52 | 52 |
53 if (stub_code->CallToRuntime_entry() != NULL) { | 53 if (stub_code->CallToRuntime_entry() != NULL) { |
54 object_pool_wrapper_.AddExternalLabel( | 54 object_pool_wrapper_.AddObject( |
55 &stub_code->CallToRuntimeLabel(), kNotPatchable); | 55 Code::Handle(stub_code->CallToRuntimeCode()), kNotPatchable); |
srdjan
2015/06/18 21:29:46
Code::Handle(isolate,
Florian Schneider
2015/06/29 14:50:24
Done.
| |
56 } else { | 56 } else { |
57 object_pool_wrapper_.AddObject(vacant); | 57 object_pool_wrapper_.AddObject(vacant); |
58 } | 58 } |
59 } | 59 } |
60 } | 60 } |
61 | 61 |
62 | 62 |
63 void Assembler::InitializeMemoryWithBreakpoints(uword data, intptr_t length) { | 63 void Assembler::InitializeMemoryWithBreakpoints(uword data, intptr_t length) { |
64 memset(reinterpret_cast<void*>(data), Instr::kBreakPointInstruction, length); | 64 memset(reinterpret_cast<void*>(data), Instr::kBreakPointInstruction, length); |
65 } | 65 } |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
104 { // Encode movq(TMP, Immediate(label->address())), but always as imm64. | 104 { // Encode movq(TMP, Immediate(label->address())), but always as imm64. |
105 AssemblerBuffer::EnsureCapacity ensured(&buffer_); | 105 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
106 EmitRegisterREX(TMP, REX_W); | 106 EmitRegisterREX(TMP, REX_W); |
107 EmitUint8(0xB8 | (TMP & 7)); | 107 EmitUint8(0xB8 | (TMP & 7)); |
108 EmitInt64(label->address()); | 108 EmitInt64(label->address()); |
109 } | 109 } |
110 call(TMP); | 110 call(TMP); |
111 } | 111 } |
112 | 112 |
113 | 113 |
114 void Assembler::CallPatchable(const ExternalLabel* label) { | 114 void Assembler::CallPatchable(const Code& target) { |
115 ASSERT(allow_constant_pool()); | 115 ASSERT(allow_constant_pool()); |
116 intptr_t call_start = buffer_.GetPosition(); | 116 intptr_t call_start = buffer_.GetPosition(); |
117 const int32_t offset = ObjectPool::element_offset( | 117 const int32_t offset = ObjectPool::element_offset( |
118 object_pool_wrapper_.FindExternalLabel(label, kPatchable)); | 118 object_pool_wrapper_.FindObject(target, kPatchable)); |
119 call(Address::AddressBaseImm32(PP, offset - kHeapObjectTag)); | 119 LoadWordFromPoolOffset(CODE_REG, PP, offset - kHeapObjectTag); |
120 movq(TMP, FieldAddress(CODE_REG, Code::instructions_offset())); | |
121 addq(TMP, Immediate(Instructions::HeaderSize() - kHeapObjectTag)); | |
122 call(TMP); | |
120 ASSERT((buffer_.GetPosition() - call_start) == kCallExternalLabelSize); | 123 ASSERT((buffer_.GetPosition() - call_start) == kCallExternalLabelSize); |
121 } | 124 } |
122 | 125 |
123 | 126 |
124 void Assembler::Call(const ExternalLabel* label, Register pp) { | 127 void Assembler::Call(const Code& target, Register pp) { |
125 if (Isolate::Current() == Dart::vm_isolate()) { | 128 if (Isolate::Current() == Dart::vm_isolate()) { |
126 call(label); | 129 UNREACHABLE(); |
127 } else { | 130 } else { |
128 const int32_t offset = ObjectPool::element_offset( | 131 const int32_t offset = ObjectPool::element_offset( |
129 object_pool_wrapper_.FindExternalLabel(label, kNotPatchable)); | 132 object_pool_wrapper_.FindObject(target, kNotPatchable)); |
130 call(Address::AddressBaseImm32(pp, offset - kHeapObjectTag)); | 133 LoadWordFromPoolOffset(CODE_REG, PP, offset - kHeapObjectTag); |
134 movq(TMP, FieldAddress(CODE_REG, Code::instructions_offset())); | |
135 addq(TMP, Immediate(Instructions::HeaderSize() - kHeapObjectTag)); | |
136 call(TMP); | |
131 } | 137 } |
132 } | 138 } |
133 | 139 |
134 | 140 |
135 void Assembler::pushq(Register reg) { | 141 void Assembler::pushq(Register reg) { |
136 AssemblerBuffer::EnsureCapacity ensured(&buffer_); | 142 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
137 EmitRegisterREX(reg, REX_NONE); | 143 EmitRegisterREX(reg, REX_NONE); |
138 EmitUint8(0x50 | (reg & 7)); | 144 EmitUint8(0x50 | (reg & 7)); |
139 } | 145 } |
140 | 146 |
(...skipping 2409 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2550 EmitUint8(0x70 + condition); | 2556 EmitUint8(0x70 + condition); |
2551 EmitNearLabelLink(label); | 2557 EmitNearLabelLink(label); |
2552 } else { | 2558 } else { |
2553 EmitUint8(0x0F); | 2559 EmitUint8(0x0F); |
2554 EmitUint8(0x80 + condition); | 2560 EmitUint8(0x80 + condition); |
2555 EmitLabelLink(label); | 2561 EmitLabelLink(label); |
2556 } | 2562 } |
2557 } | 2563 } |
2558 | 2564 |
2559 | 2565 |
2560 void Assembler::j(Condition condition, const ExternalLabel* label) { | |
2561 Label no_jump; | |
2562 // Negate condition. | |
2563 j(static_cast<Condition>(condition ^ 1), &no_jump, Assembler::kNearJump); | |
2564 jmp(label); | |
2565 Bind(&no_jump); | |
2566 } | |
2567 | |
2568 | |
2569 void Assembler::J(Condition condition, const ExternalLabel* label, | |
2570 Register pp) { | |
2571 Label no_jump; | |
2572 // Negate condition. | |
2573 j(static_cast<Condition>(condition ^ 1), &no_jump, Assembler::kNearJump); | |
2574 Jmp(label, pp); | |
2575 Bind(&no_jump); | |
2576 } | |
2577 | |
2578 | |
2579 void Assembler::jmp(Register reg) { | 2566 void Assembler::jmp(Register reg) { |
2580 AssemblerBuffer::EnsureCapacity ensured(&buffer_); | 2567 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
2581 Operand operand(reg); | 2568 Operand operand(reg); |
2582 EmitOperandREX(4, operand, REX_NONE); | 2569 EmitOperandREX(4, operand, REX_NONE); |
2583 EmitUint8(0xFF); | 2570 EmitUint8(0xFF); |
2584 EmitOperand(4, operand); | 2571 EmitOperand(4, operand); |
2585 } | 2572 } |
2586 | 2573 |
2587 | 2574 |
2588 void Assembler::jmp(const Address& dst) { | 2575 void Assembler::jmp(const Address& dst) { |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2624 { // Encode movq(TMP, Immediate(label->address())), but always as imm64. | 2611 { // Encode movq(TMP, Immediate(label->address())), but always as imm64. |
2625 AssemblerBuffer::EnsureCapacity ensured(&buffer_); | 2612 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
2626 EmitRegisterREX(TMP, REX_W); | 2613 EmitRegisterREX(TMP, REX_W); |
2627 EmitUint8(0xB8 | (TMP & 7)); | 2614 EmitUint8(0xB8 | (TMP & 7)); |
2628 EmitInt64(label->address()); | 2615 EmitInt64(label->address()); |
2629 } | 2616 } |
2630 jmp(TMP); | 2617 jmp(TMP); |
2631 } | 2618 } |
2632 | 2619 |
2633 | 2620 |
2634 void Assembler::JmpPatchable(const ExternalLabel* label, Register pp) { | 2621 void Assembler::JmpPatchable(const Code& target, Register pp) { |
2635 ASSERT(allow_constant_pool()); | 2622 ASSERT(allow_constant_pool()); |
2636 intptr_t call_start = buffer_.GetPosition(); | 2623 intptr_t call_start = buffer_.GetPosition(); |
2637 const int32_t offset = ObjectPool::element_offset( | 2624 const int32_t offset = ObjectPool::element_offset( |
2638 object_pool_wrapper_.FindExternalLabel(label, kPatchable)); | 2625 object_pool_wrapper_.FindObject(target, kPatchable)); |
2639 // Patchable jumps always use a 32-bit immediate encoding. | 2626 LoadWordFromPoolOffset(CODE_REG, pp, offset - kHeapObjectTag); |
2640 jmp(Address::AddressBaseImm32(pp, offset - kHeapObjectTag)); | 2627 movq(TMP, FieldAddress(CODE_REG, Code::instructions_offset())); |
2628 addq(TMP, Immediate(Instructions::HeaderSize() - kHeapObjectTag)); | |
2629 jmp(TMP); | |
2641 ASSERT((buffer_.GetPosition() - call_start) == JumpPattern::kLengthInBytes); | 2630 ASSERT((buffer_.GetPosition() - call_start) == JumpPattern::kLengthInBytes); |
2642 } | 2631 } |
2643 | 2632 |
2644 | 2633 |
2645 void Assembler::Jmp(const ExternalLabel* label, Register pp) { | 2634 void Assembler::Jmp(const Code& target, Register pp) { |
2646 const int32_t offset = ObjectPool::element_offset( | 2635 const int32_t offset = ObjectPool::element_offset( |
2647 object_pool_wrapper_.FindExternalLabel(label, kNotPatchable)); | 2636 object_pool_wrapper_.FindObject(target, kNotPatchable)); |
2648 jmp(Address(pp, offset - kHeapObjectTag)); | 2637 movq(CODE_REG, FieldAddress(pp, offset)); |
2638 movq(TMP, FieldAddress(CODE_REG, Code::instructions_offset())); | |
2639 addq(TMP, Immediate(Instructions::HeaderSize() - kHeapObjectTag)); | |
2640 jmp(TMP); | |
2649 } | 2641 } |
2650 | 2642 |
2651 | 2643 |
2644 void Assembler::J(Condition condition, | |
2645 const Code& target, | |
2646 Register pp) { | |
srdjan
2015/06/18 21:29:47
All arguments on one line
Florian Schneider
2015/06/29 14:50:24
Done.
| |
2647 Label no_jump; | |
2648 j(static_cast<Condition>(condition ^ 1), &no_jump); // Negate condition. | |
2649 Jmp(target, pp); | |
2650 Bind(&no_jump); | |
2651 } | |
2652 | |
2653 | |
2652 void Assembler::lock() { | 2654 void Assembler::lock() { |
2653 AssemblerBuffer::EnsureCapacity ensured(&buffer_); | 2655 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
2654 EmitUint8(0xF0); | 2656 EmitUint8(0xF0); |
2655 } | 2657 } |
2656 | 2658 |
2657 | 2659 |
2658 void Assembler::cmpxchgl(const Address& address, Register reg) { | 2660 void Assembler::cmpxchgl(const Address& address, Register reg) { |
2659 AssemblerBuffer::EnsureCapacity ensured(&buffer_); | 2661 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
2660 EmitOperandREX(reg, address, REX_NONE); | 2662 EmitOperandREX(reg, address, REX_NONE); |
2661 EmitUint8(0x0F); | 2663 EmitUint8(0x0F); |
(...skipping 413 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3075 StoreIntoObjectFilter(object, value, &done); | 3077 StoreIntoObjectFilter(object, value, &done); |
3076 } else { | 3078 } else { |
3077 StoreIntoObjectFilterNoSmi(object, value, &done); | 3079 StoreIntoObjectFilterNoSmi(object, value, &done); |
3078 } | 3080 } |
3079 // A store buffer update is required. | 3081 // A store buffer update is required. |
3080 if (value != RDX) pushq(RDX); | 3082 if (value != RDX) pushq(RDX); |
3081 if (object != RDX) { | 3083 if (object != RDX) { |
3082 movq(RDX, object); | 3084 movq(RDX, object); |
3083 } | 3085 } |
3084 StubCode* stub_code = Isolate::Current()->stub_code(); | 3086 StubCode* stub_code = Isolate::Current()->stub_code(); |
3085 Call(&stub_code->UpdateStoreBufferLabel(), PP); | 3087 Call(Code::Handle(stub_code->UpdateStoreBufferCode()), PP); |
3086 if (value != RDX) popq(RDX); | 3088 if (value != RDX) popq(RDX); |
3087 Bind(&done); | 3089 Bind(&done); |
3088 } | 3090 } |
3089 | 3091 |
3090 | 3092 |
3091 void Assembler::StoreIntoObjectNoBarrier(Register object, | 3093 void Assembler::StoreIntoObjectNoBarrier(Register object, |
3092 const Address& dest, | 3094 const Address& dest, |
3093 Register value, | 3095 Register value, |
3094 FieldContent old_content) { | 3096 FieldContent old_content) { |
3095 VerifiedWrite(dest, value, old_content); | 3097 VerifiedWrite(dest, value, old_content); |
(...skipping 289 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3385 call(reg); | 3387 call(reg); |
3386 } | 3388 } |
3387 | 3389 |
3388 | 3390 |
3389 void Assembler::CallRuntime(const RuntimeEntry& entry, | 3391 void Assembler::CallRuntime(const RuntimeEntry& entry, |
3390 intptr_t argument_count) { | 3392 intptr_t argument_count) { |
3391 entry.Call(this, argument_count); | 3393 entry.Call(this, argument_count); |
3392 } | 3394 } |
3393 | 3395 |
3394 | 3396 |
3397 void Assembler::RestoreCodePointer() { | |
3398 movq(CODE_REG, Address(RBP, kPcMarkerSlotFromFp * kWordSize)); | |
3399 } | |
3400 | |
3401 | |
3395 void Assembler::LoadPoolPointer(Register pp) { | 3402 void Assembler::LoadPoolPointer(Register pp) { |
3396 // Load new pool pointer. | 3403 // Load new pool pointer. |
3397 const intptr_t kRIPRelativeMovqSize = 7; | 3404 CheckCodePointer(); |
3398 const intptr_t entry_to_rip_offset = CodeSize() + kRIPRelativeMovqSize; | 3405 movq(pp, FieldAddress(CODE_REG, Code::object_pool_offset())); |
3399 const intptr_t object_pool_pc_dist = | |
3400 Instructions::HeaderSize() - Instructions::object_pool_offset(); | |
3401 movq(pp, Address::AddressRIPRelative( | |
3402 -entry_to_rip_offset - object_pool_pc_dist)); | |
3403 ASSERT(CodeSize() == entry_to_rip_offset); | |
3404 } | 3406 } |
3405 | 3407 |
3406 | 3408 |
3407 void Assembler::EnterDartFrameWithInfo(intptr_t frame_size, | 3409 void Assembler::EnterDartFrame(intptr_t frame_size, Register new_pp) { |
3408 Register new_pp, | 3410 CheckCodePointer(); |
3409 Register pc_marker_override) { | |
3410 EnterFrame(0); | 3411 EnterFrame(0); |
3411 pushq(pc_marker_override); | 3412 pushq(CODE_REG); |
3412 pushq(PP); | 3413 pushq(PP); |
3413 movq(PP, new_pp); | 3414 if (new_pp == kNoRegister) { |
3415 LoadPoolPointer(PP); | |
3416 } else { | |
3417 movq(PP, new_pp); | |
3418 } | |
3414 if (frame_size != 0) { | 3419 if (frame_size != 0) { |
3415 subq(RSP, Immediate(frame_size)); | 3420 subq(RSP, Immediate(frame_size)); |
3416 } | 3421 } |
3417 } | 3422 } |
3418 | 3423 |
3419 | 3424 |
3420 void Assembler::LeaveDartFrame() { | 3425 void Assembler::LeaveDartFrame(RestorePP restore_pp) { |
3421 // Restore caller's PP register that was pushed in EnterDartFrame. | 3426 // Restore caller's PP register that was pushed in EnterDartFrame. |
3422 movq(PP, Address(RBP, (kSavedCallerPpSlotFromFp * kWordSize))); | 3427 if (restore_pp == kRestoreCallerPP) { |
3428 movq(PP, Address(RBP, (kSavedCallerPpSlotFromFp * kWordSize))); | |
3429 } | |
3423 LeaveFrame(); | 3430 LeaveFrame(); |
3424 } | 3431 } |
3425 | 3432 |
3426 | 3433 |
3434 void Assembler::CheckCodePointer() { | |
3435 #ifdef DEBUG | |
3436 Label cid_ok, instructions_ok; | |
3437 pushq(RAX); | |
3438 LoadClassId(RAX, CODE_REG); | |
3439 cmpq(RAX, Immediate(kCodeCid)); | |
3440 j(EQUAL, &cid_ok); | |
3441 int3(); | |
3442 Bind(&cid_ok); | |
3443 { | |
3444 const intptr_t kRIPRelativeLeaqSize = 7; | |
3445 const intptr_t header_to_entry_offset = | |
3446 (Instructions::HeaderSize() - kHeapObjectTag); | |
3447 const intptr_t header_to_rip_offset = | |
3448 CodeSize() + kRIPRelativeLeaqSize + header_to_entry_offset; | |
3449 leaq(RAX, Address::AddressRIPRelative(-header_to_rip_offset)); | |
3450 ASSERT(CodeSize() == (header_to_rip_offset - header_to_entry_offset)); | |
3451 } | |
3452 cmpq(RAX, FieldAddress(CODE_REG, Code::instructions_offset())); | |
3453 j(EQUAL, &instructions_ok); | |
3454 int3(); | |
3455 Bind(&instructions_ok); | |
3456 popq(RAX); | |
3457 #endif | |
3458 } | |
3459 | |
3460 | |
3427 // On entry to a function compiled for OSR, the caller's frame pointer, the | 3461 // On entry to a function compiled for OSR, the caller's frame pointer, the |
3428 // stack locals, and any copied parameters are already in place. The frame | 3462 // stack locals, and any copied parameters are already in place. The frame |
3429 // pointer is already set up. The PC marker is not correct for the | 3463 // pointer is already set up. The PC marker is not correct for the |
3430 // optimized function and there may be extra space for spill slots to | 3464 // optimized function and there may be extra space for spill slots to |
3431 // allocate. | 3465 // allocate. |
3432 void Assembler::EnterOsrFrame(intptr_t extra_size, | 3466 void Assembler::EnterOsrFrame(intptr_t extra_size) { |
3433 Register new_pp, | |
3434 Register pc_marker_override) { | |
3435 if (prologue_offset_ == -1) { | 3467 if (prologue_offset_ == -1) { |
3436 Comment("PrologueOffset = %" Pd "", CodeSize()); | 3468 Comment("PrologueOffset = %" Pd "", CodeSize()); |
3437 prologue_offset_ = CodeSize(); | 3469 prologue_offset_ = CodeSize(); |
3438 } | 3470 } |
3439 movq(Address(RBP, kPcMarkerSlotFromFp * kWordSize), pc_marker_override); | 3471 RestoreCodePointer(); |
3440 movq(PP, new_pp); | 3472 movq(PP, FieldAddress(CODE_REG, Code::object_pool_offset())); |
3473 | |
3474 CheckCodePointer(); | |
3441 if (extra_size != 0) { | 3475 if (extra_size != 0) { |
3442 subq(RSP, Immediate(extra_size)); | 3476 subq(RSP, Immediate(extra_size)); |
3443 } | 3477 } |
3444 } | 3478 } |
3445 | 3479 |
3446 | 3480 |
3447 void Assembler::EnterStubFrame() { | 3481 void Assembler::EnterStubFrame() { |
3482 CheckCodePointer(); | |
3448 EnterFrame(0); | 3483 EnterFrame(0); |
3449 pushq(Immediate(0)); // Push 0 in the saved PC area for stub frames. | 3484 pushq(CODE_REG); |
3450 pushq(PP); // Save caller's pool pointer | 3485 pushq(PP); // Save caller's pool pointer |
3451 LoadPoolPointer(PP); | 3486 LoadPoolPointer(PP); |
3452 } | 3487 } |
3453 | 3488 |
3454 | 3489 |
3455 void Assembler::LeaveStubFrame() { | 3490 void Assembler::LeaveStubFrame() { |
3456 // Restore caller's PP register that was pushed in EnterStubFrame. | 3491 // Restore caller's PP register that was pushed in EnterStubFrame. |
3457 movq(PP, Address(RBP, (kSavedCallerPpSlotFromFp * kWordSize))); | 3492 movq(PP, Address(RBP, (kSavedCallerPpSlotFromFp * kWordSize))); |
3458 LeaveFrame(); | 3493 LeaveFrame(); |
3459 } | 3494 } |
(...skipping 466 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3926 | 3961 |
3927 | 3962 |
3928 const char* Assembler::FpuRegisterName(FpuRegister reg) { | 3963 const char* Assembler::FpuRegisterName(FpuRegister reg) { |
3929 ASSERT((0 <= reg) && (reg < kNumberOfXmmRegisters)); | 3964 ASSERT((0 <= reg) && (reg < kNumberOfXmmRegisters)); |
3930 return xmm_reg_names[reg]; | 3965 return xmm_reg_names[reg]; |
3931 } | 3966 } |
3932 | 3967 |
3933 } // namespace dart | 3968 } // namespace dart |
3934 | 3969 |
3935 #endif // defined TARGET_ARCH_X64 | 3970 #endif // defined TARGET_ARCH_X64 |
OLD | NEW |