Index: src/preparser.cc |
diff --git a/src/preparser.cc b/src/preparser.cc |
index 95339dac33ca08b6b87bdf4bfed467c294a93280..e3c421ea140b8c3da40156c548880df358a2d4c1 100644 |
--- a/src/preparser.cc |
+++ b/src/preparser.cc |
@@ -99,7 +99,8 @@ PreParserExpression PreParserTraits::ParseFunctionLiteral( |
PreParser::PreParseResult PreParser::PreParseLazyFunction( |
- LanguageMode language_mode, FunctionKind kind, ParserRecorder* log) { |
+ LanguageMode language_mode, FunctionKind kind, ParserRecorder* log, |
+ Scanner::BookmarkScope* bookmark) { |
log_ = log; |
// Lazy functions always have trivial outer scopes (no with/catch scopes). |
Scope* top_scope = NewScope(scope_, SCRIPT_SCOPE); |
@@ -114,9 +115,12 @@ PreParser::PreParseResult PreParser::PreParseLazyFunction( |
DCHECK_EQ(Token::LBRACE, scanner()->current_token()); |
bool ok = true; |
int start_position = peek_position(); |
- ParseLazyFunctionLiteralBody(&ok); |
- if (stack_overflow()) return kPreParseStackOverflow; |
- if (!ok) { |
+ ParseLazyFunctionLiteralBody(&ok, bookmark); |
+ if (bookmark && bookmark->HasBeenReset()) { |
+ ; // Do nothing, as we've just aborted scanning this function. |
+ } else if (stack_overflow()) { |
+ return kPreParseStackOverflow; |
+ } else if (!ok) { |
ReportUnexpectedToken(scanner()->current_token()); |
} else { |
DCHECK_EQ(Token::RBRACE, scanner()->peek()); |
@@ -196,15 +200,22 @@ PreParser::Statement PreParser::ParseStatementListItem(bool* ok) { |
} |
-void PreParser::ParseStatementList(int end_token, bool* ok) { |
+void PreParser::ParseStatementList(int end_token, bool* ok, |
+ Scanner::BookmarkScope* bookmark) { |
// SourceElements :: |
// (Statement)* <end_token> |
+ // Bookkeeping for trial parse if bookmark is set: |
+ DCHECK_IMPLIES(bookmark, bookmark->HasBeenSet()); |
+ bool maybe_reset = bookmark != nullptr; |
+ int count_statements = 0; |
+ |
bool directive_prologue = true; |
while (peek() != end_token) { |
if (directive_prologue && peek() != Token::STRING) { |
directive_prologue = false; |
} |
+ bool starts_with_identifier = peek() == Token::IDENTIFIER; |
Scanner::Location token_loc = scanner()->peek_location(); |
Scanner::Location old_this_loc = function_state_->this_location(); |
Scanner::Location old_super_loc = function_state_->super_location(); |
@@ -241,6 +252,20 @@ void PreParser::ParseStatementList(int end_token, bool* ok) { |
directive_prologue = false; |
} |
} |
+ |
+ // If we're allowed to reset to a bookmark, we will do so when we see a long |
+ // and trivial function. |
+ // Our current definition of 'long and trivial' is: |
+ // - over 200 statements |
+ // - all starting with an identifier (i.e., no if, for, while, etc.) |
+ if (maybe_reset && (!starts_with_identifier || |
+ ++count_statements > kLazyParseTrialLimit)) { |
+ if (count_statements > kLazyParseTrialLimit) { |
+ bookmark->Reset(); |
+ return; |
+ } |
+ maybe_reset = false; |
+ } |
} |
} |
@@ -1057,10 +1082,12 @@ PreParser::Expression PreParser::ParseFunctionLiteral( |
} |
-void PreParser::ParseLazyFunctionLiteralBody(bool* ok) { |
+void PreParser::ParseLazyFunctionLiteralBody(bool* ok, |
+ Scanner::BookmarkScope* bookmark) { |
int body_start = position(); |
- ParseStatementList(Token::RBRACE, ok); |
+ ParseStatementList(Token::RBRACE, ok, bookmark); |
if (!*ok) return; |
+ if (bookmark && bookmark->HasBeenReset()) return; |
// Position right after terminal '}'. |
DCHECK_EQ(Token::RBRACE, scanner()->peek()); |