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

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: The Great Rebase Adventure. 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 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_lines = 0;
marja 2015/04/24 12:08:13 Nit: Not really lines, but statements
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:
marja 2015/04/24 12:08:13 Nit: ) -> '
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_lines > 200)) {
marja 2015/04/24 12:08:13 IMO clearer: if (!starts_with_identifier) maybe_r
262 if (count_lines > 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 783 matching lines...) Expand 10 before | Expand all | Expand 10 after
1037 kReferenceError); 1061 kReferenceError);
1038 *ok = false; 1062 *ok = false;
1039 return Expression::Default(); 1063 return Expression::Default();
1040 } 1064 }
1041 } 1065 }
1042 1066
1043 return Expression::Default(); 1067 return Expression::Default();
1044 } 1068 }
1045 1069
1046 1070
1047 void PreParser::ParseLazyFunctionLiteralBody(bool* ok) { 1071 void PreParser::ParseLazyFunctionLiteralBody(bool* ok,
1072 Scanner::BookmarkScope* bookmark) {
1048 int body_start = position(); 1073 int body_start = position();
1049 ParseStatementList(Token::RBRACE, ok); 1074 ParseStatementList(Token::RBRACE, ok, bookmark);
1050 if (!*ok) return; 1075 if (!*ok) return;
1076 if (bookmark && bookmark->HasBeenReset()) return;
1051 1077
1052 // Position right after terminal '}'. 1078 // Position right after terminal '}'.
1053 DCHECK_EQ(Token::RBRACE, scanner()->peek()); 1079 DCHECK_EQ(Token::RBRACE, scanner()->peek());
1054 int body_end = scanner()->peek_location().end_pos; 1080 int body_end = scanner()->peek_location().end_pos;
1055 log_->LogFunction(body_start, body_end, 1081 log_->LogFunction(body_start, body_end,
1056 function_state_->materialized_literal_count(), 1082 function_state_->materialized_literal_count(),
1057 function_state_->expected_property_count(), language_mode(), 1083 function_state_->expected_property_count(), language_mode(),
1058 scope_->uses_super_property()); 1084 scope_->uses_super_property());
1059 } 1085 }
1060 1086
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after
1134 1160
1135 DCHECK(!spread_pos.IsValid()); 1161 DCHECK(!spread_pos.IsValid());
1136 1162
1137 return Expression::Default(); 1163 return Expression::Default();
1138 } 1164 }
1139 1165
1140 #undef CHECK_OK 1166 #undef CHECK_OK
1141 1167
1142 1168
1143 } } // v8::internal 1169 } } // 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