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_X87 | 5 #if V8_TARGET_ARCH_X87 |
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 #include "src/x87/frames-x87.h" | 12 #include "src/x87/frames-x87.h" |
12 | 13 |
13 namespace v8 { | 14 namespace v8 { |
14 namespace internal { | 15 namespace internal { |
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 154 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
174 void Deoptimizer::FillInputFrame(Address tos, JavaScriptFrame* frame) { | 175 void Deoptimizer::FillInputFrame(Address tos, JavaScriptFrame* frame) { |
175 // Set the register values. The values are not important as there are no | 176 // Set the register values. The values are not important as there are no |
176 // callee saved registers in JavaScript frames, so all registers are | 177 // callee saved registers in JavaScript frames, so all registers are |
177 // spilled. Registers ebp and esp are set to the correct values though. | 178 // spilled. Registers ebp and esp are set to the correct values though. |
178 | 179 |
179 for (int i = 0; i < Register::kNumRegisters; i++) { | 180 for (int i = 0; i < Register::kNumRegisters; i++) { |
180 input_->SetRegister(i, i * 4); | 181 input_->SetRegister(i, i * 4); |
181 } | 182 } |
182 input_->SetRegister(esp.code(), reinterpret_cast<intptr_t>(frame->sp())); | 183 input_->SetRegister(esp.code(), reinterpret_cast<intptr_t>(frame->sp())); |
183 input_->SetRegister(ebp.code(), reinterpret_cast<intptr_t>(frame->fp())); | 184 input_->SetRegister(ebp.code(), reinterpret_cast<intptr_t>(frame->fp())); |
184 for (int i = 0; i < DoubleRegister::NumAllocatableRegisters(); i++) { | 185 for (int i = 0; i < X87Register::kMaxNumRegisters; i++) { |
185 input_->SetDoubleRegister(i, 0.0); | 186 input_->SetDoubleRegister(i, 0.0); |
186 } | 187 } |
187 | 188 |
188 // Fill the frame content from the actual data on the frame. | 189 // Fill the frame content from the actual data on the frame. |
189 for (unsigned i = 0; i < input_->GetFrameSize(); i += kPointerSize) { | 190 for (unsigned i = 0; i < input_->GetFrameSize(); i += kPointerSize) { |
190 input_->SetFrameSlot(i, Memory::uint32_at(tos + i)); | 191 input_->SetFrameSlot(i, Memory::uint32_at(tos + i)); |
191 } | 192 } |
192 } | 193 } |
193 | 194 |
194 | 195 |
195 void Deoptimizer::SetPlatformCompiledStubRegisters( | 196 void Deoptimizer::SetPlatformCompiledStubRegisters( |
196 FrameDescription* output_frame, CodeStubDescriptor* descriptor) { | 197 FrameDescription* output_frame, CodeStubDescriptor* descriptor) { |
197 intptr_t handler = | 198 intptr_t handler = |
198 reinterpret_cast<intptr_t>(descriptor->deoptimization_handler()); | 199 reinterpret_cast<intptr_t>(descriptor->deoptimization_handler()); |
199 int params = descriptor->GetHandlerParameterCount(); | 200 int params = descriptor->GetHandlerParameterCount(); |
200 output_frame->SetRegister(eax.code(), params); | 201 output_frame->SetRegister(eax.code(), params); |
201 output_frame->SetRegister(ebx.code(), handler); | 202 output_frame->SetRegister(ebx.code(), handler); |
202 } | 203 } |
203 | 204 |
204 | 205 |
205 void Deoptimizer::CopyDoubleRegisters(FrameDescription* output_frame) { | 206 void Deoptimizer::CopyDoubleRegisters(FrameDescription* output_frame) { |
206 for (int i = 0; i < X87Register::kMaxNumAllocatableRegisters; ++i) { | 207 for (int i = 0; i < X87Register::kMaxNumRegisters; ++i) { |
207 double double_value = input_->GetDoubleRegister(i); | 208 double double_value = input_->GetDoubleRegister(i); |
208 output_frame->SetDoubleRegister(i, double_value); | 209 output_frame->SetDoubleRegister(i, double_value); |
209 } | 210 } |
210 } | 211 } |
211 | 212 |
212 | 213 |
213 bool Deoptimizer::HasAlignmentPadding(JSFunction* function) { | 214 bool Deoptimizer::HasAlignmentPadding(JSFunction* function) { |
214 int parameter_count = | 215 int parameter_count = |
215 function->shared()->internal_formal_parameter_count() + 1; | 216 function->shared()->internal_formal_parameter_count() + 1; |
216 unsigned input_frame_size = input_->GetFrameSize(); | 217 unsigned input_frame_size = input_->GetFrameSize(); |
217 unsigned alignment_state_offset = | 218 unsigned alignment_state_offset = |
218 input_frame_size - parameter_count * kPointerSize - | 219 input_frame_size - parameter_count * kPointerSize - |
219 StandardFrameConstants::kFixedFrameSize - | 220 StandardFrameConstants::kFixedFrameSize - |
220 kPointerSize; | 221 kPointerSize; |
221 DCHECK(JavaScriptFrameConstants::kDynamicAlignmentStateOffset == | 222 DCHECK(JavaScriptFrameConstants::kDynamicAlignmentStateOffset == |
222 JavaScriptFrameConstants::kLocal0Offset); | 223 JavaScriptFrameConstants::kLocal0Offset); |
223 int32_t alignment_state = input_->GetFrameSlot(alignment_state_offset); | 224 int32_t alignment_state = input_->GetFrameSlot(alignment_state_offset); |
224 return (alignment_state == kAlignmentPaddingPushed); | 225 return (alignment_state == kAlignmentPaddingPushed); |
225 } | 226 } |
226 | 227 |
227 | 228 |
228 #define __ masm()-> | 229 #define __ masm()-> |
229 | 230 |
230 void Deoptimizer::TableEntryGenerator::Generate() { | 231 void Deoptimizer::TableEntryGenerator::Generate() { |
231 GeneratePrologue(); | 232 GeneratePrologue(); |
232 | 233 |
233 // Save all general purpose registers before messing with them. | 234 // Save all general purpose registers before messing with them. |
234 const int kNumberOfRegisters = Register::kNumRegisters; | 235 const int kNumberOfRegisters = Register::kNumRegisters; |
235 | 236 |
236 const int kDoubleRegsSize = | 237 const int kDoubleRegsSize = kDoubleSize * X87Register::kMaxNumRegisters; |
237 kDoubleSize * X87Register::kMaxNumAllocatableRegisters; | |
238 | 238 |
239 // Reserve space for x87 fp registers. | 239 // Reserve space for x87 fp registers. |
240 __ sub(esp, Immediate(kDoubleRegsSize)); | 240 __ sub(esp, Immediate(kDoubleRegsSize)); |
241 | 241 |
242 __ pushad(); | 242 __ pushad(); |
243 | 243 |
244 ExternalReference c_entry_fp_address(Isolate::kCEntryFPAddress, isolate()); | 244 ExternalReference c_entry_fp_address(Isolate::kCEntryFPAddress, isolate()); |
245 __ mov(Operand::StaticVariable(c_entry_fp_address), ebp); | 245 __ mov(Operand::StaticVariable(c_entry_fp_address), ebp); |
246 | 246 |
247 // GP registers are safe to use now. | 247 // GP registers are safe to use now. |
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
305 // frame descriptor pointer. | 305 // frame descriptor pointer. |
306 __ mov(ebx, Operand(eax, Deoptimizer::input_offset())); | 306 __ mov(ebx, Operand(eax, Deoptimizer::input_offset())); |
307 | 307 |
308 // Fill in the input registers. | 308 // Fill in the input registers. |
309 for (int i = kNumberOfRegisters - 1; i >= 0; i--) { | 309 for (int i = kNumberOfRegisters - 1; i >= 0; i--) { |
310 int offset = (i * kPointerSize) + FrameDescription::registers_offset(); | 310 int offset = (i * kPointerSize) + FrameDescription::registers_offset(); |
311 __ pop(Operand(ebx, offset)); | 311 __ pop(Operand(ebx, offset)); |
312 } | 312 } |
313 | 313 |
314 int double_regs_offset = FrameDescription::double_registers_offset(); | 314 int double_regs_offset = FrameDescription::double_registers_offset(); |
| 315 const RegisterConfiguration* config = |
| 316 RegisterConfiguration::ArchDefault(RegisterConfiguration::CRANKSHAFT); |
315 // Fill in the double input registers. | 317 // Fill in the double input registers. |
316 for (int i = 0; i < X87Register::kMaxNumAllocatableRegisters; ++i) { | 318 for (int i = 0; i < X87Register::kMaxNumAllocatableRegisters; ++i) { |
317 int dst_offset = i * kDoubleSize + double_regs_offset; | 319 int code = config->GetAllocatableDoubleCode(i); |
318 int src_offset = i * kDoubleSize; | 320 int dst_offset = code * kDoubleSize + double_regs_offset; |
| 321 int src_offset = code * kDoubleSize; |
319 __ fld_d(Operand(esp, src_offset)); | 322 __ fld_d(Operand(esp, src_offset)); |
320 __ fstp_d(Operand(ebx, dst_offset)); | 323 __ fstp_d(Operand(ebx, dst_offset)); |
321 } | 324 } |
322 | 325 |
323 // Clear FPU all exceptions. | 326 // Clear FPU all exceptions. |
324 // TODO(ulan): Find out why the TOP register is not zero here in some cases, | 327 // TODO(ulan): Find out why the TOP register is not zero here in some cases, |
325 // and check that the generated code never deoptimizes with unbalanced stack. | 328 // and check that the generated code never deoptimizes with unbalanced stack. |
326 __ fnclex(); | 329 __ fnclex(); |
327 | 330 |
328 // Remove the bailout id, return address and the double registers. | 331 // Remove the bailout id, return address and the double registers. |
(...skipping 137 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
466 } | 469 } |
467 | 470 |
468 | 471 |
469 #undef __ | 472 #undef __ |
470 | 473 |
471 | 474 |
472 } // namespace internal | 475 } // namespace internal |
473 } // namespace v8 | 476 } // namespace v8 |
474 | 477 |
475 #endif // V8_TARGET_ARCH_X87 | 478 #endif // V8_TARGET_ARCH_X87 |
OLD | NEW |