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 4338 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
4349 SmiToInteger64(actual.reg(), actual.reg()); | 4349 SmiToInteger64(actual.reg(), actual.reg()); |
4350 } | 4350 } |
4351 if (expected.is_reg()) { | 4351 if (expected.is_reg()) { |
4352 Pop(expected.reg()); | 4352 Pop(expected.reg()); |
4353 SmiToInteger64(expected.reg(), expected.reg()); | 4353 SmiToInteger64(expected.reg(), expected.reg()); |
4354 } | 4354 } |
4355 } | 4355 } |
4356 bind(&skip_flooding); | 4356 bind(&skip_flooding); |
4357 } | 4357 } |
4358 | 4358 |
4359 | 4359 void MacroAssembler::StubPrologue(StackFrame::Type type) { |
4360 void MacroAssembler::StubPrologue() { | 4360 pushq(rbp); // Caller's frame pointer. |
4361 pushq(rbp); // Caller's frame pointer. | 4361 movp(rbp, rsp); |
4362 movp(rbp, rsp); | 4362 Push(Smi::FromInt(type)); |
4363 Push(rsi); // Callee's context. | |
4364 Push(Smi::FromInt(StackFrame::STUB)); | |
4365 } | 4363 } |
4366 | 4364 |
4367 | |
4368 void MacroAssembler::Prologue(bool code_pre_aging) { | 4365 void MacroAssembler::Prologue(bool code_pre_aging) { |
4369 PredictableCodeSizeScope predictible_code_size_scope(this, | 4366 PredictableCodeSizeScope predictible_code_size_scope(this, |
4370 kNoCodeAgeSequenceLength); | 4367 kNoCodeAgeSequenceLength); |
4371 if (code_pre_aging) { | 4368 if (code_pre_aging) { |
4372 // Pre-age the code. | 4369 // Pre-age the code. |
4373 Call(isolate()->builtins()->MarkCodeAsExecutedOnce(), | 4370 Call(isolate()->builtins()->MarkCodeAsExecutedOnce(), |
4374 RelocInfo::CODE_AGE_SEQUENCE); | 4371 RelocInfo::CODE_AGE_SEQUENCE); |
4375 Nop(kNoCodeAgeSequenceLength - Assembler::kShortCallInstructionLength); | 4372 Nop(kNoCodeAgeSequenceLength - Assembler::kShortCallInstructionLength); |
4376 } else { | 4373 } else { |
4377 pushq(rbp); // Caller's frame pointer. | 4374 pushq(rbp); // Caller's frame pointer. |
(...skipping 14 matching lines...) Expand all Loading... | |
4392 void MacroAssembler::EnterFrame(StackFrame::Type type, | 4389 void MacroAssembler::EnterFrame(StackFrame::Type type, |
4393 bool load_constant_pool_pointer_reg) { | 4390 bool load_constant_pool_pointer_reg) { |
4394 // Out-of-line constant pool not implemented on x64. | 4391 // Out-of-line constant pool not implemented on x64. |
4395 UNREACHABLE(); | 4392 UNREACHABLE(); |
4396 } | 4393 } |
4397 | 4394 |
4398 | 4395 |
4399 void MacroAssembler::EnterFrame(StackFrame::Type type) { | 4396 void MacroAssembler::EnterFrame(StackFrame::Type type) { |
4400 pushq(rbp); | 4397 pushq(rbp); |
4401 movp(rbp, rsp); | 4398 movp(rbp, rsp); |
4402 Push(rsi); // Context. | |
4403 Push(Smi::FromInt(type)); | 4399 Push(Smi::FromInt(type)); |
4404 Move(kScratchRegister, CodeObject(), RelocInfo::EMBEDDED_OBJECT); | 4400 if (type == StackFrame::INTERNAL) { |
4405 Push(kScratchRegister); | 4401 Move(kScratchRegister, CodeObject(), RelocInfo::EMBEDDED_OBJECT); |
4402 Push(kScratchRegister); | |
4403 } | |
4406 if (emit_debug_code()) { | 4404 if (emit_debug_code()) { |
4407 Move(kScratchRegister, | 4405 Move(kScratchRegister, |
4408 isolate()->factory()->undefined_value(), | 4406 isolate()->factory()->undefined_value(), |
4409 RelocInfo::EMBEDDED_OBJECT); | 4407 RelocInfo::EMBEDDED_OBJECT); |
4410 cmpp(Operand(rsp, 0), kScratchRegister); | 4408 cmpp(Operand(rsp, 0), kScratchRegister); |
4411 Check(not_equal, kCodeObjectNotProperlyPatched); | 4409 Check(not_equal, kCodeObjectNotProperlyPatched); |
4412 } | 4410 } |
4413 } | 4411 } |
4414 | 4412 |
4415 | 4413 |
4416 void MacroAssembler::LeaveFrame(StackFrame::Type type) { | 4414 void MacroAssembler::LeaveFrame(StackFrame::Type type) { |
4417 if (emit_debug_code()) { | 4415 if (emit_debug_code()) { |
4418 Move(kScratchRegister, Smi::FromInt(type)); | 4416 Move(kScratchRegister, Smi::FromInt(type)); |
4419 cmpp(Operand(rbp, StandardFrameConstants::kMarkerOffset), kScratchRegister); | 4417 cmpp(Operand(rbp, CommonFrameConstants::kContextOrFrameTypeOffset), |
4418 kScratchRegister); | |
4420 Check(equal, kStackFrameTypesMustMatch); | 4419 Check(equal, kStackFrameTypesMustMatch); |
4421 } | 4420 } |
4422 movp(rsp, rbp); | 4421 movp(rsp, rbp); |
4423 popq(rbp); | 4422 popq(rbp); |
4424 } | 4423 } |
4425 | 4424 |
4426 | 4425 |
4427 void MacroAssembler::EnterExitFramePrologue(bool save_rax) { | 4426 void MacroAssembler::EnterExitFramePrologue(bool save_rax) { |
4428 // Set up the frame structure on the stack. | 4427 // Set up the frame structure on the stack. |
4429 // All constants are relative to the frame pointer of the exit frame. | 4428 // All constants are relative to the frame pointer of the exit frame. |
4430 DCHECK(ExitFrameConstants::kCallerSPDisplacement == | 4429 DCHECK_EQ(kFPOnStackSize + kPCOnStackSize, |
4431 kFPOnStackSize + kPCOnStackSize); | 4430 ExitFrameConstants::kCallerSPDisplacement); |
4432 DCHECK(ExitFrameConstants::kCallerPCOffset == kFPOnStackSize); | 4431 DCHECK_EQ(kFPOnStackSize, ExitFrameConstants::kCallerPCOffset); |
4433 DCHECK(ExitFrameConstants::kCallerFPOffset == 0 * kPointerSize); | 4432 DCHECK_EQ(0 * kPointerSize, ExitFrameConstants::kCallerFPOffset); |
4434 pushq(rbp); | 4433 pushq(rbp); |
4435 movp(rbp, rsp); | 4434 movp(rbp, rsp); |
4436 | 4435 |
4437 // Reserve room for entry stack pointer and push the code object. | 4436 // Reserve room for entry stack pointer and push the code object. |
4438 DCHECK(ExitFrameConstants::kSPOffset == -1 * kPointerSize); | 4437 Push(Smi::FromInt(StackFrame::EXIT)); |
4438 DCHECK_EQ(-2 * kPointerSize, ExitFrameConstants::kSPOffset); | |
4439 Push(Immediate(0)); // Saved entry sp, patched before call. | 4439 Push(Immediate(0)); // Saved entry sp, patched before call. |
4440 Move(kScratchRegister, CodeObject(), RelocInfo::EMBEDDED_OBJECT); | 4440 Move(kScratchRegister, CodeObject(), RelocInfo::EMBEDDED_OBJECT); |
4441 Push(kScratchRegister); // Accessed from EditFrame::code_slot. | 4441 Push(kScratchRegister); // Accessed from EditFrame::code_slot. |
4442 | 4442 |
4443 // Save the frame pointer and the context in top. | 4443 // Save the frame pointer and the context in top. |
4444 if (save_rax) { | 4444 if (save_rax) { |
4445 movp(r14, rax); // Backup rax in callee-save register. | 4445 movp(r14, rax); // Backup rax in callee-save register. |
4446 } | 4446 } |
4447 | 4447 |
4448 Store(ExternalReference(Isolate::kCEntryFPAddress, isolate()), rbp); | 4448 Store(ExternalReference(Isolate::kCEntryFPAddress, isolate()), rbp); |
4449 Store(ExternalReference(Isolate::kContextAddress, isolate()), rsi); | 4449 Store(ExternalReference(Isolate::kContextAddress, isolate()), rsi); |
4450 Store(ExternalReference(Isolate::kCFunctionAddress, isolate()), rbx); | 4450 Store(ExternalReference(Isolate::kCFunctionAddress, isolate()), rbx); |
4451 } | 4451 } |
4452 | 4452 |
4453 | 4453 |
4454 void MacroAssembler::EnterExitFrameEpilogue(int arg_stack_space, | 4454 void MacroAssembler::EnterExitFrameEpilogue(int arg_stack_space, |
4455 bool save_doubles) { | 4455 bool save_doubles) { |
4456 #ifdef _WIN64 | 4456 #ifdef _WIN64 |
4457 const int kShadowSpace = 4; | 4457 const int kShadowSpace = 4; |
4458 arg_stack_space += kShadowSpace; | 4458 arg_stack_space += kShadowSpace; |
4459 #endif | 4459 #endif |
4460 // Optionally save all XMM registers. | 4460 // Optionally save all XMM registers. |
4461 if (save_doubles) { | 4461 if (save_doubles) { |
4462 int space = XMMRegister::kMaxNumRegisters * kDoubleSize + | 4462 int space = XMMRegister::kMaxNumRegisters * kDoubleSize + |
4463 arg_stack_space * kRegisterSize; | 4463 arg_stack_space * kRegisterSize; |
4464 subp(rsp, Immediate(space)); | 4464 subp(rsp, Immediate(space)); |
4465 int offset = -2 * kPointerSize; | 4465 int offset = -ExitFrameConstants::kFixedFrameSizeFromFp; |
4466 const RegisterConfiguration* config = | 4466 const RegisterConfiguration* config = |
4467 RegisterConfiguration::ArchDefault(RegisterConfiguration::CRANKSHAFT); | 4467 RegisterConfiguration::ArchDefault(RegisterConfiguration::CRANKSHAFT); |
4468 for (int i = 0; i < config->num_allocatable_double_registers(); ++i) { | 4468 for (int i = 0; i < config->num_allocatable_double_registers(); ++i) { |
4469 DoubleRegister reg = | 4469 DoubleRegister reg = |
4470 DoubleRegister::from_code(config->GetAllocatableDoubleCode(i)); | 4470 DoubleRegister::from_code(config->GetAllocatableDoubleCode(i)); |
4471 Movsd(Operand(rbp, offset - ((i + 1) * kDoubleSize)), reg); | 4471 Movsd(Operand(rbp, offset - ((i + 1) * kDoubleSize)), reg); |
4472 } | 4472 } |
4473 } else if (arg_stack_space > 0) { | 4473 } else if (arg_stack_space > 0) { |
4474 subp(rsp, Immediate(arg_stack_space * kRegisterSize)); | 4474 subp(rsp, Immediate(arg_stack_space * kRegisterSize)); |
4475 } | 4475 } |
(...skipping 26 matching lines...) Expand all Loading... | |
4502 void MacroAssembler::EnterApiExitFrame(int arg_stack_space) { | 4502 void MacroAssembler::EnterApiExitFrame(int arg_stack_space) { |
4503 EnterExitFramePrologue(false); | 4503 EnterExitFramePrologue(false); |
4504 EnterExitFrameEpilogue(arg_stack_space, false); | 4504 EnterExitFrameEpilogue(arg_stack_space, false); |
4505 } | 4505 } |
4506 | 4506 |
4507 | 4507 |
4508 void MacroAssembler::LeaveExitFrame(bool save_doubles, bool pop_arguments) { | 4508 void MacroAssembler::LeaveExitFrame(bool save_doubles, bool pop_arguments) { |
4509 // Registers: | 4509 // Registers: |
4510 // r15 : argv | 4510 // r15 : argv |
4511 if (save_doubles) { | 4511 if (save_doubles) { |
4512 int offset = -2 * kPointerSize; | 4512 int offset = -ExitFrameConstants::kFixedFrameSizeFromFp; |
4513 const RegisterConfiguration* config = | 4513 const RegisterConfiguration* config = |
4514 RegisterConfiguration::ArchDefault(RegisterConfiguration::CRANKSHAFT); | 4514 RegisterConfiguration::ArchDefault(RegisterConfiguration::CRANKSHAFT); |
4515 for (int i = 0; i < config->num_allocatable_double_registers(); ++i) { | 4515 for (int i = 0; i < config->num_allocatable_double_registers(); ++i) { |
4516 DoubleRegister reg = | 4516 DoubleRegister reg = |
4517 DoubleRegister::from_code(config->GetAllocatableDoubleCode(i)); | 4517 DoubleRegister::from_code(config->GetAllocatableDoubleCode(i)); |
4518 Movsd(reg, Operand(rbp, offset - ((i + 1) * kDoubleSize))); | 4518 Movsd(reg, Operand(rbp, offset - ((i + 1) * kDoubleSize))); |
4519 } | 4519 } |
4520 } | 4520 } |
4521 | 4521 |
4522 if (pop_arguments) { | 4522 if (pop_arguments) { |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
4565 } | 4565 } |
4566 | 4566 |
4567 | 4567 |
4568 void MacroAssembler::CheckAccessGlobalProxy(Register holder_reg, | 4568 void MacroAssembler::CheckAccessGlobalProxy(Register holder_reg, |
4569 Register scratch, | 4569 Register scratch, |
4570 Label* miss) { | 4570 Label* miss) { |
4571 Label same_contexts; | 4571 Label same_contexts; |
4572 | 4572 |
4573 DCHECK(!holder_reg.is(scratch)); | 4573 DCHECK(!holder_reg.is(scratch)); |
4574 DCHECK(!scratch.is(kScratchRegister)); | 4574 DCHECK(!scratch.is(kScratchRegister)); |
4575 // Load current lexical context from the stack frame. | 4575 // Load current lexical context from the active StandardFrame, which |
4576 movp(scratch, Operand(rbp, StandardFrameConstants::kContextOffset)); | 4576 // may require crawling past STUB frames. |
4577 Label load_context; | |
4578 Label has_context; | |
4579 movp(scratch, rbp); | |
4580 bind(&load_context); | |
4581 DCHECK(SmiValuesAre32Bits()); | |
4582 int smi_tag_offset = kSmiShift / kBitsPerByte; | |
4583 cmpl(MemOperand(scratch, CommonFrameConstants::kContextOrFrameTypeOffset + | |
4584 smi_tag_offset), | |
4585 Immediate(StackFrame::STUB)); | |
4586 j(not_equal, &has_context); | |
4587 movp(scratch, MemOperand(scratch, CommonFrameConstants::kCallerFPOffset)); | |
4588 jmp(&load_context); | |
4589 bind(&has_context); | |
4590 movp(scratch, | |
4591 MemOperand(scratch, CommonFrameConstants::kContextOrFrameTypeOffset)); | |
Jakob Kummerow
2016/03/09 14:19:43
This is crashing in the wild, because |scratch| ca
| |
4577 | 4592 |
4578 // When generating debug code, make sure the lexical context is set. | 4593 // When generating debug code, make sure the lexical context is set. |
4579 if (emit_debug_code()) { | 4594 if (emit_debug_code()) { |
4580 cmpp(scratch, Immediate(0)); | 4595 cmpp(scratch, Immediate(0)); |
4581 Check(not_equal, kWeShouldNotHaveAnEmptyLexicalContext); | 4596 Check(not_equal, kWeShouldNotHaveAnEmptyLexicalContext); |
4582 } | 4597 } |
4583 // Load the native context of the current context. | 4598 // Load the native context of the current context. |
4584 movp(scratch, ContextOperand(scratch, Context::NATIVE_CONTEXT_INDEX)); | 4599 movp(scratch, ContextOperand(scratch, Context::NATIVE_CONTEXT_INDEX)); |
4585 | 4600 |
4586 // Check the context is a native context. | 4601 // Check the context is a native context. |
(...skipping 1063 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
5650 movl(rax, dividend); | 5665 movl(rax, dividend); |
5651 shrl(rax, Immediate(31)); | 5666 shrl(rax, Immediate(31)); |
5652 addl(rdx, rax); | 5667 addl(rdx, rax); |
5653 } | 5668 } |
5654 | 5669 |
5655 | 5670 |
5656 } // namespace internal | 5671 } // namespace internal |
5657 } // namespace v8 | 5672 } // namespace v8 |
5658 | 5673 |
5659 #endif // V8_TARGET_ARCH_X64 | 5674 #endif // V8_TARGET_ARCH_X64 |
OLD | NEW |