| Index: runtime/vm/stub_code_x64.cc
|
| diff --git a/runtime/vm/stub_code_x64.cc b/runtime/vm/stub_code_x64.cc
|
| index 490d473692993c48e5a38167f13756265c03bda5..9da0ef2d2537eb5cc047ed89d57270c2a5d8a0e9 100644
|
| --- a/runtime/vm/stub_code_x64.cc
|
| +++ b/runtime/vm/stub_code_x64.cc
|
| @@ -88,7 +88,11 @@ void StubCode::GenerateCallToRuntimeStub(Assembler* assembler) {
|
| __ movq(Address(RSP, argv_offset), RAX); // Set argv in NativeArguments.
|
| __ addq(RAX, Immediate(1 * kWordSize)); // Retval is next to 1st argument.
|
| __ movq(Address(RSP, retval_offset), RAX); // Set retval in NativeArguments.
|
| - __ call(RBX);
|
| +#if defined(_WIN64)
|
| + ASSERT(sizeof(NativeArguments) > CallingConventions::kRegisterTransferLimit);
|
| + __ movq(CallingConventions::kArg1Reg, RSP);
|
| +#endif
|
| + __ CallCFunction(RBX);
|
|
|
| // Mark that the isolate is executing Dart code.
|
| __ movq(Address(CTX, Isolate::vm_tag_offset()),
|
| @@ -126,6 +130,9 @@ END_LEAF_RUNTIME_ENTRY
|
| void StubCode::GeneratePrintStopMessageStub(Assembler* assembler) {
|
| __ EnterCallRuntimeFrame(0);
|
| // Call the runtime leaf function. RDI already contains the parameter.
|
| +#if defined(_WIN64)
|
| + __ movq(CallingConventions::kArg1Reg, RDI);
|
| +#endif
|
| __ CallRuntime(kPrintStopMessageRuntimeEntry, 1);
|
| __ LeaveCallRuntimeFrame();
|
| __ ret();
|
| @@ -192,18 +199,21 @@ void StubCode::GenerateCallNativeCFunctionStub(Assembler* assembler) {
|
| __ movq(Address(RSP, argv_offset), RAX); // Set argv in NativeArguments.
|
| __ leaq(RAX, Address(RBP, 2 * kWordSize)); // Compute return value addr.
|
| __ movq(Address(RSP, retval_offset), RAX); // Set retval in NativeArguments.
|
| - __ movq(RDI, RSP); // Pass the pointer to the NativeArguments.
|
| +
|
| + // Pass the pointer to the NativeArguments.
|
| + __ movq(CallingConventions::kArg1Reg, RSP);
|
|
|
| // Call native function (setsup scope if not leaf function).
|
| Label leaf_call;
|
| Label done;
|
| __ testq(R10, Immediate(NativeArguments::AutoSetupScopeMask()));
|
| __ j(ZERO, &leaf_call);
|
| - __ movq(RSI, RBX); // Pass pointer to function entrypoint.
|
| - __ call(&NativeEntry::NativeCallWrapperLabel());
|
| + // Pass pointer to function entrypoint.
|
| + __ movq(CallingConventions::kArg2Reg, RBX);
|
| + __ CallCFunction(&NativeEntry::NativeCallWrapperLabel());
|
| __ jmp(&done);
|
| __ Bind(&leaf_call);
|
| - __ call(RBX);
|
| + __ CallCFunction(RBX);
|
| __ Bind(&done);
|
|
|
| // Mark that the isolate is executing Dart code.
|
| @@ -288,8 +298,10 @@ void StubCode::GenerateCallBootstrapCFunctionStub(Assembler* assembler) {
|
| __ movq(Address(RSP, argv_offset), RAX); // Set argv in NativeArguments.
|
| __ leaq(RAX, Address(RBP, 2 * kWordSize)); // Compute return value addr.
|
| __ movq(Address(RSP, retval_offset), RAX); // Set retval in NativeArguments.
|
| - __ movq(RDI, RSP); // Pass the pointer to the NativeArguments.
|
| - __ call(RBX);
|
| +
|
| + // Pass the pointer to the NativeArguments.
|
| + __ movq(CallingConventions::kArg1Reg, RSP);
|
| + __ CallCFunction(RBX);
|
|
|
| // Mark that the isolate is executing Dart code.
|
| __ movq(Address(CTX, Isolate::vm_tag_offset()),
|
| @@ -438,8 +450,9 @@ static void GenerateDeoptimizationSequence(Assembler* assembler,
|
| offset += kFpuRegisterSize;
|
| }
|
|
|
| - __ movq(RDI, RSP); // Pass address of saved registers block.
|
| - __ ReserveAlignedFrameSpace(0);
|
| + // Pass address of saved registers block.
|
| + __ movq(CallingConventions::kArg1Reg, RSP);
|
| + __ ReserveAlignedFrameSpace(0); // Ensure stack is aligned before the call.
|
| __ CallRuntime(kDeoptimizeCopyFrameRuntimeEntry, 1);
|
| // Result (RAX) is stack-size (FP - SP) in bytes.
|
|
|
| @@ -466,7 +479,8 @@ static void GenerateDeoptimizationSequence(Assembler* assembler,
|
| __ pushq(RBX); // Preserve result as first local.
|
| }
|
| __ ReserveAlignedFrameSpace(0);
|
| - __ movq(RDI, RBP); // Pass last FP as parameter in RDI.
|
| + // Pass last FP as a parameter.
|
| + __ movq(CallingConventions::kArg1Reg, RBP);
|
| __ CallRuntime(kDeoptimizeFillFrameRuntimeEntry, 1);
|
| if (preserve_result) {
|
| // Restore result into RBX.
|
| @@ -685,6 +699,11 @@ void StubCode::GenerateInvokeDartCodeStub(Assembler* assembler) {
|
| // Save frame pointer coming in.
|
| __ EnterFrame(0);
|
|
|
| + const Register kEntryPointReg = CallingConventions::kArg1Reg;
|
| + const Register kArgDescReg = CallingConventions::kArg2Reg;
|
| + const Register kArgsReg = CallingConventions::kArg3Reg;
|
| + const Register kNewContextReg = CallingConventions::kArg4Reg;
|
| +
|
| // At this point, the stack looks like:
|
| // | saved RBP | <-- RBP
|
| // | saved PC (return to DartEntry::InvokeFunction) |
|
| @@ -692,16 +711,13 @@ void StubCode::GenerateInvokeDartCodeStub(Assembler* assembler) {
|
| const intptr_t kInitialOffset = 1;
|
| // Save arguments descriptor array and new context.
|
| const intptr_t kArgumentsDescOffset = -(kInitialOffset) * kWordSize;
|
| - __ pushq(RSI);
|
| + __ pushq(kArgDescReg);
|
| const intptr_t kNewContextOffset = -(kInitialOffset + 1) * kWordSize;
|
| - __ pushq(RCX);
|
| + __ pushq(kNewContextReg);
|
|
|
| // Save C++ ABI callee-saved registers.
|
| - __ pushq(RBX);
|
| - __ pushq(R12);
|
| - __ pushq(R13);
|
| - __ pushq(R14);
|
| - __ pushq(R15);
|
| + __ PushRegisters(CallingConventions::kCalleeSaveCpuRegisters,
|
| + CallingConventions::kCalleeSaveXmmRegisters);
|
|
|
| // We now load the pool pointer(PP) as we are about to invoke dart code and we
|
| // could potentially invoke some intrinsic functions which need the PP to be
|
| @@ -719,28 +735,50 @@ void StubCode::GenerateInvokeDartCodeStub(Assembler* assembler) {
|
| // compiled or runtime stub code.
|
|
|
| // Cache the new Context pointer into CTX while executing Dart code.
|
| - __ movq(CTX, Address(RCX, VMHandles::kOffsetOfRawPtrInHandle));
|
| + __ movq(CTX, Address(kNewContextReg, VMHandles::kOffsetOfRawPtrInHandle));
|
| +
|
| + const Register kIsolateReg = RBX;
|
|
|
| // Load Isolate pointer from Context structure into R8.
|
| - __ movq(R8, FieldAddress(CTX, Context::isolate_offset()));
|
| + __ movq(kIsolateReg, FieldAddress(CTX, Context::isolate_offset()));
|
|
|
| // Save the current VMTag on the stack.
|
| - ASSERT(kSavedVMTagSlotFromEntryFp == -8);
|
| - __ movq(RAX, Address(R8, Isolate::vm_tag_offset()));
|
| + __ movq(RAX, Address(kIsolateReg, Isolate::vm_tag_offset()));
|
| __ pushq(RAX);
|
| +#if defined(DEBUG)
|
| + {
|
| + Label ok;
|
| + __ leaq(RAX, Address(RBP, kSavedVMTagSlotFromEntryFp * kWordSize));
|
| + __ cmpq(RAX, RSP);
|
| + __ j(EQUAL, &ok);
|
| + __ Stop("kSavedVMTagSlotFromEntryFp mismatch");
|
| + __ Bind(&ok);
|
| + }
|
| +#endif
|
|
|
| // Mark that the isolate is executing Dart code.
|
| - __ movq(Address(R8, Isolate::vm_tag_offset()),
|
| + __ movq(Address(kIsolateReg, Isolate::vm_tag_offset()),
|
| Immediate(VMTag::kScriptTagId));
|
|
|
| // Save the top exit frame info. Use RAX as a temporary register.
|
| // StackFrameIterator reads the top exit frame info saved in this frame.
|
| // The constant kExitLinkSlotFromEntryFp must be kept in sync with the
|
| // code below.
|
| - ASSERT(kExitLinkSlotFromEntryFp == -9);
|
| - __ movq(RAX, Address(R8, Isolate::top_exit_frame_info_offset()));
|
| + __ movq(RAX, Address(kIsolateReg, Isolate::top_exit_frame_info_offset()));
|
| __ pushq(RAX);
|
| - __ movq(Address(R8, Isolate::top_exit_frame_info_offset()), Immediate(0));
|
| +#if defined(DEBUG)
|
| + {
|
| + Label ok;
|
| + __ leaq(RAX, Address(RBP, kExitLinkSlotFromEntryFp * kWordSize));
|
| + __ cmpq(RAX, RSP);
|
| + __ j(EQUAL, &ok);
|
| + __ Stop("kExitLinkSlotFromEntryFp mismatch");
|
| + __ Bind(&ok);
|
| + }
|
| +#endif
|
| +
|
| + __ movq(Address(kIsolateReg, Isolate::top_exit_frame_info_offset()),
|
| + Immediate(0));
|
|
|
| // Save the old Context pointer. Use RAX as a temporary register.
|
| // Note that VisitObjectPointers will find this saved Context pointer during
|
| @@ -749,19 +787,31 @@ void StubCode::GenerateInvokeDartCodeStub(Assembler* assembler) {
|
| // EntryFrame::SavedContext reads the context saved in this frame.
|
| // The constant kSavedContextSlotFromEntryFp must be kept in sync with
|
| // the code below.
|
| - ASSERT(kSavedContextSlotFromEntryFp == -10);
|
| - __ movq(RAX, Address(R8, Isolate::top_context_offset()));
|
| + __ movq(RAX, Address(kIsolateReg, Isolate::top_context_offset()));
|
| __ pushq(RAX);
|
| +#if defined(DEBUG)
|
| + {
|
| + Label ok;
|
| + __ leaq(RAX, Address(RBP, kSavedContextSlotFromEntryFp * kWordSize));
|
| + __ cmpq(RAX, RSP);
|
| + __ j(EQUAL, &ok);
|
| + __ Stop("kSavedContextSlotFromEntryFp mismatch");
|
| + __ Bind(&ok);
|
| + }
|
| +#endif
|
|
|
| // Load arguments descriptor array into R10, which is passed to Dart code.
|
| - __ movq(R10, Address(RSI, VMHandles::kOffsetOfRawPtrInHandle));
|
| + __ movq(R10, Address(kArgDescReg, VMHandles::kOffsetOfRawPtrInHandle));
|
| +
|
| + // Push arguments. At this point we only need to preserve kEntryPointReg.
|
| + ASSERT(kEntryPointReg != RDX);
|
|
|
| // Load number of arguments into RBX.
|
| __ movq(RBX, FieldAddress(R10, ArgumentsDescriptor::count_offset()));
|
| __ SmiUntag(RBX);
|
|
|
| // Compute address of 'arguments array' data area into RDX.
|
| - __ movq(RDX, Address(RDX, VMHandles::kOffsetOfRawPtrInHandle));
|
| + __ movq(RDX, Address(kArgsReg, VMHandles::kOffsetOfRawPtrInHandle));
|
| __ leaq(RDX, FieldAddress(RDX, Array::data_offset()));
|
|
|
| // Set up arguments for the Dart call.
|
| @@ -771,51 +821,45 @@ void StubCode::GenerateInvokeDartCodeStub(Assembler* assembler) {
|
| __ j(ZERO, &done_push_arguments, Assembler::kNearJump);
|
| __ movq(RAX, Immediate(0));
|
| __ Bind(&push_arguments);
|
| - __ movq(RCX, Address(RDX, RAX, TIMES_8, 0)); // RDX is start of arguments.
|
| - __ pushq(RCX);
|
| + __ pushq(Address(RDX, RAX, TIMES_8, 0));
|
| __ incq(RAX);
|
| __ cmpq(RAX, RBX);
|
| __ j(LESS, &push_arguments, Assembler::kNearJump);
|
| __ Bind(&done_push_arguments);
|
|
|
| // Call the Dart code entrypoint.
|
| - __ call(RDI); // R10 is the arguments descriptor array.
|
| + __ call(kEntryPointReg); // R10 is the arguments descriptor array.
|
|
|
| - // Read the saved new Context pointer.
|
| + // Restore CTX from the saved context handle.
|
| __ movq(CTX, Address(RBP, kNewContextOffset));
|
| __ movq(CTX, Address(CTX, VMHandles::kOffsetOfRawPtrInHandle));
|
|
|
| // Read the saved arguments descriptor array to obtain the number of passed
|
| // arguments.
|
| - __ movq(RSI, Address(RBP, kArgumentsDescOffset));
|
| - __ movq(R10, Address(RSI, VMHandles::kOffsetOfRawPtrInHandle));
|
| + __ movq(kArgDescReg, Address(RBP, kArgumentsDescOffset));
|
| + __ movq(R10, Address(kArgDescReg, VMHandles::kOffsetOfRawPtrInHandle));
|
| __ movq(RDX, FieldAddress(R10, ArgumentsDescriptor::count_offset()));
|
| // Get rid of arguments pushed on the stack.
|
| __ leaq(RSP, Address(RSP, RDX, TIMES_4, 0)); // RDX is a Smi.
|
|
|
| // Load Isolate pointer from Context structure into CTX. Drop Context.
|
| - __ movq(CTX, FieldAddress(CTX, Context::isolate_offset()));
|
| + __ movq(kIsolateReg, FieldAddress(CTX, Context::isolate_offset()));
|
|
|
| // Restore the saved Context pointer into the Isolate structure.
|
| - // Uses RCX as a temporary register for this.
|
| - __ popq(RCX);
|
| - __ movq(Address(CTX, Isolate::top_context_offset()), RCX);
|
| + __ popq(RDX);
|
| + __ movq(Address(kIsolateReg, Isolate::top_context_offset()), RDX);
|
|
|
| // Restore the saved top exit frame info back into the Isolate structure.
|
| - // Uses RDX as a temporary register for this.
|
| __ popq(RDX);
|
| - __ movq(Address(CTX, Isolate::top_exit_frame_info_offset()), RDX);
|
| + __ movq(Address(kIsolateReg, Isolate::top_exit_frame_info_offset()), RDX);
|
|
|
| // Restore the current VMTag from the stack.
|
| __ popq(RDX);
|
| - __ movq(Address(CTX, Isolate::vm_tag_offset()), RDX);
|
| + __ movq(Address(kIsolateReg, Isolate::vm_tag_offset()), RDX);
|
|
|
| // Restore C++ ABI callee-saved registers.
|
| - __ popq(R15);
|
| - __ popq(R14);
|
| - __ popq(R13);
|
| - __ popq(R12);
|
| - __ popq(RBX);
|
| + __ PopRegisters(CallingConventions::kCalleeSaveCpuRegisters,
|
| + CallingConventions::kCalleeSaveXmmRegisters);
|
|
|
| // Restore the frame pointer.
|
| __ LeaveFrame();
|
| @@ -1005,7 +1049,8 @@ void StubCode::GenerateUpdateStoreBufferStub(Assembler* assembler) {
|
| __ Bind(&L);
|
| // Setup frame, push callee-saved registers.
|
| __ EnterCallRuntimeFrame(0);
|
| - __ movq(RDI, FieldAddress(CTX, Context::isolate_offset()));
|
| + __ movq(CallingConventions::kArg1Reg,
|
| + FieldAddress(CTX, Context::isolate_offset()));
|
| __ CallRuntime(kStoreBufferBlockProcessRuntimeEntry, 1);
|
| __ LeaveCallRuntimeFrame();
|
| __ ret();
|
| @@ -1667,20 +1712,30 @@ void StubCode::GenerateGetStackPointerStub(Assembler* assembler) {
|
|
|
| // Jump to the exception or error handler.
|
| // TOS + 0: return address
|
| -// RDI: program counter
|
| -// RSI: stack pointer
|
| -// RDX: frame_pointer
|
| -// RCX: exception object
|
| -// R8: stacktrace object
|
| +// Arg1: program counter
|
| +// Arg2: stack pointer
|
| +// Arg3: frame_pointer
|
| +// Arg4: exception object
|
| +// Arg5: stacktrace object
|
| // No Result.
|
| void StubCode::GenerateJumpToExceptionHandlerStub(Assembler* assembler) {
|
| ASSERT(kExceptionObjectReg == RAX);
|
| ASSERT(kStackTraceObjectReg == RDX);
|
| - __ movq(RBP, RDX); // target frame pointer.
|
| - __ movq(kStackTraceObjectReg, R8); // stacktrace object.
|
| - __ movq(kExceptionObjectReg, RCX); // exception object.
|
| - __ movq(RSP, RSI); // target stack_pointer.
|
| - __ jmp(RDI); // Jump to the exception handler code.
|
| + ASSERT(CallingConventions::kArg4Reg != kStackTraceObjectReg);
|
| + ASSERT(CallingConventions::kArg1Reg != kStackTraceObjectReg);
|
| +
|
| +#if defined(_WIN64)
|
| + Register stacktrace_reg = RBX;
|
| + __ movq(stacktrace_reg, Address(RSP, 5 * kWordSize));
|
| +#else
|
| + Register stacktrace_reg = CallingConventions::kArg5Reg;
|
| +#endif
|
| +
|
| + __ movq(RBP, CallingConventions::kArg3Reg);
|
| + __ movq(RSP, CallingConventions::kArg2Reg);
|
| + __ movq(kStackTraceObjectReg, stacktrace_reg);
|
| + __ movq(kExceptionObjectReg, CallingConventions::kArg4Reg);
|
| + __ jmp(CallingConventions::kArg1Reg); // Jump to the exception handler code.
|
| }
|
|
|
|
|
| @@ -1756,8 +1811,8 @@ void StubCode::GenerateIdenticalWithNumberCheckStub(Assembler* assembler,
|
| __ j(NOT_EQUAL, &done, Assembler::kNearJump);
|
| __ EnterFrame(0);
|
| __ ReserveAlignedFrameSpace(0);
|
| - __ movq(RDI, left);
|
| - __ movq(RSI, right);
|
| + __ movq(CallingConventions::kArg1Reg, left);
|
| + __ movq(CallingConventions::kArg2Reg, right);
|
| __ CallRuntime(kBigintCompareRuntimeEntry, 2);
|
| // Result in RAX, 0 means equal.
|
| __ LeaveFrame();
|
|
|