Chromium Code Reviews| 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 |