| Index: src/x64/full-codegen-x64.cc
|
| diff --git a/src/x64/full-codegen-x64.cc b/src/x64/full-codegen-x64.cc
|
| index 9c7a41f44906a2e4c326d9b52d40f9fbc496899d..2f57778435ddb643a137e5440210829217f77bae 100644
|
| --- a/src/x64/full-codegen-x64.cc
|
| +++ b/src/x64/full-codegen-x64.cc
|
| @@ -312,6 +312,7 @@ void FullCodeGenerator::Generate() {
|
|
|
| } else {
|
| PrepareForBailoutForId(BailoutId::FunctionEntry(), NO_REGISTERS);
|
| +
|
| { Comment cmnt(masm_, "[ Declarations");
|
| // For named function expressions, declare the function name as a
|
| // constant.
|
| @@ -334,6 +335,11 @@ void FullCodeGenerator::Generate() {
|
| __ bind(&ok);
|
| }
|
|
|
| + if (info->function()->default_values()->length()) {
|
| + Comment cmnt(masm_, "[ Optional parameters");
|
| + EmitInitializeOptionalParameters(info->scope(), info->function());
|
| + }
|
| +
|
| { Comment cmnt(masm_, "[ Body");
|
| DCHECK(loop_depth() == 0);
|
| VisitStatements(function()->body());
|
| @@ -4624,6 +4630,57 @@ void FullCodeGenerator::EmitCallJSRuntimeFunction(CallRuntime* expr) {
|
| }
|
|
|
|
|
| +void FullCodeGenerator::EmitInitializeOptionalParameters(Scope* scope,
|
| + FunctionLiteral* fn) {
|
| + ZoneList<Expression*>* defaults = fn->default_values();
|
| + if (defaults->is_empty()) return;
|
| +
|
| + int num_parameters = scope->num_parameters();
|
| + int heap_slots = scope->num_heap_slots() - Context::MIN_CONTEXT_SLOTS;
|
| +
|
| + int current_default = 0;
|
| +
|
| + for (int i = 0; i < num_parameters; ++i) {
|
| + Variable* param = scope->parameter(i);
|
| +
|
| + if (param->isRestParameter()) break;
|
| +
|
| + if (param->isOptionalParameter()) {
|
| + Expression* default_value = defaults->at(current_default++);
|
| +
|
| + // If the default value is undefined, there is no point initializing it.
|
| + if (default_value->IsUndefinedLiteral(isolate())) continue;
|
| +
|
| + int parameter_offset = StandardFrameConstants::kCallerSPOffset +
|
| + (num_parameters - 1 - i) * kPointerSize;
|
| +
|
| + Label next;
|
| +
|
| + __ movp(rax, Operand(rbp, parameter_offset));
|
| +
|
| + __ CompareRoot(rax, Heap::kUndefinedValueRootIndex);
|
| + __ j(not_equal, &next);
|
| +
|
| + VisitForAccumulatorValue(default_value);
|
| +
|
| + if (param->IsContextSlot() && heap_slots > 0) {
|
| + bool write_barrier = heap_slots > FastNewContextStub::kMaximumSlots;
|
| + int context_offset = Context::SlotOffset(param->index());
|
| + __ movp(Operand(rsi, context_offset), rax);
|
| + if (write_barrier) {
|
| + __ RecordWriteContextSlot(rsi, context_offset, rax, rbx,
|
| + kDontSaveFPRegs);
|
| + }
|
| + } else if (!param->IsUnallocated()) {
|
| + SetVar(param, rax, rbx, rdx);
|
| + }
|
| +
|
| + __ bind(&next);
|
| + }
|
| + }
|
| +}
|
| +
|
| +
|
| void FullCodeGenerator::VisitCallRuntime(CallRuntime* expr) {
|
| ZoneList<Expression*>* args = expr->arguments();
|
| int arg_count = args->length();
|
|
|