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

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: Use a seperate 'hint' bit for "to be executed once" code aging. Created 5 years, 7 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') | no next file with comments »
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 4018 matching lines...) Expand 10 before | Expand all | Expand 10 after
4029 ? NewScope(declaration_scope, FUNCTION_SCOPE, kind) 4029 ? NewScope(declaration_scope, FUNCTION_SCOPE, kind)
4030 : NewScope(scope_, FUNCTION_SCOPE, kind); 4030 : NewScope(scope_, FUNCTION_SCOPE, kind);
4031 ZoneList<Statement*>* body = NULL; 4031 ZoneList<Statement*>* body = NULL;
4032 int materialized_literal_count = -1; 4032 int materialized_literal_count = -1;
4033 int expected_property_count = -1; 4033 int expected_property_count = -1;
4034 int handler_count = 0; 4034 int handler_count = 0;
4035 FormalParameterErrorLocations error_locs; 4035 FormalParameterErrorLocations error_locs;
4036 FunctionLiteral::EagerCompileHint eager_compile_hint = 4036 FunctionLiteral::EagerCompileHint eager_compile_hint =
4037 parenthesized_function_ ? FunctionLiteral::kShouldEagerCompile 4037 parenthesized_function_ ? FunctionLiteral::kShouldEagerCompile
4038 : FunctionLiteral::kShouldLazyCompile; 4038 : FunctionLiteral::kShouldLazyCompile;
4039 bool should_be_used_once_hint = false;
4039 // Parse function body. 4040 // Parse function body.
4040 { 4041 {
4041 AstNodeFactory function_factory(ast_value_factory()); 4042 AstNodeFactory function_factory(ast_value_factory());
4042 FunctionState function_state(&function_state_, &scope_, scope, kind, 4043 FunctionState function_state(&function_state_, &scope_, scope, kind,
4043 &function_factory); 4044 &function_factory);
4044 scope_->SetScopeName(function_name); 4045 scope_->SetScopeName(function_name);
4045 4046
4046 if (is_generator) { 4047 if (is_generator) {
4047 // For generators, allocating variables in contexts is currently a win 4048 // For generators, allocating variables in contexts is currently a win
4048 // because it minimizes the work needed to suspend and resume an 4049 // because it minimizes the work needed to suspend and resume an
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after
4126 // possible reference to the variable in foo's scope. However, it's possible 4127 // possible reference to the variable in foo's scope. However, it's possible
4127 // that it will be compiled lazily. 4128 // that it will be compiled lazily.
4128 4129
4129 // To make this additional case work, both Parser and PreParser implement a 4130 // To make this additional case work, both Parser and PreParser implement a
4130 // logic where only top-level functions will be parsed lazily. 4131 // logic where only top-level functions will be parsed lazily.
4131 bool is_lazily_parsed = (mode() == PARSE_LAZILY && 4132 bool is_lazily_parsed = (mode() == PARSE_LAZILY &&
4132 scope_->AllowsLazyCompilation() && 4133 scope_->AllowsLazyCompilation() &&
4133 !parenthesized_function_); 4134 !parenthesized_function_);
4134 parenthesized_function_ = false; // The bit was set for this function only. 4135 parenthesized_function_ = false; // The bit was set for this function only.
4135 4136
4137 // Eager or lazy parse?
4138 // If is_lazily_parsed, we'll parse lazy. If we can set a bookmark, we'll
4139 // pass it to SkipLazyFunctionBody, which may use it to abort lazy
4140 // parsing if it suspect that wasn't a good idea. If so, or if we didn't
4141 // try to lazy parse in the first place, we'll have to parse eagerly.
4142 Scanner::BookmarkScope bookmark(scanner());
4136 if (is_lazily_parsed) { 4143 if (is_lazily_parsed) {
4137 for (Scope* s = scope_->outer_scope(); 4144 for (Scope* s = scope_->outer_scope();
4138 s != nullptr && (s != s->DeclarationScope()); s = s->outer_scope()) { 4145 s != nullptr && (s != s->DeclarationScope()); s = s->outer_scope()) {
4139 s->ForceContextAllocation(); 4146 s->ForceContextAllocation();
4140 } 4147 }
4148
4149 Scanner::BookmarkScope* maybe_bookmark =
4150 bookmark.Set() ? &bookmark : nullptr;
4141 SkipLazyFunctionBody(&materialized_literal_count, 4151 SkipLazyFunctionBody(&materialized_literal_count,
4142 &expected_property_count, CHECK_OK); 4152 &expected_property_count, /*CHECK_OK*/ ok,
4143 } else { 4153 maybe_bookmark);
4154
4155 if (bookmark.HasBeenReset()) {
4156 // Trigger eager (re-)parsing, just below this block.
4157 is_lazily_parsed = false;
4158
4159 // This is probably an initialization function. Inform the compiler it
4160 // should also eager-compile this function, and that we expect it to be
4161 // used once.
4162 eager_compile_hint = FunctionLiteral::kShouldEagerCompile;
4163 should_be_used_once_hint = true;
4164 }
4165 }
4166 if (!is_lazily_parsed) {
4144 body = ParseEagerFunctionBody(function_name, pos, fvar, fvar_init_op, 4167 body = ParseEagerFunctionBody(function_name, pos, fvar, fvar_init_op,
4145 kind, CHECK_OK); 4168 kind, CHECK_OK);
4146 materialized_literal_count = function_state.materialized_literal_count(); 4169 materialized_literal_count = function_state.materialized_literal_count();
4147 expected_property_count = function_state.expected_property_count(); 4170 expected_property_count = function_state.expected_property_count();
4148 handler_count = function_state.handler_count(); 4171 handler_count = function_state.handler_count();
4149 4172
4150 if (is_strong(language_mode()) && IsSubclassConstructor(kind)) { 4173 if (is_strong(language_mode()) && IsSubclassConstructor(kind)) {
4151 if (!function_state.super_location().IsValid()) { 4174 if (!function_state.super_location().IsValid()) {
4152 ReportMessageAt(function_name_location, 4175 ReportMessageAt(function_name_location,
4153 "strong_super_call_missing", kReferenceError); 4176 "strong_super_call_missing", kReferenceError);
(...skipping 22 matching lines...) Expand all
4176 FunctionLiteral::ParameterFlag duplicate_parameters = 4199 FunctionLiteral::ParameterFlag duplicate_parameters =
4177 error_locs.duplicate.IsValid() ? FunctionLiteral::kHasDuplicateParameters 4200 error_locs.duplicate.IsValid() ? FunctionLiteral::kHasDuplicateParameters
4178 : FunctionLiteral::kNoDuplicateParameters; 4201 : FunctionLiteral::kNoDuplicateParameters;
4179 4202
4180 FunctionLiteral* function_literal = factory()->NewFunctionLiteral( 4203 FunctionLiteral* function_literal = factory()->NewFunctionLiteral(
4181 function_name, ast_value_factory(), scope, body, 4204 function_name, ast_value_factory(), scope, body,
4182 materialized_literal_count, expected_property_count, handler_count, 4205 materialized_literal_count, expected_property_count, handler_count,
4183 num_parameters, duplicate_parameters, function_type, 4206 num_parameters, duplicate_parameters, function_type,
4184 FunctionLiteral::kIsFunction, eager_compile_hint, kind, pos); 4207 FunctionLiteral::kIsFunction, eager_compile_hint, kind, pos);
4185 function_literal->set_function_token_position(function_token_pos); 4208 function_literal->set_function_token_position(function_token_pos);
4209 if (should_be_used_once_hint)
4210 function_literal->set_should_be_used_once_hint();
4186 4211
4187 if (scope->has_rest_parameter()) { 4212 if (scope->has_rest_parameter()) {
4188 // TODO(caitp): enable optimization of functions with rest params 4213 // TODO(caitp): enable optimization of functions with rest params
4189 function_literal->set_dont_optimize_reason(kRestParameter); 4214 function_literal->set_dont_optimize_reason(kRestParameter);
4190 } 4215 }
4191 4216
4192 if (fni_ != NULL && should_infer_name) fni_->AddFunction(function_literal); 4217 if (fni_ != NULL && should_infer_name) fni_->AddFunction(function_literal);
4193 return function_literal; 4218 return function_literal;
4194 } 4219 }
4195 4220
4196 4221
4197 void Parser::SkipLazyFunctionBody(int* materialized_literal_count, 4222 void Parser::SkipLazyFunctionBody(int* materialized_literal_count,
4198 int* expected_property_count, 4223 int* expected_property_count, bool* ok,
4199 bool* ok) { 4224 Scanner::BookmarkScope* bookmark) {
4225 DCHECK_IMPLIES(bookmark, bookmark->HasBeenSet());
4200 if (produce_cached_parse_data()) CHECK(log_); 4226 if (produce_cached_parse_data()) CHECK(log_);
4201 4227
4202 int function_block_pos = position(); 4228 int function_block_pos = position();
4203 if (consume_cached_parse_data() && !cached_parse_data_->rejected()) { 4229 if (consume_cached_parse_data() && !cached_parse_data_->rejected()) {
4204 // If we have cached data, we use it to skip parsing the function body. The 4230 // If we have cached data, we use it to skip parsing the function body. The
4205 // data contains the information we need to construct the lazy function. 4231 // data contains the information we need to construct the lazy function.
4206 FunctionEntry entry = 4232 FunctionEntry entry =
4207 cached_parse_data_->GetFunctionEntry(function_block_pos); 4233 cached_parse_data_->GetFunctionEntry(function_block_pos);
4208 // Check that cached data is valid. If not, mark it as invalid (the embedder 4234 // Check that cached data is valid. If not, mark it as invalid (the embedder
4209 // handles it). Note that end position greater than end of stream is safe, 4235 // handles it). Note that end position greater than end of stream is safe,
(...skipping 12 matching lines...) Expand all
4222 scope_->SetLanguageMode(entry.language_mode()); 4248 scope_->SetLanguageMode(entry.language_mode());
4223 if (entry.uses_super_property()) scope_->RecordSuperPropertyUsage(); 4249 if (entry.uses_super_property()) scope_->RecordSuperPropertyUsage();
4224 return; 4250 return;
4225 } 4251 }
4226 cached_parse_data_->Reject(); 4252 cached_parse_data_->Reject();
4227 } 4253 }
4228 // With no cached data, we partially parse the function, without building an 4254 // With no cached data, we partially parse the function, without building an
4229 // AST. This gathers the data needed to build a lazy function. 4255 // AST. This gathers the data needed to build a lazy function.
4230 SingletonLogger logger; 4256 SingletonLogger logger;
4231 PreParser::PreParseResult result = 4257 PreParser::PreParseResult result =
4232 ParseLazyFunctionBodyWithPreParser(&logger); 4258 ParseLazyFunctionBodyWithPreParser(&logger, bookmark);
4259 if (bookmark && bookmark->HasBeenReset()) {
4260 return; // Return immediately if pre-parser devided to abort parsing.
4261 }
4233 if (result == PreParser::kPreParseStackOverflow) { 4262 if (result == PreParser::kPreParseStackOverflow) {
4234 // Propagate stack overflow. 4263 // Propagate stack overflow.
4235 set_stack_overflow(); 4264 set_stack_overflow();
4236 *ok = false; 4265 *ok = false;
4237 return; 4266 return;
4238 } 4267 }
4239 if (logger.has_error()) { 4268 if (logger.has_error()) {
4240 ParserTraits::ReportMessageAt( 4269 ParserTraits::ReportMessageAt(
4241 Scanner::Location(logger.start(), logger.end()), logger.message(), 4270 Scanner::Location(logger.start(), logger.end()), logger.message(),
4242 logger.argument_opt(), logger.error_type()); 4271 logger.argument_opt(), logger.error_type());
(...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after
4351 } 4380 }
4352 4381
4353 Expect(Token::RBRACE, CHECK_OK); 4382 Expect(Token::RBRACE, CHECK_OK);
4354 scope_->set_end_position(scanner()->location().end_pos); 4383 scope_->set_end_position(scanner()->location().end_pos);
4355 4384
4356 return body; 4385 return body;
4357 } 4386 }
4358 4387
4359 4388
4360 PreParser::PreParseResult Parser::ParseLazyFunctionBodyWithPreParser( 4389 PreParser::PreParseResult Parser::ParseLazyFunctionBodyWithPreParser(
4361 SingletonLogger* logger) { 4390 SingletonLogger* logger, Scanner::BookmarkScope* bookmark) {
4362 // This function may be called on a background thread too; record only the 4391 // This function may be called on a background thread too; record only the
4363 // main thread preparse times. 4392 // main thread preparse times.
4364 if (pre_parse_timer_ != NULL) { 4393 if (pre_parse_timer_ != NULL) {
4365 pre_parse_timer_->Start(); 4394 pre_parse_timer_->Start();
4366 } 4395 }
4367 DCHECK_EQ(Token::LBRACE, scanner()->current_token()); 4396 DCHECK_EQ(Token::LBRACE, scanner()->current_token());
4368 4397
4369 if (reusable_preparser_ == NULL) { 4398 if (reusable_preparser_ == NULL) {
4370 reusable_preparser_ = new PreParser(zone(), &scanner_, ast_value_factory(), 4399 reusable_preparser_ = new PreParser(zone(), &scanner_, ast_value_factory(),
4371 NULL, stack_limit_); 4400 NULL, stack_limit_);
(...skipping 11 matching lines...) Expand all
4383 allow_harmony_computed_property_names()); 4412 allow_harmony_computed_property_names());
4384 reusable_preparser_->set_allow_harmony_rest_params( 4413 reusable_preparser_->set_allow_harmony_rest_params(
4385 allow_harmony_rest_params()); 4414 allow_harmony_rest_params());
4386 reusable_preparser_->set_allow_harmony_spreadcalls( 4415 reusable_preparser_->set_allow_harmony_spreadcalls(
4387 allow_harmony_spreadcalls()); 4416 allow_harmony_spreadcalls());
4388 reusable_preparser_->set_allow_harmony_destructuring( 4417 reusable_preparser_->set_allow_harmony_destructuring(
4389 allow_harmony_destructuring()); 4418 allow_harmony_destructuring());
4390 reusable_preparser_->set_allow_strong_mode(allow_strong_mode()); 4419 reusable_preparser_->set_allow_strong_mode(allow_strong_mode());
4391 } 4420 }
4392 PreParser::PreParseResult result = reusable_preparser_->PreParseLazyFunction( 4421 PreParser::PreParseResult result = reusable_preparser_->PreParseLazyFunction(
4393 language_mode(), function_state_->kind(), logger); 4422 language_mode(), function_state_->kind(), logger, bookmark);
4394 if (pre_parse_timer_ != NULL) { 4423 if (pre_parse_timer_ != NULL) {
4395 pre_parse_timer_->Stop(); 4424 pre_parse_timer_->Stop();
4396 } 4425 }
4397 return result; 4426 return result;
4398 } 4427 }
4399 4428
4400 4429
4401 ClassLiteral* Parser::ParseClassLiteral(const AstRawString* name, 4430 ClassLiteral* Parser::ParseClassLiteral(const AstRawString* name,
4402 Scanner::Location class_name_location, 4431 Scanner::Location class_name_location,
4403 bool name_is_strict_reserved, int pos, 4432 bool name_is_strict_reserved, int pos,
(...skipping 1487 matching lines...) Expand 10 before | Expand all | Expand 10 after
5891 5920
5892 Expression* Parser::SpreadCallNew(Expression* function, 5921 Expression* Parser::SpreadCallNew(Expression* function,
5893 ZoneList<v8::internal::Expression*>* args, 5922 ZoneList<v8::internal::Expression*>* args,
5894 int pos) { 5923 int pos) {
5895 args->InsertAt(0, function, zone()); 5924 args->InsertAt(0, function, zone());
5896 5925
5897 return factory()->NewCallRuntime( 5926 return factory()->NewCallRuntime(
5898 ast_value_factory()->reflect_construct_string(), NULL, args, pos); 5927 ast_value_factory()->reflect_construct_string(), NULL, args, pos);
5899 } 5928 }
5900 } } // namespace v8::internal 5929 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/parser.h ('k') | src/preparser.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698