Prevent un-parsed LiteralFunction reaching the compiler.

BUG=chromium:604044
LOG=Y

Review URL: https://codereview.chromium.org/1895123002

Cr-Commit-Position: refs/heads/master@{#35650}
This commit is contained in:
vogelheim 2016-04-20 02:33:01 -07:00 committed by Commit bot
parent 2489738d4a
commit ed9b7d92e7
4 changed files with 42 additions and 18 deletions

View File

@ -98,7 +98,6 @@ class ParserBase : public Traits {
v8::Extension* extension, AstValueFactory* ast_value_factory, v8::Extension* extension, AstValueFactory* ast_value_factory,
ParserRecorder* log, typename Traits::Type::Parser this_object) ParserRecorder* log, typename Traits::Type::Parser this_object)
: Traits(this_object), : Traits(this_object),
parenthesized_function_(false),
scope_(NULL), scope_(NULL),
function_state_(NULL), function_state_(NULL),
extension_(extension), extension_(extension),
@ -266,6 +265,14 @@ class ParserBase : public Traits {
return &non_patterns_to_rewrite_; return &non_patterns_to_rewrite_;
} }
void next_function_is_parenthesized(bool parenthesized) {
next_function_is_parenthesized_ = parenthesized;
}
bool this_function_is_parenthesized() const {
return this_function_is_parenthesized_;
}
private: private:
void AddDestructuringAssignment(DestructuringAssignment pair) { void AddDestructuringAssignment(DestructuringAssignment pair) {
destructuring_assignments_to_rewrite_.Add(pair); destructuring_assignments_to_rewrite_.Add(pair);
@ -312,6 +319,14 @@ class ParserBase : public Traits {
typename Traits::Type::Factory* factory_; typename Traits::Type::Factory* factory_;
// If true, the next (and immediately following) function literal is
// preceded by a parenthesis.
bool next_function_is_parenthesized_;
// The value of the parents' next_function_is_parenthesized_, as it applies
// to this function. Filled in by constructor.
bool this_function_is_parenthesized_;
friend class ParserTraits; friend class ParserTraits;
friend class PreParserTraits; friend class PreParserTraits;
friend class Checkpoint; friend class Checkpoint;
@ -888,12 +903,6 @@ class ParserBase : public Traits {
bool has_seen_constructor_; bool has_seen_constructor_;
}; };
// If true, the next (and immediately following) function literal is
// preceded by a parenthesis.
// Heuristically that means that the function will be called immediately,
// so never lazily compile it.
bool parenthesized_function_;
Scope* scope_; // Scope stack. Scope* scope_; // Scope stack.
FunctionState* function_state_; // Function state stack. FunctionState* function_state_; // Function state stack.
v8::Extension* extension_; v8::Extension* extension_;
@ -935,9 +944,16 @@ ParserBase<Traits>::FunctionState::FunctionState(
outer_scope_(*scope_stack), outer_scope_(*scope_stack),
collect_expressions_in_tail_position_(true), collect_expressions_in_tail_position_(true),
non_patterns_to_rewrite_(0, scope->zone()), non_patterns_to_rewrite_(0, scope->zone()),
factory_(factory) { factory_(factory),
next_function_is_parenthesized_(false),
this_function_is_parenthesized_(false) {
*scope_stack_ = scope; *scope_stack_ = scope;
*function_state_stack = this; *function_state_stack = this;
if (outer_function_state_) {
this_function_is_parenthesized_ =
outer_function_state_->next_function_is_parenthesized_;
outer_function_state_->next_function_is_parenthesized_ = false;
}
} }
@ -1303,7 +1319,8 @@ ParserBase<Traits>::ParsePrimaryExpression(ExpressionClassifier* classifier,
} }
// Heuristically try to detect immediately called functions before // Heuristically try to detect immediately called functions before
// seeing the call parentheses. // seeing the call parentheses.
parenthesized_function_ = (peek() == Token::FUNCTION); function_state_->next_function_is_parenthesized(peek() ==
Token::FUNCTION);
ExpressionT expr = this->ParseExpression(true, classifier, CHECK_OK); ExpressionT expr = this->ParseExpression(true, classifier, CHECK_OK);
Expect(Token::RPAREN, CHECK_OK); Expect(Token::RPAREN, CHECK_OK);
return expr; return expr;
@ -2837,7 +2854,6 @@ ParserBase<Traits>::ParseArrowFunctionLiteral(
} else { } else {
// Single-expression body // Single-expression body
int pos = position(); int pos = position();
parenthesized_function_ = false;
ExpressionClassifier classifier(this); ExpressionClassifier classifier(this);
ExpressionT expression = ExpressionT expression =
ParseAssignmentExpression(accept_IN, &classifier, CHECK_OK); ParseAssignmentExpression(accept_IN, &classifier, CHECK_OK);

View File

@ -3996,11 +3996,10 @@ FunctionLiteral* Parser::ParseFunctionLiteral(
int materialized_literal_count = -1; int materialized_literal_count = -1;
int expected_property_count = -1; int expected_property_count = -1;
DuplicateFinder duplicate_finder(scanner()->unicode_cache()); DuplicateFinder duplicate_finder(scanner()->unicode_cache());
FunctionLiteral::EagerCompileHint eager_compile_hint =
parenthesized_function_ ? FunctionLiteral::kShouldEagerCompile
: FunctionLiteral::kShouldLazyCompile;
bool should_be_used_once_hint = false; bool should_be_used_once_hint = false;
bool has_duplicate_parameters; bool has_duplicate_parameters;
FunctionLiteral::EagerCompileHint eager_compile_hint;
// Parse function. // Parse function.
{ {
AstNodeFactory function_factory(ast_value_factory()); AstNodeFactory function_factory(ast_value_factory());
@ -4009,6 +4008,10 @@ FunctionLiteral* Parser::ParseFunctionLiteral(
scope_->SetScopeName(function_name); scope_->SetScopeName(function_name);
ExpressionClassifier formals_classifier(this, &duplicate_finder); ExpressionClassifier formals_classifier(this, &duplicate_finder);
eager_compile_hint = function_state_->this_function_is_parenthesized()
? FunctionLiteral::kShouldEagerCompile
: FunctionLiteral::kShouldLazyCompile;
if (is_generator) { if (is_generator) {
// For generators, allocating variables in contexts is currently a win // For generators, allocating variables in contexts is currently a win
// because it minimizes the work needed to suspend and resume an // because it minimizes the work needed to suspend and resume an
@ -4077,8 +4080,7 @@ FunctionLiteral* Parser::ParseFunctionLiteral(
// logic where only top-level functions will be parsed lazily. // logic where only top-level functions will be parsed lazily.
bool is_lazily_parsed = mode() == PARSE_LAZILY && bool is_lazily_parsed = mode() == PARSE_LAZILY &&
scope_->AllowsLazyParsing() && scope_->AllowsLazyParsing() &&
!parenthesized_function_; !function_state_->this_function_is_parenthesized();
parenthesized_function_ = false; // The bit was set for this function only.
// Eager or lazy parse? // Eager or lazy parse?
// If is_lazily_parsed, we'll parse lazy. If we can set a bookmark, we'll // If is_lazily_parsed, we'll parse lazy. If we can set a bookmark, we'll

View File

@ -984,9 +984,8 @@ PreParser::Expression PreParser::ParseFunctionLiteral(
// See Parser::ParseFunctionLiteral for more information about lazy parsing // See Parser::ParseFunctionLiteral for more information about lazy parsing
// and lazy compilation. // and lazy compilation.
bool is_lazily_parsed = bool is_lazily_parsed = (outer_is_script_scope && allow_lazy() &&
(outer_is_script_scope && allow_lazy() && !parenthesized_function_); !function_state_->this_function_is_parenthesized());
parenthesized_function_ = false;
Expect(Token::LBRACE, CHECK_OK); Expect(Token::LBRACE, CHECK_OK);
if (is_lazily_parsed) { if (is_lazily_parsed) {

View File

@ -0,0 +1,7 @@
// Copyright 2016 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// Flags: --min-preparse-length 1
(function(_ = function() {}){})