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_IA32 | 5 #if V8_TARGET_ARCH_IA32 |
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/ia32/frames-ia32.h" | 10 #include "src/ia32/frames-ia32.h" |
| 11 #include "src/register-configuration.h" |
11 #include "src/safepoint-table.h" | 12 #include "src/safepoint-table.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() { |
20 return Assembler::kCallInstructionLength; | 21 return Assembler::kCallInstructionLength; |
(...skipping 153 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 < XMMRegister::kMaxNumAllocatableRegisters; i++) { | 185 for (int i = 0; i < XMMRegister::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 < XMMRegister::kMaxNumAllocatableRegisters; ++i) { | 207 for (int i = 0; i < XMMRegister::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 = kDoubleSize * | 237 const int kDoubleRegsSize = kDoubleSize * XMMRegister::kMaxNumRegisters; |
237 XMMRegister::kMaxNumAllocatableRegisters; | |
238 __ sub(esp, Immediate(kDoubleRegsSize)); | 238 __ sub(esp, Immediate(kDoubleRegsSize)); |
239 for (int i = 0; i < XMMRegister::kMaxNumAllocatableRegisters; ++i) { | 239 const RegisterConfiguration* config = RegisterConfiguration::ArchDefault(); |
240 XMMRegister xmm_reg = XMMRegister::FromAllocationIndex(i); | 240 for (int i = 0; i < config->num_allocatable_double_registers(); ++i) { |
241 int offset = i * kDoubleSize; | 241 int code = config->GetAllocatableDoubleCode(i); |
| 242 XMMRegister xmm_reg = XMMRegister::from_code(code); |
| 243 int offset = code * kDoubleSize; |
242 __ movsd(Operand(esp, offset), xmm_reg); | 244 __ movsd(Operand(esp, offset), xmm_reg); |
243 } | 245 } |
244 | 246 |
245 __ pushad(); | 247 __ pushad(); |
246 | 248 |
247 ExternalReference c_entry_fp_address(Isolate::kCEntryFPAddress, isolate()); | 249 ExternalReference c_entry_fp_address(Isolate::kCEntryFPAddress, isolate()); |
248 __ mov(Operand::StaticVariable(c_entry_fp_address), ebp); | 250 __ mov(Operand::StaticVariable(c_entry_fp_address), ebp); |
249 | 251 |
250 const int kSavedRegistersAreaSize = kNumberOfRegisters * kPointerSize + | 252 const int kSavedRegistersAreaSize = kNumberOfRegisters * kPointerSize + |
251 kDoubleRegsSize; | 253 kDoubleRegsSize; |
(...skipping 29 matching lines...) Expand all Loading... |
281 __ mov(ebx, Operand(eax, Deoptimizer::input_offset())); | 283 __ mov(ebx, Operand(eax, Deoptimizer::input_offset())); |
282 | 284 |
283 // Fill in the input registers. | 285 // Fill in the input registers. |
284 for (int i = kNumberOfRegisters - 1; i >= 0; i--) { | 286 for (int i = kNumberOfRegisters - 1; i >= 0; i--) { |
285 int offset = (i * kPointerSize) + FrameDescription::registers_offset(); | 287 int offset = (i * kPointerSize) + FrameDescription::registers_offset(); |
286 __ pop(Operand(ebx, offset)); | 288 __ pop(Operand(ebx, offset)); |
287 } | 289 } |
288 | 290 |
289 int double_regs_offset = FrameDescription::double_registers_offset(); | 291 int double_regs_offset = FrameDescription::double_registers_offset(); |
290 // Fill in the double input registers. | 292 // Fill in the double input registers. |
291 for (int i = 0; i < XMMRegister::kMaxNumAllocatableRegisters; ++i) { | 293 for (int i = 0; i < config->num_allocatable_double_registers(); ++i) { |
292 int dst_offset = i * kDoubleSize + double_regs_offset; | 294 int code = config->GetAllocatableDoubleCode(i); |
293 int src_offset = i * kDoubleSize; | 295 int dst_offset = code * kDoubleSize + double_regs_offset; |
| 296 int src_offset = code * kDoubleSize; |
294 __ movsd(xmm0, Operand(esp, src_offset)); | 297 __ movsd(xmm0, Operand(esp, src_offset)); |
295 __ movsd(Operand(ebx, dst_offset), xmm0); | 298 __ movsd(Operand(ebx, dst_offset), xmm0); |
296 } | 299 } |
297 | 300 |
298 // Clear FPU all exceptions. | 301 // Clear FPU all exceptions. |
299 // TODO(ulan): Find out why the TOP register is not zero here in some cases, | 302 // TODO(ulan): Find out why the TOP register is not zero here in some cases, |
300 // and check that the generated code never deoptimizes with unbalanced stack. | 303 // and check that the generated code never deoptimizes with unbalanced stack. |
301 __ fnclex(); | 304 __ fnclex(); |
302 | 305 |
303 // Remove the bailout id, return address and the double registers. | 306 // Remove the bailout id, return address and the double registers. |
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
364 __ push(Operand(ebx, ecx, times_1, FrameDescription::frame_content_offset())); | 367 __ push(Operand(ebx, ecx, times_1, FrameDescription::frame_content_offset())); |
365 __ bind(&inner_loop_header); | 368 __ bind(&inner_loop_header); |
366 __ test(ecx, ecx); | 369 __ test(ecx, ecx); |
367 __ j(not_zero, &inner_push_loop); | 370 __ j(not_zero, &inner_push_loop); |
368 __ add(eax, Immediate(kPointerSize)); | 371 __ add(eax, Immediate(kPointerSize)); |
369 __ bind(&outer_loop_header); | 372 __ bind(&outer_loop_header); |
370 __ cmp(eax, edx); | 373 __ cmp(eax, edx); |
371 __ j(below, &outer_push_loop); | 374 __ j(below, &outer_push_loop); |
372 | 375 |
373 // In case of a failed STUB, we have to restore the XMM registers. | 376 // In case of a failed STUB, we have to restore the XMM registers. |
374 for (int i = 0; i < XMMRegister::kMaxNumAllocatableRegisters; ++i) { | 377 for (int i = 0; i < config->num_allocatable_double_registers(); ++i) { |
375 XMMRegister xmm_reg = XMMRegister::FromAllocationIndex(i); | 378 int code = config->GetAllocatableDoubleCode(i); |
376 int src_offset = i * kDoubleSize + double_regs_offset; | 379 XMMRegister xmm_reg = XMMRegister::from_code(code); |
| 380 int src_offset = code * kDoubleSize + double_regs_offset; |
377 __ movsd(xmm_reg, Operand(ebx, src_offset)); | 381 __ movsd(xmm_reg, Operand(ebx, src_offset)); |
378 } | 382 } |
379 | 383 |
380 // Push state, pc, and continuation from the last output frame. | 384 // Push state, pc, and continuation from the last output frame. |
381 __ push(Operand(ebx, FrameDescription::state_offset())); | 385 __ push(Operand(ebx, FrameDescription::state_offset())); |
382 __ push(Operand(ebx, FrameDescription::pc_offset())); | 386 __ push(Operand(ebx, FrameDescription::pc_offset())); |
383 __ push(Operand(ebx, FrameDescription::continuation_offset())); | 387 __ push(Operand(ebx, FrameDescription::continuation_offset())); |
384 | 388 |
385 | 389 |
386 // Push the registers from the last output frame. | 390 // Push the registers from the last output frame. |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
427 } | 431 } |
428 | 432 |
429 | 433 |
430 #undef __ | 434 #undef __ |
431 | 435 |
432 | 436 |
433 } // namespace internal | 437 } // namespace internal |
434 } // namespace v8 | 438 } // namespace v8 |
435 | 439 |
436 #endif // V8_TARGET_ARCH_IA32 | 440 #endif // V8_TARGET_ARCH_IA32 |
OLD | NEW |