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/base/bits.h" | 7 #include "src/base/bits.h" |
8 #include "src/base/division-by-constant.h" | 8 #include "src/base/division-by-constant.h" |
9 #include "src/bootstrapper.h" | 9 #include "src/bootstrapper.h" |
10 #include "src/codegen.h" | 10 #include "src/codegen.h" |
(...skipping 4267 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4278 SmiToInteger64(actual.reg(), actual.reg()); | 4278 SmiToInteger64(actual.reg(), actual.reg()); |
4279 } | 4279 } |
4280 if (expected.is_reg()) { | 4280 if (expected.is_reg()) { |
4281 Pop(expected.reg()); | 4281 Pop(expected.reg()); |
4282 SmiToInteger64(expected.reg(), expected.reg()); | 4282 SmiToInteger64(expected.reg(), expected.reg()); |
4283 } | 4283 } |
4284 } | 4284 } |
4285 bind(&skip_flooding); | 4285 bind(&skip_flooding); |
4286 } | 4286 } |
4287 | 4287 |
4288 | 4288 void MacroAssembler::StubPrologue(StackFrame::Type type) { |
4289 void MacroAssembler::StubPrologue() { | 4289 pushq(rbp); // Caller's frame pointer. |
4290 pushq(rbp); // Caller's frame pointer. | 4290 movp(rbp, rsp); |
4291 movp(rbp, rsp); | 4291 Push(Smi::FromInt(type)); |
4292 Push(rsi); // Callee's context. | |
4293 Push(Smi::FromInt(StackFrame::STUB)); | |
4294 } | 4292 } |
4295 | 4293 |
4296 | |
4297 void MacroAssembler::Prologue(bool code_pre_aging) { | 4294 void MacroAssembler::Prologue(bool code_pre_aging) { |
4298 PredictableCodeSizeScope predictible_code_size_scope(this, | 4295 PredictableCodeSizeScope predictible_code_size_scope(this, |
4299 kNoCodeAgeSequenceLength); | 4296 kNoCodeAgeSequenceLength); |
4300 if (code_pre_aging) { | 4297 if (code_pre_aging) { |
4301 // Pre-age the code. | 4298 // Pre-age the code. |
4302 Call(isolate()->builtins()->MarkCodeAsExecutedOnce(), | 4299 Call(isolate()->builtins()->MarkCodeAsExecutedOnce(), |
4303 RelocInfo::CODE_AGE_SEQUENCE); | 4300 RelocInfo::CODE_AGE_SEQUENCE); |
4304 Nop(kNoCodeAgeSequenceLength - Assembler::kShortCallInstructionLength); | 4301 Nop(kNoCodeAgeSequenceLength - Assembler::kShortCallInstructionLength); |
4305 } else { | 4302 } else { |
4306 pushq(rbp); // Caller's frame pointer. | 4303 pushq(rbp); // Caller's frame pointer. |
(...skipping 14 matching lines...) Expand all Loading... |
4321 void MacroAssembler::EnterFrame(StackFrame::Type type, | 4318 void MacroAssembler::EnterFrame(StackFrame::Type type, |
4322 bool load_constant_pool_pointer_reg) { | 4319 bool load_constant_pool_pointer_reg) { |
4323 // Out-of-line constant pool not implemented on x64. | 4320 // Out-of-line constant pool not implemented on x64. |
4324 UNREACHABLE(); | 4321 UNREACHABLE(); |
4325 } | 4322 } |
4326 | 4323 |
4327 | 4324 |
4328 void MacroAssembler::EnterFrame(StackFrame::Type type) { | 4325 void MacroAssembler::EnterFrame(StackFrame::Type type) { |
4329 pushq(rbp); | 4326 pushq(rbp); |
4330 movp(rbp, rsp); | 4327 movp(rbp, rsp); |
4331 Push(rsi); // Context. | |
4332 Push(Smi::FromInt(type)); | 4328 Push(Smi::FromInt(type)); |
4333 Move(kScratchRegister, CodeObject(), RelocInfo::EMBEDDED_OBJECT); | 4329 if (type == StackFrame::INTERNAL) { |
4334 Push(kScratchRegister); | 4330 Move(kScratchRegister, CodeObject(), RelocInfo::EMBEDDED_OBJECT); |
| 4331 Push(kScratchRegister); |
| 4332 } |
4335 if (emit_debug_code()) { | 4333 if (emit_debug_code()) { |
4336 Move(kScratchRegister, | 4334 Move(kScratchRegister, |
4337 isolate()->factory()->undefined_value(), | 4335 isolate()->factory()->undefined_value(), |
4338 RelocInfo::EMBEDDED_OBJECT); | 4336 RelocInfo::EMBEDDED_OBJECT); |
4339 cmpp(Operand(rsp, 0), kScratchRegister); | 4337 cmpp(Operand(rsp, 0), kScratchRegister); |
4340 Check(not_equal, kCodeObjectNotProperlyPatched); | 4338 Check(not_equal, kCodeObjectNotProperlyPatched); |
4341 } | 4339 } |
4342 } | 4340 } |
4343 | 4341 |
4344 | 4342 |
4345 void MacroAssembler::LeaveFrame(StackFrame::Type type) { | 4343 void MacroAssembler::LeaveFrame(StackFrame::Type type) { |
4346 if (emit_debug_code()) { | 4344 if (emit_debug_code()) { |
4347 Move(kScratchRegister, Smi::FromInt(type)); | 4345 Move(kScratchRegister, Smi::FromInt(type)); |
4348 cmpp(Operand(rbp, StandardFrameConstants::kMarkerOffset), kScratchRegister); | 4346 cmpp(Operand(rbp, CommonFrameConstants::kContextOrFrameTypeOffset), |
| 4347 kScratchRegister); |
4349 Check(equal, kStackFrameTypesMustMatch); | 4348 Check(equal, kStackFrameTypesMustMatch); |
4350 } | 4349 } |
4351 movp(rsp, rbp); | 4350 movp(rsp, rbp); |
4352 popq(rbp); | 4351 popq(rbp); |
4353 } | 4352 } |
4354 | 4353 |
4355 | 4354 |
4356 void MacroAssembler::EnterExitFramePrologue(bool save_rax) { | 4355 void MacroAssembler::EnterExitFramePrologue(bool save_rax) { |
4357 // Set up the frame structure on the stack. | 4356 // Set up the frame structure on the stack. |
4358 // All constants are relative to the frame pointer of the exit frame. | 4357 // All constants are relative to the frame pointer of the exit frame. |
4359 DCHECK(ExitFrameConstants::kCallerSPDisplacement == | 4358 DCHECK_EQ(kFPOnStackSize + kPCOnStackSize, |
4360 kFPOnStackSize + kPCOnStackSize); | 4359 ExitFrameConstants::kCallerSPDisplacement); |
4361 DCHECK(ExitFrameConstants::kCallerPCOffset == kFPOnStackSize); | 4360 DCHECK_EQ(kFPOnStackSize, ExitFrameConstants::kCallerPCOffset); |
4362 DCHECK(ExitFrameConstants::kCallerFPOffset == 0 * kPointerSize); | 4361 DCHECK_EQ(0 * kPointerSize, ExitFrameConstants::kCallerFPOffset); |
4363 pushq(rbp); | 4362 pushq(rbp); |
4364 movp(rbp, rsp); | 4363 movp(rbp, rsp); |
4365 | 4364 |
4366 // Reserve room for entry stack pointer and push the code object. | 4365 // Reserve room for entry stack pointer and push the code object. |
4367 DCHECK(ExitFrameConstants::kSPOffset == -1 * kPointerSize); | 4366 Push(Smi::FromInt(StackFrame::EXIT)); |
| 4367 DCHECK_EQ(-2 * kPointerSize, ExitFrameConstants::kSPOffset); |
4368 Push(Immediate(0)); // Saved entry sp, patched before call. | 4368 Push(Immediate(0)); // Saved entry sp, patched before call. |
4369 Move(kScratchRegister, CodeObject(), RelocInfo::EMBEDDED_OBJECT); | 4369 Move(kScratchRegister, CodeObject(), RelocInfo::EMBEDDED_OBJECT); |
4370 Push(kScratchRegister); // Accessed from EditFrame::code_slot. | 4370 Push(kScratchRegister); // Accessed from EditFrame::code_slot. |
4371 | 4371 |
4372 // Save the frame pointer and the context in top. | 4372 // Save the frame pointer and the context in top. |
4373 if (save_rax) { | 4373 if (save_rax) { |
4374 movp(r14, rax); // Backup rax in callee-save register. | 4374 movp(r14, rax); // Backup rax in callee-save register. |
4375 } | 4375 } |
4376 | 4376 |
4377 Store(ExternalReference(Isolate::kCEntryFPAddress, isolate()), rbp); | 4377 Store(ExternalReference(Isolate::kCEntryFPAddress, isolate()), rbp); |
4378 Store(ExternalReference(Isolate::kContextAddress, isolate()), rsi); | 4378 Store(ExternalReference(Isolate::kContextAddress, isolate()), rsi); |
4379 Store(ExternalReference(Isolate::kCFunctionAddress, isolate()), rbx); | 4379 Store(ExternalReference(Isolate::kCFunctionAddress, isolate()), rbx); |
4380 } | 4380 } |
4381 | 4381 |
4382 | 4382 |
4383 void MacroAssembler::EnterExitFrameEpilogue(int arg_stack_space, | 4383 void MacroAssembler::EnterExitFrameEpilogue(int arg_stack_space, |
4384 bool save_doubles) { | 4384 bool save_doubles) { |
4385 #ifdef _WIN64 | 4385 #ifdef _WIN64 |
4386 const int kShadowSpace = 4; | 4386 const int kShadowSpace = 4; |
4387 arg_stack_space += kShadowSpace; | 4387 arg_stack_space += kShadowSpace; |
4388 #endif | 4388 #endif |
4389 // Optionally save all XMM registers. | 4389 // Optionally save all XMM registers. |
4390 if (save_doubles) { | 4390 if (save_doubles) { |
4391 int space = XMMRegister::kMaxNumRegisters * kDoubleSize + | 4391 int space = XMMRegister::kMaxNumRegisters * kDoubleSize + |
4392 arg_stack_space * kRegisterSize; | 4392 arg_stack_space * kRegisterSize; |
4393 subp(rsp, Immediate(space)); | 4393 subp(rsp, Immediate(space)); |
4394 int offset = -2 * kPointerSize; | 4394 int offset = -ExitFrameConstants::kFixedFrameSizeFromFp; |
4395 const RegisterConfiguration* config = | 4395 const RegisterConfiguration* config = |
4396 RegisterConfiguration::ArchDefault(RegisterConfiguration::CRANKSHAFT); | 4396 RegisterConfiguration::ArchDefault(RegisterConfiguration::CRANKSHAFT); |
4397 for (int i = 0; i < config->num_allocatable_double_registers(); ++i) { | 4397 for (int i = 0; i < config->num_allocatable_double_registers(); ++i) { |
4398 DoubleRegister reg = | 4398 DoubleRegister reg = |
4399 DoubleRegister::from_code(config->GetAllocatableDoubleCode(i)); | 4399 DoubleRegister::from_code(config->GetAllocatableDoubleCode(i)); |
4400 Movsd(Operand(rbp, offset - ((i + 1) * kDoubleSize)), reg); | 4400 Movsd(Operand(rbp, offset - ((i + 1) * kDoubleSize)), reg); |
4401 } | 4401 } |
4402 } else if (arg_stack_space > 0) { | 4402 } else if (arg_stack_space > 0) { |
4403 subp(rsp, Immediate(arg_stack_space * kRegisterSize)); | 4403 subp(rsp, Immediate(arg_stack_space * kRegisterSize)); |
4404 } | 4404 } |
(...skipping 26 matching lines...) Expand all Loading... |
4431 void MacroAssembler::EnterApiExitFrame(int arg_stack_space) { | 4431 void MacroAssembler::EnterApiExitFrame(int arg_stack_space) { |
4432 EnterExitFramePrologue(false); | 4432 EnterExitFramePrologue(false); |
4433 EnterExitFrameEpilogue(arg_stack_space, false); | 4433 EnterExitFrameEpilogue(arg_stack_space, false); |
4434 } | 4434 } |
4435 | 4435 |
4436 | 4436 |
4437 void MacroAssembler::LeaveExitFrame(bool save_doubles, bool pop_arguments) { | 4437 void MacroAssembler::LeaveExitFrame(bool save_doubles, bool pop_arguments) { |
4438 // Registers: | 4438 // Registers: |
4439 // r15 : argv | 4439 // r15 : argv |
4440 if (save_doubles) { | 4440 if (save_doubles) { |
4441 int offset = -2 * kPointerSize; | 4441 int offset = -ExitFrameConstants::kFixedFrameSizeFromFp; |
4442 const RegisterConfiguration* config = | 4442 const RegisterConfiguration* config = |
4443 RegisterConfiguration::ArchDefault(RegisterConfiguration::CRANKSHAFT); | 4443 RegisterConfiguration::ArchDefault(RegisterConfiguration::CRANKSHAFT); |
4444 for (int i = 0; i < config->num_allocatable_double_registers(); ++i) { | 4444 for (int i = 0; i < config->num_allocatable_double_registers(); ++i) { |
4445 DoubleRegister reg = | 4445 DoubleRegister reg = |
4446 DoubleRegister::from_code(config->GetAllocatableDoubleCode(i)); | 4446 DoubleRegister::from_code(config->GetAllocatableDoubleCode(i)); |
4447 Movsd(reg, Operand(rbp, offset - ((i + 1) * kDoubleSize))); | 4447 Movsd(reg, Operand(rbp, offset - ((i + 1) * kDoubleSize))); |
4448 } | 4448 } |
4449 } | 4449 } |
4450 | 4450 |
4451 if (pop_arguments) { | 4451 if (pop_arguments) { |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4494 } | 4494 } |
4495 | 4495 |
4496 | 4496 |
4497 void MacroAssembler::CheckAccessGlobalProxy(Register holder_reg, | 4497 void MacroAssembler::CheckAccessGlobalProxy(Register holder_reg, |
4498 Register scratch, | 4498 Register scratch, |
4499 Label* miss) { | 4499 Label* miss) { |
4500 Label same_contexts; | 4500 Label same_contexts; |
4501 | 4501 |
4502 DCHECK(!holder_reg.is(scratch)); | 4502 DCHECK(!holder_reg.is(scratch)); |
4503 DCHECK(!scratch.is(kScratchRegister)); | 4503 DCHECK(!scratch.is(kScratchRegister)); |
4504 // Load current lexical context from the stack frame. | 4504 // Load current lexical context from the active StandardFrame, which |
4505 movp(scratch, Operand(rbp, StandardFrameConstants::kContextOffset)); | 4505 // my require crawling past STUB frames. |
| 4506 Label load_context; |
| 4507 Label has_context; |
| 4508 movp(scratch, rbp); |
| 4509 bind(&load_context); |
| 4510 DCHECK(SmiValuesAre32Bits()); |
| 4511 int smi_tag_offset = kSmiShift / kBitsPerByte; |
| 4512 cmpl(MemOperand(scratch, CommonFrameConstants::kContextOrFrameTypeOffset + |
| 4513 smi_tag_offset), |
| 4514 Immediate(StackFrame::STUB)); |
| 4515 j(not_equal, &has_context); |
| 4516 movp(scratch, MemOperand(scratch, CommonFrameConstants::kCallerFPOffset)); |
| 4517 jmp(&load_context); |
| 4518 bind(&has_context); |
| 4519 movp(scratch, |
| 4520 MemOperand(scratch, CommonFrameConstants::kContextOrFrameTypeOffset)); |
4506 | 4521 |
4507 // When generating debug code, make sure the lexical context is set. | 4522 // When generating debug code, make sure the lexical context is set. |
4508 if (emit_debug_code()) { | 4523 if (emit_debug_code()) { |
4509 cmpp(scratch, Immediate(0)); | 4524 cmpp(scratch, Immediate(0)); |
4510 Check(not_equal, kWeShouldNotHaveAnEmptyLexicalContext); | 4525 Check(not_equal, kWeShouldNotHaveAnEmptyLexicalContext); |
4511 } | 4526 } |
4512 // Load the native context of the current context. | 4527 // Load the native context of the current context. |
4513 movp(scratch, ContextOperand(scratch, Context::NATIVE_CONTEXT_INDEX)); | 4528 movp(scratch, ContextOperand(scratch, Context::NATIVE_CONTEXT_INDEX)); |
4514 | 4529 |
4515 // Check the context is a native context. | 4530 // Check the context is a native context. |
(...skipping 1063 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5579 movl(rax, dividend); | 5594 movl(rax, dividend); |
5580 shrl(rax, Immediate(31)); | 5595 shrl(rax, Immediate(31)); |
5581 addl(rdx, rax); | 5596 addl(rdx, rax); |
5582 } | 5597 } |
5583 | 5598 |
5584 | 5599 |
5585 } // namespace internal | 5600 } // namespace internal |
5586 } // namespace v8 | 5601 } // namespace v8 |
5587 | 5602 |
5588 #endif // V8_TARGET_ARCH_X64 | 5603 #endif // V8_TARGET_ARCH_X64 |
OLD | NEW |