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

Side by Side 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: Improve comments + naming. (Marja's feedback.) 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 unified diff | Download patch
« no previous file with comments | « src/preparser.h ('k') | src/scanner.h » ('j') | src/scanner.h » ('J')
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2011 the V8 project authors. All rights reserved. 1 // Copyright 2011 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include <cmath> 5 #include <cmath>
6 6
7 #include "src/allocation.h" 7 #include "src/allocation.h"
8 #include "src/base/logging.h" 8 #include "src/base/logging.h"
9 #include "src/conversions-inl.h" 9 #include "src/conversions-inl.h"
10 #include "src/conversions.h" 10 #include "src/conversions.h"
(...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after
92 bool name_is_strict_reserved, FunctionKind kind, 92 bool name_is_strict_reserved, FunctionKind kind,
93 int function_token_position, FunctionLiteral::FunctionType type, 93 int function_token_position, FunctionLiteral::FunctionType type,
94 FunctionLiteral::ArityRestriction arity_restriction, bool* ok) { 94 FunctionLiteral::ArityRestriction arity_restriction, bool* ok) {
95 return pre_parser_->ParseFunctionLiteral( 95 return pre_parser_->ParseFunctionLiteral(
96 name, function_name_location, name_is_strict_reserved, kind, 96 name, function_name_location, name_is_strict_reserved, kind,
97 function_token_position, type, arity_restriction, ok); 97 function_token_position, type, arity_restriction, ok);
98 } 98 }
99 99
100 100
101 PreParser::PreParseResult PreParser::PreParseLazyFunction( 101 PreParser::PreParseResult PreParser::PreParseLazyFunction(
102 LanguageMode language_mode, FunctionKind kind, ParserRecorder* log) { 102 LanguageMode language_mode, FunctionKind kind, ParserRecorder* log,
103 Scanner::BookmarkScope* bookmark) {
103 log_ = log; 104 log_ = log;
104 // Lazy functions always have trivial outer scopes (no with/catch scopes). 105 // Lazy functions always have trivial outer scopes (no with/catch scopes).
105 Scope* top_scope = NewScope(scope_, SCRIPT_SCOPE); 106 Scope* top_scope = NewScope(scope_, SCRIPT_SCOPE);
106 PreParserFactory top_factory(NULL); 107 PreParserFactory top_factory(NULL);
107 FunctionState top_state(&function_state_, &scope_, top_scope, kNormalFunction, 108 FunctionState top_state(&function_state_, &scope_, top_scope, kNormalFunction,
108 &top_factory); 109 &top_factory);
109 scope_->SetLanguageMode(language_mode); 110 scope_->SetLanguageMode(language_mode);
110 Scope* function_scope = NewScope(scope_, FUNCTION_SCOPE); 111 Scope* function_scope = NewScope(scope_, FUNCTION_SCOPE);
111 PreParserFactory function_factory(NULL); 112 PreParserFactory function_factory(NULL);
112 FunctionState function_state(&function_state_, &scope_, function_scope, kind, 113 FunctionState function_state(&function_state_, &scope_, function_scope, kind,
113 &function_factory); 114 &function_factory);
114 DCHECK_EQ(Token::LBRACE, scanner()->current_token()); 115 DCHECK_EQ(Token::LBRACE, scanner()->current_token());
115 bool ok = true; 116 bool ok = true;
116 int start_position = peek_position(); 117 int start_position = peek_position();
117 ParseLazyFunctionLiteralBody(&ok); 118 ParseLazyFunctionLiteralBody(&ok, bookmark);
118 if (stack_overflow()) return kPreParseStackOverflow; 119 if (bookmark && bookmark->HasBeenReset()) {
119 if (!ok) { 120 ; // Do nothing, as we've just aborted scanning this function.
121 } else if (stack_overflow()) {
122 return kPreParseStackOverflow;
123 } else if (!ok) {
120 ReportUnexpectedToken(scanner()->current_token()); 124 ReportUnexpectedToken(scanner()->current_token());
121 } else { 125 } else {
122 DCHECK_EQ(Token::RBRACE, scanner()->peek()); 126 DCHECK_EQ(Token::RBRACE, scanner()->peek());
123 if (is_strict(scope_->language_mode())) { 127 if (is_strict(scope_->language_mode())) {
124 int end_pos = scanner()->location().end_pos; 128 int end_pos = scanner()->location().end_pos;
125 CheckStrictOctalLiteral(start_position, end_pos, &ok); 129 CheckStrictOctalLiteral(start_position, end_pos, &ok);
126 if (!ok) return kPreParseSuccess; 130 if (!ok) return kPreParseSuccess;
127 131
128 if (is_strong(scope_->language_mode()) && IsSubclassConstructor(kind)) { 132 if (is_strong(scope_->language_mode()) && IsSubclassConstructor(kind)) {
129 if (!function_state.super_location().IsValid()) { 133 if (!function_state.super_location().IsValid()) {
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after
189 if (is_strict(language_mode())) { 193 if (is_strict(language_mode())) {
190 return ParseVariableStatement(kStatementListItem, ok); 194 return ParseVariableStatement(kStatementListItem, ok);
191 } 195 }
192 // Fall through. 196 // Fall through.
193 default: 197 default:
194 return ParseStatement(ok); 198 return ParseStatement(ok);
195 } 199 }
196 } 200 }
197 201
198 202
199 void PreParser::ParseStatementList(int end_token, bool* ok) { 203 void PreParser::ParseStatementList(int end_token, bool* ok,
204 Scanner::BookmarkScope* bookmark) {
200 // SourceElements :: 205 // SourceElements ::
201 // (Statement)* <end_token> 206 // (Statement)* <end_token>
202 207
208 // Bookkeeping for trial parse if bookmark is set:
209 DCHECK_IMPLIES(bookmark, bookmark->HasBeenSet());
210 bool maybe_reset = bookmark != nullptr;
211 int count_statements = 0;
212
203 bool directive_prologue = true; 213 bool directive_prologue = true;
204 while (peek() != end_token) { 214 while (peek() != end_token) {
205 if (directive_prologue && peek() != Token::STRING) { 215 if (directive_prologue && peek() != Token::STRING) {
206 directive_prologue = false; 216 directive_prologue = false;
207 } 217 }
218 bool starts_with_identifier = peek() == Token::IDENTIFIER;
208 Scanner::Location token_loc = scanner()->peek_location(); 219 Scanner::Location token_loc = scanner()->peek_location();
209 Scanner::Location old_this_loc = function_state_->this_location(); 220 Scanner::Location old_this_loc = function_state_->this_location();
210 Scanner::Location old_super_loc = function_state_->super_location(); 221 Scanner::Location old_super_loc = function_state_->super_location();
211 Statement statement = ParseStatementListItem(ok); 222 Statement statement = ParseStatementListItem(ok);
212 if (!*ok) return; 223 if (!*ok) return;
213 224
214 if (is_strong(language_mode()) && 225 if (is_strong(language_mode()) &&
215 scope_->is_function_scope() && 226 scope_->is_function_scope() &&
216 i::IsConstructor(function_state_->kind())) { 227 i::IsConstructor(function_state_->kind())) {
217 Scanner::Location this_loc = function_state_->this_location(); 228 Scanner::Location this_loc = function_state_->this_location();
(...skipping 16 matching lines...) Expand all
234 if (statement.IsUseStrictLiteral()) { 245 if (statement.IsUseStrictLiteral()) {
235 scope_->SetLanguageMode( 246 scope_->SetLanguageMode(
236 static_cast<LanguageMode>(scope_->language_mode() | STRICT_BIT)); 247 static_cast<LanguageMode>(scope_->language_mode() | STRICT_BIT));
237 } else if (statement.IsUseStrongLiteral() && allow_strong_mode()) { 248 } else if (statement.IsUseStrongLiteral() && allow_strong_mode()) {
238 scope_->SetLanguageMode(static_cast<LanguageMode>( 249 scope_->SetLanguageMode(static_cast<LanguageMode>(
239 scope_->language_mode() | STRICT_BIT | STRONG_BIT)); 250 scope_->language_mode() | STRICT_BIT | STRONG_BIT));
240 } else if (!statement.IsStringLiteral()) { 251 } else if (!statement.IsStringLiteral()) {
241 directive_prologue = false; 252 directive_prologue = false;
242 } 253 }
243 } 254 }
255
256 // If we're allowed to reset to a bookmark, we will do so when we see a long
257 // and trivial function.
258 // Our current definition of 'long and trivial' is:
259 // - over 200 statements
260 // - all starting with an identifier (i.e., no if, for, while, etc.)
261 if (maybe_reset && (!starts_with_identifier || ++count_statements > 200)) {
jochen (gone - plz use gerrit) 2015/04/30 13:20:18 can we define 200 has a const?
vogelheim 2015/04/30 15:35:05 Done.
262 if (count_statements > 200) {
263 bookmark->Reset();
264 return;
265 }
266 maybe_reset = false;
267 }
244 } 268 }
245 } 269 }
246 270
247 271
248 #define CHECK_OK ok); \ 272 #define CHECK_OK ok); \
249 if (!*ok) return Statement::Default(); \ 273 if (!*ok) return Statement::Default(); \
250 ((void)0 274 ((void)0
251 #define DUMMY ) // to make indentation work 275 #define DUMMY ) // to make indentation work
252 #undef DUMMY 276 #undef DUMMY
253 277
(...skipping 796 matching lines...) Expand 10 before | Expand all | Expand 10 after
1050 kReferenceError); 1074 kReferenceError);
1051 *ok = false; 1075 *ok = false;
1052 return Expression::Default(); 1076 return Expression::Default();
1053 } 1077 }
1054 } 1078 }
1055 1079
1056 return Expression::Default(); 1080 return Expression::Default();
1057 } 1081 }
1058 1082
1059 1083
1060 void PreParser::ParseLazyFunctionLiteralBody(bool* ok) { 1084 void PreParser::ParseLazyFunctionLiteralBody(bool* ok,
1085 Scanner::BookmarkScope* bookmark) {
1061 int body_start = position(); 1086 int body_start = position();
1062 ParseStatementList(Token::RBRACE, ok); 1087 ParseStatementList(Token::RBRACE, ok, bookmark);
1063 if (!*ok) return; 1088 if (!*ok) return;
1089 if (bookmark && bookmark->HasBeenReset()) return;
1064 1090
1065 // Position right after terminal '}'. 1091 // Position right after terminal '}'.
1066 DCHECK_EQ(Token::RBRACE, scanner()->peek()); 1092 DCHECK_EQ(Token::RBRACE, scanner()->peek());
1067 int body_end = scanner()->peek_location().end_pos; 1093 int body_end = scanner()->peek_location().end_pos;
1068 log_->LogFunction(body_start, body_end, 1094 log_->LogFunction(body_start, body_end,
1069 function_state_->materialized_literal_count(), 1095 function_state_->materialized_literal_count(),
1070 function_state_->expected_property_count(), language_mode(), 1096 function_state_->expected_property_count(), language_mode(),
1071 scope_->uses_super_property()); 1097 scope_->uses_super_property());
1072 } 1098 }
1073 1099
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after
1147 1173
1148 DCHECK(!spread_pos.IsValid()); 1174 DCHECK(!spread_pos.IsValid());
1149 1175
1150 return Expression::Default(); 1176 return Expression::Default();
1151 } 1177 }
1152 1178
1153 #undef CHECK_OK 1179 #undef CHECK_OK
1154 1180
1155 1181
1156 } } // v8::internal 1182 } } // v8::internal
OLDNEW
« no previous file with comments | « src/preparser.h ('k') | src/scanner.h » ('j') | src/scanner.h » ('J')

Powered by Google App Engine
This is Rietveld 408576698