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:
parent
2489738d4a
commit
ed9b7d92e7
@ -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);
|
||||||
|
@ -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
|
||||||
|
@ -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) {
|
||||||
|
7
test/mjsunit/regress-604044.js
Normal file
7
test/mjsunit/regress-604044.js
Normal 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() {}){})
|
Loading…
Reference in New Issue
Block a user