Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(133)

Unified Diff: src/preparser.cc

Issue 1102523003: Implement a 'trial parse' step, that will abort pre-parsing excessively (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Created 5 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
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());

Powered by Google App Engine
This is Rietveld 408576698