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

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: 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
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): DCHECK(block_->ignore_completion_value());
411
410 auto temp = *temp_var = CreateTempVar(current_value_); 412 auto temp = *temp_var = CreateTempVar(current_value_);
411
412 block_->statements()->Add(parser_->BuildAssertIsCoercible(temp), zone());
413
414 auto iterator = CreateTempVar(parser_->GetIterator( 413 auto iterator = CreateTempVar(parser_->GetIterator(
415 factory()->NewVariableProxy(temp), factory(), RelocInfo::kNoPosition)); 414 factory()->NewVariableProxy(temp), factory(), RelocInfo::kNoPosition));
416 auto done = CreateTempVar( 415 auto done = CreateTempVar(
417 factory()->NewBooleanLiteral(false, RelocInfo::kNoPosition)); 416 factory()->NewBooleanLiteral(false, RelocInfo::kNoPosition));
418 auto result = CreateTempVar(); 417 auto result = CreateTempVar();
419 auto v = CreateTempVar(); 418 auto v = CreateTempVar();
419 auto completion = CreateTempVar();
420 auto nopos = RelocInfo::kNoPosition;
421
422 // For the purpose of iterator finalization, we temporarily set block_ to a
423 // new block. In the main body of this function, we write to block_ (both
424 // explicitly and implicitly via recursion). At the end of the function, we
425 // wrap this new block in a try-finally statement, restore block_ to its
426 // original value, and add the try-finally statement to block_.
427 auto target = block_;
428 if (FLAG_harmony_iterator_close) {
429 block_ = factory()->NewBlock(nullptr, 8, true, nopos);
430 }
420 431
421 Spread* spread = nullptr; 432 Spread* spread = nullptr;
422 for (Expression* value : *node->values()) { 433 for (Expression* value : *node->values()) {
423 if (value->IsSpread()) { 434 if (value->IsSpread()) {
424 spread = value->AsSpread(); 435 spread = value->AsSpread();
425 break; 436 break;
426 } 437 }
427 438
428 PatternContext context = SetInitializerContextIfNeeded(value); 439 PatternContext context = SetInitializerContextIfNeeded(value);
440
429 // if (!done) { 441 // if (!done) {
430 // result = IteratorNext(iterator); 442 // result = IteratorNext(iterator);
431 // v = (done = result.done) ? undefined : result.value; 443 // v = (done = result.done) ? undefined : result.value;
432 // } 444 // }
433 auto next_block = 445 Statement* if_statement;
434 factory()->NewBlock(nullptr, 2, true, RelocInfo::kNoPosition); 446 {
435 next_block->statements()->Add(factory()->NewExpressionStatement( 447 auto next_block =
436 parser_->BuildIteratorNextResult( 448 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.
437 factory()->NewVariableProxy(iterator), 449 next_block->statements()->Add(
438 result, RelocInfo::kNoPosition), 450 factory()->NewExpressionStatement(
439 RelocInfo::kNoPosition), 451 parser_->BuildIteratorNextResult(
440 zone()); 452 factory()->NewVariableProxy(iterator), result, nopos),
453 nopos),
454 zone());
441 455
442 auto assign_to_done = factory()->NewAssignment( 456 auto assign_to_done = factory()->NewAssignment(
443 Token::ASSIGN, factory()->NewVariableProxy(done), 457 Token::ASSIGN, factory()->NewVariableProxy(done),
444 factory()->NewProperty( 458 factory()->NewProperty(
445 factory()->NewVariableProxy(result), 459 factory()->NewVariableProxy(result),
446 factory()->NewStringLiteral(ast_value_factory()->done_string(), 460 factory()->NewStringLiteral(ast_value_factory()->done_string(),
447 RelocInfo::kNoPosition), 461 nopos),
448 RelocInfo::kNoPosition), 462 nopos),
449 RelocInfo::kNoPosition); 463 nopos);
450 auto next_value = factory()->NewConditional( 464 auto next_value = factory()->NewConditional(
451 assign_to_done, factory()->NewUndefinedLiteral(RelocInfo::kNoPosition), 465 assign_to_done, factory()->NewUndefinedLiteral(nopos),
452 factory()->NewProperty( 466 factory()->NewProperty(
453 factory()->NewVariableProxy(result), 467 factory()->NewVariableProxy(result),
454 factory()->NewStringLiteral(ast_value_factory()->value_string(), 468 factory()->NewStringLiteral(ast_value_factory()->value_string(),
455 RelocInfo::kNoPosition), 469 nopos),
456 RelocInfo::kNoPosition), 470 nopos),
457 RelocInfo::kNoPosition); 471 nopos);
458 next_block->statements()->Add( 472 next_block->statements()->Add(
459 factory()->NewExpressionStatement( 473 factory()->NewExpressionStatement(
460 factory()->NewAssignment(Token::ASSIGN, 474 factory()->NewAssignment(
461 factory()->NewVariableProxy(v), next_value, 475 Token::ASSIGN, factory()->NewVariableProxy(v), next_value,
462 RelocInfo::kNoPosition), 476 nopos),
463 RelocInfo::kNoPosition), 477 nopos),
464 zone()); 478 zone());
465 479
466 auto if_statement = factory()->NewIfStatement( 480 if_statement = factory()->NewIfStatement(
467 factory()->NewUnaryOperation(Token::NOT, 481 factory()->NewUnaryOperation(Token::NOT,
468 factory()->NewVariableProxy(done), 482 factory()->NewVariableProxy(done),
469 RelocInfo::kNoPosition), 483 nopos),
470 next_block, factory()->NewEmptyStatement(RelocInfo::kNoPosition), 484 next_block, factory()->NewEmptyStatement(nopos),
471 RelocInfo::kNoPosition); 485 nopos);
486 }
472 block_->statements()->Add(if_statement, zone()); 487 block_->statements()->Add(if_statement, zone());
473 488
474 if (!(value->IsLiteral() && value->AsLiteral()->raw_value()->IsTheHole())) { 489 if (!(value->IsLiteral() && value->AsLiteral()->raw_value()->IsTheHole())) {
490 if (FLAG_harmony_iterator_close) {
491 // completion = ABRUPT;
492 Expression* proxy = factory()->NewVariableProxy(completion);
493 Expression* assignment = factory()->NewAssignment(
494 Token::ASSIGN, proxy,
495 factory()->NewSmiLiteral(ABRUPT, nopos),
496 nopos);
497 block_->statements()->Add(
498 factory()->NewExpressionStatement(assignment, nopos), zone());
499 }
500
475 RecurseIntoSubpattern(value, factory()->NewVariableProxy(v)); 501 RecurseIntoSubpattern(value, factory()->NewVariableProxy(v));
502
503 if (FLAG_harmony_iterator_close) {
504 // completion = NORMAL;
505 Expression* proxy = factory()->NewVariableProxy(completion);
506 Expression* assignment = factory()->NewAssignment(
507 Token::ASSIGN, proxy, factory()->NewSmiLiteral(NORMAL, nopos),
508 nopos);
509 block_->statements()->Add(
510 factory()->NewExpressionStatement(assignment, nopos), zone());
511 }
476 } 512 }
477 set_context(context); 513 set_context(context);
478 } 514 }
479 515
480 if (spread != nullptr) { 516 if (spread != nullptr) {
481 // array = []; 517 // A spread can only occur as the last component. It is not handled by
482 // if (!done) %concat_iterable_to_array(array, iterator); 518 // RecurseIntoSubpattern above.
519 //
520 // let array = [];
521 // 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.
522 // result = IteratorNext(iterator);
523 // if (!(done = result.done)) %AppendElement(array, result.value);
524 // }
525 // <.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
526 // #recurse
527 // <.completion = NORMAL>
528
483 auto empty_exprs = new (zone()) ZoneList<Expression*>(0, zone()); 529 auto empty_exprs = new (zone()) ZoneList<Expression*>(0, zone());
484 auto array = CreateTempVar(factory()->NewArrayLiteral( 530 auto array = CreateTempVar(factory()->NewArrayLiteral(
485 empty_exprs, 531 empty_exprs,
486 // Reuse pattern's literal index - it is unused since there is no 532 // Reuse pattern's literal index - it is unused since there is no
487 // actual literal allocated. 533 // actual literal allocated.
488 node->literal_index(), RelocInfo::kNoPosition)); 534 node->literal_index(), nopos));
489 535
490 auto arguments = new (zone()) ZoneList<Expression*>(2, zone()); 536 // result = IteratorNext(iterator);
491 arguments->Add(factory()->NewVariableProxy(array), zone()); 537 Statement* get_next = factory()->NewExpressionStatement(
492 arguments->Add(factory()->NewVariableProxy(iterator), zone()); 538 parser_->BuildIteratorNextResult(
493 auto spread_into_array_call = 539 factory()->NewVariableProxy(iterator), result, nopos),
494 factory()->NewCallRuntime(Context::CONCAT_ITERABLE_TO_ARRAY_INDEX, 540 nopos);
495 arguments, RelocInfo::kNoPosition);
496 541
497 auto if_statement = factory()->NewIfStatement( 542 // done = result.done
498 factory()->NewUnaryOperation(Token::NOT, 543 auto set_done = factory()->NewAssignment(
499 factory()->NewVariableProxy(done), 544 Token::ASSIGN, factory()->NewVariableProxy(done),
500 RelocInfo::kNoPosition), 545 factory()->NewProperty(
501 factory()->NewExpressionStatement(spread_into_array_call, 546 factory()->NewVariableProxy(result),
502 RelocInfo::kNoPosition), 547 factory()->NewStringLiteral(ast_value_factory()->done_string(),
503 factory()->NewEmptyStatement(RelocInfo::kNoPosition), 548 nopos),
504 RelocInfo::kNoPosition); 549 nopos), nopos);
505 block_->statements()->Add(if_statement, zone());
506 550
551 // result.value
552 Expression* result_value = factory()->NewProperty(
553 factory()->NewVariableProxy(result),
554 factory()->NewStringLiteral(ast_value_factory()->value_string(), nopos),
555 nopos);
556
557 // %AppendElement(array, result.value);
558 Statement* append_element;
559 {
560 auto args = new (zone()) ZoneList<Expression*>(2, zone());
561 args->Add(factory()->NewVariableProxy(array), zone());
562 args->Add(result_value, zone());
563
564 append_element = factory()->NewExpressionStatement(
565 factory()->NewCallRuntime(Runtime::kAppendElement, args, nopos),
566 nopos);
567 }
568
569 // if (!#set_done) #append_element;
570 auto maybe_append = factory()->NewIfStatement(
571 factory()->NewUnaryOperation(Token::NOT, set_done, nopos),
572 append_element, factory()->NewEmptyStatement(nopos), nopos);
573
574 // while (#not_done) {
575 // #get_next;
576 // #maybe_append;
577 // }
578 WhileStatement* loop = factory()->NewWhileStatement(nullptr, nopos);
579 {
580 Expression* condition = factory()->NewUnaryOperation(
581 Token::NOT, factory()->NewVariableProxy(done), nopos);
582 Block* body = factory()->NewBlock(nullptr, 2, true, nopos);
583 body->statements()->Add(get_next, zone());
584 body->statements()->Add(maybe_append, zone());
585 loop->Initialize(condition, body);
586 }
587
588 // completion = ABRUPT;
589 Statement* set_aborted;
590 if (FLAG_harmony_iterator_close) {
591 Expression* proxy = factory()->NewVariableProxy(completion);
592 Expression* assignment = factory()->NewAssignment(
593 Token::ASSIGN, proxy,
594 factory()->NewSmiLiteral(ABRUPT, nopos), nopos);
595 set_aborted =
596 factory()->NewExpressionStatement(assignment, nopos);
597 }
598
599 // completion = NORMAL;
600 Statement* set_completed;
601 if (FLAG_harmony_iterator_close) {
602 Expression* proxy = factory()->NewVariableProxy(completion);
603 Expression* assignment = factory()->NewAssignment(
604 Token::ASSIGN, proxy,
605 factory()->NewSmiLiteral(NORMAL, nopos), nopos);
606 set_completed =
607 factory()->NewExpressionStatement(assignment, nopos);
608 }
609
610 block_->statements()->Add(loop, zone());
611 if (FLAG_harmony_iterator_close) {
612 block_->statements()->Add(set_aborted, zone());
613 }
507 RecurseIntoSubpattern(spread->expression(), 614 RecurseIntoSubpattern(spread->expression(),
508 factory()->NewVariableProxy(array)); 615 factory()->NewVariableProxy(array));
616 if (FLAG_harmony_iterator_close) {
617 block_->statements()->Add(set_completed, zone());
618 }
619 }
620
621 if (FLAG_harmony_iterator_close) {
622 Expression* condition = factory()->NewUnaryOperation(
623 Token::NOT, factory()->NewVariableProxy(done), nopos);
624 parser_->FinalizeIteratorUse(
625 completion, condition, iterator, block_, target);
626 block_ = target;
509 } 627 }
510 } 628 }
511 629
512 630
513 void Parser::PatternRewriter::VisitArrayLiteral(ArrayLiteral* node) { 631 void Parser::PatternRewriter::VisitArrayLiteral(ArrayLiteral* node) {
514 Variable* temp_var = nullptr; 632 Variable* temp_var = nullptr;
515 VisitArrayLiteral(node, &temp_var); 633 VisitArrayLiteral(node, &temp_var);
516 } 634 }
517 635
518 636
(...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after
615 NOT_A_PATTERN(TryFinallyStatement) 733 NOT_A_PATTERN(TryFinallyStatement)
616 NOT_A_PATTERN(UnaryOperation) 734 NOT_A_PATTERN(UnaryOperation)
617 NOT_A_PATTERN(VariableDeclaration) 735 NOT_A_PATTERN(VariableDeclaration)
618 NOT_A_PATTERN(WhileStatement) 736 NOT_A_PATTERN(WhileStatement)
619 NOT_A_PATTERN(WithStatement) 737 NOT_A_PATTERN(WithStatement)
620 NOT_A_PATTERN(Yield) 738 NOT_A_PATTERN(Yield)
621 739
622 #undef NOT_A_PATTERN 740 #undef NOT_A_PATTERN
623 } // namespace internal 741 } // namespace internal
624 } // namespace v8 742 } // namespace v8
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698