From 086fe2199ba7849113413a21ceb38d167eb74176 Mon Sep 17 00:00:00 2001 From: ishell Date: Tue, 26 Apr 2016 02:05:48 -0700 Subject: [PATCH] [es6] Fix tail call elimination in single-expression arrow functions. BUG=v8:4698 LOG=Y Review URL: https://codereview.chromium.org/1921083002 Cr-Commit-Position: refs/heads/master@{#35786} --- src/parsing/parser-base.h | 4 ++++ src/parsing/parser.cc | 5 ++++- src/parsing/parser.h | 2 ++ src/parsing/preparser.h | 2 ++ test/mjsunit/es6/tail-call.js | 21 +++++++++++++++++++++ 5 files changed, 33 insertions(+), 1 deletion(-) diff --git a/src/parsing/parser-base.h b/src/parsing/parser-base.h index 868650afd9..530ce5aa18 100644 --- a/src/parsing/parser-base.h +++ b/src/parsing/parser-base.h @@ -2866,6 +2866,10 @@ ParserBase::ParseArrowFunctionLiteral( body->Add(factory()->NewReturnStatement(expression, pos), zone()); materialized_literal_count = function_state.materialized_literal_count(); expected_property_count = function_state.expected_property_count(); + // ES6 14.6.1 Static Semantics: IsInTailPosition + if (allow_tailcalls() && !is_sloppy(language_mode())) { + this->MarkTailPosition(expression); + } } super_loc = function_state.super_location(); diff --git a/src/parsing/parser.cc b/src/parsing/parser.cc index 8bd525af12..6e05fcbb01 100644 --- a/src/parsing/parser.cc +++ b/src/parsing/parser.cc @@ -762,6 +762,9 @@ ClassLiteral* ParserTraits::ParseClassLiteral( name_is_strict_reserved, pos, ok); } +void ParserTraits::MarkTailPosition(Expression* expression) { + expression->MarkTail(); +} Parser::Parser(ParseInfo* info) : ParserBase(info->zone(), &scanner_, info->stack_limit(), @@ -4573,7 +4576,7 @@ ZoneList* Parser::ParseEagerFunctionBody( const List& 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(); + MarkTailPosition(expressions_in_tail_position[i]); } return result; } diff --git a/src/parsing/parser.h b/src/parsing/parser.h index dab2f92c0a..3df630a4ef 100644 --- a/src/parsing/parser.h +++ b/src/parsing/parser.h @@ -572,6 +572,8 @@ class ParserTraits { bool name_is_strict_reserved, int pos, bool* ok); + V8_INLINE void MarkTailPosition(Expression* expression); + V8_INLINE void CheckConflictingVarDeclarations(v8::internal::Scope* scope, bool* ok); diff --git a/src/parsing/preparser.h b/src/parsing/preparser.h index e2b4edab0f..62581cf74d 100644 --- a/src/parsing/preparser.h +++ b/src/parsing/preparser.h @@ -887,6 +887,8 @@ class PreParserTraits { bool name_is_strict_reserved, int pos, bool* ok); + V8_INLINE void MarkTailPosition(PreParserExpression) {} + PreParserExpressionList PrepareSpreadArguments(PreParserExpressionList list) { return list; } diff --git a/test/mjsunit/es6/tail-call.js b/test/mjsunit/es6/tail-call.js index 3df53230ff..318519b355 100644 --- a/test/mjsunit/es6/tail-call.js +++ b/test/mjsunit/es6/tail-call.js @@ -392,3 +392,24 @@ function f_153(expected_call_stack, a) { %OptimizeFunctionOnNextCall(test); test(); })(); + + +// Test tail calls from arrow functions. +(function () { + function g1(a) { + return (() => { return f_153([f_153, test]); })(); + } + + function g2(a) { + return (() => f_153([f_153, test]))(); + } + + function test() { + assertEquals(153, g1()); + assertEquals(153, g2()); + } + test(); + test(); + %OptimizeFunctionOnNextCall(test); + test(); +})();