| 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 6000 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6011 // | 6011 // |
| 6012 // if (mode === kReturn) { | 6012 // if (mode === kReturn) { |
| 6013 // return {value: output.value, done: true}; | 6013 // return {value: output.value, done: true}; |
| 6014 // } | 6014 // } |
| 6015 // output.value | 6015 // output.value |
| 6016 // } | 6016 // } |
| 6017 // | 6017 // |
| 6018 // IteratorClose(iterator) expands to the following: | 6018 // IteratorClose(iterator) expands to the following: |
| 6019 // | 6019 // |
| 6020 // let iteratorReturn = iterator.return; | 6020 // let iteratorReturn = iterator.return; |
| 6021 // if (IS_NULL_OR_UNDEFINED(iteratorReturn)) return; | 6021 // if (!IS_NULL_OR_UNDEFINED(iteratorReturn)) { |
| 6022 // let output = %_Call(iteratorReturn, iterator); | 6022 // let output = %_Call(iteratorReturn, iterator); |
| 6023 // if (!IS_RECEIVER(output)) %ThrowIterResultNotAnObject(output); | 6023 // if (!IS_RECEIVER(output)) %ThrowIterResultNotAnObject(output); |
| 6024 // } |
| 6024 // | 6025 // |
| 6025 // IteratorClose(iterator, input, output) expands to the following: | 6026 // IteratorClose(iterator, input, output) expands to the following: |
| 6026 // | 6027 // |
| 6027 // let iteratorReturn = iterator.return; | 6028 // let iteratorReturn = iterator.return; |
| 6028 // if (IS_NULL_OR_UNDEFINED(iteratorReturn)) return input; | 6029 // if (IS_NULL_OR_UNDEFINED(iteratorReturn)) return input; |
| 6029 // output = %_Call(iteratorReturn, iterator, input); | 6030 // output = %_Call(iteratorReturn, iterator, input); |
| 6030 // if (!IS_RECEIVER(output)) %ThrowIterResultNotAnObject(output); | 6031 // if (!IS_RECEIVER(output)) %ThrowIterResultNotAnObject(output); |
| 6031 | 6032 |
| 6032 | |
| 6033 Expression* ParserTraits::RewriteYieldStar( | 6033 Expression* ParserTraits::RewriteYieldStar( |
| 6034 Expression* generator, Expression* iterable, int pos) { | 6034 Expression* generator, Expression* iterable, int pos) { |
| 6035 | 6035 |
| 6036 const int nopos = RelocInfo::kNoPosition; | 6036 const int nopos = RelocInfo::kNoPosition; |
| 6037 | 6037 |
| 6038 auto factory = parser_->factory(); | 6038 auto factory = parser_->factory(); |
| 6039 auto avfactory = parser_->ast_value_factory(); | 6039 auto avfactory = parser_->ast_value_factory(); |
| 6040 auto scope = parser_->scope_; | 6040 auto scope = parser_->scope_; |
| 6041 auto zone = parser_->zone(); | 6041 auto zone = parser_->zone(); |
| 6042 | 6042 |
| (...skipping 142 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6185 Expression* condition = factory->NewCompareOperation( | 6185 Expression* condition = factory->NewCompareOperation( |
| 6186 Token::EQ, factory->NewVariableProxy(var_throw), | 6186 Token::EQ, factory->NewVariableProxy(var_throw), |
| 6187 factory->NewNullLiteral(nopos), nopos); | 6187 factory->NewNullLiteral(nopos), nopos); |
| 6188 | 6188 |
| 6189 Expression* call = NewThrowTypeError( | 6189 Expression* call = NewThrowTypeError( |
| 6190 MessageTemplate::kThrowMethodMissing, | 6190 MessageTemplate::kThrowMethodMissing, |
| 6191 avfactory->empty_string(), nopos); | 6191 avfactory->empty_string(), nopos); |
| 6192 Statement* throw_call = factory->NewExpressionStatement(call, nopos); | 6192 Statement* throw_call = factory->NewExpressionStatement(call, nopos); |
| 6193 | 6193 |
| 6194 Block* then = factory->NewBlock(nullptr, 4+1, false, nopos); | 6194 Block* then = factory->NewBlock(nullptr, 4+1, false, nopos); |
| 6195 Variable* var_tmp = scope->NewTemporary(avfactory->empty_string()); | 6195 parser_->BuildIteratorCloseForCompletion( |
| 6196 BuildIteratorClose(then->statements(), var_iterator, Nothing<Variable*>(), | 6196 then->statements(), var_iterator, |
| 6197 var_tmp); | 6197 factory->NewSmiLiteral(Parser::kNormalCompletion, nopos)); |
| 6198 then->statements()->Add(throw_call, zone); | 6198 then->statements()->Add(throw_call, zone); |
| 6199 check_throw = factory->NewIfStatement( | 6199 check_throw = factory->NewIfStatement( |
| 6200 condition, then, factory->NewEmptyStatement(nopos), nopos); | 6200 condition, then, factory->NewEmptyStatement(nopos), nopos); |
| 6201 } | 6201 } |
| 6202 | 6202 |
| 6203 | 6203 |
| 6204 // output = %_Call(iteratorThrow, iterator, input); | 6204 // output = %_Call(iteratorThrow, iterator, input); |
| 6205 Statement* call_throw; | 6205 Statement* call_throw; |
| 6206 { | 6206 { |
| 6207 auto args = new (zone) ZoneList<Expression*>(3, zone); | 6207 auto args = new (zone) ZoneList<Expression*>(3, zone); |
| (...skipping 176 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6384 | 6384 |
| 6385 // switch (mode) { ... } | 6385 // switch (mode) { ... } |
| 6386 SwitchStatement* switch_mode = factory->NewSwitchStatement(nullptr, nopos); | 6386 SwitchStatement* switch_mode = factory->NewSwitchStatement(nullptr, nopos); |
| 6387 { | 6387 { |
| 6388 auto case_next = new (zone) ZoneList<Statement*>(3, zone); | 6388 auto case_next = new (zone) ZoneList<Statement*>(3, zone); |
| 6389 case_next->Add(call_next, zone); | 6389 case_next->Add(call_next, zone); |
| 6390 case_next->Add(validate_next_output, zone); | 6390 case_next->Add(validate_next_output, zone); |
| 6391 case_next->Add(factory->NewBreakStatement(switch_mode, nopos), zone); | 6391 case_next->Add(factory->NewBreakStatement(switch_mode, nopos), zone); |
| 6392 | 6392 |
| 6393 auto case_return = new (zone) ZoneList<Statement*>(5, zone); | 6393 auto case_return = new (zone) ZoneList<Statement*>(5, zone); |
| 6394 BuildIteratorClose(case_return, var_iterator, Just(var_input), var_output); | 6394 BuildIteratorClose(case_return, var_iterator, var_input, var_output); |
| 6395 case_return->Add(factory->NewBreakStatement(switch_mode, nopos), zone); | 6395 case_return->Add(factory->NewBreakStatement(switch_mode, nopos), zone); |
| 6396 | 6396 |
| 6397 auto case_throw = new (zone) ZoneList<Statement*>(5, zone); | 6397 auto case_throw = new (zone) ZoneList<Statement*>(5, zone); |
| 6398 case_throw->Add(get_throw, zone); | 6398 case_throw->Add(get_throw, zone); |
| 6399 case_throw->Add(check_throw, zone); | 6399 case_throw->Add(check_throw, zone); |
| 6400 case_throw->Add(call_throw, zone); | 6400 case_throw->Add(call_throw, zone); |
| 6401 case_throw->Add(validate_throw_output, zone); | 6401 case_throw->Add(validate_throw_output, zone); |
| 6402 case_throw->Add(factory->NewBreakStatement(switch_mode, nopos), zone); | 6402 case_throw->Add(factory->NewBreakStatement(switch_mode, nopos), zone); |
| 6403 | 6403 |
| 6404 auto cases = new (zone) ZoneList<CaseClause*>(3, zone); | 6404 auto cases = new (zone) ZoneList<CaseClause*>(3, zone); |
| (...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6471 | 6471 |
| 6472 Statement* throw_call = factory->NewExpressionStatement(error, pos); | 6472 Statement* throw_call = factory->NewExpressionStatement(error, pos); |
| 6473 | 6473 |
| 6474 validate_var = factory->NewIfStatement( | 6474 validate_var = factory->NewIfStatement( |
| 6475 condition, factory->NewEmptyStatement(nopos), throw_call, nopos); | 6475 condition, factory->NewEmptyStatement(nopos), throw_call, nopos); |
| 6476 } | 6476 } |
| 6477 return validate_var; | 6477 return validate_var; |
| 6478 } | 6478 } |
| 6479 | 6479 |
| 6480 void ParserTraits::BuildIteratorClose(ZoneList<Statement*>* statements, | 6480 void ParserTraits::BuildIteratorClose(ZoneList<Statement*>* statements, |
| 6481 Variable* iterator, | 6481 Variable* iterator, Variable* input, |
| 6482 Maybe<Variable*> input, | |
| 6483 Variable* var_output) { | 6482 Variable* var_output) { |
| 6484 // | 6483 // |
| 6485 // This function adds four statements to [statements], corresponding to the | 6484 // This function adds four statements to [statements], corresponding to the |
| 6486 // following code: | 6485 // following code: |
| 6487 // | 6486 // |
| 6488 // let iteratorReturn = iterator.return; | 6487 // let iteratorReturn = iterator.return; |
| 6489 // if (IS_NULL_OR_UNDEFINED(iteratorReturn) { | 6488 // if (IS_NULL_OR_UNDEFINED(iteratorReturn) { |
| 6490 // return {value: input, done: true}; | 6489 // return {value: input, done: true}; |
| 6491 // } | 6490 // } |
| 6492 // output = %_Call(iteratorReturn, iterator, input); | 6491 // output = %_Call(iteratorReturn, iterator, input); |
| 6493 // if (!IS_RECEIVER(output)) %ThrowIterResultNotAnObject(output); | 6492 // if (!IS_RECEIVER(output)) %ThrowIterResultNotAnObject(output); |
| 6494 // | 6493 // |
| 6495 // When the input variable is not given, the return statement becomes | |
| 6496 // return {value: undefined, done: true}; | |
| 6497 // and %_Call has only two arguments: | |
| 6498 // output = %_Call(iteratorReturn, iterator); | |
| 6499 // | |
| 6500 // The reason for allowing input is that BuildIteratorClose | |
| 6501 // can then be reused to handle the return case in yield*. | |
| 6502 // | |
| 6503 | 6494 |
| 6504 const int nopos = RelocInfo::kNoPosition; | 6495 const int nopos = RelocInfo::kNoPosition; |
| 6505 auto factory = parser_->factory(); | 6496 auto factory = parser_->factory(); |
| 6506 auto avfactory = parser_->ast_value_factory(); | 6497 auto avfactory = parser_->ast_value_factory(); |
| 6507 auto zone = parser_->zone(); | 6498 auto zone = parser_->zone(); |
| 6508 | 6499 |
| 6509 // let iteratorReturn = iterator.return; | 6500 // let iteratorReturn = iterator.return; |
| 6510 Variable* var_return = var_output; // Reusing the output variable. | 6501 Variable* var_return = var_output; // Reusing the output variable. |
| 6511 Statement* get_return; | 6502 Statement* get_return; |
| 6512 { | 6503 { |
| (...skipping 10 matching lines...) Expand all Loading... |
| 6523 | 6514 |
| 6524 // if (IS_NULL_OR_UNDEFINED(iteratorReturn) { | 6515 // if (IS_NULL_OR_UNDEFINED(iteratorReturn) { |
| 6525 // return {value: input, done: true}; | 6516 // return {value: input, done: true}; |
| 6526 // } | 6517 // } |
| 6527 Statement* check_return; | 6518 Statement* check_return; |
| 6528 { | 6519 { |
| 6529 Expression* condition = factory->NewCompareOperation( | 6520 Expression* condition = factory->NewCompareOperation( |
| 6530 Token::EQ, factory->NewVariableProxy(var_return), | 6521 Token::EQ, factory->NewVariableProxy(var_return), |
| 6531 factory->NewNullLiteral(nopos), nopos); | 6522 factory->NewNullLiteral(nopos), nopos); |
| 6532 | 6523 |
| 6533 Expression* value = input.IsJust() | 6524 Expression* value = factory->NewVariableProxy(input); |
| 6534 ? static_cast<Expression*>( | |
| 6535 factory->NewVariableProxy(input.FromJust())) | |
| 6536 : factory->NewUndefinedLiteral(nopos); | |
| 6537 | 6525 |
| 6538 Statement* return_input = | 6526 Statement* return_input = |
| 6539 factory->NewReturnStatement(BuildIteratorResult(value, true), nopos); | 6527 factory->NewReturnStatement(BuildIteratorResult(value, true), nopos); |
| 6540 | 6528 |
| 6541 check_return = factory->NewIfStatement( | 6529 check_return = factory->NewIfStatement( |
| 6542 condition, return_input, factory->NewEmptyStatement(nopos), nopos); | 6530 condition, return_input, factory->NewEmptyStatement(nopos), nopos); |
| 6543 } | 6531 } |
| 6544 | 6532 |
| 6545 // output = %_Call(iteratorReturn, iterator, input); | 6533 // output = %_Call(iteratorReturn, iterator, input); |
| 6546 Statement* call_return; | 6534 Statement* call_return; |
| 6547 { | 6535 { |
| 6548 auto args = new (zone) ZoneList<Expression*>(3, zone); | 6536 auto args = new (zone) ZoneList<Expression*>(3, zone); |
| 6549 args->Add(factory->NewVariableProxy(var_return), zone); | 6537 args->Add(factory->NewVariableProxy(var_return), zone); |
| 6550 args->Add(factory->NewVariableProxy(iterator), zone); | 6538 args->Add(factory->NewVariableProxy(iterator), zone); |
| 6551 if (input.IsJust()) { | 6539 args->Add(factory->NewVariableProxy(input), zone); |
| 6552 args->Add(factory->NewVariableProxy(input.FromJust()), zone); | |
| 6553 } | |
| 6554 | 6540 |
| 6555 Expression* call = | 6541 Expression* call = |
| 6556 factory->NewCallRuntime(Runtime::kInlineCall, args, nopos); | 6542 factory->NewCallRuntime(Runtime::kInlineCall, args, nopos); |
| 6557 Expression* output_proxy = factory->NewVariableProxy(var_output); | 6543 Expression* output_proxy = factory->NewVariableProxy(var_output); |
| 6558 Expression* assignment = factory->NewAssignment( | 6544 Expression* assignment = factory->NewAssignment( |
| 6559 Token::ASSIGN, output_proxy, call, nopos); | 6545 Token::ASSIGN, output_proxy, call, nopos); |
| 6560 call_return = factory->NewExpressionStatement(assignment, nopos); | 6546 call_return = factory->NewExpressionStatement(assignment, nopos); |
| 6561 } | 6547 } |
| 6562 | 6548 |
| 6563 // if (!IS_RECEIVER(output)) %ThrowIteratorResultNotAnObject(output); | 6549 // if (!IS_RECEIVER(output)) %ThrowIteratorResultNotAnObject(output); |
| (...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6643 set_completion_throw = factory->NewIfStatement( | 6629 set_completion_throw = factory->NewIfStatement( |
| 6644 condition, statement, factory->NewEmptyStatement(nopos), nopos); | 6630 condition, statement, factory->NewEmptyStatement(nopos), nopos); |
| 6645 } | 6631 } |
| 6646 | 6632 |
| 6647 // if (condition) { | 6633 // if (condition) { |
| 6648 // #BuildIteratorCloseForCompletion(iter, completion) | 6634 // #BuildIteratorCloseForCompletion(iter, completion) |
| 6649 // } | 6635 // } |
| 6650 Block* maybe_close; | 6636 Block* maybe_close; |
| 6651 { | 6637 { |
| 6652 Block* block = factory->NewBlock(nullptr, 2, true, nopos); | 6638 Block* block = factory->NewBlock(nullptr, 2, true, nopos); |
| 6653 parser_->BuildIteratorCloseForCompletion(block->statements(), iter, | 6639 Expression* proxy = factory->NewVariableProxy(completion); |
| 6654 completion); | 6640 parser_->BuildIteratorCloseForCompletion(block->statements(), iter, proxy); |
| 6655 DCHECK(block->statements()->length() == 2); | 6641 DCHECK(block->statements()->length() == 2); |
| 6656 | 6642 |
| 6657 maybe_close = factory->NewBlock(nullptr, 1, true, nopos); | 6643 maybe_close = factory->NewBlock(nullptr, 1, true, nopos); |
| 6658 maybe_close->statements()->Add( | 6644 maybe_close->statements()->Add( |
| 6659 factory->NewIfStatement(condition, block, | 6645 factory->NewIfStatement(condition, block, |
| 6660 factory->NewEmptyStatement(nopos), nopos), | 6646 factory->NewEmptyStatement(nopos), nopos), |
| 6661 zone); | 6647 zone); |
| 6662 } | 6648 } |
| 6663 | 6649 |
| 6664 // try { #try_block } | 6650 // try { #try_block } |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6703 try_finally = | 6689 try_finally = |
| 6704 factory->NewTryFinallyStatement(try_block, maybe_close, nopos); | 6690 factory->NewTryFinallyStatement(try_block, maybe_close, nopos); |
| 6705 } | 6691 } |
| 6706 | 6692 |
| 6707 target->statements()->Add(initialize_completion, zone); | 6693 target->statements()->Add(initialize_completion, zone); |
| 6708 target->statements()->Add(try_finally, zone); | 6694 target->statements()->Add(try_finally, zone); |
| 6709 } | 6695 } |
| 6710 | 6696 |
| 6711 void ParserTraits::BuildIteratorCloseForCompletion( | 6697 void ParserTraits::BuildIteratorCloseForCompletion( |
| 6712 ZoneList<Statement*>* statements, Variable* iterator, | 6698 ZoneList<Statement*>* statements, Variable* iterator, |
| 6713 Variable* completion) { | 6699 Expression* completion) { |
| 6714 // | 6700 // |
| 6715 // This function adds two statements to [statements], corresponding to the | 6701 // This function adds two statements to [statements], corresponding to the |
| 6716 // following code: | 6702 // following code: |
| 6717 // | 6703 // |
| 6718 // let iteratorReturn = iterator.return; | 6704 // let iteratorReturn = iterator.return; |
| 6719 // if (!IS_NULL_OR_UNDEFINED(iteratorReturn)) { | 6705 // if (!IS_NULL_OR_UNDEFINED(iteratorReturn)) { |
| 6720 // if (completion === kThrowCompletion) { | 6706 // if (completion === kThrowCompletion) { |
| 6721 // if (!IS_CALLABLE(iteratorReturn)) { | 6707 // if (!IS_CALLABLE(iteratorReturn)) { |
| 6722 // throw MakeTypeError(kReturnMethodNotCallable); | 6708 // throw MakeTypeError(kReturnMethodNotCallable); |
| 6723 // } | 6709 // } |
| (...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6838 | 6824 |
| 6839 // if (completion === kThrowCompletion) { | 6825 // if (completion === kThrowCompletion) { |
| 6840 // #check_return_callable; | 6826 // #check_return_callable; |
| 6841 // #try_call_return; | 6827 // #try_call_return; |
| 6842 // } else { | 6828 // } else { |
| 6843 // #validate_return; | 6829 // #validate_return; |
| 6844 // } | 6830 // } |
| 6845 Statement* call_return_carefully; | 6831 Statement* call_return_carefully; |
| 6846 { | 6832 { |
| 6847 Expression* condition = factory->NewCompareOperation( | 6833 Expression* condition = factory->NewCompareOperation( |
| 6848 Token::EQ_STRICT, factory->NewVariableProxy(completion), | 6834 Token::EQ_STRICT, completion, |
| 6849 factory->NewSmiLiteral(Parser::kThrowCompletion, nopos), nopos); | 6835 factory->NewSmiLiteral(Parser::kThrowCompletion, nopos), nopos); |
| 6850 | 6836 |
| 6851 Block* then_block = factory->NewBlock(nullptr, 2, false, nopos); | 6837 Block* then_block = factory->NewBlock(nullptr, 2, false, nopos); |
| 6852 then_block->statements()->Add(check_return_callable, zone); | 6838 then_block->statements()->Add(check_return_callable, zone); |
| 6853 then_block->statements()->Add(try_call_return, zone); | 6839 then_block->statements()->Add(try_call_return, zone); |
| 6854 | 6840 |
| 6855 call_return_carefully = | 6841 call_return_carefully = |
| 6856 factory->NewIfStatement(condition, then_block, validate_return, nopos); | 6842 factory->NewIfStatement(condition, then_block, validate_return, nopos); |
| 6857 } | 6843 } |
| 6858 | 6844 |
| (...skipping 144 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 7003 try_block, target); | 6989 try_block, target); |
| 7004 final_loop = target; | 6990 final_loop = target; |
| 7005 } | 6991 } |
| 7006 | 6992 |
| 7007 return final_loop; | 6993 return final_loop; |
| 7008 } | 6994 } |
| 7009 | 6995 |
| 7010 | 6996 |
| 7011 } // namespace internal | 6997 } // namespace internal |
| 7012 } // namespace v8 | 6998 } // namespace v8 |
| OLD | NEW |