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

Unified Diff: src/parsing/pattern-rewriter.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/pattern-rewriter.cc
diff --git a/src/parsing/pattern-rewriter.cc b/src/parsing/pattern-rewriter.cc
index 2a194ee14b32d9145bddd82f26285ab86ad81241..0afa757b83bd8e014ad4c6d7efdcac79f51994de 100644
--- a/src/parsing/pattern-rewriter.cc
+++ b/src/parsing/pattern-rewriter.cc
@@ -407,16 +407,27 @@ void Parser::PatternRewriter::VisitObjectLiteral(ObjectLiteral* node) {
void Parser::PatternRewriter::VisitArrayLiteral(ArrayLiteral* node,
Variable** temp_var) {
- auto temp = *temp_var = CreateTempVar(current_value_);
-
- block_->statements()->Add(parser_->BuildAssertIsCoercible(temp), zone());
+ // TODO(neis): DCHECK(block_->ignore_completion_value());
+ auto temp = *temp_var = CreateTempVar(current_value_);
auto iterator = CreateTempVar(parser_->GetIterator(
factory()->NewVariableProxy(temp), factory(), RelocInfo::kNoPosition));
auto done = CreateTempVar(
factory()->NewBooleanLiteral(false, RelocInfo::kNoPosition));
auto result = CreateTempVar();
auto v = CreateTempVar();
+ auto completion = CreateTempVar();
+ auto nopos = RelocInfo::kNoPosition;
+
+ // For the purpose of iterator finalization, we temporarily set block_ to a
+ // new block. In the main body of this function, we write to block_ (both
+ // explicitly and implicitly via recursion). At the end of the function, we
+ // wrap this new block in a try-finally statement, restore block_ to its
+ // original value, and add the try-finally statement to block_.
+ auto target = block_;
+ if (FLAG_harmony_iterator_close) {
+ block_ = factory()->NewBlock(nullptr, 8, true, nopos);
+ }
Spread* spread = nullptr;
for (Expression* value : *node->values()) {
@@ -426,86 +437,193 @@ void Parser::PatternRewriter::VisitArrayLiteral(ArrayLiteral* node,
}
PatternContext context = SetInitializerContextIfNeeded(value);
+
// if (!done) {
// result = IteratorNext(iterator);
// v = (done = result.done) ? undefined : result.value;
// }
- auto next_block =
- factory()->NewBlock(nullptr, 2, true, RelocInfo::kNoPosition);
- next_block->statements()->Add(factory()->NewExpressionStatement(
- parser_->BuildIteratorNextResult(
- factory()->NewVariableProxy(iterator),
- result, RelocInfo::kNoPosition),
- RelocInfo::kNoPosition),
- zone());
-
- auto assign_to_done = factory()->NewAssignment(
- Token::ASSIGN, factory()->NewVariableProxy(done),
- factory()->NewProperty(
- factory()->NewVariableProxy(result),
- factory()->NewStringLiteral(ast_value_factory()->done_string(),
- RelocInfo::kNoPosition),
- RelocInfo::kNoPosition),
- RelocInfo::kNoPosition);
- auto next_value = factory()->NewConditional(
- assign_to_done, factory()->NewUndefinedLiteral(RelocInfo::kNoPosition),
- factory()->NewProperty(
- factory()->NewVariableProxy(result),
- factory()->NewStringLiteral(ast_value_factory()->value_string(),
- RelocInfo::kNoPosition),
- RelocInfo::kNoPosition),
- RelocInfo::kNoPosition);
- next_block->statements()->Add(
- factory()->NewExpressionStatement(
- factory()->NewAssignment(Token::ASSIGN,
- factory()->NewVariableProxy(v), next_value,
- RelocInfo::kNoPosition),
- RelocInfo::kNoPosition),
- zone());
+ Statement* if_statement;
+ {
+ auto next_block =
+ factory()->NewBlock(nullptr, 2, true, nopos);
adamk 2016/03/07 20:28:05 Can you leave stylistic changes out of this patch?
neis 2016/03/08 13:40:10 Ok, I removed them.
+ next_block->statements()->Add(
+ factory()->NewExpressionStatement(
+ parser_->BuildIteratorNextResult(
+ factory()->NewVariableProxy(iterator), result, nopos),
+ nopos),
+ zone());
- auto if_statement = factory()->NewIfStatement(
- factory()->NewUnaryOperation(Token::NOT,
- factory()->NewVariableProxy(done),
- RelocInfo::kNoPosition),
- next_block, factory()->NewEmptyStatement(RelocInfo::kNoPosition),
- RelocInfo::kNoPosition);
+ auto assign_to_done = factory()->NewAssignment(
+ Token::ASSIGN, factory()->NewVariableProxy(done),
+ factory()->NewProperty(
+ factory()->NewVariableProxy(result),
+ factory()->NewStringLiteral(ast_value_factory()->done_string(),
+ nopos),
+ nopos),
+ nopos);
+ auto next_value = factory()->NewConditional(
+ assign_to_done, factory()->NewUndefinedLiteral(nopos),
+ factory()->NewProperty(
+ factory()->NewVariableProxy(result),
+ factory()->NewStringLiteral(ast_value_factory()->value_string(),
+ nopos),
+ nopos),
+ nopos);
+ next_block->statements()->Add(
+ factory()->NewExpressionStatement(
+ factory()->NewAssignment(
+ Token::ASSIGN, factory()->NewVariableProxy(v), next_value,
+ nopos),
+ nopos),
+ zone());
+
+ if_statement = factory()->NewIfStatement(
+ factory()->NewUnaryOperation(Token::NOT,
+ factory()->NewVariableProxy(done),
+ nopos),
+ next_block, factory()->NewEmptyStatement(nopos),
+ nopos);
+ }
block_->statements()->Add(if_statement, zone());
if (!(value->IsLiteral() && value->AsLiteral()->raw_value()->IsTheHole())) {
+ if (FLAG_harmony_iterator_close) {
+ // completion = ABRUPT;
+ Expression* proxy = factory()->NewVariableProxy(completion);
+ Expression* assignment = factory()->NewAssignment(
+ Token::ASSIGN, proxy,
+ factory()->NewSmiLiteral(ABRUPT, nopos),
+ nopos);
+ block_->statements()->Add(
+ factory()->NewExpressionStatement(assignment, nopos), zone());
+ }
+
RecurseIntoSubpattern(value, factory()->NewVariableProxy(v));
+
+ if (FLAG_harmony_iterator_close) {
+ // completion = NORMAL;
+ Expression* proxy = factory()->NewVariableProxy(completion);
+ Expression* assignment = factory()->NewAssignment(
+ Token::ASSIGN, proxy, factory()->NewSmiLiteral(NORMAL, nopos),
+ nopos);
+ block_->statements()->Add(
+ factory()->NewExpressionStatement(assignment, nopos), zone());
+ }
}
set_context(context);
}
if (spread != nullptr) {
- // array = [];
- // if (!done) %concat_iterable_to_array(array, iterator);
+ // A spread can only occur as the last component. It is not handled by
+ // RecurseIntoSubpattern above.
+ //
+ // let array = [];
+ // while (!done) {
adamk 2016/03/07 20:28:05 This change is already giant (and thus tricky to r
neis 2016/03/08 13:40:10 Except that 'done' must be set to true at the end.
+ // result = IteratorNext(iterator);
+ // if (!(done = result.done)) %AppendElement(array, result.value);
+ // }
+ // <.completion = ABRUPT>
adamk 2016/03/07 20:28:05 This doesn't seem right to me. The recursion is ov
neis 2016/03/08 13:40:10 Oops, these two assignments were wrong here indeed
+ // #recurse
+ // <.completion = NORMAL>
+
auto empty_exprs = new (zone()) ZoneList<Expression*>(0, zone());
auto array = CreateTempVar(factory()->NewArrayLiteral(
empty_exprs,
// Reuse pattern's literal index - it is unused since there is no
// actual literal allocated.
- node->literal_index(), RelocInfo::kNoPosition));
-
- auto arguments = new (zone()) ZoneList<Expression*>(2, zone());
- arguments->Add(factory()->NewVariableProxy(array), zone());
- arguments->Add(factory()->NewVariableProxy(iterator), zone());
- auto spread_into_array_call =
- factory()->NewCallRuntime(Context::CONCAT_ITERABLE_TO_ARRAY_INDEX,
- arguments, RelocInfo::kNoPosition);
-
- auto if_statement = factory()->NewIfStatement(
- factory()->NewUnaryOperation(Token::NOT,
- factory()->NewVariableProxy(done),
- RelocInfo::kNoPosition),
- factory()->NewExpressionStatement(spread_into_array_call,
- RelocInfo::kNoPosition),
- factory()->NewEmptyStatement(RelocInfo::kNoPosition),
- RelocInfo::kNoPosition);
- block_->statements()->Add(if_statement, zone());
+ node->literal_index(), nopos));
+
+ // result = IteratorNext(iterator);
+ Statement* get_next = factory()->NewExpressionStatement(
+ parser_->BuildIteratorNextResult(
+ factory()->NewVariableProxy(iterator), result, nopos),
+ nopos);
+
+ // done = result.done
+ auto set_done = factory()->NewAssignment(
+ Token::ASSIGN, factory()->NewVariableProxy(done),
+ factory()->NewProperty(
+ factory()->NewVariableProxy(result),
+ factory()->NewStringLiteral(ast_value_factory()->done_string(),
+ nopos),
+ nopos), nopos);
+
+ // result.value
+ Expression* result_value = factory()->NewProperty(
+ factory()->NewVariableProxy(result),
+ factory()->NewStringLiteral(ast_value_factory()->value_string(), nopos),
+ nopos);
+
+ // %AppendElement(array, result.value);
+ Statement* append_element;
+ {
+ auto args = new (zone()) ZoneList<Expression*>(2, zone());
+ args->Add(factory()->NewVariableProxy(array), zone());
+ args->Add(result_value, zone());
+
+ append_element = factory()->NewExpressionStatement(
+ factory()->NewCallRuntime(Runtime::kAppendElement, args, nopos),
+ nopos);
+ }
+ // if (!#set_done) #append_element;
+ auto maybe_append = factory()->NewIfStatement(
+ factory()->NewUnaryOperation(Token::NOT, set_done, nopos),
+ append_element, factory()->NewEmptyStatement(nopos), nopos);
+
+ // while (#not_done) {
+ // #get_next;
+ // #maybe_append;
+ // }
+ WhileStatement* loop = factory()->NewWhileStatement(nullptr, nopos);
+ {
+ Expression* condition = factory()->NewUnaryOperation(
+ Token::NOT, factory()->NewVariableProxy(done), nopos);
+ Block* body = factory()->NewBlock(nullptr, 2, true, nopos);
+ body->statements()->Add(get_next, zone());
+ body->statements()->Add(maybe_append, zone());
+ loop->Initialize(condition, body);
+ }
+
+ // completion = ABRUPT;
+ Statement* set_aborted;
+ if (FLAG_harmony_iterator_close) {
+ Expression* proxy = factory()->NewVariableProxy(completion);
+ Expression* assignment = factory()->NewAssignment(
+ Token::ASSIGN, proxy,
+ factory()->NewSmiLiteral(ABRUPT, nopos), nopos);
+ set_aborted =
+ factory()->NewExpressionStatement(assignment, nopos);
+ }
+
+ // completion = NORMAL;
+ Statement* set_completed;
+ if (FLAG_harmony_iterator_close) {
+ Expression* proxy = factory()->NewVariableProxy(completion);
+ Expression* assignment = factory()->NewAssignment(
+ Token::ASSIGN, proxy,
+ factory()->NewSmiLiteral(NORMAL, nopos), nopos);
+ set_completed =
+ factory()->NewExpressionStatement(assignment, nopos);
+ }
+
+ block_->statements()->Add(loop, zone());
+ if (FLAG_harmony_iterator_close) {
+ block_->statements()->Add(set_aborted, zone());
+ }
RecurseIntoSubpattern(spread->expression(),
factory()->NewVariableProxy(array));
+ if (FLAG_harmony_iterator_close) {
+ block_->statements()->Add(set_completed, zone());
+ }
+ }
+
+ if (FLAG_harmony_iterator_close) {
+ Expression* condition = factory()->NewUnaryOperation(
+ Token::NOT, factory()->NewVariableProxy(done), nopos);
+ parser_->FinalizeIteratorUse(
+ completion, condition, iterator, block_, target);
+ block_ = target;
}
}

Powered by Google App Engine
This is Rietveld 408576698