| 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 |