Index: src/x64/full-codegen-x64.cc |
diff --git a/src/x64/full-codegen-x64.cc b/src/x64/full-codegen-x64.cc |
index 8fe07975c225d1cf34c47d629907afc3ccb49609..292f7e6e20954dac38f99952b839b68a3b4fdbd7 100644 |
--- a/src/x64/full-codegen-x64.cc |
+++ b/src/x64/full-codegen-x64.cc |
@@ -2912,20 +2912,40 @@ void FullCodeGenerator::EmitCall(Call* expr, CallICState::CallType call_type) { |
// Load the arguments. |
ZoneList<Expression*>* args = expr->arguments(); |
int arg_count = args->length(); |
+ if (expr->HasSpreadArguments()) { |
+ __ movp(rax, Immediate(arg_count)); |
+ } |
+ |
{ PreservePositionScope scope(masm()->positions_recorder()); |
for (int i = 0; i < arg_count; i++) { |
- VisitForStackValue(args->at(i)); |
+ Expression* e = args->at(i); |
+ if (e->IsSpreadOperation()) { |
+ DoSpreadArgument(e->AsSpreadOperation(), rax); |
+ } else { |
+ VisitForStackValue(args->at(i)); |
+ } |
} |
} |
// Record source position of the IC call. |
SetSourcePosition(expr->position()); |
- Handle<Code> ic = CodeFactory::CallIC(isolate(), arg_count, call_type).code(); |
- __ Move(rdx, SmiFromSlot(expr->CallFeedbackICSlot())); |
- __ movp(rdi, Operand(rsp, (arg_count + 1) * kPointerSize)); |
- // Don't assign a type feedback id to the IC, since type feedback is provided |
- // by the vector above. |
- CallIC(ic); |
+ if (expr->HasSpreadArguments()) { |
+ CallFunctionFlags flags = call_type == CallICState::METHOD ? |
+ CALL_AS_METHOD : NO_CALL_FUNCTION_FLAGS; |
+ CallFunctionStub stub(isolate(), arg_count, flags, true); |
+ __ movp(rdi, Operand(rsp, rax, times_pointer_size, kPointerSize)); |
+ __ CallStub(&stub); |
+ } else { |
+ Handle<Code> ic = |
+ CodeFactory::CallIC(isolate(), arg_count, call_type).code(); |
+ __ Move(rdx, SmiFromSlot(expr->CallFeedbackICSlot())); |
+ |
+ __ movp(rdi, Operand(rsp, (arg_count + 1) * kPointerSize)); |
+ |
+ // Don't assign a type feedback id to the IC, since type feedback is |
+ // provided by the vector above. |
+ CallIC(ic); |
+ } |
RecordJSReturnSite(expr); |
@@ -5109,6 +5129,47 @@ void FullCodeGenerator::EmitLiteralCompareNil(CompareOperation* expr, |
} |
+void FullCodeGenerator::DoSpreadArgument(SpreadOperation* expr, |
+ Register arg_count) { |
+ Comment cmnt(masm_, "[ SpreadArgument"); |
+ |
+ Label loop, not_done, done; |
+ |
+ __ decp(arg_count); |
+ __ pushq(arg_count); |
+ |
+ // var iterator = iterable[Symbol.iterator](); |
+ VisitForEffect(expr->assign_iterator()); |
+ |
+ // Loop entry. |
+ __ bind(&loop); |
+ |
+ // result = iterator.next() |
+ VisitForEffect(expr->next_result()); |
+ |
+ // if (result.done) break; |
+ VisitForControl(expr->result_done(), &done, ¬_done, ¬_done); |
+ __ bind(¬_done); |
+ |
+ // %rax = result.value |
+ VisitForAccumulatorValue(expr->result_value()); |
arv (Not doing code reviews)
2015/02/12 21:41:34
Why not VisitForStackValue?
caitp (gmail)
2015/02/12 21:58:54
right now, it's sort of like this:
before first v
|
+ __ pushq(Operand(rsp, 0)); |
+ __ incp(Operand(rsp, 0)); |
+ __ movp(Operand(rsp, 1 * kPointerSize), rax); |
+ |
+ // loop |
+ __ jmp(&loop); |
+ |
+ __ bind(&done); |
+ __ popq(arg_count); |
+} |
+ |
+ |
+void FullCodeGenerator::VisitSpreadOperation(SpreadOperation* expr) { |
+ UNREACHABLE(); |
+} |
+ |
+ |
void FullCodeGenerator::VisitThisFunction(ThisFunction* expr) { |
__ movp(rax, Operand(rbp, JavaScriptFrameConstants::kFunctionOffset)); |
context()->Plug(rax); |