Index: src/preparser.cc |
diff --git a/src/preparser.cc b/src/preparser.cc |
index 4371cdb27b1c703d001937296774e5135eec9169..d809bd8db6a9114f6bdc3aecbe4a6de5c36e0bfe 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()); |
@@ -187,10 +191,17 @@ 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 start_pos = scanner()->location().beg_pos; |
+ int count_lines = 0; |
+ |
bool directive_prologue = true; |
while (peek() != end_token) { |
if (directive_prologue && peek() != Token::STRING) { |
@@ -220,6 +231,24 @@ 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: |
+ // - within the first 10k characters, |
+ // - over 200 statements |
+ // - all starting with an identifier (i.e., no if, for, while, etc.) |
+ if (maybe_reset) { |
+ if (token != Token::IDENTIFIER) { |
+ maybe_reset = false; |
+ } else if (scanner()->location().end_pos - start_pos > 10000) { |
+ maybe_reset = false; |
+ if (count_lines++ > 200 && bookmark->CanReset()) { |
marja
2015/04/22 16:40:55
Hmm, I find this is quite a late point to check wh
vogelheim
2015/04/22 17:08:35
The code certainly gets a lot cleaner if we can pr
|
+ bookmark->Reset(); |
+ return; |
+ } |
+ } |
+ } |
} |
} |
@@ -1023,10 +1052,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()); |