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 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
68 if (scanner()->LiteralMatches("prototype", 9)) | 68 if (scanner()->LiteralMatches("prototype", 9)) |
69 return PreParserIdentifier::Prototype(); | 69 return PreParserIdentifier::Prototype(); |
70 if (scanner()->LiteralMatches("constructor", 11)) | 70 if (scanner()->LiteralMatches("constructor", 11)) |
71 return PreParserIdentifier::Constructor(); | 71 return PreParserIdentifier::Constructor(); |
72 return PreParserIdentifier::Default(); | 72 return PreParserIdentifier::Default(); |
73 } | 73 } |
74 } | 74 } |
75 | 75 |
76 PreParser::PreParseResult PreParser::PreParseLazyFunction( | 76 PreParser::PreParseResult PreParser::PreParseLazyFunction( |
77 LanguageMode language_mode, FunctionKind kind, bool has_simple_parameters, | 77 LanguageMode language_mode, FunctionKind kind, bool has_simple_parameters, |
78 bool parsing_module, ParserRecorder* log, Scanner::BookmarkScope* bookmark, | 78 bool parsing_module, ParserRecorder* log, bool may_abort, int* use_counts) { |
79 int* use_counts) { | |
80 parsing_module_ = parsing_module; | 79 parsing_module_ = parsing_module; |
81 log_ = log; | 80 log_ = log; |
82 use_counts_ = use_counts; | 81 use_counts_ = use_counts; |
83 // Lazy functions always have trivial outer scopes (no with/catch scopes). | 82 // Lazy functions always have trivial outer scopes (no with/catch scopes). |
84 DCHECK_NULL(scope_state_); | 83 DCHECK_NULL(scope_state_); |
85 DeclarationScope* top_scope = NewScriptScope(); | 84 DeclarationScope* top_scope = NewScriptScope(); |
86 FunctionState top_state(&function_state_, &scope_state_, top_scope, | 85 FunctionState top_state(&function_state_, &scope_state_, top_scope, |
87 kNormalFunction); | 86 kNormalFunction); |
88 scope()->SetLanguageMode(language_mode); | 87 scope()->SetLanguageMode(language_mode); |
89 DeclarationScope* function_scope = NewFunctionScope(kind); | 88 DeclarationScope* function_scope = NewFunctionScope(kind); |
90 if (!has_simple_parameters) function_scope->SetHasNonSimpleParameters(); | 89 if (!has_simple_parameters) function_scope->SetHasNonSimpleParameters(); |
91 FunctionState function_state(&function_state_, &scope_state_, function_scope, | 90 FunctionState function_state(&function_state_, &scope_state_, function_scope, |
92 kind); | 91 kind); |
93 DCHECK_EQ(Token::LBRACE, scanner()->current_token()); | 92 DCHECK_EQ(Token::LBRACE, scanner()->current_token()); |
94 bool ok = true; | 93 bool ok = true; |
95 int start_position = peek_position(); | 94 int start_position = peek_position(); |
96 ParseLazyFunctionLiteralBody(&ok, bookmark); | 95 bool aborted = ParseLazyFunctionLiteralBody(may_abort, &ok); |
97 use_counts_ = nullptr; | 96 use_counts_ = nullptr; |
98 if (bookmark && bookmark->HasBeenReset()) { | 97 if (aborted) { |
99 // Do nothing, as we've just aborted scanning this function. | 98 return kPreParseAbort; |
100 } else if (stack_overflow()) { | 99 } else if (stack_overflow()) { |
101 return kPreParseStackOverflow; | 100 return kPreParseStackOverflow; |
102 } else if (!ok) { | 101 } else if (!ok) { |
103 ReportUnexpectedToken(scanner()->current_token()); | 102 ReportUnexpectedToken(scanner()->current_token()); |
104 } else { | 103 } else { |
105 DCHECK_EQ(Token::RBRACE, scanner()->peek()); | 104 DCHECK_EQ(Token::RBRACE, scanner()->peek()); |
106 if (is_strict(scope()->language_mode())) { | 105 if (is_strict(scope()->language_mode())) { |
107 int end_pos = scanner()->location().end_pos; | 106 int end_pos = scanner()->location().end_pos; |
108 CheckStrictOctalLiteral(start_position, end_pos, &ok); | 107 CheckStrictOctalLiteral(start_position, end_pos, &ok); |
109 CheckDecimalLiteralWithLeadingZero(use_counts, start_position, end_pos); | 108 CheckDecimalLiteralWithLeadingZero(use_counts, start_position, end_pos); |
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
164 Consume(Token::ASYNC); | 163 Consume(Token::ASYNC); |
165 return ParseAsyncFunctionDeclaration(ok); | 164 return ParseAsyncFunctionDeclaration(ok); |
166 } | 165 } |
167 /* falls through */ | 166 /* falls through */ |
168 default: | 167 default: |
169 break; | 168 break; |
170 } | 169 } |
171 return ParseStatement(kAllowLabelledFunctionStatement, ok); | 170 return ParseStatement(kAllowLabelledFunctionStatement, ok); |
172 } | 171 } |
173 | 172 |
174 | 173 bool PreParser::ParseStatementList(int end_token, bool may_abort, bool* ok) { |
175 void PreParser::ParseStatementList(int end_token, bool* ok, | |
176 Scanner::BookmarkScope* bookmark) { | |
177 // SourceElements :: | 174 // SourceElements :: |
178 // (Statement)* <end_token> | 175 // (Statement)* <end_token> |
179 | 176 |
180 // Bookkeeping for trial parse if bookmark is set: | |
181 DCHECK_IMPLIES(bookmark, bookmark->HasBeenSet()); | |
182 bool maybe_reset = bookmark != nullptr; | |
183 int count_statements = 0; | 177 int count_statements = 0; |
184 | 178 |
185 bool directive_prologue = true; | 179 bool directive_prologue = true; |
186 while (peek() != end_token) { | 180 while (peek() != end_token) { |
187 if (directive_prologue && peek() != Token::STRING) { | 181 if (directive_prologue && peek() != Token::STRING) { |
188 directive_prologue = false; | 182 directive_prologue = false; |
189 } | 183 } |
190 bool starts_with_identifier = peek() == Token::IDENTIFIER; | 184 bool starts_with_identifier = peek() == Token::IDENTIFIER; |
191 Scanner::Location token_loc = scanner()->peek_location(); | 185 Scanner::Location token_loc = scanner()->peek_location(); |
192 Statement statement = ParseStatementListItem(CHECK_OK_CUSTOM(Void)); | 186 Statement statement = ParseStatementListItem(ok); |
187 if (!*ok) return false; | |
193 | 188 |
194 if (directive_prologue) { | 189 if (directive_prologue) { |
195 bool use_strict_found = statement.IsUseStrictLiteral(); | 190 bool use_strict_found = statement.IsUseStrictLiteral(); |
196 | 191 |
197 if (use_strict_found) { | 192 if (use_strict_found) { |
198 scope()->SetLanguageMode( | 193 scope()->SetLanguageMode( |
199 static_cast<LanguageMode>(scope()->language_mode() | STRICT)); | 194 static_cast<LanguageMode>(scope()->language_mode() | STRICT)); |
200 } else if (!statement.IsStringLiteral()) { | 195 } else if (!statement.IsStringLiteral()) { |
201 directive_prologue = false; | 196 directive_prologue = false; |
202 } | 197 } |
203 | 198 |
204 if (use_strict_found && !scope()->HasSimpleParameters()) { | 199 if (use_strict_found && !scope()->HasSimpleParameters()) { |
205 // TC39 deemed "use strict" directives to be an error when occurring | 200 // TC39 deemed "use strict" directives to be an error when occurring |
206 // in the body of a function with non-simple parameter list, on | 201 // in the body of a function with non-simple parameter list, on |
207 // 29/7/2015. https://goo.gl/ueA7Ln | 202 // 29/7/2015. https://goo.gl/ueA7Ln |
208 ReportMessageAt(token_loc, | 203 ReportMessageAt(token_loc, |
209 MessageTemplate::kIllegalLanguageModeDirective, | 204 MessageTemplate::kIllegalLanguageModeDirective, |
210 "use strict"); | 205 "use strict"); |
211 *ok = false; | 206 *ok = false; |
212 return; | 207 return false; |
213 } | 208 } |
214 } | 209 } |
215 | 210 |
216 // If we're allowed to reset to a bookmark, we will do so when we see a long | 211 // If we're allowed to reset to a bookmark, we will do so when we see a long |
217 // and trivial function. | 212 // and trivial function. |
218 // Our current definition of 'long and trivial' is: | 213 // Our current definition of 'long and trivial' is: |
219 // - over 200 statements | 214 // - over 200 statements |
220 // - all starting with an identifier (i.e., no if, for, while, etc.) | 215 // - all starting with an identifier (i.e., no if, for, while, etc.) |
221 if (maybe_reset && (!starts_with_identifier || | 216 if (may_abort) { |
222 ++count_statements > kLazyParseTrialLimit)) { | 217 if (!starts_with_identifier) |
adamk
2016/08/30 22:13:14
Please add curly braces around the if/else stateme
nickie
2016/08/31 13:23:36
Done.
| |
223 if (count_statements > kLazyParseTrialLimit) { | 218 may_abort = false; |
224 bookmark->Reset(); | 219 else if (++count_statements > kLazyParseTrialLimit) |
225 return; | 220 return true; |
226 } | |
227 maybe_reset = false; | |
228 } | 221 } |
229 } | 222 } |
223 return false; | |
230 } | 224 } |
231 | 225 |
232 | 226 |
233 PreParser::Statement PreParser::ParseStatement( | 227 PreParser::Statement PreParser::ParseStatement( |
234 AllowLabelledFunctionStatement allow_function, bool* ok) { | 228 AllowLabelledFunctionStatement allow_function, bool* ok) { |
235 // Statement :: | 229 // Statement :: |
236 // EmptyStatement | 230 // EmptyStatement |
237 // ... | 231 // ... |
238 | 232 |
239 if (peek() == Token::SEMICOLON) { | 233 if (peek() == Token::SEMICOLON) { |
(...skipping 815 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1055 CheckArityRestrictions(formals.arity, kind, formals.has_rest, start_position, | 1049 CheckArityRestrictions(formals.arity, kind, formals.has_rest, start_position, |
1056 formals_end_position, CHECK_OK); | 1050 formals_end_position, CHECK_OK); |
1057 | 1051 |
1058 // See Parser::ParseFunctionLiteral for more information about lazy parsing | 1052 // See Parser::ParseFunctionLiteral for more information about lazy parsing |
1059 // and lazy compilation. | 1053 // and lazy compilation. |
1060 bool is_lazily_parsed = (outer_is_script_scope && allow_lazy() && | 1054 bool is_lazily_parsed = (outer_is_script_scope && allow_lazy() && |
1061 !function_state_->this_function_is_parenthesized()); | 1055 !function_state_->this_function_is_parenthesized()); |
1062 | 1056 |
1063 Expect(Token::LBRACE, CHECK_OK); | 1057 Expect(Token::LBRACE, CHECK_OK); |
1064 if (is_lazily_parsed) { | 1058 if (is_lazily_parsed) { |
1065 ParseLazyFunctionLiteralBody(CHECK_OK); | 1059 ParseLazyFunctionLiteralBody(false, CHECK_OK); |
1066 } else { | 1060 } else { |
1067 ParseStatementList(Token::RBRACE, CHECK_OK); | 1061 ParseStatementList(Token::RBRACE, CHECK_OK); |
1068 } | 1062 } |
1069 Expect(Token::RBRACE, CHECK_OK); | 1063 Expect(Token::RBRACE, CHECK_OK); |
1070 | 1064 |
1071 // Parsing the body may change the language mode in our scope. | 1065 // Parsing the body may change the language mode in our scope. |
1072 language_mode = function_scope->language_mode(); | 1066 language_mode = function_scope->language_mode(); |
1073 | 1067 |
1074 // Validate name and parameter names. We can do this only after parsing the | 1068 // Validate name and parameter names. We can do this only after parsing the |
1075 // function, since the function can declare itself strict. | 1069 // function, since the function can declare itself strict. |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1109 } | 1103 } |
1110 | 1104 |
1111 ParseFunctionLiteral(name, scanner()->location(), | 1105 ParseFunctionLiteral(name, scanner()->location(), |
1112 is_strict_reserved ? kFunctionNameIsStrictReserved | 1106 is_strict_reserved ? kFunctionNameIsStrictReserved |
1113 : kFunctionNameValidityUnknown, | 1107 : kFunctionNameValidityUnknown, |
1114 FunctionKind::kAsyncFunction, pos, type, language_mode(), | 1108 FunctionKind::kAsyncFunction, pos, type, language_mode(), |
1115 CHECK_OK); | 1109 CHECK_OK); |
1116 return Expression::Default(); | 1110 return Expression::Default(); |
1117 } | 1111 } |
1118 | 1112 |
1119 void PreParser::ParseLazyFunctionLiteralBody(bool* ok, | 1113 bool PreParser::ParseLazyFunctionLiteralBody(bool may_abort, bool* ok) { |
1120 Scanner::BookmarkScope* bookmark) { | |
1121 int body_start = position(); | 1114 int body_start = position(); |
1122 ParseStatementList(Token::RBRACE, ok, bookmark); | 1115 bool aborted = ParseStatementList(Token::RBRACE, may_abort, ok); |
1123 if (!*ok) return; | 1116 if (!*ok) return false; |
1124 if (bookmark && bookmark->HasBeenReset()) return; | 1117 if (aborted) return true; |
adamk
2016/08/30 22:13:14
And having gotten this far I also think it would b
nickie
2016/08/31 13:23:36
Done.
| |
1125 | 1118 |
1126 // Position right after terminal '}'. | 1119 // Position right after terminal '}'. |
1127 DCHECK_EQ(Token::RBRACE, scanner()->peek()); | 1120 DCHECK_EQ(Token::RBRACE, scanner()->peek()); |
1128 int body_end = scanner()->peek_location().end_pos; | 1121 int body_end = scanner()->peek_location().end_pos; |
1129 DeclarationScope* scope = this->scope()->AsDeclarationScope(); | 1122 DeclarationScope* scope = this->scope()->AsDeclarationScope(); |
1130 DCHECK(scope->is_function_scope()); | 1123 DCHECK(scope->is_function_scope()); |
1131 log_->LogFunction(body_start, body_end, | 1124 log_->LogFunction(body_start, body_end, |
1132 function_state_->materialized_literal_count(), | 1125 function_state_->materialized_literal_count(), |
1133 function_state_->expected_property_count(), language_mode(), | 1126 function_state_->expected_property_count(), language_mode(), |
1134 scope->uses_super_property(), scope->calls_eval()); | 1127 scope->uses_super_property(), scope->calls_eval()); |
1128 return false; | |
1135 } | 1129 } |
1136 | 1130 |
1137 PreParserExpression PreParser::ParseClassLiteral( | 1131 PreParserExpression PreParser::ParseClassLiteral( |
1138 PreParserIdentifier name, Scanner::Location class_name_location, | 1132 PreParserIdentifier name, Scanner::Location class_name_location, |
1139 bool name_is_strict_reserved, int pos, bool* ok) { | 1133 bool name_is_strict_reserved, int pos, bool* ok) { |
1140 // All parts of a ClassDeclaration and ClassExpression are strict code. | 1134 // All parts of a ClassDeclaration and ClassExpression are strict code. |
1141 if (name_is_strict_reserved) { | 1135 if (name_is_strict_reserved) { |
1142 ReportMessageAt(class_name_location, | 1136 ReportMessageAt(class_name_location, |
1143 MessageTemplate::kUnexpectedStrictReserved); | 1137 MessageTemplate::kUnexpectedStrictReserved); |
1144 *ok = false; | 1138 *ok = false; |
(...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1233 | 1227 |
1234 body->Add(PreParserStatement::ExpressionStatement(return_value), zone()); | 1228 body->Add(PreParserStatement::ExpressionStatement(return_value), zone()); |
1235 } | 1229 } |
1236 | 1230 |
1237 #undef CHECK_OK | 1231 #undef CHECK_OK |
1238 #undef CHECK_OK_CUSTOM | 1232 #undef CHECK_OK_CUSTOM |
1239 | 1233 |
1240 | 1234 |
1241 } // namespace internal | 1235 } // namespace internal |
1242 } // namespace v8 | 1236 } // namespace v8 |
OLD | NEW |