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

Side by Side 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: Address comments. 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 unified diff | Download patch
« no previous file with comments | « src/parsing/parser.cc ('k') | test/cctest/interpreter/bytecode_expectations/ForOf.golden » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2015 the V8 project authors. All rights reserved. 1 // Copyright 2015 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "src/ast/ast.h" 5 #include "src/ast/ast.h"
6 #include "src/messages.h" 6 #include "src/messages.h"
7 #include "src/parsing/parameter-initializer-rewriter.h" 7 #include "src/parsing/parameter-initializer-rewriter.h"
8 #include "src/parsing/parser.h" 8 #include "src/parsing/parser.h"
9 9
10 namespace v8 { 10 namespace v8 {
(...skipping 389 matching lines...) Expand 10 before | Expand all | Expand 10 after
400 400
401 401
402 void Parser::PatternRewriter::VisitObjectLiteral(ObjectLiteral* node) { 402 void Parser::PatternRewriter::VisitObjectLiteral(ObjectLiteral* node) {
403 Variable* temp_var = nullptr; 403 Variable* temp_var = nullptr;
404 VisitObjectLiteral(node, &temp_var); 404 VisitObjectLiteral(node, &temp_var);
405 } 405 }
406 406
407 407
408 void Parser::PatternRewriter::VisitArrayLiteral(ArrayLiteral* node, 408 void Parser::PatternRewriter::VisitArrayLiteral(ArrayLiteral* node,
409 Variable** temp_var) { 409 Variable** temp_var) {
410 // TODO(neis): Enable after rebase:
411 // DCHECK(block_->ignore_completion_value());
412
410 auto temp = *temp_var = CreateTempVar(current_value_); 413 auto temp = *temp_var = CreateTempVar(current_value_);
411
412 block_->statements()->Add(parser_->BuildAssertIsCoercible(temp), zone());
413
414 auto iterator = CreateTempVar(parser_->GetIterator( 414 auto iterator = CreateTempVar(parser_->GetIterator(
415 factory()->NewVariableProxy(temp), factory(), RelocInfo::kNoPosition)); 415 factory()->NewVariableProxy(temp), factory(), RelocInfo::kNoPosition));
416 auto done = CreateTempVar( 416 auto done = CreateTempVar(
417 factory()->NewBooleanLiteral(false, RelocInfo::kNoPosition)); 417 factory()->NewBooleanLiteral(false, RelocInfo::kNoPosition));
418 auto result = CreateTempVar(); 418 auto result = CreateTempVar();
419 auto v = CreateTempVar(); 419 auto v = CreateTempVar();
420 auto completion = CreateTempVar();
421 auto nopos = RelocInfo::kNoPosition;
422
423 // For the purpose of iterator finalization, we temporarily set block_ to a
424 // new block. In the main body of this function, we write to block_ (both
425 // explicitly and implicitly via recursion). At the end of the function, we
426 // wrap this new block in a try-finally statement, restore block_ to its
427 // original value, and add the try-finally statement to block_.
428 auto target = block_;
429 if (FLAG_harmony_iterator_close) {
430 block_ = factory()->NewBlock(nullptr, 8, true, nopos);
431 }
420 432
421 Spread* spread = nullptr; 433 Spread* spread = nullptr;
422 for (Expression* value : *node->values()) { 434 for (Expression* value : *node->values()) {
423 if (value->IsSpread()) { 435 if (value->IsSpread()) {
424 spread = value->AsSpread(); 436 spread = value->AsSpread();
425 break; 437 break;
426 } 438 }
427 439
428 PatternContext context = SetInitializerContextIfNeeded(value); 440 PatternContext context = SetInitializerContextIfNeeded(value);
441
429 // if (!done) { 442 // if (!done) {
443 // done = true; // If .next, .done or .value throws, don't close.
430 // result = IteratorNext(iterator); 444 // result = IteratorNext(iterator);
431 // v = (done = result.done) ? undefined : result.value; 445 // v = (done = result.done) ? undefined : result.value;
432 // } 446 // }
433 auto next_block = 447 Statement* if_statement;
434 factory()->NewBlock(nullptr, 2, true, RelocInfo::kNoPosition); 448 {
435 next_block->statements()->Add(factory()->NewExpressionStatement( 449 auto next_block =
436 parser_->BuildIteratorNextResult( 450 factory()->NewBlock(nullptr, 2, true, RelocInfo::kNoPosition);
adamk 2016/03/08 18:41:13 This block now contains 3 statements.
437 factory()->NewVariableProxy(iterator),
438 result, RelocInfo::kNoPosition),
439 RelocInfo::kNoPosition),
440 zone());
441 451
442 auto assign_to_done = factory()->NewAssignment( 452 next_block->statements()->Add(
443 Token::ASSIGN, factory()->NewVariableProxy(done), 453 factory()->NewExpressionStatement(
444 factory()->NewProperty( 454 factory()->NewAssignment(
445 factory()->NewVariableProxy(result), 455 Token::ASSIGN, factory()->NewVariableProxy(done),
446 factory()->NewStringLiteral(ast_value_factory()->done_string(), 456 factory()->NewBooleanLiteral(true, nopos), nopos),
447 RelocInfo::kNoPosition), 457 nopos),
448 RelocInfo::kNoPosition), 458 zone());
449 RelocInfo::kNoPosition);
450 auto next_value = factory()->NewConditional(
451 assign_to_done, factory()->NewUndefinedLiteral(RelocInfo::kNoPosition),
452 factory()->NewProperty(
453 factory()->NewVariableProxy(result),
454 factory()->NewStringLiteral(ast_value_factory()->value_string(),
455 RelocInfo::kNoPosition),
456 RelocInfo::kNoPosition),
457 RelocInfo::kNoPosition);
458 next_block->statements()->Add(
459 factory()->NewExpressionStatement(
460 factory()->NewAssignment(Token::ASSIGN,
461 factory()->NewVariableProxy(v), next_value,
462 RelocInfo::kNoPosition),
463 RelocInfo::kNoPosition),
464 zone());
465 459
466 auto if_statement = factory()->NewIfStatement( 460 next_block->statements()->Add(
467 factory()->NewUnaryOperation(Token::NOT, 461 factory()->NewExpressionStatement(
468 factory()->NewVariableProxy(done), 462 parser_->BuildIteratorNextResult(
469 RelocInfo::kNoPosition), 463 factory()->NewVariableProxy(iterator), result,
470 next_block, factory()->NewEmptyStatement(RelocInfo::kNoPosition), 464 RelocInfo::kNoPosition),
471 RelocInfo::kNoPosition); 465 RelocInfo::kNoPosition),
466 zone());
467
468 auto assign_to_done = factory()->NewAssignment(
469 Token::ASSIGN, factory()->NewVariableProxy(done),
470 factory()->NewProperty(
471 factory()->NewVariableProxy(result),
472 factory()->NewStringLiteral(ast_value_factory()->done_string(),
473 RelocInfo::kNoPosition),
474 RelocInfo::kNoPosition),
475 RelocInfo::kNoPosition);
476 auto next_value = factory()->NewConditional(
477 assign_to_done,
478 factory()->NewUndefinedLiteral(RelocInfo::kNoPosition),
479 factory()->NewProperty(
480 factory()->NewVariableProxy(result),
481 factory()->NewStringLiteral(ast_value_factory()->value_string(),
482 RelocInfo::kNoPosition),
483 RelocInfo::kNoPosition),
484 RelocInfo::kNoPosition);
485 next_block->statements()->Add(
486 factory()->NewExpressionStatement(
487 factory()->NewAssignment(
488 Token::ASSIGN, factory()->NewVariableProxy(v), next_value,
489 RelocInfo::kNoPosition),
490 RelocInfo::kNoPosition),
491 zone());
492
493 if_statement = factory()->NewIfStatement(
494 factory()->NewUnaryOperation(Token::NOT,
495 factory()->NewVariableProxy(done),
496 RelocInfo::kNoPosition),
497 next_block, factory()->NewEmptyStatement(RelocInfo::kNoPosition),
498 RelocInfo::kNoPosition);
499 }
472 block_->statements()->Add(if_statement, zone()); 500 block_->statements()->Add(if_statement, zone());
473 501
474 if (!(value->IsLiteral() && value->AsLiteral()->raw_value()->IsTheHole())) { 502 if (!(value->IsLiteral() && value->AsLiteral()->raw_value()->IsTheHole())) {
503 if (FLAG_harmony_iterator_close) {
504 // completion = ABRUPT;
505 Expression* proxy = factory()->NewVariableProxy(completion);
506 Expression* assignment = factory()->NewAssignment(
507 Token::ASSIGN, proxy,
508 factory()->NewSmiLiteral(ABRUPT, nopos),
509 nopos);
510 block_->statements()->Add(
511 factory()->NewExpressionStatement(assignment, nopos), zone());
512 }
513
475 RecurseIntoSubpattern(value, factory()->NewVariableProxy(v)); 514 RecurseIntoSubpattern(value, factory()->NewVariableProxy(v));
515
516 if (FLAG_harmony_iterator_close) {
517 // completion = NORMAL;
518 Expression* proxy = factory()->NewVariableProxy(completion);
519 Expression* assignment = factory()->NewAssignment(
520 Token::ASSIGN, proxy, factory()->NewSmiLiteral(NORMAL, nopos),
521 nopos);
522 block_->statements()->Add(
523 factory()->NewExpressionStatement(assignment, nopos), zone());
524 }
476 } 525 }
477 set_context(context); 526 set_context(context);
478 } 527 }
479 528
480 if (spread != nullptr) { 529 if (spread != nullptr) {
481 // array = []; 530 // A spread can only occur as the last component. It is not handled by
531 // RecurseIntoSubpattern above.
532
533 // let array = [];
482 // if (!done) %concat_iterable_to_array(array, iterator); 534 // if (!done) %concat_iterable_to_array(array, iterator);
535 // done = true;
536
483 auto empty_exprs = new (zone()) ZoneList<Expression*>(0, zone()); 537 auto empty_exprs = new (zone()) ZoneList<Expression*>(0, zone());
484 auto array = CreateTempVar(factory()->NewArrayLiteral( 538 auto array = CreateTempVar(factory()->NewArrayLiteral(
485 empty_exprs, 539 empty_exprs,
486 // Reuse pattern's literal index - it is unused since there is no 540 // Reuse pattern's literal index - it is unused since there is no
487 // actual literal allocated. 541 // actual literal allocated.
488 node->literal_index(), RelocInfo::kNoPosition)); 542 node->literal_index(), RelocInfo::kNoPosition));
489 543
490 auto arguments = new (zone()) ZoneList<Expression*>(2, zone()); 544 auto arguments = new (zone()) ZoneList<Expression*>(2, zone());
491 arguments->Add(factory()->NewVariableProxy(array), zone()); 545 arguments->Add(factory()->NewVariableProxy(array), zone());
492 arguments->Add(factory()->NewVariableProxy(iterator), zone()); 546 arguments->Add(factory()->NewVariableProxy(iterator), zone());
493 auto spread_into_array_call = 547 auto spread_into_array_call =
494 factory()->NewCallRuntime(Context::CONCAT_ITERABLE_TO_ARRAY_INDEX, 548 factory()->NewCallRuntime(Context::CONCAT_ITERABLE_TO_ARRAY_INDEX,
495 arguments, RelocInfo::kNoPosition); 549 arguments, RelocInfo::kNoPosition);
496 550
497 auto if_statement = factory()->NewIfStatement( 551 auto if_statement = factory()->NewIfStatement(
498 factory()->NewUnaryOperation(Token::NOT, 552 factory()->NewUnaryOperation(Token::NOT,
499 factory()->NewVariableProxy(done), 553 factory()->NewVariableProxy(done),
500 RelocInfo::kNoPosition), 554 RelocInfo::kNoPosition),
501 factory()->NewExpressionStatement(spread_into_array_call, 555 factory()->NewExpressionStatement(spread_into_array_call,
502 RelocInfo::kNoPosition), 556 RelocInfo::kNoPosition),
503 factory()->NewEmptyStatement(RelocInfo::kNoPosition), 557 factory()->NewEmptyStatement(RelocInfo::kNoPosition),
504 RelocInfo::kNoPosition); 558 RelocInfo::kNoPosition);
505 block_->statements()->Add(if_statement, zone()); 559 block_->statements()->Add(if_statement, zone());
506 560
561 auto set_done = factory()->NewAssignment(
562 Token::ASSIGN, factory()->NewVariableProxy(done),
563 factory()->NewBooleanLiteral(true, nopos), nopos);
564 block_->statements()->Add(
565 factory()->NewExpressionStatement(set_done, nopos), zone());
566
507 RecurseIntoSubpattern(spread->expression(), 567 RecurseIntoSubpattern(spread->expression(),
508 factory()->NewVariableProxy(array)); 568 factory()->NewVariableProxy(array));
509 } 569 }
570
571 if (FLAG_harmony_iterator_close) {
572 Expression* closing_condition = factory()->NewUnaryOperation(
573 Token::NOT, factory()->NewVariableProxy(done), nopos);
574 parser_->FinalizeIteratorUse(
575 completion, closing_condition, iterator, block_, target);
576 block_ = target;
577 }
510 } 578 }
511 579
512 580
513 void Parser::PatternRewriter::VisitArrayLiteral(ArrayLiteral* node) { 581 void Parser::PatternRewriter::VisitArrayLiteral(ArrayLiteral* node) {
514 Variable* temp_var = nullptr; 582 Variable* temp_var = nullptr;
515 VisitArrayLiteral(node, &temp_var); 583 VisitArrayLiteral(node, &temp_var);
516 } 584 }
517 585
518 586
519 void Parser::PatternRewriter::VisitAssignment(Assignment* node) { 587 void Parser::PatternRewriter::VisitAssignment(Assignment* node) {
(...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after
615 NOT_A_PATTERN(TryFinallyStatement) 683 NOT_A_PATTERN(TryFinallyStatement)
616 NOT_A_PATTERN(UnaryOperation) 684 NOT_A_PATTERN(UnaryOperation)
617 NOT_A_PATTERN(VariableDeclaration) 685 NOT_A_PATTERN(VariableDeclaration)
618 NOT_A_PATTERN(WhileStatement) 686 NOT_A_PATTERN(WhileStatement)
619 NOT_A_PATTERN(WithStatement) 687 NOT_A_PATTERN(WithStatement)
620 NOT_A_PATTERN(Yield) 688 NOT_A_PATTERN(Yield)
621 689
622 #undef NOT_A_PATTERN 690 #undef NOT_A_PATTERN
623 } // namespace internal 691 } // namespace internal
624 } // namespace v8 692 } // namespace v8
OLDNEW
« no previous file with comments | « src/parsing/parser.cc ('k') | test/cctest/interpreter/bytecode_expectations/ForOf.golden » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698