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

Unified Diff: src/x64/code-stubs-x64.cc

Issue 919703003: WIP: Implement ES6 Spread-calls (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Flag calls as spread calls in parser, error on spread intrinsics/construct calls Created 5 years, 10 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
Index: src/x64/code-stubs-x64.cc
diff --git a/src/x64/code-stubs-x64.cc b/src/x64/code-stubs-x64.cc
index e56fc4a5702f3662125b6b911d8bd61d88418c0c..5b8745f583ba60e4291180f98290a103df9bf783 100644
--- a/src/x64/code-stubs-x64.cc
+++ b/src/x64/code-stubs-x64.cc
@@ -1884,14 +1884,17 @@ static void EmitSlowCase(Isolate* isolate,
MacroAssembler* masm,
StackArgumentsAccessor* args,
int argc,
- Label* non_function) {
+ Label* non_function,
+ bool is_spread = false) {
// Check for function proxy.
__ CmpInstanceType(rcx, JS_FUNCTION_PROXY_TYPE);
__ j(not_equal, non_function);
__ PopReturnAddressTo(rcx);
__ Push(rdi); // put proxy as additional argument under return address
__ PushReturnAddressFrom(rcx);
- __ Set(rax, argc + 1);
+ if (!is_spread) {
+ __ Set(rax, argc + 1);
+ }
__ Set(rbx, 0);
__ GetBuiltinEntry(rdx, Builtins::CALL_FUNCTION_PROXY);
{
@@ -1904,7 +1907,9 @@ static void EmitSlowCase(Isolate* isolate,
// of the original receiver from the call site).
__ bind(non_function);
__ movp(args->GetReceiverOperand(), rdi);
- __ Set(rax, argc);
+ if (!is_spread) {
+ __ Set(rax, argc);
+ }
__ Set(rbx, 0);
__ GetBuiltinEntry(rdx, Builtins::CALL_NON_FUNCTION);
Handle<Code> adaptor =
@@ -1915,29 +1920,40 @@ static void EmitSlowCase(Isolate* isolate,
static void EmitWrapCase(MacroAssembler* masm,
StackArgumentsAccessor* args,
- Label* cont) {
+ Label* cont, bool is_spread = false) {
// Wrap the receiver and patch it back onto the stack.
{ FrameScope frame_scope(masm, StackFrame::INTERNAL);
+ // If is_spread is true, dynamic argument count is in $r8 temporarily
+ if (is_spread) __ Push(r8);
__ Push(rdi);
__ Push(rax);
__ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION);
__ Pop(rdi);
+ if (is_spread) __ Pop(r8);
+ }
+ if (is_spread) {
+ DCHECK(args->argument_count_reg().is(rax));
+ __ xchgp(rax, r8);
+ __ movp(args->GetReceiverOperand(), r8);
+ } else {
+ __ movp(args->GetReceiverOperand(), rax);
}
- __ movp(args->GetReceiverOperand(), rax);
__ jmp(cont);
}
static void CallFunctionNoFeedback(MacroAssembler* masm,
int argc, bool needs_checks,
- bool call_as_method) {
+ bool call_as_method,
+ bool is_spread = false) {
// rdi : the function to call
+ // rcx : the dynamic argument count (if is_spread is true)
// wrap_and_call can only be true if we are compiling a monomorphic method.
Isolate* isolate = masm->isolate();
Label slow, non_function, wrap, cont;
- StackArgumentsAccessor args(rsp, argc);
-
+ StackArgumentsAccessor args = is_spread ?
+ StackArgumentsAccessor(rsp, rax) : StackArgumentsAccessor(rsp, argc);
if (needs_checks) {
// Check that the function really is a JavaScript function.
__ JumpIfSmi(rdi, &non_function);
@@ -1948,14 +1964,19 @@ static void CallFunctionNoFeedback(MacroAssembler* masm,
}
// Fast-case: Just invoke the function.
- ParameterCount actual(argc);
+ ParameterCount actual = is_spread ?
+ ParameterCount(rax) : ParameterCount(argc);
if (call_as_method) {
+ // If is_spread is true, preserve dynamic argument count in r8
+ if (is_spread) __ xchgp(r8, rax);
+
if (needs_checks) {
EmitContinueIfStrictOrNative(masm, &cont);
}
- // Load the receiver from the stack.
+ // Load the receiver from the stack. If is_spread is true, args is now
+ // broken.
__ movp(rax, args.GetReceiverOperand());
if (needs_checks) {
@@ -1975,18 +1996,19 @@ static void CallFunctionNoFeedback(MacroAssembler* masm,
if (needs_checks) {
// Slow-case: Non-function called.
__ bind(&slow);
- EmitSlowCase(isolate, masm, &args, argc, &non_function);
+ EmitSlowCase(isolate, masm, &args, argc, &non_function, is_spread);
}
if (call_as_method) {
__ bind(&wrap);
- EmitWrapCase(masm, &args, &cont);
+ EmitWrapCase(masm, &args, &cont, is_spread);
}
}
void CallFunctionStub::Generate(MacroAssembler* masm) {
- CallFunctionNoFeedback(masm, argc(), NeedsChecks(), CallAsMethod());
+ CallFunctionNoFeedback(masm, argc(), NeedsChecks(), CallAsMethod(),
+ is_spread());
}
@@ -2113,6 +2135,7 @@ void CallIC_ArrayStub::Generate(MacroAssembler* masm) {
void CallICStub::Generate(MacroAssembler* masm) {
+ // rax - argument count (only if call is a spread call)
// rdi - function
// rdx - slot id
// rbx - vector
@@ -2125,8 +2148,10 @@ void CallICStub::Generate(MacroAssembler* masm) {
Label slow, non_function, wrap, cont;
Label have_js_function;
int argc = arg_count();
- StackArgumentsAccessor args(rsp, argc);
- ParameterCount actual(argc);
+ StackArgumentsAccessor args = is_spread() ?
+ StackArgumentsAccessor(rsp, rax) : StackArgumentsAccessor(rsp, argc);
+ ParameterCount actual = is_spread() ?
+ ParameterCount(rax) : ParameterCount(argc);
// The checks. First, does rdi match the recorded monomorphic target?
__ SmiToInteger32(rdx, rdx);

Powered by Google App Engine
This is Rietveld 408576698