Index: src/parser.cc |
diff --git a/src/parser.cc b/src/parser.cc |
index c1ae28577974f5e91f9aa87864bdcd7b6886e46c..7acb3cde58d697d7480895c3b9606150d81cc581 100644 |
--- a/src/parser.cc |
+++ b/src/parser.cc |
@@ -2828,7 +2828,7 @@ Statement* Parser::ParseReturnStatement(bool* ok) { |
// |
// return (temp = expr) === undefined ? this : |
// %_IsSpecObject(temp) ? temp : throw new TypeError(...); |
- Variable* temp = scope_->DeclarationScope()->NewTemporary( |
+ Variable* temp = scope_->TempScope()->NewTemporary( |
ast_value_factory()->empty_string()); |
Assignment* assign = factory()->NewAssignment( |
Token::ASSIGN, factory()->NewVariableProxy(temp), return_value, pos); |
@@ -3182,9 +3182,9 @@ void Parser::InitializeForEachStatement(ForEachStatement* stmt, |
ForOfStatement* for_of = stmt->AsForOfStatement(); |
if (for_of != NULL) { |
- Variable* iterator = scope_->DeclarationScope()->NewTemporary( |
+ Variable* iterator = scope_->TempScope()->NewTemporary( |
ast_value_factory()->dot_iterator_string()); |
- Variable* result = scope_->DeclarationScope()->NewTemporary( |
+ Variable* result = scope_->TempScope()->NewTemporary( |
ast_value_factory()->dot_result_string()); |
Expression* assign_iterator; |
@@ -3300,7 +3300,7 @@ Statement* Parser::DesugarLexicalBindingsInForStatement( |
// make statement: temp_x = x. |
for (int i = 0; i < names->length(); i++) { |
VariableProxy* proxy = NewUnresolved(names->at(i), LET); |
- Variable* temp = scope_->DeclarationScope()->NewTemporary(temp_name); |
+ Variable* temp = scope_->TempScope()->NewTemporary(temp_name); |
VariableProxy* temp_proxy = factory()->NewVariableProxy(temp); |
Assignment* assignment = factory()->NewAssignment( |
Token::ASSIGN, temp_proxy, proxy, RelocInfo::kNoPosition); |
@@ -3313,7 +3313,7 @@ Statement* Parser::DesugarLexicalBindingsInForStatement( |
Variable* first = NULL; |
// Make statement: first = 1. |
if (next) { |
- first = scope_->DeclarationScope()->NewTemporary(temp_name); |
+ first = scope_->TempScope()->NewTemporary(temp_name); |
VariableProxy* first_proxy = factory()->NewVariableProxy(first); |
Expression* const1 = factory()->NewSmiLiteral(1, RelocInfo::kNoPosition); |
Assignment* assignment = factory()->NewAssignment( |
@@ -3393,7 +3393,7 @@ Statement* Parser::DesugarLexicalBindingsInForStatement( |
ignore_completion_block->AddStatement(clear_first_or_next, zone()); |
} |
- Variable* flag = scope_->DeclarationScope()->NewTemporary(temp_name); |
+ Variable* flag = scope_->TempScope()->NewTemporary(temp_name); |
// Make statement: flag = 1. |
{ |
VariableProxy* flag_proxy = factory()->NewVariableProxy(flag); |
@@ -3579,7 +3579,7 @@ Statement* Parser::ParseForStatement(ZoneList<const AstRawString*>* labels, |
// let x; // for TDZ |
// } |
- Variable* temp = scope_->DeclarationScope()->NewTemporary( |
+ Variable* temp = scope_->TempScope()->NewTemporary( |
ast_value_factory()->dot_for_string()); |
ForEachStatement* loop = |
factory()->NewForEachStatement(mode, labels, stmt_pos); |
@@ -4012,7 +4012,7 @@ FunctionLiteral* Parser::ParseFunctionLiteral( |
// Calling a generator returns a generator object. That object is stored |
// in a temporary variable, a definition that is used by "yield" |
// expressions. This also marks the FunctionState as a generator. |
- Variable* temp = scope_->DeclarationScope()->NewTemporary( |
+ Variable* temp = scope_->TempScope()->NewTemporary( |
ast_value_factory()->dot_generator_object_string()); |
function_state.set_generator_object_variable(temp); |
} |
@@ -4173,11 +4173,6 @@ FunctionLiteral* Parser::ParseFunctionLiteral( |
if (should_be_used_once_hint) |
function_literal->set_should_be_used_once_hint(); |
- if (scope->has_rest_parameter()) { |
- // TODO(caitp): enable optimization of functions with rest params |
- function_literal->set_dont_optimize_reason(kRestParameter); |
- } |
- |
if (fni_ != NULL && should_infer_name) fni_->AddFunction(function_literal); |
return function_literal; |
} |
@@ -4309,6 +4304,7 @@ Statement* Parser::BuildAssertIsCoercible(Variable* var) { |
bool Parser::IsSimpleParameterList( |
const ParserFormalParameterParsingState& formal_parameters) { |
+ if (formal_parameters.has_rest) return false; |
for (auto parameter : formal_parameters.params) { |
if (parameter.pattern != nullptr) return false; |
} |
@@ -4341,6 +4337,99 @@ Block* Parser::BuildParameterInitializationBlock( |
PatternRewriter::DeclareAndInitializeVariables(init_block, &descriptor, |
&decl, nullptr, CHECK_OK); |
} |
+ if (formal_parameters.has_rest) { |
+ auto rest_parameter = formal_parameters.params.last(); |
+ int rest_index = formal_parameters.params.length() - 1; |
+ DCHECK_NULL(rest_parameter.pattern); |
+ |
+ // DESUGAR: |
+ // let <rest_params> = []; |
+ // for (int i = <rest_index>; i < <arguments.length>; ++i) { |
+ // %AddElement(<rest_params>, <rest_params.length>, arguments[i++]); |
+ // } |
+ VariableProxy* proxy = factory()->NewVariableProxy(rest_parameter.var); |
+ Declaration* declaration = factory()->NewVariableDeclaration( |
+ proxy, VAR, scope_, RelocInfo::kNoPosition); |
+ Variable* var = this->Declare(declaration, DeclarationDescriptor::PARAMETER, |
+ false, CHECK_OK); |
+ proxy = factory()->NewVariableProxy(var); |
+ |
+ // TODO(@caitp): use an array literal to avoid escaping the object and |
+ // needing 2 runtime functions which do the same thing. |
+ auto empty_values = new (zone()) ZoneList<Expression*>(0, zone()); |
+ Expression* empty_array = factory()->NewCallRuntime( |
+ is_strong(language_mode()) |
+ ? ast_value_factory()->strong_empty_array_string() |
+ : ast_value_factory()->empty_array_string(), |
+ nullptr, empty_values, RelocInfo::kNoPosition); |
+ |
+ Assignment* init_array = factory()->NewAssignment( |
+ Token::INIT_VAR, proxy, empty_array, RelocInfo::kNoPosition); |
+ |
+ auto loop = factory()->NewForStatement(NULL, RelocInfo::kNoPosition); |
+ |
+ // argument_index = rest_index |
+ Variable* argument_index = |
+ scope_->NewTemporary(ast_value_factory()->dot_string()); |
+ auto init = factory()->NewExpressionStatement( |
+ factory()->NewAssignment( |
+ Token::INIT_VAR, factory()->NewVariableProxy(argument_index), |
+ factory()->NewSmiLiteral(rest_index, RelocInfo::kNoPosition), |
+ RelocInfo::kNoPosition), |
+ RelocInfo::kNoPosition); |
+ |
+ auto arguments_length = Runtime::FunctionForId(Runtime::kArgumentsLength); |
+ auto empty_arguments = new (zone()) ZoneList<Expression*>(0, zone()); |
+ |
+ // argument_index < %_ArgumentsLength() |
+ auto cond = factory()->NewCompareOperation( |
+ Token::LT, factory()->NewVariableProxy(argument_index), |
+ factory()->NewCallRuntime(ast_value_factory()->empty_string(), |
+ arguments_length, empty_arguments, |
+ RelocInfo::kNoPosition), |
+ RelocInfo::kNoPosition); |
+ |
+ // ++argument_index |
+ auto next = factory()->NewExpressionStatement( |
+ factory()->NewCountOperation( |
+ Token::INC, true, factory()->NewVariableProxy(argument_index), |
+ RelocInfo::kNoPosition), |
+ RelocInfo::kNoPosition); |
+ |
+ auto arguments = Runtime::FunctionForId(Runtime::kArguments); |
+ // %_Arguments(<argument_index>) |
+ auto arguments_args = new (zone()) ZoneList<Expression*>(1, zone()); |
+ arguments_args->Add(factory()->NewVariableProxy(argument_index), zone()); |
+ |
+ // %AddElement( |
+ // <restParam>, <restParam.length>, %_Arguments(<argument_index>)); |
+ auto add_element = Runtime::FunctionForId(Runtime::kAddElement); |
+ auto add_element_args = new (zone()) ZoneList<Expression*>(3, zone()); |
+ add_element_args->Add(factory()->NewVariableProxy(var), zone()); |
+ add_element_args->Add( |
+ factory()->NewProperty( |
+ factory()->NewVariableProxy(var), |
+ factory()->NewStringLiteral(ast_value_factory()->length_string(), |
+ RelocInfo::kNoPosition), |
+ RelocInfo::kNoPosition), |
+ zone()); |
+ add_element_args->Add(factory()->NewCallRuntime( |
+ ast_value_factory()->empty_string(), arguments, |
+ arguments_args, RelocInfo::kNoPosition), |
+ zone()); |
+ |
+ auto body = factory()->NewExpressionStatement( |
+ factory()->NewCallRuntime(ast_value_factory()->empty_string(), |
+ add_element, add_element_args, |
+ RelocInfo::kNoPosition), |
+ RelocInfo::kNoPosition); |
+ |
+ loop->Initialize(init, cond, next, body); |
+ init_block->AddStatement( |
+ factory()->NewExpressionStatement(init_array, RelocInfo::kNoPosition), |
+ zone()); |
+ init_block->AddStatement(loop, zone()); |
+ } |
return init_block; |
} |
@@ -5964,8 +6053,8 @@ Expression* Parser::SpreadCall(Expression* function, |
args->InsertAt(0, function, zone()); |
args->InsertAt(1, home, zone()); |
} else { |
- Variable* temp = |
- scope_->NewTemporary(ast_value_factory()->empty_string()); |
+ Variable* temp = scope_->TempScope()->NewTemporary( |
+ ast_value_factory()->empty_string()); |
VariableProxy* obj = factory()->NewVariableProxy(temp); |
Assignment* assign_obj = factory()->NewAssignment( |
Token::ASSIGN, obj, function->AsProperty()->obj(), |