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

Side by Side 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 unified diff | Download patch
OLDNEW
1 // Copyright 2012 the V8 project authors. All rights reserved. 1 // Copyright 2012 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/parsing/parser.h" 5 #include "src/parsing/parser.h"
6 6
7 #include "src/api.h" 7 #include "src/api.h"
8 #include "src/ast/ast.h" 8 #include "src/ast/ast.h"
9 #include "src/ast/ast-expression-rewriter.h" 9 #include "src/ast/ast-expression-rewriter.h"
10 #include "src/ast/ast-expression-visitor.h" 10 #include "src/ast/ast-expression-visitor.h"
(...skipping 6260 matching lines...) Expand 10 before | Expand all | Expand 10 after
6271 do_block->statements()->Add(get_value, zone); 6271 do_block->statements()->Add(get_value, zone);
6272 6272
6273 Variable* dot_result = scope->NewTemporary(avfactory->dot_result_string()); 6273 Variable* dot_result = scope->NewTemporary(avfactory->dot_result_string());
6274 yield_star = factory->NewDoExpression(do_block, dot_result, nopos); 6274 yield_star = factory->NewDoExpression(do_block, dot_result, nopos);
6275 Rewriter::Rewrite(parser_, yield_star, avfactory); 6275 Rewriter::Rewrite(parser_, yield_star, avfactory);
6276 } 6276 }
6277 6277
6278 return yield_star; 6278 return yield_star;
6279 } 6279 }
6280 6280
6281
6281 // Desugaring of (lhs) instanceof (rhs) 6282 // Desugaring of (lhs) instanceof (rhs)
6282 // ==================================== 6283 // ====================================
6283 // 6284 //
6284 // We desugar instanceof into a load of property @@hasInstance on the rhs. 6285 // We desugar instanceof into a load of property @@hasInstance on the rhs.
6285 // We end up with roughly the following code (O, C): 6286 // We end up with roughly the following code:
6286 // 6287 //
6287 // do { 6288 // do {
6288 // let O = lhs; 6289 // let O = lhs;
6289 // let C = rhs; 6290 // let C = rhs;
6290 // if (!IS_RECEIVER(C)) throw MakeTypeError(kNonObjectInInstanceOfCheck); 6291 // if (!IS_RECEIVER(C)) throw MakeTypeError(kNonObjectInInstanceOfCheck);
6291 // let handler_result = C[Symbol.hasInstance]; 6292 // let handler_result = C[Symbol.hasInstance];
6292 // if (handler_result === undefined) { 6293 // if (handler_result === undefined) {
6293 // if (!IS_CALLABLE(C)) { 6294 // if (!IS_CALLABLE(C)) {
6294 // throw MakeTypeError(kCalledNonCallableInstanceOf); 6295 // throw MakeTypeError(kCalledNonCallableInstanceOf);
6295 // } 6296 // }
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after
6359 Expression* handler_proxy = factory->NewVariableProxy(var_handler_result); 6360 Expression* handler_proxy = factory->NewVariableProxy(var_handler_result);
6360 Expression* assignment = 6361 Expression* assignment =
6361 factory->NewAssignment(Token::ASSIGN, handler_proxy, prop, nopos); 6362 factory->NewAssignment(Token::ASSIGN, handler_proxy, prop, nopos);
6362 initialize_handler = factory->NewExpressionStatement(assignment, nopos); 6363 initialize_handler = factory->NewExpressionStatement(assignment, nopos);
6363 } 6364 }
6364 6365
6365 // if (handler_result === undefined) { 6366 // if (handler_result === undefined) {
6366 // if (!IS_CALLABLE(C)) { 6367 // if (!IS_CALLABLE(C)) {
6367 // throw MakeTypeError(kCalledNonCallableInstanceOf); 6368 // throw MakeTypeError(kCalledNonCallableInstanceOf);
6368 // } 6369 // }
6369 // result = %ordinary_has_instance(C, O); 6370 // handler_result = %ordinary_has_instance(C, O);
6370 // } else { 6371 // } else {
6371 // handler_result = !!%_Call(handler_result, C, O); 6372 // handler_result = !!%_Call(handler_result, C, O);
6372 // } 6373 // }
6373 Statement* call_handler; 6374 Statement* call_handler;
6374 { 6375 {
6375 Expression* condition = factory->NewCompareOperation( 6376 Expression* condition = factory->NewCompareOperation(
6376 Token::EQ_STRICT, factory->NewVariableProxy(var_handler_result), 6377 Token::EQ_STRICT, factory->NewVariableProxy(var_handler_result),
6377 factory->NewUndefinedLiteral(nopos), nopos); 6378 factory->NewUndefinedLiteral(nopos), nopos);
6378 6379
6379 Block* then_side = factory->NewBlock(nullptr, 2, false, nopos); 6380 Block* then_side = factory->NewBlock(nullptr, 2, false, nopos);
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after
6430 block->statements()->Add(call_handler, zone); 6431 block->statements()->Add(call_handler, zone);
6431 6432
6432 // Here is the desugared instanceof. 6433 // Here is the desugared instanceof.
6433 instanceof = factory->NewDoExpression(block, var_handler_result, nopos); 6434 instanceof = factory->NewDoExpression(block, var_handler_result, nopos);
6434 Rewriter::Rewrite(parser_, instanceof, avfactory); 6435 Rewriter::Rewrite(parser_, instanceof, avfactory);
6435 } 6436 }
6436 6437
6437 return instanceof; 6438 return instanceof;
6438 } 6439 }
6439 6440
6441
6440 Statement* ParserTraits::CheckCallable(Variable* var, Expression* error) { 6442 Statement* ParserTraits::CheckCallable(Variable* var, Expression* error) {
6441 auto factory = parser_->factory(); 6443 auto factory = parser_->factory();
6442 auto avfactory = parser_->ast_value_factory(); 6444 auto avfactory = parser_->ast_value_factory();
6443 const int nopos = RelocInfo::kNoPosition; 6445 const int nopos = RelocInfo::kNoPosition;
6444 Statement* validate_var; 6446 Statement* validate_var;
6445 { 6447 {
6446 Expression* type_of = factory->NewUnaryOperation( 6448 Expression* type_of = factory->NewUnaryOperation(
6447 Token::TYPEOF, factory->NewVariableProxy(var), nopos); 6449 Token::TYPEOF, factory->NewVariableProxy(var), nopos);
6448 Expression* function_literal = 6450 Expression* function_literal =
6449 factory->NewStringLiteral(avfactory->function_string(), nopos); 6451 factory->NewStringLiteral(avfactory->function_string(), nopos);
6450 Expression* condition = factory->NewCompareOperation( 6452 Expression* condition = factory->NewCompareOperation(
6451 Token::EQ_STRICT, type_of, function_literal, nopos); 6453 Token::EQ_STRICT, type_of, function_literal, nopos);
6452 6454
6453 Statement* throw_call = factory->NewExpressionStatement(error, nopos); 6455 Statement* throw_call = factory->NewExpressionStatement(error, nopos);
6454 6456
6455 validate_var = factory->NewIfStatement( 6457 validate_var = factory->NewIfStatement(
6456 condition, factory->NewEmptyStatement(nopos), throw_call, nopos); 6458 condition, factory->NewEmptyStatement(nopos), throw_call, nopos);
6457 } 6459 }
6458 return validate_var; 6460 return validate_var;
6459 } 6461 }
6460 6462
6463
6461 void ParserTraits::BuildIteratorClose(ZoneList<Statement*>* statements, 6464 void ParserTraits::BuildIteratorClose(ZoneList<Statement*>* statements,
6462 Variable* iterator, 6465 Variable* iterator,
6463 Maybe<Variable*> input, 6466 Maybe<Variable*> input,
6464 Variable* var_output) { 6467 Variable* var_output) {
6465 // 6468 //
6466 // This function adds four statements to [statements], corresponding to the 6469 // This function adds four statements to [statements], corresponding to the
6467 // following code: 6470 // following code:
6468 // 6471 //
6469 // let iteratorReturn = iterator.return; 6472 // let iteratorReturn = iterator.return;
6470 // if (IS_NULL_OR_UNDEFINED(iteratorReturn) return |input|; 6473 // if (IS_NULL_OR_UNDEFINED(iteratorReturn) return |input|;
(...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after
6556 is_receiver_call, factory->NewEmptyStatement(nopos), throw_call, nopos); 6559 is_receiver_call, factory->NewEmptyStatement(nopos), throw_call, nopos);
6557 } 6560 }
6558 6561
6559 statements->Add(get_return, zone); 6562 statements->Add(get_return, zone);
6560 statements->Add(check_return, zone); 6563 statements->Add(check_return, zone);
6561 statements->Add(call_return, zone); 6564 statements->Add(call_return, zone);
6562 statements->Add(validate_output, zone); 6565 statements->Add(validate_output, zone);
6563 } 6566 }
6564 6567
6565 6568
6566 // Runtime encoding of different completion modes. 6569 void ParserTraits::FinalizeIteratorUse(
6567 enum ForOfLoopBodyCompletion { BODY_COMPLETED, BODY_ABORTED, BODY_THREW }; 6570 Variable* completion, Expression* condition, Variable* iter,
6571 Block* iterator_use, Block* target) {
6572 if (!FLAG_harmony_iterator_close) return;
6573
6574 //
6575 // This function adds two statements to [target], corresponding to the
6576 // 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.
6577 //
6578 // completion = NORMAL;
6579 // try {
6580 // iterator_use
6581 // } catch(e) {
6582 // if (completion === ABRUPT) completion = THROW;
6583 // throw e;
6584 // } finally {
6585 // if (condition) {
6586 // #BuildIteratorCloseForCompletion(iter, completion)
6587 // }
6588 // }
6589 //
6590
6591 const int nopos = RelocInfo::kNoPosition;
6592 auto factory = parser_->factory();
adamk 2016/03/08 01:57:07 If you put this function in Parser instead of Pars
6593 auto avfactory = parser_->ast_value_factory();
6594 auto scope = parser_->scope_;
6595 auto zone = parser_->zone();
6596
6597 // completion = NORMAL;
6598 Statement* initialize_completion;
6599 {
6600 Expression* proxy = factory->NewVariableProxy(completion);
6601 Expression* assignment = factory->NewAssignment(
6602 Token::ASSIGN, proxy,
6603 factory->NewSmiLiteral(Parser::NORMAL, nopos), nopos);
6604 initialize_completion =
6605 factory->NewExpressionStatement(assignment, nopos);
6606 }
6607
6608 // if (completion === ABRUPT) completion = THROW;
6609 Statement* set_completion_throw;
6610 {
6611 Expression* condition = factory->NewCompareOperation(
6612 Token::EQ_STRICT, factory->NewVariableProxy(completion),
6613 factory->NewSmiLiteral(Parser::ABRUPT, nopos), nopos);
6614
6615 Expression* proxy = factory->NewVariableProxy(completion);
6616 Expression* assignment = factory->NewAssignment(
6617 Token::ASSIGN, proxy, factory->NewSmiLiteral(Parser::THROW, nopos),
6618 nopos);
6619 Statement* statement = factory->NewExpressionStatement(assignment, nopos);
6620 set_completion_throw = factory->NewIfStatement(
6621 condition, statement, factory->NewEmptyStatement(nopos), nopos);
6622 }
6623
6624 // if (condition) {
6625 // #BuildIteratorCloseForCompletion(iter, completion)
6626 // }
6627 Block* maybe_close;
6628 {
6629 Block* block = factory->NewBlock(nullptr, 2, true, nopos);
6630 parser_->BuildIteratorCloseForCompletion(
6631 block->statements(), iter, completion);
6632 DCHECK(block->statements()->length() == 2);
6633
6634 maybe_close = factory->NewBlock(nullptr, 1, true, nopos);
6635 maybe_close->statements()->Add(factory->NewIfStatement(
6636 condition, block, factory->NewEmptyStatement(nopos), nopos), zone);
6637 }
6638
6639 // try { #try_block }
6640 // catch(e) {
6641 // #set_completion_throw;
6642 // throw e;
6643 // }
6644 Statement* try_catch;
6645 {
6646 Scope* catch_scope = parser_->NewScope(scope, CATCH_SCOPE);
6647 Variable* catch_variable = catch_scope->DeclareLocal(
6648 avfactory->dot_catch_string(), VAR, kCreatedInitialized,
6649 Variable::NORMAL);
6650
6651 Statement* rethrow;
6652 {
6653 Expression* proxy = factory->NewVariableProxy(catch_variable);
6654 rethrow = factory->NewExpressionStatement(
6655 factory->NewThrow(proxy, nopos), nopos);
6656 }
6657
6658 Block* catch_block = factory->NewBlock(nullptr, 2, false, nopos);
6659 catch_block->statements()->Add(set_completion_throw, zone);
6660 catch_block->statements()->Add(rethrow, zone);
6661
6662 try_catch = factory->NewTryCatchStatement(
6663 iterator_use, catch_scope, catch_variable, catch_block, nopos);
6664 }
6665
6666 // try { #try_catch } finally { #maybe_close }
6667 Statement* try_finally;
6668 {
6669 Block* try_block = factory->NewBlock(nullptr, 1, false, nopos);
6670 try_block->statements()->Add(try_catch, zone);
6671
6672 try_finally =
6673 factory->NewTryFinallyStatement(try_block, maybe_close, nopos);
6674 }
6675
6676 target->statements()->Add(initialize_completion, zone);
6677 target->statements()->Add(try_finally, zone);
6678 }
6679
6568 6680
6569 void ParserTraits::BuildIteratorCloseForCompletion( 6681 void ParserTraits::BuildIteratorCloseForCompletion(
6570 ZoneList<Statement*>* statements, Variable* iterator, 6682 ZoneList<Statement*>* statements, Variable* iterator,
6571 Variable* completion) { 6683 Variable* completion) {
6572 // 6684 //
6573 // This function adds two statements to [statements], corresponding to the 6685 // This function adds two statements to [statements], corresponding to the
6574 // following code: 6686 // following code:
6575 // 6687 //
6576 // let iteratorReturn = iterator.return; 6688 // let iteratorReturn = iterator.return;
6577 // if (!IS_NULL_OR_UNDEFINED(iteratorReturn)) { 6689 // if (!IS_NULL_OR_UNDEFINED(iteratorReturn)) {
6578 // if (completion === BODY_THREW) { 6690 // if (completion === THROW) {
6579 // if (!IS_CALLABLE(iteratorReturn)) { 6691 // if (!IS_CALLABLE(iteratorReturn)) {
6580 // throw MakeTypeError(kReturnMethodNotCallable); 6692 // throw MakeTypeError(kReturnMethodNotCallable);
6581 // } 6693 // }
6582 // try { %_Call(iteratorReturn, iterator) } catch (_) { } 6694 // try { %_Call(iteratorReturn, iterator) } catch (_) { }
6583 // } else { 6695 // } else {
6584 // let output = %_Call(iteratorReturn, iterator); 6696 // let output = %_Call(iteratorReturn, iterator);
6585 // if (!IS_RECEIVER(output)) { 6697 // if (!IS_RECEIVER(output)) {
6586 // %ThrowIterResultNotAnObject(output); 6698 // %ThrowIterResultNotAnObject(output);
6587 // } 6699 // }
6588 // } 6700 // }
(...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after
6686 } 6798 }
6687 6799
6688 Statement* check_return = factory->NewIfStatement( 6800 Statement* check_return = factory->NewIfStatement(
6689 is_receiver_call, factory->NewEmptyStatement(nopos), throw_call, nopos); 6801 is_receiver_call, factory->NewEmptyStatement(nopos), throw_call, nopos);
6690 6802
6691 validate_return = factory->NewBlock(nullptr, 2, false, nopos); 6803 validate_return = factory->NewBlock(nullptr, 2, false, nopos);
6692 validate_return->statements()->Add(call_return, zone); 6804 validate_return->statements()->Add(call_return, zone);
6693 validate_return->statements()->Add(check_return, zone); 6805 validate_return->statements()->Add(check_return, zone);
6694 } 6806 }
6695 6807
6696 // if (completion === BODY_THREW) { 6808 // if (completion === THROW) {
6697 // #check_return_callable; 6809 // #check_return_callable;
6698 // #try_call_return; 6810 // #try_call_return;
6699 // } else { 6811 // } else {
6700 // #validate_return; 6812 // #validate_return;
6701 // } 6813 // }
6702 Statement* call_return_carefully; 6814 Statement* call_return_carefully;
6703 { 6815 {
6704 Expression* condition = factory->NewCompareOperation( 6816 Expression* condition = factory->NewCompareOperation(
6705 Token::EQ_STRICT, factory->NewVariableProxy(completion), 6817 Token::EQ_STRICT, factory->NewVariableProxy(completion),
6706 factory->NewSmiLiteral(BODY_THREW, nopos), nopos); 6818 factory->NewSmiLiteral(Parser::THROW, nopos), nopos);
6707 6819
6708 Block* then_block = factory->NewBlock(nullptr, 2, false, nopos); 6820 Block* then_block = factory->NewBlock(nullptr, 2, false, nopos);
6709 then_block->statements()->Add(check_return_callable, zone); 6821 then_block->statements()->Add(check_return_callable, zone);
6710 then_block->statements()->Add(try_call_return, zone); 6822 then_block->statements()->Add(try_call_return, zone);
6711 6823
6712 call_return_carefully = 6824 call_return_carefully =
6713 factory->NewIfStatement(condition, then_block, validate_return, nopos); 6825 factory->NewIfStatement(condition, then_block, validate_return, nopos);
6714 } 6826 }
6715 6827
6716 // if (!IS_NULL_OR_UNDEFINED(iteratorReturn)) { ... } 6828 // if (!IS_NULL_OR_UNDEFINED(iteratorReturn)) { ... }
(...skipping 13 matching lines...) Expand all
6730 statements->Add(maybe_call_return, zone); 6842 statements->Add(maybe_call_return, zone);
6731 } 6843 }
6732 6844
6733 6845
6734 Statement* ParserTraits::FinalizeForOfStatement(ForOfStatement* loop, int pos) { 6846 Statement* ParserTraits::FinalizeForOfStatement(ForOfStatement* loop, int pos) {
6735 if (!FLAG_harmony_iterator_close) return loop; 6847 if (!FLAG_harmony_iterator_close) return loop;
6736 6848
6737 // 6849 //
6738 // This function replaces the loop with the following wrapping: 6850 // This function replaces the loop with the following wrapping:
6739 // 6851 //
6740 // let completion = BODY_COMPLETED;
6741 // let each; 6852 // let each;
6853 // let completion = NORMAL;
6742 // try { 6854 // try {
6743 // #loop; 6855 // #loop;
6744 // } catch(e) { 6856 // } catch(e) {
6745 // if (completion === BODY_ABORTED) completion = BODY_THREW; 6857 // if (completion === ABRUPT) completion = THROW;
6746 // throw e; 6858 // throw e;
6747 // } finally { 6859 // } finally {
6748 // if (!(completion === BODY_COMPLETED || IS_UNDEFINED(#iterator))) { 6860 // if (!(completion === NORMAL || IS_UNDEFINED(#iterator))) {
6749 // #BuildIteratorCloseForCompletion(#iterator, completion) 6861 // #BuildIteratorCloseForCompletion(#iterator, completion)
6750 // } 6862 // }
6751 // } 6863 // }
6752 // 6864 //
6753 // where the loop's body is wrapped as follows: 6865 // where the loop's body is wrapped as follows:
6754 // 6866 //
6755 // { 6867 // {
6756 // #loop-body 6868 // #loop-body
6757 // {{completion = BODY_COMPLETED;}} 6869 // {{completion = NORMAL;}}
6758 // } 6870 // }
6759 // 6871 //
6760 // and assign_each is wrapped as follows 6872 // and the loop's assign_each is wrapped as follows
6761 // 6873 //
6762 // do { 6874 // do {
6763 // {{completion = BODY_ABORTED;}} 6875 // {{completion = ABRUPT;}}
6764 // #assign-each 6876 // #assign-each
6765 // } into each 6877 // }
6878 //
6766 6879
6767 const int nopos = RelocInfo::kNoPosition; 6880 const int nopos = RelocInfo::kNoPosition;
6768 auto factory = parser_->factory(); 6881 auto factory = parser_->factory();
6769 auto avfactory = parser_->ast_value_factory(); 6882 auto avfactory = parser_->ast_value_factory();
6770 auto scope = parser_->scope_; 6883 auto scope = parser_->scope_;
6771 auto zone = parser_->zone(); 6884 auto zone = parser_->zone();
6772 6885
6773 // let completion = BODY_COMPLETED;
6774 Variable* var_completion = scope->NewTemporary(avfactory->empty_string()); 6886 Variable* var_completion = scope->NewTemporary(avfactory->empty_string());
6775 Statement* initialize_completion;
6776 {
6777 Expression* proxy = factory->NewVariableProxy(var_completion);
6778 Expression* assignment = factory->NewAssignment(
6779 Token::ASSIGN, proxy,
6780 factory->NewSmiLiteral(BODY_COMPLETED, nopos), nopos);
6781 initialize_completion =
6782 factory->NewExpressionStatement(assignment, nopos);
6783 }
6784 6887
6785 // let each; 6888 // let each;
6786 Variable* var_each = scope->NewTemporary(avfactory->empty_string()); 6889 Variable* var_each = scope->NewTemporary(avfactory->empty_string());
6787 Statement* initialize_each; 6890 Statement* initialize_each;
6788 { 6891 {
6789 Expression* proxy = factory->NewVariableProxy(var_each); 6892 Expression* proxy = factory->NewVariableProxy(var_each);
6790 Expression* assignment = factory->NewAssignment( 6893 Expression* assignment = factory->NewAssignment(
6791 Token::ASSIGN, proxy, 6894 Token::ASSIGN, proxy,
6792 factory->NewUndefinedLiteral(nopos), nopos); 6895 factory->NewUndefinedLiteral(nopos), nopos);
6793 initialize_each = 6896 initialize_each =
6794 factory->NewExpressionStatement(assignment, nopos); 6897 factory->NewExpressionStatement(assignment, nopos);
6795 } 6898 }
6796 6899
6797 // if (completion === BODY_ABORTED) completion = BODY_THREW; 6900 // !(completion === NORMAL || IS_UNDEFINED(#iterator))
6798 Statement* set_completion_throw; 6901 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.
6799 { 6902 {
6800 Expression* condition = factory->NewCompareOperation( 6903 Expression* lhs = factory->NewCompareOperation(
6801 Token::EQ_STRICT, factory->NewVariableProxy(var_completion), 6904 Token::EQ_STRICT, factory->NewVariableProxy(var_completion),
6802 factory->NewSmiLiteral(BODY_ABORTED, nopos), nopos); 6905 factory->NewSmiLiteral(Parser::NORMAL, nopos), nopos);
6803 6906 Expression* rhs = factory->NewCompareOperation(
6804 Expression* proxy = factory->NewVariableProxy(var_completion); 6907 Token::EQ_STRICT, factory->NewVariableProxy(loop->iterator()),
6805 Expression* assignment = factory->NewAssignment( 6908 factory->NewUndefinedLiteral(nopos), nopos);
6806 Token::ASSIGN, proxy, factory->NewSmiLiteral(BODY_THREW, nopos), 6909 condition = factory->NewUnaryOperation(
6910 Token::NOT,
6911 factory->NewBinaryOperation(Token::OR, lhs, rhs, nopos),
6807 nopos); 6912 nopos);
6808 Statement* statement = factory->NewExpressionStatement(assignment, nopos);
6809 set_completion_throw = factory->NewIfStatement(
6810 condition, statement, factory->NewEmptyStatement(nopos), nopos);
6811 } 6913 }
6812 6914
6813 // if (!(completion === BODY_COMPLETED || IS_UNDEFINED(#iterator))) { 6915 // {{completion = NORMAL;}}
6814 // #BuildIteratorCloseForCompletion(#iterator, completion)
6815 // }
6816 Block* maybe_close;
6817 {
6818 Expression* condition1 = factory->NewCompareOperation(
6819 Token::EQ_STRICT, factory->NewVariableProxy(var_completion),
6820 factory->NewSmiLiteral(BODY_COMPLETED, nopos), nopos);
6821 Expression* condition2 = factory->NewCompareOperation(
6822 Token::EQ_STRICT, factory->NewVariableProxy(loop->iterator()),
6823 factory->NewUndefinedLiteral(nopos), nopos);
6824 Expression* condition = factory->NewBinaryOperation(
6825 Token::OR, condition1, condition2, nopos);
6826
6827 Block* block = factory->NewBlock(nullptr, 2, false, nopos);
6828 BuildIteratorCloseForCompletion(
6829 block->statements(), loop->iterator(), var_completion);
6830 DCHECK(block->statements()->length() == 2);
6831
6832 maybe_close = factory->NewBlock(nullptr, 1, false, nopos);
6833 maybe_close->statements()->Add(factory->NewIfStatement(
6834 condition, factory->NewEmptyStatement(nopos), block, nopos), zone);
6835 }
6836
6837 // try { #try_block }
6838 // catch(e) {
6839 // #set_completion_throw;
6840 // throw e;
6841 // }
6842 Statement* try_catch;
6843 {
6844 Scope* catch_scope = NewScope(scope, CATCH_SCOPE);
6845 Variable* catch_variable = catch_scope->DeclareLocal(
6846 avfactory->dot_catch_string(), VAR, kCreatedInitialized,
6847 Variable::NORMAL);
6848
6849 Statement* rethrow;
6850 {
6851 Expression* proxy = factory->NewVariableProxy(catch_variable);
6852 rethrow = factory->NewExpressionStatement(
6853 factory->NewThrow(proxy, nopos), nopos);
6854 }
6855
6856 Block* try_block = factory->NewBlock(nullptr, 1, false, nopos);
6857 try_block->statements()->Add(loop, zone);
6858
6859 Block* catch_block = factory->NewBlock(nullptr, 2, false, nopos);
6860 catch_block->statements()->Add(set_completion_throw, zone);
6861 catch_block->statements()->Add(rethrow, zone);
6862
6863 try_catch = factory->NewTryCatchStatement(
6864 try_block, catch_scope, catch_variable, catch_block, nopos);
6865 }
6866
6867 // try { #try_catch } finally { #maybe_close }
6868 Statement* try_finally;
6869 {
6870 Block* try_block = factory->NewBlock(nullptr, 1, false, nopos);
6871 try_block->statements()->Add(try_catch, zone);
6872
6873 try_finally =
6874 factory->NewTryFinallyStatement(try_block, maybe_close, nopos);
6875 }
6876
6877 // #initialize_completion;
6878 // #initialize_each;
6879 // #try_finally;
6880 Statement* final_loop;
6881 {
6882 Block* block = factory->NewBlock(nullptr, 2, false, nopos);
6883 block->statements()->Add(initialize_completion, zone);
6884 block->statements()->Add(initialize_each, zone);
6885 block->statements()->Add(try_finally, zone);
6886 final_loop = block;
6887 }
6888
6889 // {{completion = BODY_COMPLETED;}}
6890 Statement* set_completion_normal; 6916 Statement* set_completion_normal;
6891 { 6917 {
6892 Expression* proxy = factory->NewVariableProxy(var_completion); 6918 Expression* proxy = factory->NewVariableProxy(var_completion);
6893 Expression* assignment = factory->NewAssignment( 6919 Expression* assignment = factory->NewAssignment(
6894 Token::ASSIGN, proxy, factory->NewSmiLiteral(BODY_COMPLETED, nopos), 6920 Token::ASSIGN, proxy, factory->NewSmiLiteral(Parser::NORMAL, nopos),
6895 nopos); 6921 nopos);
6896 6922
6897 Block* block = factory->NewBlock(nullptr, 1, true, nopos); 6923 Block* block = factory->NewBlock(nullptr, 1, true, nopos);
6898 block->statements()->Add( 6924 block->statements()->Add(
6899 factory->NewExpressionStatement(assignment, nopos), zone); 6925 factory->NewExpressionStatement(assignment, nopos), zone);
6900 set_completion_normal = block; 6926 set_completion_normal = block;
6901 } 6927 }
6902 6928
6903 // { #loop-body; #set_completion_normal } 6929 // {{completion = ABRUPT;}}
6904 Block* new_body = factory->NewBlock(nullptr, 2, false, nopos); 6930 Statement* set_completion_abrupt;
6905 new_body->statements()->Add(loop->body(), zone);
6906 new_body->statements()->Add(set_completion_normal, zone);
6907
6908 loop->set_body(new_body);
6909
6910 // {{completion = BODY_ABORTED;}}
6911 Statement* set_completion_break;
6912 { 6931 {
6913 Expression* proxy = factory->NewVariableProxy(var_completion); 6932 Expression* proxy = factory->NewVariableProxy(var_completion);
6914 Expression* assignment = factory->NewAssignment( 6933 Expression* assignment = factory->NewAssignment(
6915 Token::ASSIGN, proxy, factory->NewSmiLiteral(BODY_ABORTED, nopos), 6934 Token::ASSIGN, proxy, factory->NewSmiLiteral(Parser::ABRUPT, nopos),
6916 nopos); 6935 nopos);
6917 6936
6918 Block* block = factory->NewBlock(nullptr, 1, true, nopos); 6937 Block* block = factory->NewBlock(nullptr, 1, true, nopos);
6919 block->statements()->Add(factory->NewExpressionStatement(assignment, nopos), 6938 block->statements()->Add(factory->NewExpressionStatement(assignment, nopos),
6920 zone); 6939 zone);
6921 set_completion_break = block; 6940 set_completion_abrupt = block;
6922 } 6941 }
6923 6942
6924 // { #set_completion_break; #assign-each } 6943 // { #loop-body; #set_completion_normal }
6944 Block* new_body = factory->NewBlock(nullptr, 2, false, nopos);
6945 {
6946 new_body->statements()->Add(loop->body(), zone);
6947 new_body->statements()->Add(set_completion_normal, zone);
6948 }
6949
6950 // { #set_completion_abrupt; #assign-each }
6925 Block* new_assign_each = factory->NewBlock(nullptr, 2, false, nopos); 6951 Block* new_assign_each = factory->NewBlock(nullptr, 2, false, nopos);
6926 new_assign_each->statements()->Add(set_completion_break, zone); 6952 {
6927 new_assign_each->statements()->Add( 6953 new_assign_each->statements()->Add(set_completion_abrupt, zone);
6928 factory->NewExpressionStatement(loop->assign_each(), nopos), zone); 6954 new_assign_each->statements()->Add(
6955 factory->NewExpressionStatement(loop->assign_each(), nopos), zone);
6956 }
6929 6957
6930 Expression* do_each = 6958 // Now put things together.
6931 factory->NewDoExpression(new_assign_each, var_each, nopos); 6959
6932 loop->set_assign_each(do_each); 6960 loop->set_body(new_body);
6961 loop->set_assign_each(
6962 factory->NewDoExpression(new_assign_each, var_each, nopos));
6963
6964 Statement* final_loop;
6965 {
6966 Block* target = factory->NewBlock(nullptr, 3, false, nopos);
6967 target->statements()->Add(initialize_each, zone);
6968
6969 Block* try_block = factory->NewBlock(nullptr, 1, false, nopos);
6970 try_block->statements()->Add(loop, zone);
6971
6972 FinalizeIteratorUse(
6973 var_completion, condition, loop->iterator(), try_block, target);
6974 final_loop = target;
6975 }
6933 6976
6934 return final_loop; 6977 return final_loop;
6935 } 6978 }
6936 6979
6937 6980
6938 } // namespace internal 6981 } // namespace internal
6939 } // namespace v8 6982 } // namespace v8
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698