| Index: src/x64/builtins-x64.cc
|
| diff --git a/src/x64/builtins-x64.cc b/src/x64/builtins-x64.cc
|
| index 3f1cd9fabae675b58358c985121b8da843530697..7ed3fb0c265165f169856b4013142434e5f0dd53 100644
|
| --- a/src/x64/builtins-x64.cc
|
| +++ b/src/x64/builtins-x64.cc
|
| @@ -27,10 +27,13 @@
|
|
|
| #include "v8.h"
|
| #include "codegen-inl.h"
|
| +#include "macro-assembler.h"
|
|
|
| namespace v8 {
|
| namespace internal {
|
|
|
| +#define __ ACCESS_MASM(masm)
|
| +
|
| void Builtins::Generate_Adaptor(MacroAssembler* masm,
|
| Builtins::CFunctionId id) {
|
| masm->int3(); // UNIMPLEMENTED.
|
| @@ -52,12 +55,125 @@ void Builtins::Generate_JSConstructCall(MacroAssembler* masm) {
|
| masm->int3(); // UNIMPLEMENTED.
|
| }
|
|
|
| -void Builtins::Generate_JSConstructEntryTrampoline(MacroAssembler* masm) {
|
| - masm->int3(); // UNIMPLEMENTED.
|
| +static void Generate_JSEntryTrampolineHelper(MacroAssembler* masm,
|
| + bool is_construct) {
|
| + // Expects five C++ function parameters.
|
| + // - Address entry (ignored)
|
| + // - JSFunction* function (
|
| + // - Object* receiver
|
| + // - int argc
|
| + // - Object*** argv
|
| + // (see Handle::Invoke in execution.cc).
|
| +
|
| + // Platform specific argument handling. After this, the stack contains
|
| + // an internal frame and the pushed function and receiver, and
|
| + // register rax and rbx holds the argument count and argument array,
|
| + // while rdi holds the function pointer and rsi the context.
|
| +#ifdef __MSVC__
|
| + // MSVC parameters in:
|
| + // rcx : entry (ignored)
|
| + // rdx : function
|
| + // r8 : receiver
|
| + // r9 : argc
|
| + // [rsp+0x20] : argv
|
| +
|
| + // Clear the context before we push it when entering the JS frame.
|
| + __ xor_(rsi, rsi);
|
| + // Enter an internal frame.
|
| + __ EnterInternalFrame();
|
| +
|
| + // Load the previous frame pointer to access C argument on stack
|
| + __ movq(kScratchRegister, Operand(rbp, 0));
|
| +
|
| + // Load the function context into rsi.
|
| + __ movq(rsi, FieldOperand(rdx, JSFunction::kContextOffset));
|
| +
|
| + // Push the function and the receiver onto the stack.
|
| + __ push(rdx);
|
| + __ push(r8);
|
| +
|
| + // Load the number of arguments and setup pointer to the arguments.
|
| + __ movq(rax, r9);
|
| + __ movq(rbx, Operand(kScratchRegister, EntryFrameConstants::kArgvOffset));
|
| + // Load the function pointer into rdi.
|
| + __ movq(rdi, rdx);
|
| +#else // !defined(__MSVC__)
|
| + // GCC parameters in:
|
| + // rdi : entry (ignored)
|
| + // rsi : function
|
| + // rdx : receiver
|
| + // rcx : argc
|
| + // r8 : argv
|
| +
|
| + __ movq(rdi, rsi);
|
| + // rdi : function
|
| +
|
| + // Clear the context before we push it when entering the JS frame.
|
| + __ xor_(rsi, rsi);
|
| + // Enter an internal frame.
|
| + __ EnterInternalFrame();
|
| +
|
| + // Push the function and receiver and setup the context.
|
| + __ push(rdi);
|
| + __ push(rdx);
|
| + __ movq(rsi, FieldOperand(rdi, JSFunction::kContextOffset));
|
| +
|
| + // Load the number of arguments and setup pointer to the arguments.
|
| + __ movq(rax, rcx);
|
| + __ movq(rbx, r8);
|
| +#endif // __MSVC__
|
| + // Current stack contents:
|
| + // [rsp + 2 * kPointerSize ... ]: Internal frame
|
| + // [rsp + kPointerSize] : function
|
| + // [rsp] : receiver
|
| + // Current register contents:
|
| + // rax : argc
|
| + // rbx : argv
|
| + // rsi : context
|
| + // rdi : function
|
| +
|
| + // Copy arguments to the stack in a loop.
|
| + // Register rbx points to array of pointers to handle locations.
|
| + // Push the values of these handles.
|
| + Label loop, entry;
|
| + __ xor_(rcx, rcx); // Set loop variable to 0.
|
| + __ jmp(&entry);
|
| + __ bind(&loop);
|
| + __ movq(kScratchRegister, Operand(rbx, rcx, kTimesPointerSize, 0));
|
| + __ push(Operand(kScratchRegister, 0)); // dereference handle
|
| + __ add(rcx, Immediate(1));
|
| + __ bind(&entry);
|
| + __ cmp(rcx, rax);
|
| + __ j(not_equal, &loop);
|
| +
|
| + // Invoke the code.
|
| + if (is_construct) {
|
| + // Expects rdi to hold function pointer.
|
| + __ movq(kScratchRegister,
|
| + Handle<Code>(Builtins::builtin(Builtins::JSConstructCall)),
|
| + RelocInfo::CODE_TARGET);
|
| + __ call(kScratchRegister);
|
| + } else {
|
| + ParameterCount actual(rax);
|
| + __ InvokeFunction(rdi, actual, CALL_FUNCTION);
|
| + }
|
| +
|
| + // Exit the JS frame. Notice that this also removes the empty
|
| + // context and the function left on the stack by the code
|
| + // invocation.
|
| + __ LeaveInternalFrame();
|
| + // TODO(X64): Is argument correct? Is there a receiver to remove?
|
| + __ ret(1 * kPointerSize); // remove receiver
|
| }
|
|
|
| +
|
| void Builtins::Generate_JSEntryTrampoline(MacroAssembler* masm) {
|
| - masm->int3(); // UNIMPLEMENTED.
|
| + Generate_JSEntryTrampolineHelper(masm, false);
|
| +}
|
| +
|
| +
|
| +void Builtins::Generate_JSConstructEntryTrampoline(MacroAssembler* masm) {
|
| + Generate_JSEntryTrampolineHelper(masm, true);
|
| }
|
|
|
| } } // namespace v8::internal
|
|
|