| Index: runtime/vm/stub_code_x64.cc
|
| ===================================================================
|
| --- runtime/vm/stub_code_x64.cc (revision 2205)
|
| +++ runtime/vm/stub_code_x64.cc (working copy)
|
| @@ -5,34 +5,165 @@
|
| #include "vm/globals.h"
|
| #if defined(TARGET_ARCH_X64)
|
|
|
| +#include "vm/native_entry.h"
|
| #include "vm/stub_code.h"
|
|
|
| #define __ assembler->
|
|
|
| namespace dart {
|
|
|
| +// Input parameters:
|
| +// RSP : points to return address.
|
| +// RSP + 8 : address of last argument in argument array.
|
| +// RSP + 8*R10 : address of first argument in argument array.
|
| +// RSP + 8*R10 + 8 : address of return value.
|
| +// RBX : address of the runtime function to call.
|
| +// R10 : number of arguments to the call.
|
| +static void GenerateCallRuntimeStub(Assembler* assembler) {
|
| + const intptr_t isolate_offset = NativeArguments::isolate_offset();
|
| + const intptr_t argc_offset = NativeArguments::argc_offset();
|
| + const intptr_t argv_offset = NativeArguments::argv_offset();
|
| + const intptr_t retval_offset = NativeArguments::retval_offset();
|
| +
|
| + __ EnterFrame(0);
|
| +
|
| + // Load current Isolate pointer from Context structure into RAX.
|
| + __ movq(RAX, FieldAddress(CTX, Context::isolate_offset()));
|
| +
|
| + // Save exit frame information to enable stack walking as we are about
|
| + // to transition to Dart VM C++ code.
|
| + __ movq(Address(RAX, Isolate::top_exit_frame_info_offset()), RSP);
|
| +
|
| + // Save current Context pointer into Isolate structure.
|
| + __ movq(Address(RAX, Isolate::top_context_offset()), CTX);
|
| +
|
| + // Cache Isolate pointer into CTX while executing runtime code.
|
| + __ movq(CTX, RAX);
|
| +
|
| + // Reserve space for arguments and align frame before entering C++ world.
|
| + __ AddImmediate(RSP, Immediate(-sizeof(NativeArguments)));
|
| + if (OS::ActivationFrameAlignment() > 0) {
|
| + __ andq(RSP, Immediate(~(OS::ActivationFrameAlignment() - 1)));
|
| + }
|
| +
|
| + // Pass NativeArguments structure by value and call runtime.
|
| + __ movq(Address(RSP, isolate_offset), CTX); // Set isolate in NativeArgs.
|
| + __ movq(Address(RSP, argc_offset), R10); // Set argc in NativeArguments.
|
| + __ leaq(RAX, Address(RBP, R10, TIMES_8, 1 * kWordSize)); // Compute argv.
|
| + __ 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);
|
| +
|
| + // Reset exit frame information in Isolate structure.
|
| + __ movq(Address(CTX, Isolate::top_exit_frame_info_offset()), Immediate(0));
|
| +
|
| + // Load Context pointer from Isolate structure into RBX.
|
| + __ movq(RBX, Address(CTX, Isolate::top_context_offset()));
|
| +
|
| + // Reset Context pointer in Isolate structure.
|
| + const Immediate raw_null =
|
| + Immediate(reinterpret_cast<intptr_t>(Object::null()));
|
| + __ movq(Address(CTX, Isolate::top_context_offset()), raw_null);
|
| +
|
| + // Cache Context pointer into CTX while executing Dart code.
|
| + __ movq(CTX, RBX);
|
| +
|
| + __ LeaveFrame();
|
| + __ ret();
|
| +}
|
| +
|
| +
|
| +// Input parameters:
|
| +// RSP : points to return address.
|
| +// RSP + 8 : address of last argument in argument array.
|
| +// RSP + 8*R10 : address of first argument in argument array.
|
| +// RSP + 8*R10 + 8 : address of return value.
|
| +// RBX : address of the runtime function to call.
|
| +// R10 : number of arguments to the call.
|
| void StubCode::GenerateDartCallToRuntimeStub(Assembler* assembler) {
|
| - __ Unimplemented("DartCallToRuntime stub");
|
| + GenerateCallRuntimeStub(assembler);
|
| }
|
|
|
|
|
| +// Input parameters:
|
| +// RSP : points to return address.
|
| +// RSP + 8 : address of last argument in argument array.
|
| +// RSP + 8*R10 : address of first argument in argument array.
|
| +// RSP + 8*R10 + 8 : address of return value.
|
| +// RBX : address of the runtime function to call.
|
| +// R10 : number of arguments to the call.
|
| void StubCode::GenerateStubCallToRuntimeStub(Assembler* assembler) {
|
| - __ Unimplemented("StubCallToRuntime stub");
|
| + GenerateCallRuntimeStub(assembler);
|
| }
|
|
|
|
|
| +// Input parameters:
|
| +// RSP : points to return address.
|
| +// RSP + 8 : address of return value.
|
| +// RAX : address of first argument in argument array.
|
| +// RAX - 8*R10 + 8 : address of last argument in argument array.
|
| +// RBX : address of the native function to call.
|
| +// R10 : number of arguments to the call.
|
| void StubCode::GenerateCallNativeCFunctionStub(Assembler* assembler) {
|
| - __ Unimplemented("CallNativeCFunction stub");
|
| -}
|
| + const intptr_t native_args_struct_offset = 0;
|
| + const intptr_t isolate_offset =
|
| + NativeArguments::isolate_offset() + native_args_struct_offset;
|
| + const intptr_t argc_offset =
|
| + NativeArguments::argc_offset() + native_args_struct_offset;
|
| + const intptr_t argv_offset =
|
| + NativeArguments::argv_offset() + native_args_struct_offset;
|
| + const intptr_t retval_offset =
|
| + NativeArguments::retval_offset() + native_args_struct_offset;
|
|
|
| + __ EnterFrame(0);
|
|
|
| -void StubCode::GenerateCallNoSuchMethodFunctionStub(Assembler* assembler) {
|
| - __ Unimplemented("CallNoSuchMethodFunction stub");
|
| -}
|
| + // Load current Isolate pointer from Context structure into R8.
|
| + __ movq(R8, FieldAddress(CTX, Context::isolate_offset()));
|
|
|
| + // Save exit frame information to enable stack walking as we are about
|
| + // to transition to native code.
|
| + __ movq(Address(R8, Isolate::top_exit_frame_info_offset()), RSP);
|
|
|
| -void StubCode::GenerateInvokeDartCodeStub(Assembler* assembler) {
|
| - __ Unimplemented("InvokeDartCode stub");
|
| + // Save current Context pointer into Isolate structure.
|
| + __ movq(Address(R8, Isolate::top_context_offset()), CTX);
|
| +
|
| + // Cache Isolate pointer into CTX while executing native code.
|
| + __ movq(CTX, R8);
|
| +
|
| + // Reserve space for the native arguments structure passed on the stack (the
|
| + // outgoing pointer parameter to the native arguments structure is passed in
|
| + // RDI) and align frame before entering the C++ world.
|
| + __ AddImmediate(RSP, Immediate(-sizeof(NativeArguments)));
|
| + if (OS::ActivationFrameAlignment() > 0) {
|
| + __ andq(RSP, Immediate(~(OS::ActivationFrameAlignment() - 1)));
|
| + }
|
| +
|
| + // Pass NativeArguments structure by value and call native function.
|
| + __ movq(Address(RSP, isolate_offset), CTX); // Set isolate in NativeArgs.
|
| + __ movq(Address(RSP, argc_offset), R10); // Set argc in NativeArguments.
|
| + __ 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);
|
| +
|
| + // Reset exit frame information in Isolate structure.
|
| + __ movq(Address(CTX, Isolate::top_exit_frame_info_offset()), Immediate(0));
|
| +
|
| + // Load Context pointer from Isolate structure into R8.
|
| + __ movq(R8, Address(CTX, Isolate::top_context_offset()));
|
| +
|
| + // Reset Context pointer in Isolate structure.
|
| + const Immediate raw_null =
|
| + Immediate(reinterpret_cast<intptr_t>(Object::null()));
|
| + __ movq(Address(CTX, Isolate::top_context_offset()), raw_null);
|
| +
|
| + // Cache Context pointer into CTX while executing Dart code.
|
| + __ movq(CTX, R8);
|
| +
|
| + __ LeaveFrame();
|
| + __ ret();
|
| }
|
|
|
|
|
| @@ -41,16 +172,157 @@
|
| }
|
|
|
|
|
| +void StubCode::GenerateStackOverflowStub(Assembler* assembler) {
|
| + __ Unimplemented("StackOverflow stub");
|
| +}
|
| +
|
| +
|
| +void StubCode::GenerateOptimizeInvokedFunctionStub(Assembler* assembler) {
|
| + __ Unimplemented("OptimizeInvokedFunction stub");
|
| +}
|
| +
|
| +
|
| +void StubCode::GenerateFixCallersTargetStub(Assembler* assembler) {
|
| + __ Unimplemented("FixCallersTarget stub");
|
| +}
|
| +
|
| +
|
| void StubCode::GenerateMegamorphicLookupStub(Assembler* assembler) {
|
| __ Unimplemented("MegamorphicLookup stub");
|
| }
|
|
|
|
|
| +void StubCode::GenerateDeoptimizeStub(Assembler* assembler) {
|
| + __ Unimplemented("Deoptimize stub");
|
| +}
|
| +
|
| +
|
| +void StubCode::GenerateAllocateArrayStub(Assembler* assembler) {
|
| + __ Unimplemented("AllocateArray stub");
|
| +}
|
| +
|
| +
|
| void StubCode::GenerateCallClosureFunctionStub(Assembler* assembler) {
|
| __ Unimplemented("CallClosureFunction stub");
|
| }
|
|
|
|
|
| +// Called when invoking Dart code from C++ (VM code).
|
| +// Input parameters:
|
| +// RSP : points to return address.
|
| +// RDI : entrypoint of the Dart function to call.
|
| +// RSI : arguments descriptor array.
|
| +// RDX : pointer to the argument array.
|
| +// RCX : new context containing the current isolate pointer.
|
| +void StubCode::GenerateInvokeDartCodeStub(Assembler* assembler) {
|
| + // Save frame pointer coming in.
|
| + __ EnterFrame(0);
|
| +
|
| + // Save arguments descriptor array and new context.
|
| + const intptr_t kArgumentsDescOffset = -1 * kWordSize;
|
| + __ pushq(RSI);
|
| + const intptr_t kNewContextOffset = -2 * kWordSize;
|
| + __ pushq(RCX);
|
| +
|
| + // Save C++ ABI callee-saved registers.
|
| + __ pushq(RBX);
|
| + __ pushq(R12);
|
| + __ pushq(R13);
|
| + __ pushq(R14);
|
| + __ pushq(R15);
|
| +
|
| + // The new Context structure contains a pointer to the current Isolate
|
| + // structure. Cache the Context pointer in the CTX register so that it is
|
| + // available in generated code and calls to Isolate::Current() need not be
|
| + // done. The assumption is that this register will never be clobbered by
|
| + // compiled or runtime stub code.
|
| +
|
| + // Cache the new Context pointer into CTX while executing Dart code.
|
| + __ movq(CTX, Address(RCX, VMHandles::kOffsetOfRawPtrInHandle));
|
| +
|
| + // Load Isolate pointer from Context structure into R8.
|
| + __ movq(R8, FieldAddress(CTX, Context::isolate_offset()));
|
| +
|
| + // Save the top exit frame info. Use RAX as a temporary register.
|
| + __ movq(RAX, Address(R8, Isolate::top_exit_frame_info_offset()));
|
| + __ pushq(RAX);
|
| + __ movq(Address(R8, Isolate::top_exit_frame_info_offset()), Immediate(0));
|
| +
|
| + // StackFrameIterator reads the top exit frame info saved in this frame.
|
| + // The constant kExitLinkOffsetInEntryFrame must be kept in sync with the
|
| + // code above: kExitLinkOffsetInEntryFrame = -8 * kWordSize.
|
| +
|
| + // Save the old Context pointer. Use RAX as a temporary register.
|
| + // Note that VisitObjectPointers will find this saved Context pointer during
|
| + // GC marking, since it traverses any information between SP and
|
| + // FP - kExitLinkOffsetInEntryFrame.
|
| + __ movq(RAX, Address(R8, Isolate::top_context_offset()));
|
| + __ pushq(RAX);
|
| +
|
| + // Load arguments descriptor array into R10, which is passed to Dart code.
|
| + __ movq(R10, Address(RSI, VMHandles::kOffsetOfRawPtrInHandle));
|
| +
|
| + // Load number of arguments into RBX.
|
| + __ movq(RBX, FieldAddress(R10, Array::data_offset()));
|
| + __ SmiUntag(RBX);
|
| +
|
| + // Set up arguments for the Dart call.
|
| + Label push_arguments;
|
| + Label done_push_arguments;
|
| + __ testq(RBX, RBX); // check if there are arguments.
|
| + __ 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.
|
| + __ movq(RCX, Address(RCX, VMHandles::kOffsetOfRawPtrInHandle));
|
| + __ pushq(RCX);
|
| + __ 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.
|
| +
|
| + // Read the saved new Context pointer.
|
| + __ movq(CTX, Address(RBP, kNewContextOffset));
|
| + __ movq(CTX, Address(CTX, VMHandles::kOffsetOfRawPtrInHandle));
|
| +
|
| + // Read the saved arguments descriptor array to obtain the number of passed
|
| + // arguments, which is the first element of the array, a Smi.
|
| + __ movq(RSI, Address(RBP, kArgumentsDescOffset));
|
| + __ movq(R10, Address(RSI, VMHandles::kOffsetOfRawPtrInHandle));
|
| + __ movq(RDX, FieldAddress(R10, Array::data_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()));
|
| +
|
| + // 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);
|
| +
|
| + // 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);
|
| +
|
| + // Restore C++ ABI callee-saved registers.
|
| + __ popq(R15);
|
| + __ popq(R14);
|
| + __ popq(R13);
|
| + __ popq(R12);
|
| + __ popq(RBX);
|
| +
|
| + // Restore the frame pointer.
|
| + __ LeaveFrame();
|
| +
|
| + __ ret();
|
| +}
|
| +
|
| +
|
| void StubCode::GenerateAllocateContextStub(Assembler* assembler) {
|
| __ Unimplemented("AllocateContext stub");
|
| }
|
| @@ -67,6 +339,26 @@
|
| __ Unimplemented("AllocateClosure stub");
|
| }
|
|
|
| +
|
| +void StubCode::GenerateCallNoSuchMethodFunctionStub(Assembler* assembler) {
|
| + __ Unimplemented("CallNoSuchMethodFunction stub");
|
| +}
|
| +
|
| +
|
| +void StubCode::GenerateInlineCacheStub(Assembler* assembler) {
|
| + __ Unimplemented("InlineCache stub");
|
| +}
|
| +
|
| +
|
| +void StubCode::GenerateBreakpointStaticStub(Assembler* assembler) {
|
| + __ Unimplemented("BreakpointStatic stub");
|
| +}
|
| +
|
| +
|
| +void StubCode::GenerateBreakpointDynamicStub(Assembler* assembler) {
|
| + __ Unimplemented("BreakpointDynamic stub");
|
| +}
|
| +
|
| } // namespace dart
|
|
|
| #endif // defined TARGET_ARCH_X64
|
|
|