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" | |
12 #include "src/safepoint-table.h" | 11 #include "src/safepoint-table.h" |
13 | 12 |
14 namespace v8 { | 13 namespace v8 { |
15 namespace internal { | 14 namespace internal { |
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() { |
21 return Assembler::kCallInstructionLength; | 20 return Assembler::kCallInstructionLength; |
(...skipping 153 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
175 void Deoptimizer::FillInputFrame(Address tos, JavaScriptFrame* frame) { | 174 void Deoptimizer::FillInputFrame(Address tos, JavaScriptFrame* frame) { |
176 // Set the register values. The values are not important as there are no | 175 // Set the register values. The values are not important as there are no |
177 // callee saved registers in JavaScript frames, so all registers are | 176 // callee saved registers in JavaScript frames, so all registers are |
178 // spilled. Registers ebp and esp are set to the correct values though. | 177 // spilled. Registers ebp and esp are set to the correct values though. |
179 | 178 |
180 for (int i = 0; i < Register::kNumRegisters; i++) { | 179 for (int i = 0; i < Register::kNumRegisters; i++) { |
181 input_->SetRegister(i, i * 4); | 180 input_->SetRegister(i, i * 4); |
182 } | 181 } |
183 input_->SetRegister(esp.code(), reinterpret_cast<intptr_t>(frame->sp())); | 182 input_->SetRegister(esp.code(), reinterpret_cast<intptr_t>(frame->sp())); |
184 input_->SetRegister(ebp.code(), reinterpret_cast<intptr_t>(frame->fp())); | 183 input_->SetRegister(ebp.code(), reinterpret_cast<intptr_t>(frame->fp())); |
185 for (int i = 0; i < XMMRegister::kMaxNumRegisters; i++) { | 184 for (int i = 0; i < XMMRegister::kMaxNumAllocatableRegisters; i++) { |
186 input_->SetDoubleRegister(i, 0.0); | 185 input_->SetDoubleRegister(i, 0.0); |
187 } | 186 } |
188 | 187 |
189 // Fill the frame content from the actual data on the frame. | 188 // Fill the frame content from the actual data on the frame. |
190 for (unsigned i = 0; i < input_->GetFrameSize(); i += kPointerSize) { | 189 for (unsigned i = 0; i < input_->GetFrameSize(); i += kPointerSize) { |
191 input_->SetFrameSlot(i, Memory::uint32_at(tos + i)); | 190 input_->SetFrameSlot(i, Memory::uint32_at(tos + i)); |
192 } | 191 } |
193 } | 192 } |
194 | 193 |
195 | 194 |
196 void Deoptimizer::SetPlatformCompiledStubRegisters( | 195 void Deoptimizer::SetPlatformCompiledStubRegisters( |
197 FrameDescription* output_frame, CodeStubDescriptor* descriptor) { | 196 FrameDescription* output_frame, CodeStubDescriptor* descriptor) { |
198 intptr_t handler = | 197 intptr_t handler = |
199 reinterpret_cast<intptr_t>(descriptor->deoptimization_handler()); | 198 reinterpret_cast<intptr_t>(descriptor->deoptimization_handler()); |
200 int params = descriptor->GetHandlerParameterCount(); | 199 int params = descriptor->GetHandlerParameterCount(); |
201 output_frame->SetRegister(eax.code(), params); | 200 output_frame->SetRegister(eax.code(), params); |
202 output_frame->SetRegister(ebx.code(), handler); | 201 output_frame->SetRegister(ebx.code(), handler); |
203 } | 202 } |
204 | 203 |
205 | 204 |
206 void Deoptimizer::CopyDoubleRegisters(FrameDescription* output_frame) { | 205 void Deoptimizer::CopyDoubleRegisters(FrameDescription* output_frame) { |
207 for (int i = 0; i < XMMRegister::kMaxNumRegisters; ++i) { | 206 for (int i = 0; i < XMMRegister::kMaxNumAllocatableRegisters; ++i) { |
208 double double_value = input_->GetDoubleRegister(i); | 207 double double_value = input_->GetDoubleRegister(i); |
209 output_frame->SetDoubleRegister(i, double_value); | 208 output_frame->SetDoubleRegister(i, double_value); |
210 } | 209 } |
211 } | 210 } |
212 | 211 |
213 | 212 |
214 bool Deoptimizer::HasAlignmentPadding(JSFunction* function) { | 213 bool Deoptimizer::HasAlignmentPadding(JSFunction* function) { |
215 int parameter_count = | 214 int parameter_count = |
216 function->shared()->internal_formal_parameter_count() + 1; | 215 function->shared()->internal_formal_parameter_count() + 1; |
217 unsigned input_frame_size = input_->GetFrameSize(); | 216 unsigned input_frame_size = input_->GetFrameSize(); |
218 unsigned alignment_state_offset = | 217 unsigned alignment_state_offset = |
219 input_frame_size - parameter_count * kPointerSize - | 218 input_frame_size - parameter_count * kPointerSize - |
220 StandardFrameConstants::kFixedFrameSize - | 219 StandardFrameConstants::kFixedFrameSize - |
221 kPointerSize; | 220 kPointerSize; |
222 DCHECK(JavaScriptFrameConstants::kDynamicAlignmentStateOffset == | 221 DCHECK(JavaScriptFrameConstants::kDynamicAlignmentStateOffset == |
223 JavaScriptFrameConstants::kLocal0Offset); | 222 JavaScriptFrameConstants::kLocal0Offset); |
224 int32_t alignment_state = input_->GetFrameSlot(alignment_state_offset); | 223 int32_t alignment_state = input_->GetFrameSlot(alignment_state_offset); |
225 return (alignment_state == kAlignmentPaddingPushed); | 224 return (alignment_state == kAlignmentPaddingPushed); |
226 } | 225 } |
227 | 226 |
228 | 227 |
229 #define __ masm()-> | 228 #define __ masm()-> |
230 | 229 |
231 void Deoptimizer::TableEntryGenerator::Generate() { | 230 void Deoptimizer::TableEntryGenerator::Generate() { |
232 GeneratePrologue(); | 231 GeneratePrologue(); |
233 | 232 |
234 // Save all general purpose registers before messing with them. | 233 // Save all general purpose registers before messing with them. |
235 const int kNumberOfRegisters = Register::kNumRegisters; | 234 const int kNumberOfRegisters = Register::kNumRegisters; |
236 | 235 |
237 const int kDoubleRegsSize = kDoubleSize * XMMRegister::kMaxNumRegisters; | 236 const int kDoubleRegsSize = kDoubleSize * |
| 237 XMMRegister::kMaxNumAllocatableRegisters; |
238 __ sub(esp, Immediate(kDoubleRegsSize)); | 238 __ sub(esp, Immediate(kDoubleRegsSize)); |
239 const RegisterConfiguration* config = RegisterConfiguration::ArchDefault(); | 239 for (int i = 0; i < XMMRegister::kMaxNumAllocatableRegisters; ++i) { |
240 for (int i = 0; i < config->num_allocatable_double_registers(); ++i) { | 240 XMMRegister xmm_reg = XMMRegister::FromAllocationIndex(i); |
241 int code = config->GetAllocatableDoubleCode(i); | 241 int offset = i * kDoubleSize; |
242 XMMRegister xmm_reg = XMMRegister::from_code(code); | |
243 int offset = code * kDoubleSize; | |
244 __ movsd(Operand(esp, offset), xmm_reg); | 242 __ movsd(Operand(esp, offset), xmm_reg); |
245 } | 243 } |
246 | 244 |
247 __ pushad(); | 245 __ pushad(); |
248 | 246 |
249 ExternalReference c_entry_fp_address(Isolate::kCEntryFPAddress, isolate()); | 247 ExternalReference c_entry_fp_address(Isolate::kCEntryFPAddress, isolate()); |
250 __ mov(Operand::StaticVariable(c_entry_fp_address), ebp); | 248 __ mov(Operand::StaticVariable(c_entry_fp_address), ebp); |
251 | 249 |
252 const int kSavedRegistersAreaSize = kNumberOfRegisters * kPointerSize + | 250 const int kSavedRegistersAreaSize = kNumberOfRegisters * kPointerSize + |
253 kDoubleRegsSize; | 251 kDoubleRegsSize; |
(...skipping 29 matching lines...) Expand all Loading... |
283 __ mov(ebx, Operand(eax, Deoptimizer::input_offset())); | 281 __ mov(ebx, Operand(eax, Deoptimizer::input_offset())); |
284 | 282 |
285 // Fill in the input registers. | 283 // Fill in the input registers. |
286 for (int i = kNumberOfRegisters - 1; i >= 0; i--) { | 284 for (int i = kNumberOfRegisters - 1; i >= 0; i--) { |
287 int offset = (i * kPointerSize) + FrameDescription::registers_offset(); | 285 int offset = (i * kPointerSize) + FrameDescription::registers_offset(); |
288 __ pop(Operand(ebx, offset)); | 286 __ pop(Operand(ebx, offset)); |
289 } | 287 } |
290 | 288 |
291 int double_regs_offset = FrameDescription::double_registers_offset(); | 289 int double_regs_offset = FrameDescription::double_registers_offset(); |
292 // Fill in the double input registers. | 290 // Fill in the double input registers. |
293 for (int i = 0; i < config->num_allocatable_double_registers(); ++i) { | 291 for (int i = 0; i < XMMRegister::kMaxNumAllocatableRegisters; ++i) { |
294 int code = config->GetAllocatableDoubleCode(i); | 292 int dst_offset = i * kDoubleSize + double_regs_offset; |
295 int dst_offset = code * kDoubleSize + double_regs_offset; | 293 int src_offset = i * kDoubleSize; |
296 int src_offset = code * kDoubleSize; | |
297 __ movsd(xmm0, Operand(esp, src_offset)); | 294 __ movsd(xmm0, Operand(esp, src_offset)); |
298 __ movsd(Operand(ebx, dst_offset), xmm0); | 295 __ movsd(Operand(ebx, dst_offset), xmm0); |
299 } | 296 } |
300 | 297 |
301 // Clear FPU all exceptions. | 298 // Clear FPU all exceptions. |
302 // TODO(ulan): Find out why the TOP register is not zero here in some cases, | 299 // TODO(ulan): Find out why the TOP register is not zero here in some cases, |
303 // and check that the generated code never deoptimizes with unbalanced stack. | 300 // and check that the generated code never deoptimizes with unbalanced stack. |
304 __ fnclex(); | 301 __ fnclex(); |
305 | 302 |
306 // Remove the bailout id, return address and the double registers. | 303 // Remove the bailout id, return address and the double registers. |
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
367 __ push(Operand(ebx, ecx, times_1, FrameDescription::frame_content_offset())); | 364 __ push(Operand(ebx, ecx, times_1, FrameDescription::frame_content_offset())); |
368 __ bind(&inner_loop_header); | 365 __ bind(&inner_loop_header); |
369 __ test(ecx, ecx); | 366 __ test(ecx, ecx); |
370 __ j(not_zero, &inner_push_loop); | 367 __ j(not_zero, &inner_push_loop); |
371 __ add(eax, Immediate(kPointerSize)); | 368 __ add(eax, Immediate(kPointerSize)); |
372 __ bind(&outer_loop_header); | 369 __ bind(&outer_loop_header); |
373 __ cmp(eax, edx); | 370 __ cmp(eax, edx); |
374 __ j(below, &outer_push_loop); | 371 __ j(below, &outer_push_loop); |
375 | 372 |
376 // In case of a failed STUB, we have to restore the XMM registers. | 373 // In case of a failed STUB, we have to restore the XMM registers. |
377 for (int i = 0; i < config->num_allocatable_double_registers(); ++i) { | 374 for (int i = 0; i < XMMRegister::kMaxNumAllocatableRegisters; ++i) { |
378 int code = config->GetAllocatableDoubleCode(i); | 375 XMMRegister xmm_reg = XMMRegister::FromAllocationIndex(i); |
379 XMMRegister xmm_reg = XMMRegister::from_code(code); | 376 int src_offset = i * kDoubleSize + double_regs_offset; |
380 int src_offset = code * kDoubleSize + double_regs_offset; | |
381 __ movsd(xmm_reg, Operand(ebx, src_offset)); | 377 __ movsd(xmm_reg, Operand(ebx, src_offset)); |
382 } | 378 } |
383 | 379 |
384 // Push state, pc, and continuation from the last output frame. | 380 // Push state, pc, and continuation from the last output frame. |
385 __ push(Operand(ebx, FrameDescription::state_offset())); | 381 __ push(Operand(ebx, FrameDescription::state_offset())); |
386 __ push(Operand(ebx, FrameDescription::pc_offset())); | 382 __ push(Operand(ebx, FrameDescription::pc_offset())); |
387 __ push(Operand(ebx, FrameDescription::continuation_offset())); | 383 __ push(Operand(ebx, FrameDescription::continuation_offset())); |
388 | 384 |
389 | 385 |
390 // Push the registers from the last output frame. | 386 // Push the registers from the last output frame. |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
431 } | 427 } |
432 | 428 |
433 | 429 |
434 #undef __ | 430 #undef __ |
435 | 431 |
436 | 432 |
437 } // namespace internal | 433 } // namespace internal |
438 } // namespace v8 | 434 } // namespace v8 |
439 | 435 |
440 #endif // V8_TARGET_ARCH_IA32 | 436 #endif // V8_TARGET_ARCH_IA32 |
OLD | NEW |