| 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 |