Chromium Code Reviews| 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); |