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

Unified Diff: src/parser.cc

Issue 1235153006: [es6] re-implement rest parameters via desugaring (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Refactor Scope::TempScope Created 5 years, 5 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
« no previous file with comments | « src/parser.h ('k') | src/pattern-rewriter.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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(),
« no previous file with comments | « src/parser.h ('k') | src/pattern-rewriter.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698