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

Side by Side Diff: src/parser.cc

Issue 1102523003: Implement a 'trial parse' step, that will abort pre-parsing excessively (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Created 5 years, 8 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
« no previous file with comments | « src/parser.h ('k') | src/preparser.h » ('j') | src/preparser.cc » ('J')
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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/v8.h" 5 #include "src/v8.h"
6 6
7 #include "src/api.h" 7 #include "src/api.h"
8 #include "src/ast.h" 8 #include "src/ast.h"
9 #include "src/bailout-reason.h" 9 #include "src/bailout-reason.h"
10 #include "src/base/platform/platform.h" 10 #include "src/base/platform/platform.h"
(...skipping 4019 matching lines...) Expand 10 before | Expand all | Expand 10 after
4030 // possible reference to the variable in foo's scope. However, it's possible 4030 // possible reference to the variable in foo's scope. However, it's possible
4031 // that it will be compiled lazily. 4031 // that it will be compiled lazily.
4032 4032
4033 // To make this additional case work, both Parser and PreParser implement a 4033 // To make this additional case work, both Parser and PreParser implement a
4034 // logic where only top-level functions will be parsed lazily. 4034 // logic where only top-level functions will be parsed lazily.
4035 bool is_lazily_parsed = (mode() == PARSE_LAZILY && 4035 bool is_lazily_parsed = (mode() == PARSE_LAZILY &&
4036 scope_->AllowsLazyCompilation() && 4036 scope_->AllowsLazyCompilation() &&
4037 !parenthesized_function_); 4037 !parenthesized_function_);
4038 parenthesized_function_ = false; // The bit was set for this function only. 4038 parenthesized_function_ = false; // The bit was set for this function only.
4039 4039
4040 if (is_lazily_parsed) { 4040 // Trial parse.
4041 Scanner::BookmarkScope bookmark(scanner());
4042 if (is_lazily_parsed && bookmark.Set()) {
4043 // We call SkipLazyFunctionBody with a bookmark, meaning that
4044 // SkipLazyFunctionBody may decide to abort the skipping if it
4045 // finds out the function should really have been eagerly parsed
4046 // afterall.
4041 SkipLazyFunctionBody(function_name, &materialized_literal_count, 4047 SkipLazyFunctionBody(function_name, &materialized_literal_count,
4042 &expected_property_count, CHECK_OK); 4048 &expected_property_count, ok /*CHECK_OK*/,
4043 } else { 4049 &bookmark);
4050 }
4051
4052 // Following the trial parse we can be in one of these states now:
4053 // - we wanted to eagerly parse all along
4054 // condition: !is_lazily_parsed
4055 // action: eager parse.
4056 // - we wanted to lazy parse and have not tried trial parsing
4057 // condition: is_lazily_parsed (but none of the conditions below)
marja 2015/04/22 16:40:55 ... is this the same as "couldn't trial parse beca
vogelheim 2015/04/22 17:08:34 Yes. Cannot bookmark, or !is_lazily_parsed
4058 // action: lazy parse
4059 // - we trial parsed, and trial parsing finished
4060 // condition: is_lazily_parsed && bookmark.HasBeenSet()
4061 // action: we're done.
4062 // - we trial parsed, and trial parsing aborted
4063 // condition: is_lazily_parsed && bookmark.HasBeenReset()
4064 // action: eager parse.
marja 2015/04/22 16:40:55 The logic sounds correct, but... isn't there a sim
vogelheim 2015/04/22 17:08:34 That'd work as well. I'll change it.
4065 if (!is_lazily_parsed || (is_lazily_parsed && bookmark.HasBeenReset())) {
4066 if (bookmark.HasBeenReset()) {
4067 // TODO(vogelheim): We're lying, the function is not parenthesized.
4068 // But this will cause the compiler to actually compile it.
marja 2015/04/22 16:40:55 ... we might want to use the non-hacky way of sayi
4069 parenthesized = FunctionLiteral::kIsParenthesized;
4070 }
4071
4044 body = ParseEagerFunctionBody(function_name, pos, fvar, fvar_init_op, 4072 body = ParseEagerFunctionBody(function_name, pos, fvar, fvar_init_op,
4045 kind, CHECK_OK); 4073 kind, CHECK_OK);
4046 materialized_literal_count = function_state.materialized_literal_count(); 4074 materialized_literal_count = function_state.materialized_literal_count();
4047 expected_property_count = function_state.expected_property_count(); 4075 expected_property_count = function_state.expected_property_count();
4048 handler_count = function_state.handler_count(); 4076 handler_count = function_state.handler_count();
4077 } else if (is_lazily_parsed && bookmark.HasBeenSet()) {
4078 ; // Work was already done in trial parse, above.
4079 } else {
4080 SkipLazyFunctionBody(function_name, &materialized_literal_count,
4081 &expected_property_count, /*CHECK_OK*/ ok);
4049 } 4082 }
4050 4083
4051 // Validate name and parameter names. We can do this only after parsing the 4084 // Validate name and parameter names. We can do this only after parsing the
4052 // function, since the function can declare itself strict. 4085 // function, since the function can declare itself strict.
4053 CheckFunctionName(language_mode(), kind, function_name, 4086 CheckFunctionName(language_mode(), kind, function_name,
4054 name_is_strict_reserved, function_name_location, 4087 name_is_strict_reserved, function_name_location,
4055 CHECK_OK); 4088 CHECK_OK);
4056 const bool use_strict_params = is_rest || IsConciseMethod(kind); 4089 const bool use_strict_params = is_rest || IsConciseMethod(kind);
4057 CheckFunctionParameterNames(language_mode(), use_strict_params, 4090 CheckFunctionParameterNames(language_mode(), use_strict_params,
4058 eval_args_loc, undefined_loc, dupe_loc, 4091 eval_args_loc, undefined_loc, dupe_loc,
(...skipping 28 matching lines...) Expand all
4087 function_literal->set_dont_optimize_reason(kRestParameter); 4120 function_literal->set_dont_optimize_reason(kRestParameter);
4088 } 4121 }
4089 4122
4090 if (fni_ != NULL && should_infer_name) fni_->AddFunction(function_literal); 4123 if (fni_ != NULL && should_infer_name) fni_->AddFunction(function_literal);
4091 return function_literal; 4124 return function_literal;
4092 } 4125 }
4093 4126
4094 4127
4095 void Parser::SkipLazyFunctionBody(const AstRawString* function_name, 4128 void Parser::SkipLazyFunctionBody(const AstRawString* function_name,
4096 int* materialized_literal_count, 4129 int* materialized_literal_count,
4097 int* expected_property_count, 4130 int* expected_property_count, bool* ok,
4098 bool* ok) { 4131 Scanner::BookmarkScope* bookmark) {
4132 DCHECK_IMPLIES(bookmark, bookmark->HasBeenSet());
4099 if (produce_cached_parse_data()) CHECK(log_); 4133 if (produce_cached_parse_data()) CHECK(log_);
4100 4134
4101 int function_block_pos = position(); 4135 int function_block_pos = position();
4102 if (consume_cached_parse_data() && !cached_parse_data_->rejected()) { 4136 if (consume_cached_parse_data() && !cached_parse_data_->rejected()) {
4103 // If we have cached data, we use it to skip parsing the function body. The 4137 // If we have cached data, we use it to skip parsing the function body. The
4104 // data contains the information we need to construct the lazy function. 4138 // data contains the information we need to construct the lazy function.
4105 FunctionEntry entry = 4139 FunctionEntry entry =
4106 cached_parse_data_->GetFunctionEntry(function_block_pos); 4140 cached_parse_data_->GetFunctionEntry(function_block_pos);
4107 // Check that cached data is valid. If not, mark it as invalid (the embedder 4141 // Check that cached data is valid. If not, mark it as invalid (the embedder
4108 // handles it). Note that end position greater than end of stream is safe, 4142 // handles it). Note that end position greater than end of stream is safe,
(...skipping 12 matching lines...) Expand all
4121 scope_->SetLanguageMode(entry.language_mode()); 4155 scope_->SetLanguageMode(entry.language_mode());
4122 if (entry.uses_super_property()) scope_->RecordSuperPropertyUsage(); 4156 if (entry.uses_super_property()) scope_->RecordSuperPropertyUsage();
4123 return; 4157 return;
4124 } 4158 }
4125 cached_parse_data_->Reject(); 4159 cached_parse_data_->Reject();
4126 } 4160 }
4127 // With no cached data, we partially parse the function, without building an 4161 // With no cached data, we partially parse the function, without building an
4128 // AST. This gathers the data needed to build a lazy function. 4162 // AST. This gathers the data needed to build a lazy function.
4129 SingletonLogger logger; 4163 SingletonLogger logger;
4130 PreParser::PreParseResult result = 4164 PreParser::PreParseResult result =
4131 ParseLazyFunctionBodyWithPreParser(&logger); 4165 ParseLazyFunctionBodyWithPreParser(&logger, bookmark);
4166 if (bookmark && bookmark->HasBeenReset()) {
4167 return; // Return immediately if pre-parser devided to abort parsing.
4168 }
4132 if (result == PreParser::kPreParseStackOverflow) { 4169 if (result == PreParser::kPreParseStackOverflow) {
4133 // Propagate stack overflow. 4170 // Propagate stack overflow.
4134 set_stack_overflow(); 4171 set_stack_overflow();
4135 *ok = false; 4172 *ok = false;
4136 return; 4173 return;
4137 } 4174 }
4138 if (logger.has_error()) { 4175 if (logger.has_error()) {
4139 ParserTraits::ReportMessageAt( 4176 ParserTraits::ReportMessageAt(
4140 Scanner::Location(logger.start(), logger.end()), logger.message(), 4177 Scanner::Location(logger.start(), logger.end()), logger.message(),
4141 logger.argument_opt(), logger.error_type()); 4178 logger.argument_opt(), logger.error_type());
(...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after
4250 } 4287 }
4251 4288
4252 Expect(Token::RBRACE, CHECK_OK); 4289 Expect(Token::RBRACE, CHECK_OK);
4253 scope_->set_end_position(scanner()->location().end_pos); 4290 scope_->set_end_position(scanner()->location().end_pos);
4254 4291
4255 return body; 4292 return body;
4256 } 4293 }
4257 4294
4258 4295
4259 PreParser::PreParseResult Parser::ParseLazyFunctionBodyWithPreParser( 4296 PreParser::PreParseResult Parser::ParseLazyFunctionBodyWithPreParser(
4260 SingletonLogger* logger) { 4297 SingletonLogger* logger, Scanner::BookmarkScope* bookmark) {
4261 // This function may be called on a background thread too; record only the 4298 // This function may be called on a background thread too; record only the
4262 // main thread preparse times. 4299 // main thread preparse times.
4263 if (pre_parse_timer_ != NULL) { 4300 if (pre_parse_timer_ != NULL) {
4264 pre_parse_timer_->Start(); 4301 pre_parse_timer_->Start();
4265 } 4302 }
4266 DCHECK_EQ(Token::LBRACE, scanner()->current_token()); 4303 DCHECK_EQ(Token::LBRACE, scanner()->current_token());
4267 4304
4268 if (reusable_preparser_ == NULL) { 4305 if (reusable_preparser_ == NULL) {
4269 reusable_preparser_ = new PreParser(zone(), &scanner_, ast_value_factory(), 4306 reusable_preparser_ = new PreParser(zone(), &scanner_, ast_value_factory(),
4270 NULL, stack_limit_); 4307 NULL, stack_limit_);
4271 reusable_preparser_->set_allow_lazy(true); 4308 reusable_preparser_->set_allow_lazy(true);
4272 reusable_preparser_->set_allow_natives(allow_natives()); 4309 reusable_preparser_->set_allow_natives(allow_natives());
4273 reusable_preparser_->set_allow_harmony_modules(allow_harmony_modules()); 4310 reusable_preparser_->set_allow_harmony_modules(allow_harmony_modules());
4274 reusable_preparser_->set_allow_harmony_arrow_functions( 4311 reusable_preparser_->set_allow_harmony_arrow_functions(
4275 allow_harmony_arrow_functions()); 4312 allow_harmony_arrow_functions());
4276 reusable_preparser_->set_allow_harmony_classes(allow_harmony_classes()); 4313 reusable_preparser_->set_allow_harmony_classes(allow_harmony_classes());
4277 reusable_preparser_->set_allow_harmony_object_literals( 4314 reusable_preparser_->set_allow_harmony_object_literals(
4278 allow_harmony_object_literals()); 4315 allow_harmony_object_literals());
4279 reusable_preparser_->set_allow_harmony_sloppy(allow_harmony_sloppy()); 4316 reusable_preparser_->set_allow_harmony_sloppy(allow_harmony_sloppy());
4280 reusable_preparser_->set_allow_harmony_unicode(allow_harmony_unicode()); 4317 reusable_preparser_->set_allow_harmony_unicode(allow_harmony_unicode());
4281 reusable_preparser_->set_allow_harmony_computed_property_names( 4318 reusable_preparser_->set_allow_harmony_computed_property_names(
4282 allow_harmony_computed_property_names()); 4319 allow_harmony_computed_property_names());
4283 reusable_preparser_->set_allow_harmony_rest_params( 4320 reusable_preparser_->set_allow_harmony_rest_params(
4284 allow_harmony_rest_params()); 4321 allow_harmony_rest_params());
4285 reusable_preparser_->set_allow_harmony_spreadcalls( 4322 reusable_preparser_->set_allow_harmony_spreadcalls(
4286 allow_harmony_spreadcalls()); 4323 allow_harmony_spreadcalls());
4287 reusable_preparser_->set_allow_strong_mode(allow_strong_mode()); 4324 reusable_preparser_->set_allow_strong_mode(allow_strong_mode());
4288 } 4325 }
4289 PreParser::PreParseResult result = reusable_preparser_->PreParseLazyFunction( 4326 PreParser::PreParseResult result = reusable_preparser_->PreParseLazyFunction(
4290 language_mode(), function_state_->kind(), logger); 4327 language_mode(), function_state_->kind(), logger, bookmark);
4291 if (pre_parse_timer_ != NULL) { 4328 if (pre_parse_timer_ != NULL) {
4292 pre_parse_timer_->Stop(); 4329 pre_parse_timer_->Stop();
4293 } 4330 }
4294 return result; 4331 return result;
4295 } 4332 }
4296 4333
4297 4334
4298 ClassLiteral* Parser::ParseClassLiteral(const AstRawString* name, 4335 ClassLiteral* Parser::ParseClassLiteral(const AstRawString* name,
4299 Scanner::Location class_name_location, 4336 Scanner::Location class_name_location,
4300 bool name_is_strict_reserved, int pos, 4337 bool name_is_strict_reserved, int pos,
(...skipping 1478 matching lines...) Expand 10 before | Expand all | Expand 10 after
5779 5816
5780 Expression* Parser::SpreadCallNew(Expression* function, 5817 Expression* Parser::SpreadCallNew(Expression* function,
5781 ZoneList<v8::internal::Expression*>* args, 5818 ZoneList<v8::internal::Expression*>* args,
5782 int pos) { 5819 int pos) {
5783 args->InsertAt(0, function, zone()); 5820 args->InsertAt(0, function, zone());
5784 5821
5785 return factory()->NewCallRuntime( 5822 return factory()->NewCallRuntime(
5786 ast_value_factory()->reflect_construct_string(), NULL, args, pos); 5823 ast_value_factory()->reflect_construct_string(), NULL, args, pos);
5787 } 5824 }
5788 } } // namespace v8::internal 5825 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/parser.h ('k') | src/preparser.h » ('j') | src/preparser.cc » ('J')

Powered by Google App Engine
This is Rietveld 408576698