Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(948)

Unified Diff: src/x64/builtins-x64.cc

Issue 1359583002: [builtins] Add support for NewTarget to Execution::New. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: REBASE. Merge mips and mips64 ports. Created 5 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « src/runtime/runtime-classes.cc ('k') | src/x64/code-stubs-x64.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/x64/builtins-x64.cc
diff --git a/src/x64/builtins-x64.cc b/src/x64/builtins-x64.cc
index 91db4c61f962fd032506dd0e4f2a9f9563f60624..e8cc4381bf26bb958e3f55d2fd6d4eeaf8cb75f6 100644
--- a/src/x64/builtins-x64.cc
+++ b/src/x64/builtins-x64.cc
@@ -23,13 +23,20 @@ void Builtins::Generate_Adaptor(MacroAssembler* masm,
// -- rax : number of arguments excluding receiver
// -- rdi : called function (only guaranteed when
// extra_args requires it)
- // -- rsi : context
// -- rsp[0] : return address
// -- rsp[8] : last argument
// -- ...
// -- rsp[8 * argc] : first argument (argc == rax)
// -- rsp[8 * (argc + 1)] : receiver
// -----------------------------------
+ __ AssertFunction(rdi);
+
+ // Make sure we operate in the context of the called function (for example
+ // ConstructStubs implemented in C++ will be run in the context of the caller
+ // instead of the callee, due to the way that [[Construct]] is defined for
+ // ordinary functions).
+ // TODO(bmeurer): Can we make this more robust?
+ __ movp(rsi, FieldOperand(rdi, JSFunction::kContextOffset));
// Insert extra arguments.
int num_extra_args = 0;
@@ -441,7 +448,7 @@ void Builtins::Generate_JSConstructStubForDerived(MacroAssembler* masm) {
enum IsTagged { kRaxIsSmiTagged, kRaxIsUntaggedInt };
-// Clobbers rcx, rdx, kScratchRegister; preserves all other registers.
+// Clobbers rcx, r11, kScratchRegister; preserves all other registers.
static void Generate_CheckStackOverflow(MacroAssembler* masm,
const int calleeOffset,
IsTagged rax_is_tagged) {
@@ -456,17 +463,17 @@ static void Generate_CheckStackOverflow(MacroAssembler* masm,
// Make rcx the space we have left. The stack might already be overflowed
// here which will cause rcx to become negative.
__ subp(rcx, kScratchRegister);
- // Make rdx the space we need for the array when it is unrolled onto the
+ // Make r11 the space we need for the array when it is unrolled onto the
// stack.
if (rax_is_tagged == kRaxIsSmiTagged) {
- __ PositiveSmiTimesPowerOfTwoToInteger64(rdx, rax, kPointerSizeLog2);
+ __ PositiveSmiTimesPowerOfTwoToInteger64(r11, rax, kPointerSizeLog2);
} else {
DCHECK(rax_is_tagged == kRaxIsUntaggedInt);
- __ movp(rdx, rax);
- __ shlq(rdx, Immediate(kPointerSizeLog2));
+ __ movp(r11, rax);
+ __ shlq(r11, Immediate(kPointerSizeLog2));
}
// Check if the arguments will overflow the stack.
- __ cmpp(rcx, rdx);
+ __ cmpp(rcx, r11);
__ j(greater, &okay); // Signed comparison.
// Out of stack space.
@@ -486,8 +493,8 @@ static void Generate_JSEntryTrampolineHelper(MacroAssembler* masm,
ProfileEntryHookStub::MaybeCallEntryHook(masm);
// Expects five C++ function parameters.
- // - Address entry (ignored)
- // - JSFunction* function (
+ // - Object* new_target
+ // - JSFunction* function
// - Object* receiver
// - int argc
// - Object*** argv
@@ -498,11 +505,12 @@ static void Generate_JSEntryTrampolineHelper(MacroAssembler* masm,
// 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.
+ // while rdi holds the function pointer, rsi the context, and rdx the
+ // new.target.
#ifdef _WIN64
// MSVC parameters in:
- // rcx : entry (ignored)
+ // rcx : new_target
// rdx : function
// r8 : receiver
// r9 : argc
@@ -510,11 +518,14 @@ static void Generate_JSEntryTrampolineHelper(MacroAssembler* masm,
// Clear the context before we push it when entering the internal frame.
__ Set(rsi, 0);
+
// Enter an internal frame.
FrameScope scope(masm, StackFrame::INTERNAL);
- // Load the function context into rsi.
- __ movp(rsi, FieldOperand(rdx, JSFunction::kContextOffset));
+ // Setup the context (we need to use the caller context from the isolate).
+ ExternalReference context_address(Isolate::kContextAddress,
+ masm->isolate());
+ __ movp(rsi, masm->ExternalOperand(context_address));
// Push the function and the receiver onto the stack.
__ Push(rdx);
@@ -527,30 +538,42 @@ static void Generate_JSEntryTrampolineHelper(MacroAssembler* masm,
__ movp(rbx, Operand(kScratchRegister, EntryFrameConstants::kArgvOffset));
// Load the function pointer into rdi.
__ movp(rdi, rdx);
+ // Load the new.target into rdx.
+ __ movp(rdx, rcx);
#else // _WIN64
// GCC parameters in:
- // rdi : entry (ignored)
+ // rdi : new_target
// rsi : function
// rdx : receiver
// rcx : argc
// r8 : argv
+ __ movp(r11, rdi);
__ movp(rdi, rsi);
// rdi : function
+ // r11 : new_target
// Clear the context before we push it when entering the internal frame.
__ Set(rsi, 0);
+
// Enter an internal frame.
FrameScope scope(masm, StackFrame::INTERNAL);
- // Push the function and receiver and setup the context.
+ // Setup the context (we need to use the caller context from the isolate).
+ ExternalReference context_address(Isolate::kContextAddress,
+ masm->isolate());
+ __ movp(rsi, masm->ExternalOperand(context_address));
+
+ // Push the function and receiver onto the stack.
__ Push(rdi);
__ Push(rdx);
- __ movp(rsi, FieldOperand(rdi, JSFunction::kContextOffset));
// Load the number of arguments and setup pointer to the arguments.
__ movp(rax, rcx);
__ movp(rbx, r8);
+
+ // Load the new.target into rdx.
+ __ movp(rdx, r11);
#endif // _WIN64
// Current stack contents:
@@ -562,13 +585,14 @@ static void Generate_JSEntryTrampolineHelper(MacroAssembler* masm,
// rbx : argv
// rsi : context
// rdi : function
+ // rdx : new.target
// Check if we have enough stack space to push all arguments.
// The function is the first thing that was pushed above after entering
// the internal frame.
const int kFunctionOffset =
InternalFrameConstants::kCodeOffset - kRegisterSize;
- // Expects argument count in rax. Clobbers rcx, rdx.
+ // Expects argument count in rax. Clobbers rcx, r11.
Generate_CheckStackOverflow(masm, kFunctionOffset, kRaxIsUntaggedInt);
// Copy arguments to the stack in a loop.
@@ -576,7 +600,7 @@ static void Generate_JSEntryTrampolineHelper(MacroAssembler* masm,
// Push the values of these handles.
Label loop, entry;
__ Set(rcx, 0); // Set loop variable to 0.
- __ jmp(&entry);
+ __ jmp(&entry, Label::kNear);
__ bind(&loop);
__ movp(kScratchRegister, Operand(rbx, rcx, times_pointer_size, 0));
__ Push(Operand(kScratchRegister, 0)); // dereference handle
@@ -585,16 +609,12 @@ static void Generate_JSEntryTrampolineHelper(MacroAssembler* masm,
__ cmpp(rcx, rax);
__ j(not_equal, &loop);
- // Invoke the code.
- if (is_construct) {
- // No type feedback cell is available
- __ LoadRoot(rbx, Heap::kUndefinedValueRootIndex);
- // Expects rdi to hold function pointer.
- CallConstructStub stub(masm->isolate(), NO_CALL_CONSTRUCTOR_FLAGS);
- __ CallStub(&stub);
- } else {
- __ Call(masm->isolate()->builtins()->Call(), RelocInfo::CODE_TARGET);
- }
+ // Invoke the builtin code.
+ Handle<Code> builtin = is_construct
+ ? masm->isolate()->builtins()->Construct()
+ : masm->isolate()->builtins()->Call();
+ __ Call(builtin, RelocInfo::CODE_TARGET);
+
// Exit the internal frame. Notice that this also removes the empty
// context and the function left on the stack by the code
// invocation.
@@ -1695,7 +1715,7 @@ void Builtins::Generate_CallFunction(MacroAssembler* masm) {
void Builtins::Generate_Call(MacroAssembler* masm) {
// ----------- S t a t e -------------
// -- rax : the number of arguments (not including the receiver)
- // -- rdi : the target to call (can be any Object).
+ // -- rdi : the target to call (can be any Object)
// -----------------------------------
Label non_smi, non_function;
@@ -1743,6 +1763,68 @@ void Builtins::Generate_Call(MacroAssembler* masm) {
// static
+void Builtins::Generate_ConstructFunction(MacroAssembler* masm) {
+ // ----------- S t a t e -------------
+ // -- rax : the number of arguments (not including the receiver)
+ // -- rdx : the original constructor (checked to be a JSFunction)
+ // -- rdi : the constructor to call (checked to be a JSFunction)
+ // -----------------------------------
+ __ AssertFunction(rdx);
+ __ AssertFunction(rdi);
+
+ // Calling convention for function specific ConstructStubs require
+ // rbx to contain either an AllocationSite or undefined.
+ __ LoadRoot(rbx, Heap::kUndefinedValueRootIndex);
+
+ // Tail call to the function-specific construct stub (still in the caller
+ // context at this point).
+ __ movp(rcx, FieldOperand(rdi, JSFunction::kSharedFunctionInfoOffset));
+ __ movp(rcx, FieldOperand(rcx, SharedFunctionInfo::kConstructStubOffset));
+ __ leap(rcx, FieldOperand(rcx, Code::kHeaderSize));
+ __ jmp(rcx);
+}
+
+
+// static
+void Builtins::Generate_Construct(MacroAssembler* masm) {
+ // ----------- S t a t e -------------
+ // -- rax : the number of arguments (not including the receiver)
+ // -- rdx : the original constructor (either the same as the constructor or
+ // the JSFunction on which new was invoked initially)
+ // -- rdi : the constructor to call (can be any Object)
+ // -----------------------------------
+
+ Label slow;
+ __ JumpIfSmi(rdi, &slow, Label::kNear);
+ __ CmpObjectType(rdi, JS_FUNCTION_TYPE, rcx);
+ __ j(equal, masm->isolate()->builtins()->ConstructFunction(),
+ RelocInfo::CODE_TARGET);
+ __ CmpInstanceType(rcx, JS_FUNCTION_PROXY_TYPE);
+ __ j(not_equal, &slow, Label::kNear);
+
+ // TODO(neis): This doesn't match the ES6 spec for [[Construct]] on proxies.
+ __ movp(rdi, FieldOperand(rdi, JSFunctionProxy::kConstructTrapOffset));
+ __ Jump(masm->isolate()->builtins()->Call(), RelocInfo::CODE_TARGET);
+
+ __ bind(&slow);
+ {
+ // Determine the delegate for the target (if any).
+ FrameScope scope(masm, StackFrame::INTERNAL);
+ __ Integer32ToSmi(rax, rax);
+ __ Push(rax);
+ __ Push(rdi);
+ __ CallRuntime(Runtime::kGetConstructorDelegate, 1);
+ __ movp(rdi, rax);
+ __ Pop(rax);
+ __ SmiToInteger32(rax, rax);
+ }
+ // The delegate is always a regular function.
+ __ AssertFunction(rdi);
+ __ Jump(masm->isolate()->builtins()->CallFunction(), RelocInfo::CODE_TARGET);
+}
+
+
+// static
void Builtins::Generate_PushArgsAndCall(MacroAssembler* masm) {
// ----------- S t a t e -------------
// -- rax : the number of arguments (not including the receiver)
« no previous file with comments | « src/runtime/runtime-classes.cc ('k') | src/x64/code-stubs-x64.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698