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

Side by Side Diff: src/parsing/parser.cc

Issue 2094253002: Fix behavior of throw on yield*. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Rebase Created 4 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/parsing/parser.h ('k') | test/mjsunit/harmony/generators.js » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 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
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
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
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
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
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
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
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
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
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
OLDNEW
« no previous file with comments | « src/parsing/parser.h ('k') | test/mjsunit/harmony/generators.js » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698