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..2fc825fc0bbf2402c4158590baaaa7665b1277cf 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.AddressUsesRegister(dst))) { |
+ movl(dst, Immediate(kSmiTagMask)); |
+ andl(dst, src); |
+ } else { |
+ movl(dst, src); |
+ 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,12 +1834,24 @@ 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; |
- arg_stack_space += kShaddowSpace; |
+ const int kShadowSpace = 4; |
+ arg_stack_space += kShadowSpace; |
#endif |
- if (arg_stack_space > 0) { |
+ // 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); |
+ movsd(Operand(rbp, offset - ((i + 1) * kDoubleSize)), reg); |
+ } |
+ } else if (arg_stack_space > 0) { |
subq(rsp, Immediate(arg_stack_space * kPointerSize)); |
} |
@@ -1797,7 +1868,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 +1876,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); |
+ movsd(reg, Operand(rbp, offset - ((i + 1) * kDoubleSize))); |
+ } |
+ } |
// 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)); |