Chromium Code Reviews| 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; |
| } |
| } |