OLD | NEW |
---|---|
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 Loading... | |
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 } | 130 } |
127 } | 131 } |
128 return kPreParseSuccess; | 132 return kPreParseSuccess; |
129 } | 133 } |
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
180 if (is_strict(language_mode())) { | 184 if (is_strict(language_mode())) { |
181 return ParseVariableStatement(kStatementListItem, ok); | 185 return ParseVariableStatement(kStatementListItem, ok); |
182 } | 186 } |
183 // Fall through. | 187 // Fall through. |
184 default: | 188 default: |
185 return ParseStatement(ok); | 189 return ParseStatement(ok); |
186 } | 190 } |
187 } | 191 } |
188 | 192 |
189 | 193 |
190 void PreParser::ParseStatementList(int end_token, bool* ok) { | 194 void PreParser::ParseStatementList(int end_token, bool* ok, |
195 Scanner::BookmarkScope* bookmark) { | |
191 // SourceElements :: | 196 // SourceElements :: |
192 // (Statement)* <end_token> | 197 // (Statement)* <end_token> |
193 | 198 |
199 // Bookkeeping for trial parse if bookmark is set: | |
200 DCHECK_IMPLIES(bookmark, bookmark->HasBeenSet()); | |
201 bool maybe_reset = bookmark != nullptr; | |
202 int start_pos = scanner()->location().beg_pos; | |
203 int count_lines = 0; | |
204 | |
194 bool directive_prologue = true; | 205 bool directive_prologue = true; |
195 while (peek() != end_token) { | 206 while (peek() != end_token) { |
196 if (directive_prologue && peek() != Token::STRING) { | 207 if (directive_prologue && peek() != Token::STRING) { |
197 directive_prologue = false; | 208 directive_prologue = false; |
198 } | 209 } |
199 Token::Value token = peek(); | 210 Token::Value token = peek(); |
200 Scanner::Location old_super_loc = function_state_->super_call_location(); | 211 Scanner::Location old_super_loc = function_state_->super_call_location(); |
201 Statement statement = ParseStatementListItem(ok); | 212 Statement statement = ParseStatementListItem(ok); |
202 if (!*ok) return; | 213 if (!*ok) return; |
203 Scanner::Location super_loc = function_state_->super_call_location(); | 214 Scanner::Location super_loc = function_state_->super_call_location(); |
204 if (is_strong(language_mode()) && | 215 if (is_strong(language_mode()) && |
205 i::IsConstructor(function_state_->kind()) && | 216 i::IsConstructor(function_state_->kind()) && |
206 !old_super_loc.IsValid() && super_loc.IsValid() && | 217 !old_super_loc.IsValid() && super_loc.IsValid() && |
207 token != Token::SUPER) { | 218 token != Token::SUPER) { |
208 ReportMessageAt(super_loc, "strong_super_call_nested"); | 219 ReportMessageAt(super_loc, "strong_super_call_nested"); |
209 *ok = false; | 220 *ok = false; |
210 return; | 221 return; |
211 } | 222 } |
212 if (directive_prologue) { | 223 if (directive_prologue) { |
213 if (statement.IsUseStrictLiteral()) { | 224 if (statement.IsUseStrictLiteral()) { |
214 scope_->SetLanguageMode( | 225 scope_->SetLanguageMode( |
215 static_cast<LanguageMode>(scope_->language_mode() | STRICT_BIT)); | 226 static_cast<LanguageMode>(scope_->language_mode() | STRICT_BIT)); |
216 } else if (statement.IsUseStrongLiteral() && allow_strong_mode()) { | 227 } else if (statement.IsUseStrongLiteral() && allow_strong_mode()) { |
217 scope_->SetLanguageMode(static_cast<LanguageMode>( | 228 scope_->SetLanguageMode(static_cast<LanguageMode>( |
218 scope_->language_mode() | STRICT_BIT | STRONG_BIT)); | 229 scope_->language_mode() | STRICT_BIT | STRONG_BIT)); |
219 } else if (!statement.IsStringLiteral()) { | 230 } else if (!statement.IsStringLiteral()) { |
220 directive_prologue = false; | 231 directive_prologue = false; |
221 } | 232 } |
222 } | 233 } |
234 | |
235 // If we're allowed to reset to a bookmark, we will do so when we see a long | |
236 // and trivial function. | |
237 // Our current definition of 'long and trivial) is: | |
238 // - within the first 10k characters, | |
239 // - over 200 statements | |
240 // - all starting with an identifier (i.e., no if, for, while, etc.) | |
241 if (maybe_reset) { | |
242 if (token != Token::IDENTIFIER) { | |
243 maybe_reset = false; | |
244 } else if (scanner()->location().end_pos - start_pos > 10000) { | |
245 maybe_reset = false; | |
246 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
| |
247 bookmark->Reset(); | |
248 return; | |
249 } | |
250 } | |
251 } | |
223 } | 252 } |
224 } | 253 } |
225 | 254 |
226 | 255 |
227 #define CHECK_OK ok); \ | 256 #define CHECK_OK ok); \ |
228 if (!*ok) return Statement::Default(); \ | 257 if (!*ok) return Statement::Default(); \ |
229 ((void)0 | 258 ((void)0 |
230 #define DUMMY ) // to make indentation work | 259 #define DUMMY ) // to make indentation work |
231 #undef DUMMY | 260 #undef DUMMY |
232 | 261 |
(...skipping 783 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1016 kReferenceError); | 1045 kReferenceError); |
1017 *ok = false; | 1046 *ok = false; |
1018 return Expression::Default(); | 1047 return Expression::Default(); |
1019 } | 1048 } |
1020 } | 1049 } |
1021 | 1050 |
1022 return Expression::Default(); | 1051 return Expression::Default(); |
1023 } | 1052 } |
1024 | 1053 |
1025 | 1054 |
1026 void PreParser::ParseLazyFunctionLiteralBody(bool* ok) { | 1055 void PreParser::ParseLazyFunctionLiteralBody(bool* ok, |
1056 Scanner::BookmarkScope* bookmark) { | |
1027 int body_start = position(); | 1057 int body_start = position(); |
1028 ParseStatementList(Token::RBRACE, ok); | 1058 ParseStatementList(Token::RBRACE, ok, bookmark); |
1029 if (!*ok) return; | 1059 if (!*ok) return; |
1060 if (bookmark && bookmark->HasBeenReset()) return; | |
1030 | 1061 |
1031 // Position right after terminal '}'. | 1062 // Position right after terminal '}'. |
1032 DCHECK_EQ(Token::RBRACE, scanner()->peek()); | 1063 DCHECK_EQ(Token::RBRACE, scanner()->peek()); |
1033 int body_end = scanner()->peek_location().end_pos; | 1064 int body_end = scanner()->peek_location().end_pos; |
1034 log_->LogFunction(body_start, body_end, | 1065 log_->LogFunction(body_start, body_end, |
1035 function_state_->materialized_literal_count(), | 1066 function_state_->materialized_literal_count(), |
1036 function_state_->expected_property_count(), language_mode(), | 1067 function_state_->expected_property_count(), language_mode(), |
1037 scope_->uses_super_property()); | 1068 scope_->uses_super_property()); |
1038 } | 1069 } |
1039 | 1070 |
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1106 | 1137 |
1107 DCHECK(!spread_pos.IsValid()); | 1138 DCHECK(!spread_pos.IsValid()); |
1108 | 1139 |
1109 return Expression::Default(); | 1140 return Expression::Default(); |
1110 } | 1141 } |
1111 | 1142 |
1112 #undef CHECK_OK | 1143 #undef CHECK_OK |
1113 | 1144 |
1114 | 1145 |
1115 } } // v8::internal | 1146 } } // v8::internal |
OLD | NEW |