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

Unified Diff: src/parsing/parser.cc

Issue 1772793002: Implement iterator finalization in array destructuring. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Created 4 years, 9 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
Index: src/parsing/parser.cc
diff --git a/src/parsing/parser.cc b/src/parsing/parser.cc
index 9216b8d959aa05517c58192781275c657bec1be4..6feaa9b1d2abdb62510a551e5e4960e8129755ae 100644
--- a/src/parsing/parser.cc
+++ b/src/parsing/parser.cc
@@ -6278,11 +6278,12 @@ Expression* ParserTraits::RewriteYieldStar(
return yield_star;
}
+
// Desugaring of (lhs) instanceof (rhs)
// ====================================
//
// We desugar instanceof into a load of property @@hasInstance on the rhs.
-// We end up with roughly the following code (O, C):
+// We end up with roughly the following code:
//
// do {
// let O = lhs;
@@ -6366,7 +6367,7 @@ Expression* ParserTraits::RewriteInstanceof(Expression* lhs, Expression* rhs,
// if (!IS_CALLABLE(C)) {
// throw MakeTypeError(kCalledNonCallableInstanceOf);
// }
- // result = %ordinary_has_instance(C, O);
+ // handler_result = %ordinary_has_instance(C, O);
// } else {
// handler_result = !!%_Call(handler_result, C, O);
// }
@@ -6437,6 +6438,7 @@ Expression* ParserTraits::RewriteInstanceof(Expression* lhs, Expression* rhs,
return instanceof;
}
+
Statement* ParserTraits::CheckCallable(Variable* var, Expression* error) {
auto factory = parser_->factory();
auto avfactory = parser_->ast_value_factory();
@@ -6458,6 +6460,7 @@ Statement* ParserTraits::CheckCallable(Variable* var, Expression* error) {
return validate_var;
}
+
void ParserTraits::BuildIteratorClose(ZoneList<Statement*>* statements,
Variable* iterator,
Maybe<Variable*> input,
@@ -6563,8 +6566,117 @@ void ParserTraits::BuildIteratorClose(ZoneList<Statement*>* statements,
}
-// Runtime encoding of different completion modes.
-enum ForOfLoopBodyCompletion { BODY_COMPLETED, BODY_ABORTED, BODY_THREW };
+void ParserTraits::FinalizeIteratorUse(
+ Variable* completion, Expression* condition, Variable* iter,
+ Block* iterator_use, Block* target) {
+ if (!FLAG_harmony_iterator_close) return;
+
+ //
+ // This function adds two statements to [target], corresponding to the
+ // following code:
adamk 2016/03/08 01:57:07 It's somewhat confusing that this code contains a
neis 2016/03/08 13:40:10 Done.
+ //
+ // completion = NORMAL;
+ // try {
+ // iterator_use
+ // } catch(e) {
+ // if (completion === ABRUPT) completion = THROW;
+ // throw e;
+ // } finally {
+ // if (condition) {
+ // #BuildIteratorCloseForCompletion(iter, completion)
+ // }
+ // }
+ //
+
+ const int nopos = RelocInfo::kNoPosition;
+ auto factory = parser_->factory();
adamk 2016/03/08 01:57:07 If you put this function in Parser instead of Pars
+ auto avfactory = parser_->ast_value_factory();
+ auto scope = parser_->scope_;
+ auto zone = parser_->zone();
+
+ // completion = NORMAL;
+ Statement* initialize_completion;
+ {
+ Expression* proxy = factory->NewVariableProxy(completion);
+ Expression* assignment = factory->NewAssignment(
+ Token::ASSIGN, proxy,
+ factory->NewSmiLiteral(Parser::NORMAL, nopos), nopos);
+ initialize_completion =
+ factory->NewExpressionStatement(assignment, nopos);
+ }
+
+ // if (completion === ABRUPT) completion = THROW;
+ Statement* set_completion_throw;
+ {
+ Expression* condition = factory->NewCompareOperation(
+ Token::EQ_STRICT, factory->NewVariableProxy(completion),
+ factory->NewSmiLiteral(Parser::ABRUPT, nopos), nopos);
+
+ Expression* proxy = factory->NewVariableProxy(completion);
+ Expression* assignment = factory->NewAssignment(
+ Token::ASSIGN, proxy, factory->NewSmiLiteral(Parser::THROW, nopos),
+ nopos);
+ Statement* statement = factory->NewExpressionStatement(assignment, nopos);
+ set_completion_throw = factory->NewIfStatement(
+ condition, statement, factory->NewEmptyStatement(nopos), nopos);
+ }
+
+ // if (condition) {
+ // #BuildIteratorCloseForCompletion(iter, completion)
+ // }
+ Block* maybe_close;
+ {
+ Block* block = factory->NewBlock(nullptr, 2, true, nopos);
+ parser_->BuildIteratorCloseForCompletion(
+ block->statements(), iter, completion);
+ DCHECK(block->statements()->length() == 2);
+
+ maybe_close = factory->NewBlock(nullptr, 1, true, nopos);
+ maybe_close->statements()->Add(factory->NewIfStatement(
+ condition, block, factory->NewEmptyStatement(nopos), nopos), zone);
+ }
+
+ // try { #try_block }
+ // catch(e) {
+ // #set_completion_throw;
+ // throw e;
+ // }
+ Statement* try_catch;
+ {
+ Scope* catch_scope = parser_->NewScope(scope, CATCH_SCOPE);
+ Variable* catch_variable = catch_scope->DeclareLocal(
+ avfactory->dot_catch_string(), VAR, kCreatedInitialized,
+ Variable::NORMAL);
+
+ Statement* rethrow;
+ {
+ Expression* proxy = factory->NewVariableProxy(catch_variable);
+ rethrow = factory->NewExpressionStatement(
+ factory->NewThrow(proxy, nopos), nopos);
+ }
+
+ Block* catch_block = factory->NewBlock(nullptr, 2, false, nopos);
+ catch_block->statements()->Add(set_completion_throw, zone);
+ catch_block->statements()->Add(rethrow, zone);
+
+ try_catch = factory->NewTryCatchStatement(
+ iterator_use, catch_scope, catch_variable, catch_block, nopos);
+ }
+
+ // try { #try_catch } finally { #maybe_close }
+ Statement* try_finally;
+ {
+ Block* try_block = factory->NewBlock(nullptr, 1, false, nopos);
+ try_block->statements()->Add(try_catch, zone);
+
+ try_finally =
+ factory->NewTryFinallyStatement(try_block, maybe_close, nopos);
+ }
+
+ target->statements()->Add(initialize_completion, zone);
+ target->statements()->Add(try_finally, zone);
+}
+
void ParserTraits::BuildIteratorCloseForCompletion(
ZoneList<Statement*>* statements, Variable* iterator,
@@ -6575,7 +6687,7 @@ void ParserTraits::BuildIteratorCloseForCompletion(
//
// let iteratorReturn = iterator.return;
// if (!IS_NULL_OR_UNDEFINED(iteratorReturn)) {
- // if (completion === BODY_THREW) {
+ // if (completion === THROW) {
// if (!IS_CALLABLE(iteratorReturn)) {
// throw MakeTypeError(kReturnMethodNotCallable);
// }
@@ -6693,7 +6805,7 @@ void ParserTraits::BuildIteratorCloseForCompletion(
validate_return->statements()->Add(check_return, zone);
}
- // if (completion === BODY_THREW) {
+ // if (completion === THROW) {
// #check_return_callable;
// #try_call_return;
// } else {
@@ -6703,7 +6815,7 @@ void ParserTraits::BuildIteratorCloseForCompletion(
{
Expression* condition = factory->NewCompareOperation(
Token::EQ_STRICT, factory->NewVariableProxy(completion),
- factory->NewSmiLiteral(BODY_THREW, nopos), nopos);
+ factory->NewSmiLiteral(Parser::THROW, nopos), nopos);
Block* then_block = factory->NewBlock(nullptr, 2, false, nopos);
then_block->statements()->Add(check_return_callable, zone);
@@ -6737,15 +6849,15 @@ Statement* ParserTraits::FinalizeForOfStatement(ForOfStatement* loop, int pos) {
//
// This function replaces the loop with the following wrapping:
//
- // let completion = BODY_COMPLETED;
// let each;
+ // let completion = NORMAL;
// try {
// #loop;
// } catch(e) {
- // if (completion === BODY_ABORTED) completion = BODY_THREW;
+ // if (completion === ABRUPT) completion = THROW;
// throw e;
// } finally {
- // if (!(completion === BODY_COMPLETED || IS_UNDEFINED(#iterator))) {
+ // if (!(completion === NORMAL || IS_UNDEFINED(#iterator))) {
// #BuildIteratorCloseForCompletion(#iterator, completion)
// }
// }
@@ -6754,15 +6866,16 @@ Statement* ParserTraits::FinalizeForOfStatement(ForOfStatement* loop, int pos) {
//
// {
// #loop-body
- // {{completion = BODY_COMPLETED;}}
+ // {{completion = NORMAL;}}
// }
//
- // and assign_each is wrapped as follows
+ // and the loop's assign_each is wrapped as follows
//
// do {
- // {{completion = BODY_ABORTED;}}
+ // {{completion = ABRUPT;}}
// #assign-each
- // } into each
+ // }
+ //
const int nopos = RelocInfo::kNoPosition;
auto factory = parser_->factory();
@@ -6770,17 +6883,7 @@ Statement* ParserTraits::FinalizeForOfStatement(ForOfStatement* loop, int pos) {
auto scope = parser_->scope_;
auto zone = parser_->zone();
- // let completion = BODY_COMPLETED;
Variable* var_completion = scope->NewTemporary(avfactory->empty_string());
- Statement* initialize_completion;
- {
- Expression* proxy = factory->NewVariableProxy(var_completion);
- Expression* assignment = factory->NewAssignment(
- Token::ASSIGN, proxy,
- factory->NewSmiLiteral(BODY_COMPLETED, nopos), nopos);
- initialize_completion =
- factory->NewExpressionStatement(assignment, nopos);
- }
// let each;
Variable* var_each = scope->NewTemporary(avfactory->empty_string());
@@ -6794,104 +6897,27 @@ Statement* ParserTraits::FinalizeForOfStatement(ForOfStatement* loop, int pos) {
factory->NewExpressionStatement(assignment, nopos);
}
- // if (completion === BODY_ABORTED) completion = BODY_THREW;
- Statement* set_completion_throw;
+ // !(completion === NORMAL || IS_UNDEFINED(#iterator))
+ Expression* condition;
adamk 2016/03/07 20:28:05 Can you give this a better name? Maybe "iterator_c
neis 2016/03/08 13:40:10 Done.
{
- Expression* condition = factory->NewCompareOperation(
+ Expression* lhs = factory->NewCompareOperation(
Token::EQ_STRICT, factory->NewVariableProxy(var_completion),
- factory->NewSmiLiteral(BODY_ABORTED, nopos), nopos);
-
- Expression* proxy = factory->NewVariableProxy(var_completion);
- Expression* assignment = factory->NewAssignment(
- Token::ASSIGN, proxy, factory->NewSmiLiteral(BODY_THREW, nopos),
- nopos);
- Statement* statement = factory->NewExpressionStatement(assignment, nopos);
- set_completion_throw = factory->NewIfStatement(
- condition, statement, factory->NewEmptyStatement(nopos), nopos);
- }
-
- // if (!(completion === BODY_COMPLETED || IS_UNDEFINED(#iterator))) {
- // #BuildIteratorCloseForCompletion(#iterator, completion)
- // }
- Block* maybe_close;
- {
- Expression* condition1 = factory->NewCompareOperation(
- Token::EQ_STRICT, factory->NewVariableProxy(var_completion),
- factory->NewSmiLiteral(BODY_COMPLETED, nopos), nopos);
- Expression* condition2 = factory->NewCompareOperation(
+ factory->NewSmiLiteral(Parser::NORMAL, nopos), nopos);
+ Expression* rhs = factory->NewCompareOperation(
Token::EQ_STRICT, factory->NewVariableProxy(loop->iterator()),
factory->NewUndefinedLiteral(nopos), nopos);
- Expression* condition = factory->NewBinaryOperation(
- Token::OR, condition1, condition2, nopos);
-
- Block* block = factory->NewBlock(nullptr, 2, false, nopos);
- BuildIteratorCloseForCompletion(
- block->statements(), loop->iterator(), var_completion);
- DCHECK(block->statements()->length() == 2);
-
- maybe_close = factory->NewBlock(nullptr, 1, false, nopos);
- maybe_close->statements()->Add(factory->NewIfStatement(
- condition, factory->NewEmptyStatement(nopos), block, nopos), zone);
- }
-
- // try { #try_block }
- // catch(e) {
- // #set_completion_throw;
- // throw e;
- // }
- Statement* try_catch;
- {
- Scope* catch_scope = NewScope(scope, CATCH_SCOPE);
- Variable* catch_variable = catch_scope->DeclareLocal(
- avfactory->dot_catch_string(), VAR, kCreatedInitialized,
- Variable::NORMAL);
-
- Statement* rethrow;
- {
- Expression* proxy = factory->NewVariableProxy(catch_variable);
- rethrow = factory->NewExpressionStatement(
- factory->NewThrow(proxy, nopos), nopos);
- }
-
- Block* try_block = factory->NewBlock(nullptr, 1, false, nopos);
- try_block->statements()->Add(loop, zone);
-
- Block* catch_block = factory->NewBlock(nullptr, 2, false, nopos);
- catch_block->statements()->Add(set_completion_throw, zone);
- catch_block->statements()->Add(rethrow, zone);
-
- try_catch = factory->NewTryCatchStatement(
- try_block, catch_scope, catch_variable, catch_block, nopos);
- }
-
- // try { #try_catch } finally { #maybe_close }
- Statement* try_finally;
- {
- Block* try_block = factory->NewBlock(nullptr, 1, false, nopos);
- try_block->statements()->Add(try_catch, zone);
-
- try_finally =
- factory->NewTryFinallyStatement(try_block, maybe_close, nopos);
- }
-
- // #initialize_completion;
- // #initialize_each;
- // #try_finally;
- Statement* final_loop;
- {
- Block* block = factory->NewBlock(nullptr, 2, false, nopos);
- block->statements()->Add(initialize_completion, zone);
- block->statements()->Add(initialize_each, zone);
- block->statements()->Add(try_finally, zone);
- final_loop = block;
+ condition = factory->NewUnaryOperation(
+ Token::NOT,
+ factory->NewBinaryOperation(Token::OR, lhs, rhs, nopos),
+ nopos);
}
- // {{completion = BODY_COMPLETED;}}
+ // {{completion = NORMAL;}}
Statement* set_completion_normal;
{
Expression* proxy = factory->NewVariableProxy(var_completion);
Expression* assignment = factory->NewAssignment(
- Token::ASSIGN, proxy, factory->NewSmiLiteral(BODY_COMPLETED, nopos),
+ Token::ASSIGN, proxy, factory->NewSmiLiteral(Parser::NORMAL, nopos),
nopos);
Block* block = factory->NewBlock(nullptr, 1, true, nopos);
@@ -6900,36 +6926,53 @@ Statement* ParserTraits::FinalizeForOfStatement(ForOfStatement* loop, int pos) {
set_completion_normal = block;
}
- // { #loop-body; #set_completion_normal }
- Block* new_body = factory->NewBlock(nullptr, 2, false, nopos);
- new_body->statements()->Add(loop->body(), zone);
- new_body->statements()->Add(set_completion_normal, zone);
-
- loop->set_body(new_body);
-
- // {{completion = BODY_ABORTED;}}
- Statement* set_completion_break;
+ // {{completion = ABRUPT;}}
+ Statement* set_completion_abrupt;
{
Expression* proxy = factory->NewVariableProxy(var_completion);
Expression* assignment = factory->NewAssignment(
- Token::ASSIGN, proxy, factory->NewSmiLiteral(BODY_ABORTED, nopos),
+ Token::ASSIGN, proxy, factory->NewSmiLiteral(Parser::ABRUPT, nopos),
nopos);
Block* block = factory->NewBlock(nullptr, 1, true, nopos);
block->statements()->Add(factory->NewExpressionStatement(assignment, nopos),
zone);
- set_completion_break = block;
+ set_completion_abrupt = block;
}
- // { #set_completion_break; #assign-each }
+ // { #loop-body; #set_completion_normal }
+ Block* new_body = factory->NewBlock(nullptr, 2, false, nopos);
+ {
+ new_body->statements()->Add(loop->body(), zone);
+ new_body->statements()->Add(set_completion_normal, zone);
+ }
+
+ // { #set_completion_abrupt; #assign-each }
Block* new_assign_each = factory->NewBlock(nullptr, 2, false, nopos);
- new_assign_each->statements()->Add(set_completion_break, zone);
- new_assign_each->statements()->Add(
- factory->NewExpressionStatement(loop->assign_each(), nopos), zone);
+ {
+ new_assign_each->statements()->Add(set_completion_abrupt, zone);
+ new_assign_each->statements()->Add(
+ factory->NewExpressionStatement(loop->assign_each(), nopos), zone);
+ }
- Expression* do_each =
- factory->NewDoExpression(new_assign_each, var_each, nopos);
- loop->set_assign_each(do_each);
+ // Now put things together.
+
+ loop->set_body(new_body);
+ loop->set_assign_each(
+ factory->NewDoExpression(new_assign_each, var_each, nopos));
+
+ Statement* final_loop;
+ {
+ Block* target = factory->NewBlock(nullptr, 3, false, nopos);
+ target->statements()->Add(initialize_each, zone);
+
+ Block* try_block = factory->NewBlock(nullptr, 1, false, nopos);
+ try_block->statements()->Add(loop, zone);
+
+ FinalizeIteratorUse(
+ var_completion, condition, loop->iterator(), try_block, target);
+ final_loop = target;
+ }
return final_loop;
}

Powered by Google App Engine
This is Rietveld 408576698