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 15 matching lines...) Expand all Loading... | |
26 prologue_offset_(-1), | 26 prologue_offset_(-1), |
27 comments_(), | 27 comments_(), |
28 allow_constant_pool_(true) { | 28 allow_constant_pool_(true) { |
29 // Far branching mode is only needed and implemented for MIPS and ARM. | 29 // Far branching mode is only needed and implemented for MIPS and ARM. |
30 ASSERT(!use_far_branches); | 30 ASSERT(!use_far_branches); |
31 Isolate* isolate = Isolate::Current(); | 31 Isolate* isolate = Isolate::Current(); |
32 if (isolate != Dart::vm_isolate()) { | 32 if (isolate != Dart::vm_isolate()) { |
33 // These objects and labels need to be accessible through every pool-pointer | 33 // These objects and labels need to be accessible through every pool-pointer |
34 // at the same index. | 34 // at the same index. |
35 intptr_t index = | 35 intptr_t index = |
36 object_pool_.AddObject(Object::null_object(), kNotPatchable); | 36 object_pool_.AddObject(Object::null_object()); |
srdjan
2015/06/09 21:49:47
On one line?
Florian Schneider
2015/06/10 08:26:17
Done.
| |
37 ASSERT(index == 0); | 37 ASSERT(index == 0); |
38 | 38 |
39 index = object_pool_.AddObject(Bool::True(), kNotPatchable); | 39 index = object_pool_.AddObject(Bool::True()); |
40 ASSERT(index == 1); | 40 ASSERT(index == 1); |
41 | 41 |
42 index = object_pool_.AddObject(Bool::False(), kNotPatchable); | 42 index = object_pool_.AddObject(Bool::False()); |
43 ASSERT(index == 2); | 43 ASSERT(index == 2); |
44 | 44 |
45 const Smi& vacant = Smi::Handle(Smi::New(0xfa >> kSmiTagShift)); | 45 const Smi& vacant = Smi::Handle(Smi::New(0xfa >> kSmiTagShift)); |
46 StubCode* stub_code = isolate->stub_code(); | 46 StubCode* stub_code = isolate->stub_code(); |
47 if (stub_code->UpdateStoreBuffer_entry() != NULL) { | 47 if (stub_code->UpdateStoreBuffer_entry() != NULL) { |
48 object_pool_.AddExternalLabel(&stub_code->UpdateStoreBufferLabel(), | 48 object_pool_.AddExternalLabel(&stub_code->UpdateStoreBufferLabel(), |
49 kNotPatchable); | 49 kNotPatchable); |
50 } else { | 50 } else { |
51 object_pool_.AddObject(vacant, kNotPatchable); | 51 object_pool_.AddObject(vacant); |
52 } | 52 } |
53 | 53 |
54 if (stub_code->CallToRuntime_entry() != NULL) { | 54 if (stub_code->CallToRuntime_entry() != NULL) { |
55 object_pool_.AddExternalLabel(&stub_code->CallToRuntimeLabel(), | 55 object_pool_.AddExternalLabel(&stub_code->CallToRuntimeLabel(), |
56 kNotPatchable); | 56 kNotPatchable); |
57 } else { | 57 } else { |
58 object_pool_.AddObject(vacant, kNotPatchable); | 58 object_pool_.AddObject(vacant); |
59 } | 59 } |
60 } | 60 } |
61 } | 61 } |
62 | 62 |
63 | 63 |
64 void Assembler::InitializeMemoryWithBreakpoints(uword data, intptr_t length) { | 64 void Assembler::InitializeMemoryWithBreakpoints(uword data, intptr_t length) { |
65 memset(reinterpret_cast<void*>(data), Instr::kBreakPointInstruction, length); | 65 memset(reinterpret_cast<void*>(data), Instr::kBreakPointInstruction, length); |
66 } | 66 } |
67 | 67 |
68 | 68 |
(...skipping 19 matching lines...) Expand all Loading... | |
88 static const int kSize = 5; | 88 static const int kSize = 5; |
89 EmitUint8(0xE8); | 89 EmitUint8(0xE8); |
90 EmitLabel(label, kSize); | 90 EmitLabel(label, kSize); |
91 } | 91 } |
92 | 92 |
93 | 93 |
94 void Assembler::LoadExternalLabel(Register dst, | 94 void Assembler::LoadExternalLabel(Register dst, |
95 const ExternalLabel* label, | 95 const ExternalLabel* label, |
96 Patchability patchable, | 96 Patchability patchable, |
97 Register pp) { | 97 Register pp) { |
98 const int32_t offset = | 98 const int32_t offset = ObjectPool::element_offset( |
99 Array::element_offset(object_pool_.FindExternalLabel(label, patchable)); | 99 object_pool_.FindExternalLabel(label, patchable)); |
100 LoadWordFromPoolOffset(dst, pp, offset - kHeapObjectTag); | 100 LoadWordFromPoolOffset(dst, pp, offset - kHeapObjectTag); |
101 } | 101 } |
102 | 102 |
103 | 103 |
104 void Assembler::call(const ExternalLabel* label) { | 104 void Assembler::call(const ExternalLabel* label) { |
105 { // Encode movq(TMP, Immediate(label->address())), but always as imm64. | 105 { // Encode movq(TMP, Immediate(label->address())), but always as imm64. |
106 AssemblerBuffer::EnsureCapacity ensured(&buffer_); | 106 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
107 EmitRegisterREX(TMP, REX_W); | 107 EmitRegisterREX(TMP, REX_W); |
108 EmitUint8(0xB8 | (TMP & 7)); | 108 EmitUint8(0xB8 | (TMP & 7)); |
109 EmitInt64(label->address()); | 109 EmitInt64(label->address()); |
110 } | 110 } |
111 call(TMP); | 111 call(TMP); |
112 } | 112 } |
113 | 113 |
114 | 114 |
115 void Assembler::CallPatchable(const ExternalLabel* label) { | 115 void Assembler::CallPatchable(const ExternalLabel* label) { |
116 ASSERT(allow_constant_pool()); | 116 ASSERT(allow_constant_pool()); |
117 intptr_t call_start = buffer_.GetPosition(); | 117 intptr_t call_start = buffer_.GetPosition(); |
118 const int32_t offset = | 118 const int32_t offset = ObjectPool::element_offset( |
119 Array::element_offset(object_pool_.FindExternalLabel(label, kPatchable)); | 119 object_pool_.FindExternalLabel(label, kPatchable)); |
120 call(Address::AddressBaseImm32(PP, offset - kHeapObjectTag)); | 120 call(Address::AddressBaseImm32(PP, offset - kHeapObjectTag)); |
121 ASSERT((buffer_.GetPosition() - call_start) == kCallExternalLabelSize); | 121 ASSERT((buffer_.GetPosition() - call_start) == kCallExternalLabelSize); |
122 } | 122 } |
123 | 123 |
124 | 124 |
125 void Assembler::Call(const ExternalLabel* label, Register pp) { | 125 void Assembler::Call(const ExternalLabel* label, Register pp) { |
126 if (Isolate::Current() == Dart::vm_isolate()) { | 126 if (Isolate::Current() == Dart::vm_isolate()) { |
127 call(label); | 127 call(label); |
128 } else { | 128 } else { |
129 const int32_t offset = Array::element_offset( | 129 const int32_t offset = ObjectPool::element_offset( |
130 object_pool_.FindExternalLabel(label, kNotPatchable)); | 130 object_pool_.FindExternalLabel(label, kNotPatchable)); |
131 call(Address::AddressBaseImm32(pp, offset - kHeapObjectTag)); | 131 call(Address::AddressBaseImm32(pp, offset - kHeapObjectTag)); |
132 } | 132 } |
133 } | 133 } |
134 | 134 |
135 | 135 |
136 void Assembler::pushq(Register reg) { | 136 void Assembler::pushq(Register reg) { |
137 AssemblerBuffer::EnsureCapacity ensured(&buffer_); | 137 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
138 EmitRegisterREX(reg, REX_NONE); | 138 EmitRegisterREX(reg, REX_NONE); |
139 EmitUint8(0x50 | (reg & 7)); | 139 EmitUint8(0x50 | (reg & 7)); |
(...skipping 2460 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2600 EmitUint8(0xB8 | (TMP & 7)); | 2600 EmitUint8(0xB8 | (TMP & 7)); |
2601 EmitInt64(label->address()); | 2601 EmitInt64(label->address()); |
2602 } | 2602 } |
2603 jmp(TMP); | 2603 jmp(TMP); |
2604 } | 2604 } |
2605 | 2605 |
2606 | 2606 |
2607 void Assembler::JmpPatchable(const ExternalLabel* label, Register pp) { | 2607 void Assembler::JmpPatchable(const ExternalLabel* label, Register pp) { |
2608 ASSERT(allow_constant_pool()); | 2608 ASSERT(allow_constant_pool()); |
2609 intptr_t call_start = buffer_.GetPosition(); | 2609 intptr_t call_start = buffer_.GetPosition(); |
2610 const int32_t offset = | 2610 const int32_t offset = ObjectPool::element_offset( |
2611 Array::element_offset(object_pool_.FindExternalLabel(label, kPatchable)); | 2611 object_pool_.FindExternalLabel(label, kPatchable)); |
2612 // Patchable jumps always use a 32-bit immediate encoding. | 2612 // Patchable jumps always use a 32-bit immediate encoding. |
2613 jmp(Address::AddressBaseImm32(pp, offset - kHeapObjectTag)); | 2613 jmp(Address::AddressBaseImm32(pp, offset - kHeapObjectTag)); |
2614 ASSERT((buffer_.GetPosition() - call_start) == JumpPattern::kLengthInBytes); | 2614 ASSERT((buffer_.GetPosition() - call_start) == JumpPattern::kLengthInBytes); |
2615 } | 2615 } |
2616 | 2616 |
2617 | 2617 |
2618 void Assembler::Jmp(const ExternalLabel* label, Register pp) { | 2618 void Assembler::Jmp(const ExternalLabel* label, Register pp) { |
2619 const int32_t offset = Array::element_offset( | 2619 const int32_t offset = ObjectPool::element_offset( |
2620 object_pool_.FindExternalLabel(label, kNotPatchable)); | 2620 object_pool_.FindExternalLabel(label, kNotPatchable)); |
2621 jmp(Address(pp, offset - kHeapObjectTag)); | 2621 jmp(Address(pp, offset - kHeapObjectTag)); |
2622 } | 2622 } |
2623 | 2623 |
2624 | 2624 |
2625 void Assembler::lock() { | 2625 void Assembler::lock() { |
2626 AssemblerBuffer::EnsureCapacity ensured(&buffer_); | 2626 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
2627 EmitUint8(0xF0); | 2627 EmitUint8(0xF0); |
2628 } | 2628 } |
2629 | 2629 |
(...skipping 180 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2810 | 2810 |
2811 | 2811 |
2812 void Assembler::LoadIsolate(Register dst) { | 2812 void Assembler::LoadIsolate(Register dst) { |
2813 movq(dst, Address(THR, Thread::isolate_offset())); | 2813 movq(dst, Address(THR, Thread::isolate_offset())); |
2814 } | 2814 } |
2815 | 2815 |
2816 | 2816 |
2817 void Assembler::LoadObject(Register dst, const Object& object, Register pp) { | 2817 void Assembler::LoadObject(Register dst, const Object& object, Register pp) { |
2818 if (CanLoadFromObjectPool(object)) { | 2818 if (CanLoadFromObjectPool(object)) { |
2819 const int32_t offset = | 2819 const int32_t offset = |
2820 Array::element_offset(object_pool_.FindObject(object, kNotPatchable)); | 2820 ObjectPool::element_offset(object_pool_.FindObject(object)); |
2821 LoadWordFromPoolOffset(dst, pp, offset - kHeapObjectTag); | 2821 LoadWordFromPoolOffset(dst, pp, offset - kHeapObjectTag); |
2822 } else { | 2822 } else { |
2823 ASSERT((Isolate::Current() == Dart::vm_isolate()) || | 2823 ASSERT((Isolate::Current() == Dart::vm_isolate()) || |
2824 object.IsSmi() || | 2824 object.IsSmi() || |
2825 object.InVMHeap()); | 2825 object.InVMHeap()); |
2826 LoadImmediate(dst, Immediate(reinterpret_cast<int64_t>(object.raw())), pp); | 2826 LoadImmediate(dst, Immediate(reinterpret_cast<int64_t>(object.raw())), pp); |
2827 } | 2827 } |
2828 } | 2828 } |
2829 | 2829 |
2830 | 2830 |
(...skipping 14 matching lines...) Expand all Loading... | |
2845 pushq(TMP); | 2845 pushq(TMP); |
2846 } else { | 2846 } else { |
2847 PushImmediate(Immediate(reinterpret_cast<int64_t>(object.raw())), pp); | 2847 PushImmediate(Immediate(reinterpret_cast<int64_t>(object.raw())), pp); |
2848 } | 2848 } |
2849 } | 2849 } |
2850 | 2850 |
2851 | 2851 |
2852 void Assembler::CompareObject(Register reg, const Object& object, Register pp) { | 2852 void Assembler::CompareObject(Register reg, const Object& object, Register pp) { |
2853 if (CanLoadFromObjectPool(object)) { | 2853 if (CanLoadFromObjectPool(object)) { |
2854 const int32_t offset = | 2854 const int32_t offset = |
2855 Array::element_offset(object_pool_.FindObject(object, kNotPatchable)); | 2855 ObjectPool::element_offset(object_pool_.FindObject(object)); |
2856 cmpq(reg, Address(pp, offset-kHeapObjectTag)); | 2856 cmpq(reg, Address(pp, offset-kHeapObjectTag)); |
2857 } else { | 2857 } else { |
2858 CompareImmediate( | 2858 CompareImmediate( |
2859 reg, Immediate(reinterpret_cast<int64_t>(object.raw())), pp); | 2859 reg, Immediate(reinterpret_cast<int64_t>(object.raw())), pp); |
2860 } | 2860 } |
2861 } | 2861 } |
2862 | 2862 |
2863 | 2863 |
2864 intptr_t Assembler::FindImmediate(int64_t imm) { | 2864 intptr_t Assembler::FindImmediate(int64_t imm) { |
2865 ASSERT(Isolate::Current() != Dart::vm_isolate()); | 2865 ASSERT(Isolate::Current() != Dart::vm_isolate()); |
2866 const Smi& smi = Smi::Handle(reinterpret_cast<RawSmi*>(imm)); | 2866 return object_pool_.FindImmediate(imm); |
2867 return object_pool_.FindObject(smi, kNotPatchable); | |
2868 } | 2867 } |
2869 | 2868 |
2870 | 2869 |
2871 bool Assembler::CanLoadImmediateFromPool(const Immediate& imm, Register pp) { | 2870 bool Assembler::CanLoadImmediateFromPool(const Immediate& imm, Register pp) { |
2872 if (!allow_constant_pool()) { | 2871 if (!allow_constant_pool()) { |
2873 return false; | 2872 return false; |
2874 } | 2873 } |
2875 return !imm.is_int32() && | 2874 return !imm.is_int32() && |
2876 (pp != kNoRegister) && | 2875 (pp != kNoRegister) && |
2877 (Isolate::Current() != Dart::vm_isolate()); | 2876 (Isolate::Current() != Dart::vm_isolate()); |
2878 } | 2877 } |
2879 | 2878 |
2880 | 2879 |
2881 void Assembler::LoadImmediate(Register reg, const Immediate& imm, Register pp) { | 2880 void Assembler::LoadImmediate(Register reg, const Immediate& imm, Register pp) { |
2882 if (CanLoadImmediateFromPool(imm, pp)) { | 2881 if (CanLoadImmediateFromPool(imm, pp)) { |
2883 // It's a 64-bit constant and we're not in the VM isolate, so load from | 2882 // It's a 64-bit constant and we're not in the VM isolate, so load from |
2884 // object pool. | 2883 // object pool. |
2885 int64_t val = imm.value(); | 2884 int32_t offset = ObjectPool::element_offset(FindImmediate(imm.value())); |
2886 // Save the bits that must be masked-off for the SmiTag | |
2887 int64_t val_smi_tag = val & kSmiTagMask; | |
2888 val &= ~kSmiTagMask; // Mask off the tag bits. | |
2889 const int32_t offset = Array::element_offset(FindImmediate(val)); | |
2890 LoadWordFromPoolOffset(reg, pp, offset - kHeapObjectTag); | 2885 LoadWordFromPoolOffset(reg, pp, offset - kHeapObjectTag); |
2891 if (val_smi_tag != 0) { | |
2892 // Add back the tag bits. | |
2893 orq(reg, Immediate(val_smi_tag)); | |
2894 } | |
2895 } else { | 2886 } else { |
2896 movq(reg, imm); | 2887 movq(reg, imm); |
2897 } | 2888 } |
2898 } | 2889 } |
2899 | 2890 |
2900 | 2891 |
2901 void Assembler::MoveImmediate(const Address& dst, const Immediate& imm, | 2892 void Assembler::MoveImmediate(const Address& dst, const Immediate& imm, |
2902 Register pp) { | 2893 Register pp) { |
2903 if (CanLoadImmediateFromPool(imm, pp)) { | 2894 if (CanLoadImmediateFromPool(imm, pp)) { |
2904 LoadImmediate(TMP, imm, pp); | 2895 LoadImmediate(TMP, imm, pp); |
(...skipping 1003 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3908 | 3899 |
3909 | 3900 |
3910 const char* Assembler::FpuRegisterName(FpuRegister reg) { | 3901 const char* Assembler::FpuRegisterName(FpuRegister reg) { |
3911 ASSERT((0 <= reg) && (reg < kNumberOfXmmRegisters)); | 3902 ASSERT((0 <= reg) && (reg < kNumberOfXmmRegisters)); |
3912 return xmm_reg_names[reg]; | 3903 return xmm_reg_names[reg]; |
3913 } | 3904 } |
3914 | 3905 |
3915 } // namespace dart | 3906 } // namespace dart |
3916 | 3907 |
3917 #endif // defined TARGET_ARCH_X64 | 3908 #endif // defined TARGET_ARCH_X64 |
OLD | NEW |