| Index: src/parsing/parser.cc
|
| diff --git a/src/parsing/parser.cc b/src/parsing/parser.cc
|
| index cd7691efc6471fb04537166c23331427701f4578..444b20cbf87352cdd4b214938e837c2a7b3b2b52 100644
|
| --- a/src/parsing/parser.cc
|
| +++ b/src/parsing/parser.cc
|
| @@ -2792,6 +2792,11 @@ Statement* Parser::ParseReturnStatement(bool* ok) {
|
| is_undefined, ThisExpression(scope_, factory(), pos),
|
| is_object_conditional, pos);
|
| }
|
| +
|
| + // ES6 14.6.1 Static Semantics: IsInTailPosition
|
| + if (FLAG_harmony_tailcalls && !is_sloppy(language_mode())) {
|
| + function_state_->AddExpressionInTailPosition(return_value);
|
| + }
|
| }
|
| ExpectSemicolon(CHECK_OK);
|
|
|
| @@ -2997,6 +3002,40 @@ Statement* Parser::ParseThrowStatement(bool* ok) {
|
| factory()->NewThrow(exception, pos), pos);
|
| }
|
|
|
| +class Parser::DontCollectExpressionsInTailPositionScope {
|
| + public:
|
| + DontCollectExpressionsInTailPositionScope(
|
| + Parser::FunctionState* function_state)
|
| + : function_state_(function_state),
|
| + old_value_(function_state->collect_expressions_in_tail_position()) {
|
| + function_state->set_collect_expressions_in_tail_position(false);
|
| + }
|
| + ~DontCollectExpressionsInTailPositionScope() {
|
| + function_state_->set_collect_expressions_in_tail_position(old_value_);
|
| + }
|
| +
|
| + private:
|
| + Parser::FunctionState* function_state_;
|
| + bool old_value_;
|
| +};
|
| +
|
| +// Collects all return expressions at tail call position in this scope
|
| +// to a separate list.
|
| +class Parser::CollectExpressionsInTailPositionToListScope {
|
| + public:
|
| + CollectExpressionsInTailPositionToListScope(
|
| + Parser::FunctionState* function_state, List<Expression*>* list)
|
| + : function_state_(function_state), list_(list) {
|
| + function_state->expressions_in_tail_position().Swap(list_);
|
| + }
|
| + ~CollectExpressionsInTailPositionToListScope() {
|
| + function_state_->expressions_in_tail_position().Swap(list_);
|
| + }
|
| +
|
| + private:
|
| + Parser::FunctionState* function_state_;
|
| + List<Expression*>* list_;
|
| +};
|
|
|
| TryStatement* Parser::ParseTryStatement(bool* ok) {
|
| // TryStatement ::
|
| @@ -3013,7 +3052,11 @@ TryStatement* Parser::ParseTryStatement(bool* ok) {
|
| Expect(Token::TRY, CHECK_OK);
|
| int pos = position();
|
|
|
| - Block* try_block = ParseBlock(NULL, CHECK_OK);
|
| + Block* try_block;
|
| + {
|
| + DontCollectExpressionsInTailPositionScope no_tail_calls(function_state_);
|
| + try_block = ParseBlock(NULL, CHECK_OK);
|
| + }
|
|
|
| Token::Value tok = peek();
|
| if (tok != Token::CATCH && tok != Token::FINALLY) {
|
| @@ -3025,6 +3068,7 @@ TryStatement* Parser::ParseTryStatement(bool* ok) {
|
| Scope* catch_scope = NULL;
|
| Variable* catch_variable = NULL;
|
| Block* catch_block = NULL;
|
| + List<Expression*> expressions_in_tail_position_in_catch_block;
|
| if (tok == Token::CATCH) {
|
| Consume(Token::CATCH);
|
|
|
| @@ -3050,6 +3094,9 @@ TryStatement* Parser::ParseTryStatement(bool* ok) {
|
| Expect(Token::RPAREN, CHECK_OK);
|
|
|
| {
|
| + CollectExpressionsInTailPositionToListScope
|
| + collect_expressions_in_tail_position_scope(
|
| + function_state_, &expressions_in_tail_position_in_catch_block);
|
| BlockState block_state(&scope_, catch_scope);
|
|
|
| // TODO(adamk): Make a version of ParseBlock that takes a scope and
|
| @@ -3124,6 +3171,11 @@ TryStatement* Parser::ParseTryStatement(bool* ok) {
|
|
|
| TryStatement* result = NULL;
|
| if (catch_block != NULL) {
|
| + // For a try-catch construct append return expressions from the catch block
|
| + // to the list of return expressions.
|
| + function_state_->expressions_in_tail_position().AddAll(
|
| + expressions_in_tail_position_in_catch_block);
|
| +
|
| DCHECK(finally_block == NULL);
|
| DCHECK(catch_scope != NULL && catch_variable != NULL);
|
| result = factory()->NewTryCatchStatement(try_block, catch_scope,
|
| @@ -4751,11 +4803,11 @@ ZoneList<Statement*>* Parser::ParseEagerFunctionBody(
|
| }
|
|
|
| // ES6 14.6.1 Static Semantics: IsInTailPosition
|
| - if (FLAG_harmony_tailcalls && !is_sloppy(language_mode())) {
|
| - for (int i = 0; i < body->length(); i++) {
|
| - Statement* stmt = body->at(i);
|
| - stmt->MarkTail();
|
| - }
|
| + // Mark collected return expressions that are in tail call position.
|
| + const List<Expression*>& expressions_in_tail_position =
|
| + function_state_->expressions_in_tail_position();
|
| + for (int i = 0; i < expressions_in_tail_position.length(); ++i) {
|
| + expressions_in_tail_position[i]->MarkTail();
|
| }
|
| return result;
|
| }
|
|
|