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 |