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

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: Use a seperate 'hint' bit for "to be executed once" code aging. Created 5 years, 7 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
« no previous file with comments | « src/preparser.h ('k') | src/scanner.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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());
« no previous file with comments | « src/preparser.h ('k') | src/scanner.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698