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

Side by Side Diff: src/parsing/parser.cc

Issue 2297733002: [parser] Refactor bookmark in SkipLazyFunctionBody (Closed)
Patch Set: Created 4 years, 3 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
OLDNEW
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
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
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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698