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

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

Issue 886173003: VM: Align implementations of assembler constant pools. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: fixed ARM debug assert Created 5 years, 10 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 | Annotate | Revision Log
« runtime/vm/assembler_arm64.cc ('K') | « runtime/vm/assembler_x64.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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"
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_(),
26 object_pool_(GrowableObjectArray::Handle()),
27 patchable_pool_entries_(),
28 prologue_offset_(-1), 26 prologue_offset_(-1),
29 comments_(), 27 comments_(),
30 allow_constant_pool_(true) { 28 allow_constant_pool_(true) {
31 // 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.
32 ASSERT(!use_far_branches); 30 ASSERT(!use_far_branches);
33 Isolate* isolate = Isolate::Current(); 31 Isolate* isolate = Isolate::Current();
34 if (isolate != Dart::vm_isolate()) { 32 if (isolate != Dart::vm_isolate()) {
35 object_pool_ = GrowableObjectArray::New(Heap::kOld);
36
37 // 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
38 // at the same index. 34 // at the same index.
39 object_pool_.Add(Object::null_object(), Heap::kOld); 35 intptr_t index =
40 patchable_pool_entries_.Add(kNotPatchable); 36 object_pool_.AddObject(Object::null_object(), kNotPatchable);
41 object_pool_index_table_.Insert(ObjIndexPair(&Object::null_object(), 0)); 37 ASSERT(index == 0);
42 38
43 object_pool_.Add(Bool::True(), Heap::kOld); 39 index = object_pool_.AddObject(Bool::True(), kNotPatchable);
44 patchable_pool_entries_.Add(kNotPatchable); 40 ASSERT(index == 1);
45 object_pool_index_table_.Insert(ObjIndexPair(&Bool::True(), 1));
46 41
47 object_pool_.Add(Bool::False(), Heap::kOld); 42 index = object_pool_.AddObject(Bool::False(), kNotPatchable);
48 patchable_pool_entries_.Add(kNotPatchable); 43 ASSERT(index == 2);
49 object_pool_index_table_.Insert(ObjIndexPair(&Bool::False(), 2));
50 44
51 const Smi& vacant = Smi::Handle(Smi::New(0xfa >> kSmiTagShift)); 45 const Smi& vacant = Smi::Handle(Smi::New(0xfa >> kSmiTagShift));
52
53 StubCode* stub_code = isolate->stub_code(); 46 StubCode* stub_code = isolate->stub_code();
54 if (stub_code->UpdateStoreBuffer_entry() != NULL) { 47 if (stub_code->UpdateStoreBuffer_entry() != NULL) {
55 FindExternalLabel(&stub_code->UpdateStoreBufferLabel(), kNotPatchable); 48 object_pool_.AddExternalLabel(&stub_code->UpdateStoreBufferLabel(),
49 kNotPatchable);
56 } else { 50 } else {
57 object_pool_.Add(vacant, Heap::kOld); 51 object_pool_.AddObject(vacant, kNotPatchable);
58 patchable_pool_entries_.Add(kNotPatchable);
59 } 52 }
60 53
61 if (stub_code->CallToRuntime_entry() != NULL) { 54 if (stub_code->CallToRuntime_entry() != NULL) {
62 FindExternalLabel(&stub_code->CallToRuntimeLabel(), kNotPatchable); 55 object_pool_.AddExternalLabel(&stub_code->CallToRuntimeLabel(),
56 kNotPatchable);
63 } else { 57 } else {
64 object_pool_.Add(vacant, Heap::kOld); 58 object_pool_.AddObject(vacant, kNotPatchable);
65 patchable_pool_entries_.Add(kNotPatchable);
66 } 59 }
67 60
68 // Create fixed object pool entries for debugger stubs. 61 // Create fixed object pool entries for debugger stubs.
69 if (stub_code->ICCallBreakpoint_entry() != NULL) { 62 if (stub_code->ICCallBreakpoint_entry() != NULL) {
70 intptr_t index = 63 index = object_pool_.AddExternalLabel(
71 FindExternalLabel(&stub_code->ICCallBreakpointLabel(), 64 &stub_code->ICCallBreakpointLabel(), kNotPatchable);
72 kNotPatchable);
73 ASSERT(index == kICCallBreakpointCPIndex); 65 ASSERT(index == kICCallBreakpointCPIndex);
74 } else { 66 } else {
75 object_pool_.Add(vacant, Heap::kOld); 67 object_pool_.AddObject(vacant, kNotPatchable);
76 patchable_pool_entries_.Add(kNotPatchable);
77 } 68 }
78 if (stub_code->ClosureCallBreakpoint_entry() != NULL) { 69 if (stub_code->ClosureCallBreakpoint_entry() != NULL) {
79 intptr_t index = 70 index = object_pool_.AddExternalLabel(
80 FindExternalLabel(&stub_code->ClosureCallBreakpointLabel(), 71 &stub_code->ClosureCallBreakpointLabel(), kNotPatchable);
81 kNotPatchable);
82 ASSERT(index == kClosureCallBreakpointCPIndex); 72 ASSERT(index == kClosureCallBreakpointCPIndex);
83 } else { 73 } else {
84 object_pool_.Add(vacant, Heap::kOld); 74 object_pool_.AddObject(vacant, kNotPatchable);
85 patchable_pool_entries_.Add(kNotPatchable);
86 } 75 }
87 if (stub_code->RuntimeCallBreakpoint_entry() != NULL) { 76 if (stub_code->RuntimeCallBreakpoint_entry() != NULL) {
88 intptr_t index = 77 index = object_pool_.AddExternalLabel(
89 FindExternalLabel(&stub_code->RuntimeCallBreakpointLabel(), 78 &stub_code->RuntimeCallBreakpointLabel(), kNotPatchable);
90 kNotPatchable);
91 ASSERT(index == kRuntimeCallBreakpointCPIndex); 79 ASSERT(index == kRuntimeCallBreakpointCPIndex);
92 } else { 80 } else {
93 object_pool_.Add(vacant, Heap::kOld); 81 object_pool_.AddObject(vacant, kNotPatchable);
94 patchable_pool_entries_.Add(kNotPatchable);
95 } 82 }
96 } 83 }
97 } 84 }
98 85
99 86
100 void Assembler::InitializeMemoryWithBreakpoints(uword data, intptr_t length) { 87 void Assembler::InitializeMemoryWithBreakpoints(uword data, intptr_t length) {
101 memset(reinterpret_cast<void*>(data), Instr::kBreakPointInstruction, length); 88 memset(reinterpret_cast<void*>(data), Instr::kBreakPointInstruction, length);
102 } 89 }
103 90
104 91
(...skipping 20 matching lines...) Expand all
125 EmitUint8(0xE8); 112 EmitUint8(0xE8);
126 EmitLabel(label, kSize); 113 EmitLabel(label, kSize);
127 } 114 }
128 115
129 116
130 void Assembler::LoadExternalLabel(Register dst, 117 void Assembler::LoadExternalLabel(Register dst,
131 const ExternalLabel* label, 118 const ExternalLabel* label,
132 Patchability patchable, 119 Patchability patchable,
133 Register pp) { 120 Register pp) {
134 const int32_t offset = 121 const int32_t offset =
135 Array::element_offset(FindExternalLabel(label, patchable)); 122 Array::element_offset(object_pool_.FindExternalLabel(label, patchable));
136 LoadWordFromPoolOffset(dst, pp, offset - kHeapObjectTag); 123 LoadWordFromPoolOffset(dst, pp, offset - kHeapObjectTag);
137 } 124 }
138 125
139 126
140 void Assembler::call(const ExternalLabel* label) { 127 void Assembler::call(const ExternalLabel* label) {
141 { // Encode movq(TMP, Immediate(label->address())), but always as imm64. 128 { // Encode movq(TMP, Immediate(label->address())), but always as imm64.
142 AssemblerBuffer::EnsureCapacity ensured(&buffer_); 129 AssemblerBuffer::EnsureCapacity ensured(&buffer_);
143 EmitRegisterREX(TMP, REX_W); 130 EmitRegisterREX(TMP, REX_W);
144 EmitUint8(0xB8 | (TMP & 7)); 131 EmitUint8(0xB8 | (TMP & 7));
145 EmitInt64(label->address()); 132 EmitInt64(label->address());
146 } 133 }
147 call(TMP); 134 call(TMP);
148 } 135 }
149 136
150 137
151 void Assembler::CallPatchable(const ExternalLabel* label) { 138 void Assembler::CallPatchable(const ExternalLabel* label) {
152 ASSERT(allow_constant_pool()); 139 ASSERT(allow_constant_pool());
153 intptr_t call_start = buffer_.GetPosition(); 140 intptr_t call_start = buffer_.GetPosition();
154 const int32_t offset = 141 const int32_t offset =
155 Array::element_offset(FindExternalLabel(label, kPatchable)); 142 Array::element_offset(object_pool_.FindExternalLabel(label, kPatchable));
156 call(Address::AddressBaseImm32(PP, offset - kHeapObjectTag)); 143 call(Address::AddressBaseImm32(PP, offset - kHeapObjectTag));
157 ASSERT((buffer_.GetPosition() - call_start) == kCallExternalLabelSize); 144 ASSERT((buffer_.GetPosition() - call_start) == kCallExternalLabelSize);
158 } 145 }
159 146
160 147
161 void Assembler::Call(const ExternalLabel* label, Register pp) { 148 void Assembler::Call(const ExternalLabel* label, Register pp) {
162 if (Isolate::Current() == Dart::vm_isolate()) { 149 if (Isolate::Current() == Dart::vm_isolate()) {
163 call(label); 150 call(label);
164 } else { 151 } else {
165 const int32_t offset = 152 const int32_t offset = Array::element_offset(
166 Array::element_offset(FindExternalLabel(label, kNotPatchable)); 153 object_pool_.FindExternalLabel(label, kNotPatchable));
167 call(Address::AddressBaseImm32(pp, offset - kHeapObjectTag)); 154 call(Address::AddressBaseImm32(pp, offset - kHeapObjectTag));
168 } 155 }
169 } 156 }
170 157
171 158
172 void Assembler::pushq(Register reg) { 159 void Assembler::pushq(Register reg) {
173 AssemblerBuffer::EnsureCapacity ensured(&buffer_); 160 AssemblerBuffer::EnsureCapacity ensured(&buffer_);
174 EmitRegisterREX(reg, REX_NONE); 161 EmitRegisterREX(reg, REX_NONE);
175 EmitUint8(0x50 | (reg & 7)); 162 EmitUint8(0x50 | (reg & 7));
176 } 163 }
(...skipping 2436 matching lines...) Expand 10 before | Expand all | Expand 10 after
2613 EmitInt64(label->address()); 2600 EmitInt64(label->address());
2614 } 2601 }
2615 jmp(TMP); 2602 jmp(TMP);
2616 } 2603 }
2617 2604
2618 2605
2619 void Assembler::JmpPatchable(const ExternalLabel* label, Register pp) { 2606 void Assembler::JmpPatchable(const ExternalLabel* label, Register pp) {
2620 ASSERT(allow_constant_pool()); 2607 ASSERT(allow_constant_pool());
2621 intptr_t call_start = buffer_.GetPosition(); 2608 intptr_t call_start = buffer_.GetPosition();
2622 const int32_t offset = 2609 const int32_t offset =
2623 Array::element_offset(FindExternalLabel(label, kPatchable)); 2610 Array::element_offset(object_pool_.FindExternalLabel(label, kPatchable));
2624 // Patchable jumps always use a 32-bit immediate encoding. 2611 // Patchable jumps always use a 32-bit immediate encoding.
2625 jmp(Address::AddressBaseImm32(pp, offset - kHeapObjectTag)); 2612 jmp(Address::AddressBaseImm32(pp, offset - kHeapObjectTag));
2626 ASSERT((buffer_.GetPosition() - call_start) == JumpPattern::kLengthInBytes); 2613 ASSERT((buffer_.GetPosition() - call_start) == JumpPattern::kLengthInBytes);
2627 } 2614 }
2628 2615
2629 2616
2630 void Assembler::Jmp(const ExternalLabel* label, Register pp) { 2617 void Assembler::Jmp(const ExternalLabel* label, Register pp) {
2631 const int32_t offset = 2618 const int32_t offset = Array::element_offset(
2632 Array::element_offset(FindExternalLabel(label, kNotPatchable)); 2619 object_pool_.FindExternalLabel(label, kNotPatchable));
2633 jmp(Address(pp, offset - kHeapObjectTag)); 2620 jmp(Address(pp, offset - kHeapObjectTag));
2634 } 2621 }
2635 2622
2636 2623
2637 void Assembler::lock() { 2624 void Assembler::lock() {
2638 AssemblerBuffer::EnsureCapacity ensured(&buffer_); 2625 AssemblerBuffer::EnsureCapacity ensured(&buffer_);
2639 EmitUint8(0xF0); 2626 EmitUint8(0xF0);
2640 } 2627 }
2641 2628
2642 2629
(...skipping 136 matching lines...) Expand 10 before | Expand all | Expand 10 after
2779 if (stack_elements <= 4) { 2766 if (stack_elements <= 4) {
2780 for (intptr_t i = 0; i < stack_elements; i++) { 2767 for (intptr_t i = 0; i < stack_elements; i++) {
2781 popq(tmp); 2768 popq(tmp);
2782 } 2769 }
2783 return; 2770 return;
2784 } 2771 }
2785 addq(RSP, Immediate(stack_elements * kWordSize)); 2772 addq(RSP, Immediate(stack_elements * kWordSize));
2786 } 2773 }
2787 2774
2788 2775
2789 intptr_t Assembler::FindObject(const Object& obj, Patchability patchable) {
2790 // The object pool cannot be used in the vm isolate.
2791 ASSERT(Isolate::Current() != Dart::vm_isolate());
2792 ASSERT(!object_pool_.IsNull());
2793
2794 // If the object is not patchable, check if we've already got it in the
2795 // object pool.
2796 if (patchable == kNotPatchable) {
2797 intptr_t idx = object_pool_index_table_.Lookup(&obj);
2798 if (idx != ObjIndexPair::kNoIndex) {
2799 ASSERT(patchable_pool_entries_[idx] == kNotPatchable);
2800 return idx;
2801 }
2802 }
2803
2804 object_pool_.Add(obj, Heap::kOld);
2805 patchable_pool_entries_.Add(patchable);
2806 if (patchable == kNotPatchable) {
2807 // The object isn't patchable. Record the index for fast lookup.
2808 object_pool_index_table_.Insert(
2809 ObjIndexPair(&obj, object_pool_.Length() - 1));
2810 }
2811 return object_pool_.Length() - 1;
2812 }
2813
2814
2815 intptr_t Assembler::FindExternalLabel(const ExternalLabel* label,
2816 Patchability patchable) {
2817 // The object pool cannot be used in the vm isolate.
2818 ASSERT(Isolate::Current() != Dart::vm_isolate());
2819 ASSERT(!object_pool_.IsNull());
2820 const uword address = label->address();
2821 ASSERT(Utils::IsAligned(address, 4));
2822 // The address is stored in the object array as a RawSmi.
2823 const Smi& smi = Smi::Handle(reinterpret_cast<RawSmi*>(address));
2824 if (patchable == kNotPatchable) {
2825 // If the call site is not patchable, we can try to re-use an existing
2826 // entry.
2827 return FindObject(smi, kNotPatchable);
2828 }
2829 // If the call is patchable, do not reuse an existing entry since each
2830 // reference may be patched independently.
2831 object_pool_.Add(smi, Heap::kOld);
2832 patchable_pool_entries_.Add(patchable);
2833 return object_pool_.Length() - 1;
2834 }
2835
2836
2837 // A set of VM objects that are present in every constant pool. 2776 // A set of VM objects that are present in every constant pool.
2838 static bool IsAlwaysInConstantPool(const Object& object) { 2777 static bool IsAlwaysInConstantPool(const Object& object) {
2839 // TODO(zra): Evaluate putting all VM heap objects into the pool. 2778 // TODO(zra): Evaluate putting all VM heap objects into the pool.
2840 return (object.raw() == Object::null()) 2779 return (object.raw() == Object::null())
2841 || (object.raw() == Bool::True().raw()) 2780 || (object.raw() == Bool::True().raw())
2842 || (object.raw() == Bool::False().raw()); 2781 || (object.raw() == Bool::False().raw());
2843 } 2782 }
2844 2783
2845 2784
2846 bool Assembler::CanLoadFromObjectPool(const Object& object) { 2785 bool Assembler::CanLoadFromObjectPool(const Object& object) {
(...skipping 23 matching lines...) Expand all
2870 2809
2871 2810
2872 void Assembler::LoadIsolate(Register dst) { 2811 void Assembler::LoadIsolate(Register dst) {
2873 movq(dst, Immediate(reinterpret_cast<uword>(Isolate::Current()))); 2812 movq(dst, Immediate(reinterpret_cast<uword>(Isolate::Current())));
2874 } 2813 }
2875 2814
2876 2815
2877 void Assembler::LoadObject(Register dst, const Object& object, Register pp) { 2816 void Assembler::LoadObject(Register dst, const Object& object, Register pp) {
2878 if (CanLoadFromObjectPool(object)) { 2817 if (CanLoadFromObjectPool(object)) {
2879 const int32_t offset = 2818 const int32_t offset =
2880 Array::element_offset(FindObject(object, kNotPatchable)); 2819 Array::element_offset(object_pool_.FindObject(object, kNotPatchable));
2881 LoadWordFromPoolOffset(dst, pp, offset - kHeapObjectTag); 2820 LoadWordFromPoolOffset(dst, pp, offset - kHeapObjectTag);
2882 } else { 2821 } else {
2883 ASSERT((Isolate::Current() == Dart::vm_isolate()) || 2822 ASSERT((Isolate::Current() == Dart::vm_isolate()) ||
2884 object.IsSmi() || 2823 object.IsSmi() ||
2885 object.InVMHeap()); 2824 object.InVMHeap());
2886 LoadImmediate(dst, Immediate(reinterpret_cast<int64_t>(object.raw())), pp); 2825 LoadImmediate(dst, Immediate(reinterpret_cast<int64_t>(object.raw())), pp);
2887 } 2826 }
2888 } 2827 }
2889 2828
2890 2829
(...skipping 14 matching lines...) Expand all
2905 pushq(TMP); 2844 pushq(TMP);
2906 } else { 2845 } else {
2907 PushImmediate(Immediate(reinterpret_cast<int64_t>(object.raw())), pp); 2846 PushImmediate(Immediate(reinterpret_cast<int64_t>(object.raw())), pp);
2908 } 2847 }
2909 } 2848 }
2910 2849
2911 2850
2912 void Assembler::CompareObject(Register reg, const Object& object, Register pp) { 2851 void Assembler::CompareObject(Register reg, const Object& object, Register pp) {
2913 if (CanLoadFromObjectPool(object)) { 2852 if (CanLoadFromObjectPool(object)) {
2914 const int32_t offset = 2853 const int32_t offset =
2915 Array::element_offset(FindObject(object, kNotPatchable)); 2854 Array::element_offset(object_pool_.FindObject(object, kNotPatchable));
2916 cmpq(reg, Address(pp, offset-kHeapObjectTag)); 2855 cmpq(reg, Address(pp, offset-kHeapObjectTag));
2917 } else { 2856 } else {
2918 CompareImmediate( 2857 CompareImmediate(
2919 reg, Immediate(reinterpret_cast<int64_t>(object.raw())), pp); 2858 reg, Immediate(reinterpret_cast<int64_t>(object.raw())), pp);
2920 } 2859 }
2921 } 2860 }
2922 2861
2923 2862
2924 intptr_t Assembler::FindImmediate(int64_t imm) { 2863 intptr_t Assembler::FindImmediate(int64_t imm) {
2925 ASSERT(Isolate::Current() != Dart::vm_isolate()); 2864 ASSERT(Isolate::Current() != Dart::vm_isolate());
2926 ASSERT(!object_pool_.IsNull());
2927 const Smi& smi = Smi::Handle(reinterpret_cast<RawSmi*>(imm)); 2865 const Smi& smi = Smi::Handle(reinterpret_cast<RawSmi*>(imm));
2928 return FindObject(smi, kNotPatchable); 2866 return object_pool_.FindObject(smi, kNotPatchable);
2929 } 2867 }
2930 2868
2931 2869
2932 bool Assembler::CanLoadImmediateFromPool(const Immediate& imm, Register pp) { 2870 bool Assembler::CanLoadImmediateFromPool(const Immediate& imm, Register pp) {
2933 if (!allow_constant_pool()) { 2871 if (!allow_constant_pool()) {
2934 return false; 2872 return false;
2935 } 2873 }
2936 return !imm.is_int32() && 2874 return !imm.is_int32() &&
2937 (pp != kNoRegister) && 2875 (pp != kNoRegister) &&
2938 (Isolate::Current() != Dart::vm_isolate()); 2876 (Isolate::Current() != Dart::vm_isolate());
(...skipping 1018 matching lines...) Expand 10 before | Expand all | Expand 10 after
3957 3895
3958 3896
3959 const char* Assembler::FpuRegisterName(FpuRegister reg) { 3897 const char* Assembler::FpuRegisterName(FpuRegister reg) {
3960 ASSERT((0 <= reg) && (reg < kNumberOfXmmRegisters)); 3898 ASSERT((0 <= reg) && (reg < kNumberOfXmmRegisters));
3961 return xmm_reg_names[reg]; 3899 return xmm_reg_names[reg];
3962 } 3900 }
3963 3901
3964 } // namespace dart 3902 } // namespace dart
3965 3903
3966 #endif // defined TARGET_ARCH_X64 3904 #endif // defined TARGET_ARCH_X64
OLDNEW
« runtime/vm/assembler_arm64.cc ('K') | « runtime/vm/assembler_x64.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698