Chromium Code Reviews| Index: src/x64/macro-assembler-x64.cc |
| diff --git a/src/x64/macro-assembler-x64.cc b/src/x64/macro-assembler-x64.cc |
| index a690bd525613dde095e6d0c90cf2579b3d2f5963..be8532cdafcdef3d93f7e0f4459f58d9af63d246 100644 |
| --- a/src/x64/macro-assembler-x64.cc |
| +++ b/src/x64/macro-assembler-x64.cc |
| @@ -375,6 +375,16 @@ void MacroAssembler::CallRuntime(Runtime::FunctionId id, int num_arguments) { |
| } |
| +void MacroAssembler::CallRuntimeSaveDoubles(Runtime::FunctionId id) { |
| + Runtime::Function* function = Runtime::FunctionForId(id); |
| + Set(rax, function->nargs); |
| + movq(rbx, ExternalReference(function)); |
| + CEntryStub ces(1); |
| + ces.SaveDoubles(); |
| + CallStub(&ces); |
| +} |
| + |
| + |
| MaybeObject* MacroAssembler::TryCallRuntime(Runtime::FunctionId id, |
| int num_arguments) { |
| return TryCallRuntime(Runtime::FunctionForId(id), num_arguments); |
| @@ -967,6 +977,27 @@ Condition MacroAssembler::CheckUInteger32ValidSmiValue(Register src) { |
| } |
| +void MacroAssembler::CheckSmiToIndicator(Register dst, Register src) { |
| + if (dst.is(src)) { |
| + andl(dst, Immediate(kSmiTagMask)); |
| + } else { |
| + movl(dst, Immediate(kSmiTagMask)); |
| + andl(dst, src); |
| + } |
| +} |
| + |
| + |
| +void MacroAssembler::CheckSmiToIndicator(Register dst, const Operand& src) { |
| + if (!(src.depends_on_register(dst))) { |
| + movl(dst, Immediate(kSmiTagMask)); |
| + andl(dst, src); |
| + } else { |
| + movl(dst, src); |
|
William Hesse
2011/01/24 16:25:27
Why is the second choice worst than the first. Wh
Lasse Reichstein
2011/01/25 10:13:27
The second choice has a following operation that d
|
| + andl(dst, Immediate(kSmiTagMask)); |
| + } |
| +} |
| + |
| + |
| void MacroAssembler::SmiAddConstant(Register dst, Register src, Smi* constant) { |
| if (constant->value() == 0) { |
| if (!dst.is(src)) { |
| @@ -1427,6 +1458,34 @@ void MacroAssembler::Popad() { |
| } |
| +void MacroAssembler::Dropad() { |
| + const int kRegistersPushedByPushad = 11; |
| + addq(rsp, Immediate(kRegistersPushedByPushad * kPointerSize)); |
| +} |
| + |
| + |
| +// Order general registers are pushed by Pushad: |
| +// rax, rcx, rdx, rbx, rsi, rdi, r8, r9, r11, r12, r14. |
| +int MacroAssembler::kSafepointPushRegisterIndices[Register::kNumRegisters] = { |
| + 0, |
| + 1, |
| + 2, |
| + 3, |
| + -1, |
| + -1, |
| + 4, |
| + 5, |
| + 6, |
| + 7, |
| + -1, |
| + 8, |
| + 9, |
| + -1, |
| + 10, |
| + -1 |
| +}; |
| + |
| + |
| void MacroAssembler::PushTryHandler(CodeLocation try_location, |
| HandlerType type) { |
| // Adjust this code if not the case. |
| @@ -1775,11 +1834,27 @@ void MacroAssembler::EnterExitFramePrologue(bool save_rax) { |
| } |
| -void MacroAssembler::EnterExitFrameEpilogue(int arg_stack_space) { |
| +void MacroAssembler::EnterExitFrameEpilogue(int arg_stack_space, |
| + bool save_doubles) { |
| #ifdef _WIN64 |
| const int kShaddowSpace = 4; |
|
William Hesse
2011/01/24 16:25:27
Shadow has one d. What is shadow space?
Lasse Reichstein
2011/01/25 10:13:27
I believe it's the space reserved on the stack for
|
| arg_stack_space += kShaddowSpace; |
| #endif |
| + // Optionally save all XMM registers. |
| + if (save_doubles) { |
| + CpuFeatures::Scope scope(SSE2); |
| + int space = XMMRegister::kNumRegisters * kDoubleSize + |
| + arg_stack_space * kPointerSize; |
| + subq(rsp, Immediate(space)); |
| + int offset = -2 * kPointerSize; |
| + for (int i = 0; i < XMMRegister::kNumAllocatableRegisters; i++) { |
| + XMMRegister reg = XMMRegister::FromAllocationIndex(i); |
| + movdqa(Operand(rbp, offset - ((i + 1) * kDoubleSize)), reg); |
|
William Hesse
2011/01/24 16:25:27
How do we know that we are 16-byte aligned here?
Lasse Reichstein
2011/01/25 10:13:27
Ack, I don't. We are only 8-byte aligned. Using mo
|
| + } |
| + } else if (arg_stack_space > 0) { |
| + subq(rsp, Immediate(arg_stack_space * kPointerSize)); |
|
William Hesse
2011/01/24 16:25:27
This code is duplicated. It seems to run twice- a
Lasse Reichstein
2011/01/25 10:13:27
Argh, removed.
|
| + } |
| + |
| if (arg_stack_space > 0) { |
| subq(rsp, Immediate(arg_stack_space * kPointerSize)); |
| } |
| @@ -1797,7 +1872,7 @@ void MacroAssembler::EnterExitFrameEpilogue(int arg_stack_space) { |
| } |
| -void MacroAssembler::EnterExitFrame(int arg_stack_space) { |
| +void MacroAssembler::EnterExitFrame(int arg_stack_space, bool save_doubles) { |
| EnterExitFramePrologue(true); |
| // Setup argv in callee-saved register r12. It is reused in LeaveExitFrame, |
| @@ -1805,25 +1880,31 @@ void MacroAssembler::EnterExitFrame(int arg_stack_space) { |
| int offset = StandardFrameConstants::kCallerSPOffset - kPointerSize; |
| lea(r12, Operand(rbp, r14, times_pointer_size, offset)); |
| - EnterExitFrameEpilogue(arg_stack_space); |
| + EnterExitFrameEpilogue(arg_stack_space, save_doubles); |
| } |
| void MacroAssembler::EnterApiExitFrame(int arg_stack_space) { |
| EnterExitFramePrologue(false); |
| - EnterExitFrameEpilogue(arg_stack_space); |
| + EnterExitFrameEpilogue(arg_stack_space, false); |
| } |
| -void MacroAssembler::LeaveExitFrame() { |
| +void MacroAssembler::LeaveExitFrame(bool save_doubles) { |
| // Registers: |
| // r12 : argv |
| - |
| + if (save_doubles) { |
| + int offset = -2 * kPointerSize; |
| + for (int i = 0; i < XMMRegister::kNumAllocatableRegisters; i++) { |
| + XMMRegister reg = XMMRegister::FromAllocationIndex(i); |
| + movdqa(reg, Operand(rbp, offset - ((i + 1) * kDoubleSize))); |
|
William Hesse
2011/01/24 16:25:27
Is this the right rbp here?
Lasse Reichstein
2011/01/25 10:13:27
It seems so. It's equivalent to the ia32 code.
|
| + } |
| + } |
| // Get the return address from the stack and restore the frame pointer. |
| movq(rcx, Operand(rbp, 1 * kPointerSize)); |
| movq(rbp, Operand(rbp, 0 * kPointerSize)); |
| - // Pop everything up to and including the arguments and the receiver |
| + // Drop everything up to and including the arguments and the receiver |
| // from the caller stack. |
| lea(rsp, Operand(r12, 1 * kPointerSize)); |