[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}
This commit is contained in:
ishell 2016-04-26 02:05:48 -07:00 committed by Commit bot
parent f38932c794
commit 086fe2199b
5 changed files with 33 additions and 1 deletions

View File

@ -2866,6 +2866,10 @@ ParserBase<Traits>::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();

View File

@ -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<ParserTraits>(info->zone(), &scanner_, info->stack_limit(),
@ -4573,7 +4576,7 @@ ZoneList<Statement*>* Parser::ParseEagerFunctionBody(
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();
MarkTailPosition(expressions_in_tail_position[i]);
}
return result;
}

View File

@ -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);

View File

@ -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;
}

View File

@ -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();
})();