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" |
11 #include "vm/instructions.h" | 11 #include "vm/instructions.h" |
12 #include "vm/locations.h" | 12 #include "vm/locations.h" |
13 #include "vm/memory_region.h" | 13 #include "vm/memory_region.h" |
14 #include "vm/runtime_entry.h" | 14 #include "vm/runtime_entry.h" |
15 #include "vm/stack_frame.h" | 15 #include "vm/stack_frame.h" |
16 #include "vm/stub_code.h" | 16 #include "vm/stub_code.h" |
17 | 17 |
18 namespace dart { | 18 namespace dart { |
19 | 19 |
20 DEFINE_FLAG(bool, print_stop_message, true, "Print stop message."); | 20 DEFINE_FLAG(bool, print_stop_message, true, "Print stop message."); |
21 DECLARE_FLAG(bool, inline_alloc); | 21 DECLARE_FLAG(bool, inline_alloc); |
22 | 22 |
23 | 23 |
24 Assembler::Assembler(bool use_far_branches) | 24 Assembler::Assembler(bool use_far_branches) |
25 : buffer_(), | 25 : buffer_(this), |
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_.AddFixedObject(Object::null_object()); |
Florian Schneider
2015/05/26 08:51:51
I'm considering removing all fixed objects / stubs
srdjan
2015/05/26 22:36:26
Where would you load them from?
| |
37 ASSERT(index == 0); | 37 ASSERT(index == 0); |
38 | 38 |
39 index = object_pool_.AddObject(Bool::True(), kNotPatchable); | 39 index = object_pool_.AddFixedObject(Bool::True()); |
40 ASSERT(index == 1); | 40 ASSERT(index == 1); |
41 | 41 |
42 index = object_pool_.AddObject(Bool::False(), kNotPatchable); | 42 index = object_pool_.AddFixedObject(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::ZoneHandle(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_.AddFixedExternalLabel(&stub_code->UpdateStoreBufferLabel()); |
49 kNotPatchable); | |
50 } else { | 49 } else { |
51 object_pool_.AddObject(vacant, kNotPatchable); | 50 object_pool_.AddFixedObject(vacant); |
52 } | 51 } |
53 | 52 |
54 if (stub_code->CallToRuntime_entry() != NULL) { | 53 if (stub_code->CallToRuntime_entry() != NULL) { |
55 object_pool_.AddExternalLabel(&stub_code->CallToRuntimeLabel(), | 54 object_pool_.AddFixedExternalLabel(&stub_code->CallToRuntimeLabel()); |
56 kNotPatchable); | |
57 } else { | 55 } else { |
58 object_pool_.AddObject(vacant, kNotPatchable); | 56 object_pool_.AddFixedObject(vacant); |
59 } | 57 } |
60 } | 58 } |
61 } | 59 } |
62 | 60 |
63 | 61 |
64 void Assembler::InitializeMemoryWithBreakpoints(uword data, intptr_t length) { | 62 void Assembler::InitializeMemoryWithBreakpoints(uword data, intptr_t length) { |
65 memset(reinterpret_cast<void*>(data), Instr::kBreakPointInstruction, length); | 63 memset(reinterpret_cast<void*>(data), Instr::kBreakPointInstruction, length); |
66 } | 64 } |
67 | 65 |
68 | 66 |
(...skipping 22 matching lines...) Expand all Loading... | |
91 } | 89 } |
92 | 90 |
93 | 91 |
94 void Assembler::LoadExternalLabel(Register dst, | 92 void Assembler::LoadExternalLabel(Register dst, |
95 const ExternalLabel* label, | 93 const ExternalLabel* label, |
96 Patchability patchable, | 94 Patchability patchable, |
97 Register pp) { | 95 Register pp) { |
98 const int32_t offset = | 96 const int32_t offset = |
99 Array::element_offset(object_pool_.FindExternalLabel(label, patchable)); | 97 Array::element_offset(object_pool_.FindExternalLabel(label, patchable)); |
100 LoadWordFromPoolOffset(dst, pp, offset - kHeapObjectTag); | 98 LoadWordFromPoolOffset(dst, pp, offset - kHeapObjectTag); |
99 EmitFixup(new ObjectPoolIndexFixup()); | |
101 } | 100 } |
102 | 101 |
103 | 102 |
104 void Assembler::call(const ExternalLabel* label) { | 103 void Assembler::call(const ExternalLabel* label) { |
105 { // Encode movq(TMP, Immediate(label->address())), but always as imm64. | 104 { // Encode movq(TMP, Immediate(label->address())), but always as imm64. |
106 AssemblerBuffer::EnsureCapacity ensured(&buffer_); | 105 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
107 EmitRegisterREX(TMP, REX_W); | 106 EmitRegisterREX(TMP, REX_W); |
108 EmitUint8(0xB8 | (TMP & 7)); | 107 EmitUint8(0xB8 | (TMP & 7)); |
109 EmitInt64(label->address()); | 108 EmitInt64(label->address()); |
110 } | 109 } |
111 call(TMP); | 110 call(TMP); |
112 } | 111 } |
113 | 112 |
114 | 113 |
115 void Assembler::CallPatchable(const ExternalLabel* label) { | 114 void Assembler::CallPatchable(const ExternalLabel* label) { |
116 ASSERT(allow_constant_pool()); | 115 ASSERT(allow_constant_pool()); |
117 intptr_t call_start = buffer_.GetPosition(); | 116 intptr_t call_start = buffer_.GetPosition(); |
118 const int32_t offset = | 117 const int32_t offset = |
119 Array::element_offset(object_pool_.FindExternalLabel(label, kPatchable)); | 118 Array::element_offset(object_pool_.FindExternalLabel(label, kPatchable)); |
120 call(Address::AddressBaseImm32(PP, offset - kHeapObjectTag)); | 119 call(Address::AddressBaseImm32(PP, offset - kHeapObjectTag)); |
121 ASSERT((buffer_.GetPosition() - call_start) == kCallExternalLabelSize); | 120 ASSERT((buffer_.GetPosition() - call_start) == kCallExternalLabelSize); |
121 EmitFixup(new ObjectPoolIndexFixup()); | |
122 } | 122 } |
123 | 123 |
124 | 124 |
125 void Assembler::Call(const ExternalLabel* label, Register pp) { | 125 void Assembler::Call(const ExternalLabel* label, Register pp, bool emit_fixup) { |
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 = Array::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 if (emit_fixup) { | |
133 EmitFixup(new ObjectPoolIndexFixup()); | |
134 } | |
132 } | 135 } |
133 } | 136 } |
134 | 137 |
135 | 138 |
136 void Assembler::pushq(Register reg) { | 139 void Assembler::pushq(Register reg) { |
137 AssemblerBuffer::EnsureCapacity ensured(&buffer_); | 140 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
138 EmitRegisterREX(reg, REX_NONE); | 141 EmitRegisterREX(reg, REX_NONE); |
139 EmitUint8(0x50 | (reg & 7)); | 142 EmitUint8(0x50 | (reg & 7)); |
140 } | 143 } |
141 | 144 |
(...skipping 2463 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2605 | 2608 |
2606 | 2609 |
2607 void Assembler::JmpPatchable(const ExternalLabel* label, Register pp) { | 2610 void Assembler::JmpPatchable(const ExternalLabel* label, Register pp) { |
2608 ASSERT(allow_constant_pool()); | 2611 ASSERT(allow_constant_pool()); |
2609 intptr_t call_start = buffer_.GetPosition(); | 2612 intptr_t call_start = buffer_.GetPosition(); |
2610 const int32_t offset = | 2613 const int32_t offset = |
2611 Array::element_offset(object_pool_.FindExternalLabel(label, kPatchable)); | 2614 Array::element_offset(object_pool_.FindExternalLabel(label, kPatchable)); |
2612 // Patchable jumps always use a 32-bit immediate encoding. | 2615 // Patchable jumps always use a 32-bit immediate encoding. |
2613 jmp(Address::AddressBaseImm32(pp, offset - kHeapObjectTag)); | 2616 jmp(Address::AddressBaseImm32(pp, offset - kHeapObjectTag)); |
2614 ASSERT((buffer_.GetPosition() - call_start) == JumpPattern::kLengthInBytes); | 2617 ASSERT((buffer_.GetPosition() - call_start) == JumpPattern::kLengthInBytes); |
2618 EmitFixup(new ObjectPoolIndexFixup()); | |
2615 } | 2619 } |
2616 | 2620 |
2617 | 2621 |
2618 void Assembler::Jmp(const ExternalLabel* label, Register pp) { | 2622 void Assembler::Jmp(const ExternalLabel* label, Register pp) { |
2619 const int32_t offset = Array::element_offset( | 2623 const int32_t offset = Array::element_offset( |
2620 object_pool_.FindExternalLabel(label, kNotPatchable)); | 2624 object_pool_.FindExternalLabel(label, kNotPatchable)); |
2621 jmp(Address(pp, offset - kHeapObjectTag)); | 2625 jmp(Address::AddressBaseImm32(pp, offset - kHeapObjectTag)); |
2626 EmitFixup(new ObjectPoolIndexFixup()); | |
2622 } | 2627 } |
2623 | 2628 |
2624 | 2629 |
2625 void Assembler::lock() { | 2630 void Assembler::lock() { |
2626 AssemblerBuffer::EnsureCapacity ensured(&buffer_); | 2631 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
2627 EmitUint8(0xF0); | 2632 EmitUint8(0xF0); |
2628 } | 2633 } |
2629 | 2634 |
2630 | 2635 |
2631 void Assembler::cmpxchgl(const Address& address, Register reg) { | 2636 void Assembler::cmpxchgl(const Address& address, Register reg) { |
(...skipping 178 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2810 | 2815 |
2811 | 2816 |
2812 void Assembler::LoadIsolate(Register dst) { | 2817 void Assembler::LoadIsolate(Register dst) { |
2813 movq(dst, Immediate(reinterpret_cast<uword>(Isolate::Current()))); | 2818 movq(dst, Immediate(reinterpret_cast<uword>(Isolate::Current()))); |
2814 } | 2819 } |
2815 | 2820 |
2816 | 2821 |
2817 void Assembler::LoadObject(Register dst, const Object& object, Register pp) { | 2822 void Assembler::LoadObject(Register dst, const Object& object, Register pp) { |
2818 if (CanLoadFromObjectPool(object)) { | 2823 if (CanLoadFromObjectPool(object)) { |
2819 const int32_t offset = | 2824 const int32_t offset = |
2820 Array::element_offset(object_pool_.FindObject(object, kNotPatchable)); | 2825 Array::element_offset(object_pool_.FindObject(object)); |
2821 LoadWordFromPoolOffset(dst, pp, offset - kHeapObjectTag); | 2826 LoadWordFromPoolOffset(dst, pp, offset - kHeapObjectTag); |
2822 } else { | 2827 } else { |
2823 ASSERT((Isolate::Current() == Dart::vm_isolate()) || | 2828 ASSERT((Isolate::Current() == Dart::vm_isolate()) || |
2824 object.IsSmi() || | 2829 object.IsSmi() || |
2825 object.InVMHeap()); | 2830 object.InVMHeap()); |
2826 LoadImmediate(dst, Immediate(reinterpret_cast<int64_t>(object.raw())), pp); | 2831 LoadImmediate(dst, Immediate(reinterpret_cast<int64_t>(object.raw())), pp); |
2827 } | 2832 } |
2828 } | 2833 } |
2829 | 2834 |
2830 | 2835 |
(...skipping 14 matching lines...) Expand all Loading... | |
2845 pushq(TMP); | 2850 pushq(TMP); |
2846 } else { | 2851 } else { |
2847 PushImmediate(Immediate(reinterpret_cast<int64_t>(object.raw())), pp); | 2852 PushImmediate(Immediate(reinterpret_cast<int64_t>(object.raw())), pp); |
2848 } | 2853 } |
2849 } | 2854 } |
2850 | 2855 |
2851 | 2856 |
2852 void Assembler::CompareObject(Register reg, const Object& object, Register pp) { | 2857 void Assembler::CompareObject(Register reg, const Object& object, Register pp) { |
2853 if (CanLoadFromObjectPool(object)) { | 2858 if (CanLoadFromObjectPool(object)) { |
2854 const int32_t offset = | 2859 const int32_t offset = |
2855 Array::element_offset(object_pool_.FindObject(object, kNotPatchable)); | 2860 Array::element_offset(object_pool_.FindObject(object)); |
2856 cmpq(reg, Address(pp, offset-kHeapObjectTag)); | 2861 cmpq(reg, Address(pp, offset-kHeapObjectTag)); |
2857 } else { | 2862 } else { |
2858 CompareImmediate( | 2863 CompareImmediate( |
2859 reg, Immediate(reinterpret_cast<int64_t>(object.raw())), pp); | 2864 reg, Immediate(reinterpret_cast<int64_t>(object.raw())), pp); |
2860 } | 2865 } |
2861 } | 2866 } |
2862 | 2867 |
2863 | 2868 |
2864 intptr_t Assembler::FindImmediate(int64_t imm) { | 2869 intptr_t Assembler::FindImmediate(int64_t imm) { |
2865 ASSERT(Isolate::Current() != Dart::vm_isolate()); | 2870 ASSERT(Isolate::Current() != Dart::vm_isolate()); |
2866 const Smi& smi = Smi::Handle(reinterpret_cast<RawSmi*>(imm)); | 2871 const Smi& smi = Smi::ZoneHandle(reinterpret_cast<RawSmi*>(imm)); |
2867 return object_pool_.FindObject(smi, kNotPatchable); | 2872 return object_pool_.FindObject(smi); |
2868 } | 2873 } |
2869 | 2874 |
2870 | 2875 |
2871 bool Assembler::CanLoadImmediateFromPool(const Immediate& imm, Register pp) { | 2876 bool Assembler::CanLoadImmediateFromPool(const Immediate& imm, Register pp) { |
2872 if (!allow_constant_pool()) { | 2877 if (!allow_constant_pool()) { |
2873 return false; | 2878 return false; |
2874 } | 2879 } |
2875 return !imm.is_int32() && | 2880 return !imm.is_int32() && |
2876 (pp != kNoRegister) && | 2881 (pp != kNoRegister) && |
2877 (Isolate::Current() != Dart::vm_isolate()); | 2882 (Isolate::Current() != Dart::vm_isolate()); |
(...skipping 179 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3057 StoreIntoObjectFilter(object, value, &done); | 3062 StoreIntoObjectFilter(object, value, &done); |
3058 } else { | 3063 } else { |
3059 StoreIntoObjectFilterNoSmi(object, value, &done); | 3064 StoreIntoObjectFilterNoSmi(object, value, &done); |
3060 } | 3065 } |
3061 // A store buffer update is required. | 3066 // A store buffer update is required. |
3062 if (value != RDX) pushq(RDX); | 3067 if (value != RDX) pushq(RDX); |
3063 if (object != RDX) { | 3068 if (object != RDX) { |
3064 movq(RDX, object); | 3069 movq(RDX, object); |
3065 } | 3070 } |
3066 StubCode* stub_code = Isolate::Current()->stub_code(); | 3071 StubCode* stub_code = Isolate::Current()->stub_code(); |
3067 Call(&stub_code->UpdateStoreBufferLabel(), PP); | 3072 Call(&stub_code->UpdateStoreBufferLabel(), PP, |
3073 false); // No fixup. Stub is at a fixed place in the object pool. | |
3068 if (value != RDX) popq(RDX); | 3074 if (value != RDX) popq(RDX); |
3069 Bind(&done); | 3075 Bind(&done); |
3070 } | 3076 } |
3071 | 3077 |
3072 | 3078 |
3073 void Assembler::StoreIntoObjectNoBarrier(Register object, | 3079 void Assembler::StoreIntoObjectNoBarrier(Register object, |
3074 const Address& dest, | 3080 const Address& dest, |
3075 Register value, | 3081 Register value, |
3076 FieldContent old_content) { | 3082 FieldContent old_content) { |
3077 VerifiedWrite(dest, value, old_content); | 3083 VerifiedWrite(dest, value, old_content); |
(...skipping 818 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3896 | 3902 |
3897 | 3903 |
3898 const char* Assembler::FpuRegisterName(FpuRegister reg) { | 3904 const char* Assembler::FpuRegisterName(FpuRegister reg) { |
3899 ASSERT((0 <= reg) && (reg < kNumberOfXmmRegisters)); | 3905 ASSERT((0 <= reg) && (reg < kNumberOfXmmRegisters)); |
3900 return xmm_reg_names[reg]; | 3906 return xmm_reg_names[reg]; |
3901 } | 3907 } |
3902 | 3908 |
3903 } // namespace dart | 3909 } // namespace dart |
3904 | 3910 |
3905 #endif // defined TARGET_ARCH_X64 | 3911 #endif // defined TARGET_ARCH_X64 |
OLD | NEW |