Chromium Code Reviews| 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()); |