Chromium Code Reviews| OLD | NEW |
|---|---|
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 |
| OLD | NEW |