OLD | NEW |
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #if V8_TARGET_ARCH_X64 | 5 #if V8_TARGET_ARCH_X64 |
6 | 6 |
7 #include "src/codegen.h" | 7 #include "src/codegen.h" |
8 #include "src/deoptimizer.h" | 8 #include "src/deoptimizer.h" |
9 #include "src/full-codegen/full-codegen.h" | 9 #include "src/full-codegen/full-codegen.h" |
| 10 #include "src/register-configuration.h" |
10 #include "src/safepoint-table.h" | 11 #include "src/safepoint-table.h" |
11 | 12 |
12 namespace v8 { | 13 namespace v8 { |
13 namespace internal { | 14 namespace internal { |
14 | 15 |
15 | 16 |
16 const int Deoptimizer::table_entry_size_ = 10; | 17 const int Deoptimizer::table_entry_size_ = 10; |
17 | 18 |
18 | 19 |
19 int Deoptimizer::patch_size() { | 20 int Deoptimizer::patch_size() { |
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
88 | 89 |
89 void Deoptimizer::FillInputFrame(Address tos, JavaScriptFrame* frame) { | 90 void Deoptimizer::FillInputFrame(Address tos, JavaScriptFrame* frame) { |
90 // Set the register values. The values are not important as there are no | 91 // Set the register values. The values are not important as there are no |
91 // callee saved registers in JavaScript frames, so all registers are | 92 // callee saved registers in JavaScript frames, so all registers are |
92 // spilled. Registers rbp and rsp are set to the correct values though. | 93 // spilled. Registers rbp and rsp are set to the correct values though. |
93 for (int i = 0; i < Register::kNumRegisters; i++) { | 94 for (int i = 0; i < Register::kNumRegisters; i++) { |
94 input_->SetRegister(i, i * 4); | 95 input_->SetRegister(i, i * 4); |
95 } | 96 } |
96 input_->SetRegister(rsp.code(), reinterpret_cast<intptr_t>(frame->sp())); | 97 input_->SetRegister(rsp.code(), reinterpret_cast<intptr_t>(frame->sp())); |
97 input_->SetRegister(rbp.code(), reinterpret_cast<intptr_t>(frame->fp())); | 98 input_->SetRegister(rbp.code(), reinterpret_cast<intptr_t>(frame->fp())); |
98 for (int i = 0; i < DoubleRegister::NumAllocatableRegisters(); i++) { | 99 for (int i = 0; i < DoubleRegister::kMaxNumRegisters; i++) { |
99 input_->SetDoubleRegister(i, 0.0); | 100 input_->SetDoubleRegister(i, 0.0); |
100 } | 101 } |
101 | 102 |
102 // Fill the frame content from the actual data on the frame. | 103 // Fill the frame content from the actual data on the frame. |
103 for (unsigned i = 0; i < input_->GetFrameSize(); i += kPointerSize) { | 104 for (unsigned i = 0; i < input_->GetFrameSize(); i += kPointerSize) { |
104 input_->SetFrameSlot(i, Memory::uintptr_at(tos + i)); | 105 input_->SetFrameSlot(i, Memory::uintptr_at(tos + i)); |
105 } | 106 } |
106 } | 107 } |
107 | 108 |
108 | 109 |
109 void Deoptimizer::SetPlatformCompiledStubRegisters( | 110 void Deoptimizer::SetPlatformCompiledStubRegisters( |
110 FrameDescription* output_frame, CodeStubDescriptor* descriptor) { | 111 FrameDescription* output_frame, CodeStubDescriptor* descriptor) { |
111 intptr_t handler = | 112 intptr_t handler = |
112 reinterpret_cast<intptr_t>(descriptor->deoptimization_handler()); | 113 reinterpret_cast<intptr_t>(descriptor->deoptimization_handler()); |
113 int params = descriptor->GetHandlerParameterCount(); | 114 int params = descriptor->GetHandlerParameterCount(); |
114 output_frame->SetRegister(rax.code(), params); | 115 output_frame->SetRegister(rax.code(), params); |
115 output_frame->SetRegister(rbx.code(), handler); | 116 output_frame->SetRegister(rbx.code(), handler); |
116 } | 117 } |
117 | 118 |
118 | 119 |
119 void Deoptimizer::CopyDoubleRegisters(FrameDescription* output_frame) { | 120 void Deoptimizer::CopyDoubleRegisters(FrameDescription* output_frame) { |
120 for (int i = 0; i < XMMRegister::NumAllocatableRegisters(); ++i) { | 121 for (int i = 0; i < XMMRegister::kMaxNumRegisters; ++i) { |
121 double double_value = input_->GetDoubleRegister(i); | 122 double double_value = input_->GetDoubleRegister(i); |
122 output_frame->SetDoubleRegister(i, double_value); | 123 output_frame->SetDoubleRegister(i, double_value); |
123 } | 124 } |
124 } | 125 } |
125 | 126 |
126 | 127 |
127 bool Deoptimizer::HasAlignmentPadding(JSFunction* function) { | 128 bool Deoptimizer::HasAlignmentPadding(JSFunction* function) { |
128 // There is no dynamic alignment padding on x64 in the input frame. | 129 // There is no dynamic alignment padding on x64 in the input frame. |
129 return false; | 130 return false; |
130 } | 131 } |
131 | 132 |
132 | 133 |
133 #define __ masm()-> | 134 #define __ masm()-> |
134 | 135 |
135 void Deoptimizer::TableEntryGenerator::Generate() { | 136 void Deoptimizer::TableEntryGenerator::Generate() { |
136 GeneratePrologue(); | 137 GeneratePrologue(); |
137 | 138 |
138 // Save all general purpose registers before messing with them. | 139 // Save all general purpose registers before messing with them. |
139 const int kNumberOfRegisters = Register::kNumRegisters; | 140 const int kNumberOfRegisters = Register::kNumRegisters; |
140 | 141 |
141 const int kDoubleRegsSize = kDoubleSize * | 142 const int kDoubleRegsSize = kDoubleSize * XMMRegister::kMaxNumRegisters; |
142 XMMRegister::NumAllocatableRegisters(); | |
143 __ subp(rsp, Immediate(kDoubleRegsSize)); | 143 __ subp(rsp, Immediate(kDoubleRegsSize)); |
144 | 144 |
145 for (int i = 0; i < XMMRegister::NumAllocatableRegisters(); ++i) { | 145 const RegisterConfiguration* config = RegisterConfiguration::ArchDefault(); |
146 XMMRegister xmm_reg = XMMRegister::FromAllocationIndex(i); | 146 for (int i = 0; i < config->num_allocatable_double_registers(); ++i) { |
147 int offset = i * kDoubleSize; | 147 int code = config->GetAllocatableDoubleCode(i); |
| 148 XMMRegister xmm_reg = XMMRegister::from_code(code); |
| 149 int offset = code * kDoubleSize; |
148 __ movsd(Operand(rsp, offset), xmm_reg); | 150 __ movsd(Operand(rsp, offset), xmm_reg); |
149 } | 151 } |
150 | 152 |
151 // We push all registers onto the stack, even though we do not need | 153 // We push all registers onto the stack, even though we do not need |
152 // to restore all later. | 154 // to restore all later. |
153 for (int i = 0; i < kNumberOfRegisters; i++) { | 155 for (int i = 0; i < kNumberOfRegisters; i++) { |
154 Register r = Register::from_code(i); | 156 Register r = Register::from_code(i); |
155 __ pushq(r); | 157 __ pushq(r); |
156 } | 158 } |
157 | 159 |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
203 __ movp(rbx, Operand(rax, Deoptimizer::input_offset())); | 205 __ movp(rbx, Operand(rax, Deoptimizer::input_offset())); |
204 | 206 |
205 // Fill in the input registers. | 207 // Fill in the input registers. |
206 for (int i = kNumberOfRegisters -1; i >= 0; i--) { | 208 for (int i = kNumberOfRegisters -1; i >= 0; i--) { |
207 int offset = (i * kPointerSize) + FrameDescription::registers_offset(); | 209 int offset = (i * kPointerSize) + FrameDescription::registers_offset(); |
208 __ PopQuad(Operand(rbx, offset)); | 210 __ PopQuad(Operand(rbx, offset)); |
209 } | 211 } |
210 | 212 |
211 // Fill in the double input registers. | 213 // Fill in the double input registers. |
212 int double_regs_offset = FrameDescription::double_registers_offset(); | 214 int double_regs_offset = FrameDescription::double_registers_offset(); |
213 for (int i = 0; i < XMMRegister::NumAllocatableRegisters(); i++) { | 215 for (int i = 0; i < XMMRegister::kMaxNumRegisters; i++) { |
214 int dst_offset = i * kDoubleSize + double_regs_offset; | 216 int dst_offset = i * kDoubleSize + double_regs_offset; |
215 __ popq(Operand(rbx, dst_offset)); | 217 __ popq(Operand(rbx, dst_offset)); |
216 } | 218 } |
217 | 219 |
218 // Remove the bailout id and return address from the stack. | 220 // Remove the bailout id and return address from the stack. |
219 __ addp(rsp, Immediate(1 * kRegisterSize + kPCOnStackSize)); | 221 __ addp(rsp, Immediate(1 * kRegisterSize + kPCOnStackSize)); |
220 | 222 |
221 // Compute a pointer to the unwinding limit in register rcx; that is | 223 // Compute a pointer to the unwinding limit in register rcx; that is |
222 // the first stack slot not part of the input frame. | 224 // the first stack slot not part of the input frame. |
223 __ movp(rcx, Operand(rbx, FrameDescription::frame_size_offset())); | 225 __ movp(rcx, Operand(rbx, FrameDescription::frame_size_offset())); |
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
267 __ subp(rcx, Immediate(sizeof(intptr_t))); | 269 __ subp(rcx, Immediate(sizeof(intptr_t))); |
268 __ Push(Operand(rbx, rcx, times_1, FrameDescription::frame_content_offset())); | 270 __ Push(Operand(rbx, rcx, times_1, FrameDescription::frame_content_offset())); |
269 __ bind(&inner_loop_header); | 271 __ bind(&inner_loop_header); |
270 __ testp(rcx, rcx); | 272 __ testp(rcx, rcx); |
271 __ j(not_zero, &inner_push_loop); | 273 __ j(not_zero, &inner_push_loop); |
272 __ addp(rax, Immediate(kPointerSize)); | 274 __ addp(rax, Immediate(kPointerSize)); |
273 __ bind(&outer_loop_header); | 275 __ bind(&outer_loop_header); |
274 __ cmpp(rax, rdx); | 276 __ cmpp(rax, rdx); |
275 __ j(below, &outer_push_loop); | 277 __ j(below, &outer_push_loop); |
276 | 278 |
277 for (int i = 0; i < XMMRegister::NumAllocatableRegisters(); ++i) { | 279 for (int i = 0; i < config->num_allocatable_double_registers(); ++i) { |
278 XMMRegister xmm_reg = XMMRegister::FromAllocationIndex(i); | 280 int code = config->GetAllocatableDoubleCode(i); |
279 int src_offset = i * kDoubleSize + double_regs_offset; | 281 XMMRegister xmm_reg = XMMRegister::from_code(code); |
| 282 int src_offset = code * kDoubleSize + double_regs_offset; |
280 __ movsd(xmm_reg, Operand(rbx, src_offset)); | 283 __ movsd(xmm_reg, Operand(rbx, src_offset)); |
281 } | 284 } |
282 | 285 |
283 // Push state, pc, and continuation from the last output frame. | 286 // Push state, pc, and continuation from the last output frame. |
284 __ Push(Operand(rbx, FrameDescription::state_offset())); | 287 __ Push(Operand(rbx, FrameDescription::state_offset())); |
285 __ PushQuad(Operand(rbx, FrameDescription::pc_offset())); | 288 __ PushQuad(Operand(rbx, FrameDescription::pc_offset())); |
286 __ PushQuad(Operand(rbx, FrameDescription::continuation_offset())); | 289 __ PushQuad(Operand(rbx, FrameDescription::continuation_offset())); |
287 | 290 |
288 // Push the registers from the last output frame. | 291 // Push the registers from the last output frame. |
289 for (int i = 0; i < kNumberOfRegisters; i++) { | 292 for (int i = 0; i < kNumberOfRegisters; i++) { |
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
349 } | 352 } |
350 | 353 |
351 | 354 |
352 #undef __ | 355 #undef __ |
353 | 356 |
354 | 357 |
355 } // namespace internal | 358 } // namespace internal |
356 } // namespace v8 | 359 } // namespace v8 |
357 | 360 |
358 #endif // V8_TARGET_ARCH_X64 | 361 #endif // V8_TARGET_ARCH_X64 |
OLD | NEW |