Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(265)

Side by Side Diff: runtime/vm/assembler_x64.cc

Issue 1192103004: VM: New calling convention for generated code. (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: Created 5 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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
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
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
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
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
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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698