OLD | NEW |
---|---|
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 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 "src/parsing/parser.h" | 5 #include "src/parsing/parser.h" |
6 | 6 |
7 #include <memory> | 7 #include <memory> |
8 | 8 |
9 #include "src/api.h" | 9 #include "src/api.h" |
10 #include "src/ast/ast-expression-rewriter.h" | 10 #include "src/ast/ast-expression-rewriter.h" |
(...skipping 4038 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
4049 | 4049 |
4050 CheckArityRestrictions(arity, kind, formals.has_rest, start_position, | 4050 CheckArityRestrictions(arity, kind, formals.has_rest, start_position, |
4051 formals_end_position, CHECK_OK); | 4051 formals_end_position, CHECK_OK); |
4052 Expect(Token::LBRACE, CHECK_OK); | 4052 Expect(Token::LBRACE, CHECK_OK); |
4053 // Don't include the rest parameter into the function's formal parameter | 4053 // Don't include the rest parameter into the function's formal parameter |
4054 // count (esp. the SharedFunctionInfo::internal_formal_parameter_count, | 4054 // count (esp. the SharedFunctionInfo::internal_formal_parameter_count, |
4055 // which says whether we need to create an arguments adaptor frame). | 4055 // which says whether we need to create an arguments adaptor frame). |
4056 if (formals.has_rest) arity--; | 4056 if (formals.has_rest) arity--; |
4057 | 4057 |
4058 // Eager or lazy parse? | 4058 // Eager or lazy parse? |
4059 // If is_lazily_parsed, we'll parse lazy. If we can set a bookmark, we'll | 4059 // If is_lazily_parsed, we'll parse lazily. We'll call SkipLazyFunctionBody, |
4060 // pass it to SkipLazyFunctionBody, which may use it to abort lazy | 4060 // which may decide to abort lazy parsing if it suspect that wasn't a good |
vogelheim
2016/08/30 16:28:42
nitpick: suspect -> suspects
nickie
2016/08/31 13:23:36
Done.
| |
4061 // parsing if it suspect that wasn't a good idea. If so, or if we didn't | 4061 // idea. If so (in which case the parser is expected to have backtracked), |
vogelheim
2016/08/30 16:28:42
nitpick: One space after "idea."
nickie
2016/08/31 13:23:36
Done.
| |
4062 // try to lazy parse in the first place, we'll have to parse eagerly. | 4062 // or if we didn't try to lazy parse in the first place, we'll have to parse |
4063 Scanner::BookmarkScope bookmark(scanner()); | 4063 // eagerly. |
4064 if (is_lazily_parsed) { | 4064 if (is_lazily_parsed) { |
4065 Scanner::BookmarkScope* maybe_bookmark = | 4065 Scanner::BookmarkScope bookmark(scanner()); |
4066 bookmark.Set() ? &bookmark : nullptr; | 4066 bool may_abort = bookmark.Set(); |
4067 SkipLazyFunctionBody(&materialized_literal_count, | 4067 bool aborted = |
4068 &expected_property_count, /*CHECK_OK*/ ok, | 4068 SkipLazyFunctionBody(&materialized_literal_count, |
4069 maybe_bookmark); | 4069 &expected_property_count, may_abort, CHECK_OK); |
4070 | 4070 |
4071 materialized_literal_count += formals.materialized_literals_count + | 4071 materialized_literal_count += formals.materialized_literals_count + |
4072 function_state.materialized_literal_count(); | 4072 function_state.materialized_literal_count(); |
4073 | 4073 |
4074 if (bookmark.HasBeenReset()) { | 4074 if (aborted) { |
4075 bookmark.Reset(); | |
4075 // Trigger eager (re-)parsing, just below this block. | 4076 // Trigger eager (re-)parsing, just below this block. |
4076 is_lazily_parsed = false; | 4077 is_lazily_parsed = false; |
4077 | 4078 |
4078 // This is probably an initialization function. Inform the compiler it | 4079 // This is probably an initialization function. Inform the compiler it |
4079 // should also eager-compile this function, and that we expect it to be | 4080 // should also eager-compile this function, and that we expect it to be |
4080 // used once. | 4081 // used once. |
4081 eager_compile_hint = FunctionLiteral::kShouldEagerCompile; | 4082 eager_compile_hint = FunctionLiteral::kShouldEagerCompile; |
4082 should_be_used_once_hint = true; | 4083 should_be_used_once_hint = true; |
4083 } | 4084 } |
4084 } | 4085 } |
(...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
4164 name = ParseIdentifierOrStrictReservedWord(FunctionKind::kAsyncFunction, | 4165 name = ParseIdentifierOrStrictReservedWord(FunctionKind::kAsyncFunction, |
4165 &is_strict_reserved, CHECK_OK); | 4166 &is_strict_reserved, CHECK_OK); |
4166 } | 4167 } |
4167 return ParseFunctionLiteral(name, scanner()->location(), | 4168 return ParseFunctionLiteral(name, scanner()->location(), |
4168 is_strict_reserved ? kFunctionNameIsStrictReserved | 4169 is_strict_reserved ? kFunctionNameIsStrictReserved |
4169 : kFunctionNameValidityUnknown, | 4170 : kFunctionNameValidityUnknown, |
4170 FunctionKind::kAsyncFunction, pos, type, | 4171 FunctionKind::kAsyncFunction, pos, type, |
4171 language_mode(), CHECK_OK); | 4172 language_mode(), CHECK_OK); |
4172 } | 4173 } |
4173 | 4174 |
4174 void Parser::SkipLazyFunctionBody(int* materialized_literal_count, | 4175 bool Parser::SkipLazyFunctionBody(int* materialized_literal_count, |
4175 int* expected_property_count, bool* ok, | 4176 int* expected_property_count, bool may_abort, |
4176 Scanner::BookmarkScope* bookmark) { | 4177 bool* ok) { |
4177 DCHECK_IMPLIES(bookmark, bookmark->HasBeenSet()); | |
4178 if (produce_cached_parse_data()) CHECK(log_); | 4178 if (produce_cached_parse_data()) CHECK(log_); |
4179 | 4179 |
4180 int function_block_pos = position(); | 4180 int function_block_pos = position(); |
4181 DeclarationScope* scope = this->scope()->AsDeclarationScope(); | 4181 DeclarationScope* scope = this->scope()->AsDeclarationScope(); |
4182 DCHECK(scope->is_function_scope()); | 4182 DCHECK(scope->is_function_scope()); |
4183 if (consume_cached_parse_data() && !cached_parse_data_->rejected()) { | 4183 if (consume_cached_parse_data() && !cached_parse_data_->rejected()) { |
4184 // If we have cached data, we use it to skip parsing the function body. The | 4184 // If we have cached data, we use it to skip parsing the function body. The |
4185 // data contains the information we need to construct the lazy function. | 4185 // data contains the information we need to construct the lazy function. |
4186 FunctionEntry entry = | 4186 FunctionEntry entry = |
4187 cached_parse_data_->GetFunctionEntry(function_block_pos); | 4187 cached_parse_data_->GetFunctionEntry(function_block_pos); |
4188 // Check that cached data is valid. If not, mark it as invalid (the embedder | 4188 // Check that cached data is valid. If not, mark it as invalid (the embedder |
4189 // handles it). Note that end position greater than end of stream is safe, | 4189 // handles it). Note that end position greater than end of stream is safe, |
4190 // and hard to check. | 4190 // and hard to check. |
4191 if (entry.is_valid() && entry.end_pos() > function_block_pos) { | 4191 if (entry.is_valid() && entry.end_pos() > function_block_pos) { |
4192 scanner()->SeekForward(entry.end_pos() - 1); | 4192 scanner()->SeekForward(entry.end_pos() - 1); |
4193 | 4193 |
4194 scope->set_end_position(entry.end_pos()); | 4194 scope->set_end_position(entry.end_pos()); |
4195 Expect(Token::RBRACE, CHECK_OK_VOID); | 4195 Expect(Token::RBRACE, ok); |
4196 if (!ok) return false; | |
adamk
2016/08/30 22:13:14
I think you mean "if (!*ok)". bool* is about my le
nickie
2016/08/31 13:23:36
Done.
| |
4196 total_preparse_skipped_ += scope->end_position() - function_block_pos; | 4197 total_preparse_skipped_ += scope->end_position() - function_block_pos; |
4197 *materialized_literal_count = entry.literal_count(); | 4198 *materialized_literal_count = entry.literal_count(); |
4198 *expected_property_count = entry.property_count(); | 4199 *expected_property_count = entry.property_count(); |
4199 SetLanguageMode(scope, entry.language_mode()); | 4200 SetLanguageMode(scope, entry.language_mode()); |
4200 if (entry.uses_super_property()) scope->RecordSuperPropertyUsage(); | 4201 if (entry.uses_super_property()) scope->RecordSuperPropertyUsage(); |
4201 if (entry.calls_eval()) scope->RecordEvalCall(); | 4202 if (entry.calls_eval()) scope->RecordEvalCall(); |
4202 return; | 4203 return false; |
4203 } | 4204 } |
4204 cached_parse_data_->Reject(); | 4205 cached_parse_data_->Reject(); |
4205 } | 4206 } |
4206 // With no cached data, we partially parse the function, without building an | 4207 // With no cached data, we partially parse the function, without building an |
4207 // AST. This gathers the data needed to build a lazy function. | 4208 // AST. This gathers the data needed to build a lazy function. |
4208 SingletonLogger logger; | 4209 SingletonLogger logger; |
4209 PreParser::PreParseResult result = | 4210 PreParser::PreParseResult result = |
4210 ParseLazyFunctionBodyWithPreParser(&logger, bookmark); | 4211 ParseLazyFunctionBodyWithPreParser(&logger, may_abort); |
4211 if (bookmark && bookmark->HasBeenReset()) { | 4212 // Return immediately if pre-parser decided to abort parsing. |
4212 return; // Return immediately if pre-parser devided to abort parsing. | 4213 if (result == PreParser::kPreParseAbort) return true; |
4213 } | |
4214 if (result == PreParser::kPreParseStackOverflow) { | 4214 if (result == PreParser::kPreParseStackOverflow) { |
4215 // Propagate stack overflow. | 4215 // Propagate stack overflow. |
4216 set_stack_overflow(); | 4216 set_stack_overflow(); |
4217 *ok = false; | 4217 *ok = false; |
4218 return; | 4218 return false; |
4219 } | 4219 } |
4220 if (logger.has_error()) { | 4220 if (logger.has_error()) { |
4221 ReportMessageAt(Scanner::Location(logger.start(), logger.end()), | 4221 ReportMessageAt(Scanner::Location(logger.start(), logger.end()), |
4222 logger.message(), logger.argument_opt(), | 4222 logger.message(), logger.argument_opt(), |
4223 logger.error_type()); | 4223 logger.error_type()); |
4224 *ok = false; | 4224 *ok = false; |
4225 return; | 4225 return false; |
4226 } | 4226 } |
4227 scope->set_end_position(logger.end()); | 4227 scope->set_end_position(logger.end()); |
4228 Expect(Token::RBRACE, CHECK_OK_VOID); | 4228 Expect(Token::RBRACE, ok); |
4229 if (!ok) return false; | |
adamk
2016/08/30 22:13:14
Ok, I think the same error twice is enough to conv
nickie
2016/08/31 13:23:36
Done.
| |
4229 total_preparse_skipped_ += scope->end_position() - function_block_pos; | 4230 total_preparse_skipped_ += scope->end_position() - function_block_pos; |
4230 *materialized_literal_count = logger.literals(); | 4231 *materialized_literal_count = logger.literals(); |
4231 *expected_property_count = logger.properties(); | 4232 *expected_property_count = logger.properties(); |
4232 SetLanguageMode(scope, logger.language_mode()); | 4233 SetLanguageMode(scope, logger.language_mode()); |
4233 if (logger.uses_super_property()) scope->RecordSuperPropertyUsage(); | 4234 if (logger.uses_super_property()) scope->RecordSuperPropertyUsage(); |
4234 if (logger.calls_eval()) scope->RecordEvalCall(); | 4235 if (logger.calls_eval()) scope->RecordEvalCall(); |
4235 if (produce_cached_parse_data()) { | 4236 if (produce_cached_parse_data()) { |
4236 DCHECK(log_); | 4237 DCHECK(log_); |
4237 // Position right after terminal '}'. | 4238 // Position right after terminal '}'. |
4238 int body_end = scanner()->location().end_pos; | 4239 int body_end = scanner()->location().end_pos; |
4239 log_->LogFunction(function_block_pos, body_end, *materialized_literal_count, | 4240 log_->LogFunction(function_block_pos, body_end, *materialized_literal_count, |
4240 *expected_property_count, language_mode(), | 4241 *expected_property_count, language_mode(), |
4241 scope->uses_super_property(), scope->calls_eval()); | 4242 scope->uses_super_property(), scope->calls_eval()); |
4242 } | 4243 } |
4244 return false; | |
4243 } | 4245 } |
4244 | 4246 |
4245 | 4247 |
4246 Statement* Parser::BuildAssertIsCoercible(Variable* var) { | 4248 Statement* Parser::BuildAssertIsCoercible(Variable* var) { |
4247 // if (var === null || var === undefined) | 4249 // if (var === null || var === undefined) |
4248 // throw /* type error kNonCoercible) */; | 4250 // throw /* type error kNonCoercible) */; |
4249 | 4251 |
4250 Expression* condition = factory()->NewBinaryOperation( | 4252 Expression* condition = factory()->NewBinaryOperation( |
4251 Token::OR, | 4253 Token::OR, |
4252 factory()->NewCompareOperation( | 4254 factory()->NewCompareOperation( |
(...skipping 432 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
4685 factory()->NewAssignment(Token::INIT, fproxy, | 4687 factory()->NewAssignment(Token::INIT, fproxy, |
4686 factory()->NewThisFunction(pos), | 4688 factory()->NewThisFunction(pos), |
4687 kNoSourcePosition), | 4689 kNoSourcePosition), |
4688 kNoSourcePosition)); | 4690 kNoSourcePosition)); |
4689 } | 4691 } |
4690 | 4692 |
4691 MarkCollectedTailCallExpressions(); | 4693 MarkCollectedTailCallExpressions(); |
4692 return result; | 4694 return result; |
4693 } | 4695 } |
4694 | 4696 |
4695 | |
4696 PreParser::PreParseResult Parser::ParseLazyFunctionBodyWithPreParser( | 4697 PreParser::PreParseResult Parser::ParseLazyFunctionBodyWithPreParser( |
4697 SingletonLogger* logger, Scanner::BookmarkScope* bookmark) { | 4698 SingletonLogger* logger, bool may_abort) { |
4698 // This function may be called on a background thread too; record only the | 4699 // This function may be called on a background thread too; record only the |
4699 // main thread preparse times. | 4700 // main thread preparse times. |
4700 if (pre_parse_timer_ != NULL) { | 4701 if (pre_parse_timer_ != NULL) { |
4701 pre_parse_timer_->Start(); | 4702 pre_parse_timer_->Start(); |
4702 } | 4703 } |
4703 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8.compile"), "V8.PreParse"); | 4704 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8.compile"), "V8.PreParse"); |
4704 | 4705 |
4705 DCHECK_EQ(Token::LBRACE, scanner()->current_token()); | 4706 DCHECK_EQ(Token::LBRACE, scanner()->current_token()); |
4706 | 4707 |
4707 if (reusable_preparser_ == NULL) { | 4708 if (reusable_preparser_ == NULL) { |
4708 reusable_preparser_ = new PreParser(zone(), &scanner_, ast_value_factory(), | 4709 reusable_preparser_ = new PreParser(zone(), &scanner_, ast_value_factory(), |
4709 NULL, stack_limit_); | 4710 NULL, stack_limit_); |
4710 reusable_preparser_->set_allow_lazy(true); | 4711 reusable_preparser_->set_allow_lazy(true); |
4711 #define SET_ALLOW(name) reusable_preparser_->set_allow_##name(allow_##name()); | 4712 #define SET_ALLOW(name) reusable_preparser_->set_allow_##name(allow_##name()); |
4712 SET_ALLOW(natives); | 4713 SET_ALLOW(natives); |
4713 SET_ALLOW(harmony_do_expressions); | 4714 SET_ALLOW(harmony_do_expressions); |
4714 SET_ALLOW(harmony_for_in); | 4715 SET_ALLOW(harmony_for_in); |
4715 SET_ALLOW(harmony_function_sent); | 4716 SET_ALLOW(harmony_function_sent); |
4716 SET_ALLOW(harmony_restrictive_declarations); | 4717 SET_ALLOW(harmony_restrictive_declarations); |
4717 SET_ALLOW(harmony_async_await); | 4718 SET_ALLOW(harmony_async_await); |
4718 SET_ALLOW(harmony_trailing_commas); | 4719 SET_ALLOW(harmony_trailing_commas); |
4719 #undef SET_ALLOW | 4720 #undef SET_ALLOW |
4720 } | 4721 } |
4721 PreParser::PreParseResult result = reusable_preparser_->PreParseLazyFunction( | 4722 PreParser::PreParseResult result = reusable_preparser_->PreParseLazyFunction( |
4722 language_mode(), function_state_->kind(), | 4723 language_mode(), function_state_->kind(), |
4723 scope()->AsDeclarationScope()->has_simple_parameters(), parsing_module_, | 4724 scope()->AsDeclarationScope()->has_simple_parameters(), parsing_module_, |
4724 logger, bookmark, use_counts_); | 4725 logger, may_abort, use_counts_); |
4725 if (pre_parse_timer_ != NULL) { | 4726 if (pre_parse_timer_ != NULL) { |
4726 pre_parse_timer_->Stop(); | 4727 pre_parse_timer_->Stop(); |
4727 } | 4728 } |
4728 return result; | 4729 return result; |
4729 } | 4730 } |
4730 | 4731 |
4731 Expression* Parser::ParseClassLiteral(const AstRawString* name, | 4732 Expression* Parser::ParseClassLiteral(const AstRawString* name, |
4732 Scanner::Location class_name_location, | 4733 Scanner::Location class_name_location, |
4733 bool name_is_strict_reserved, int pos, | 4734 bool name_is_strict_reserved, int pos, |
4734 bool* ok) { | 4735 bool* ok) { |
(...skipping 1992 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
6727 node->Print(Isolate::Current()); | 6728 node->Print(Isolate::Current()); |
6728 } | 6729 } |
6729 #endif // DEBUG | 6730 #endif // DEBUG |
6730 | 6731 |
6731 #undef CHECK_OK | 6732 #undef CHECK_OK |
6732 #undef CHECK_OK_VOID | 6733 #undef CHECK_OK_VOID |
6733 #undef CHECK_FAILED | 6734 #undef CHECK_FAILED |
6734 | 6735 |
6735 } // namespace internal | 6736 } // namespace internal |
6736 } // namespace v8 | 6737 } // namespace v8 |
OLD | NEW |