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