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/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 4115 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4126 // possible reference to the variable in foo's scope. However, it's possible | 4126 // possible reference to the variable in foo's scope. However, it's possible |
4127 // that it will be compiled lazily. | 4127 // that it will be compiled lazily. |
4128 | 4128 |
4129 // To make this additional case work, both Parser and PreParser implement a | 4129 // To make this additional case work, both Parser and PreParser implement a |
4130 // logic where only top-level functions will be parsed lazily. | 4130 // logic where only top-level functions will be parsed lazily. |
4131 bool is_lazily_parsed = (mode() == PARSE_LAZILY && | 4131 bool is_lazily_parsed = (mode() == PARSE_LAZILY && |
4132 scope_->AllowsLazyCompilation() && | 4132 scope_->AllowsLazyCompilation() && |
4133 !parenthesized_function_); | 4133 !parenthesized_function_); |
4134 parenthesized_function_ = false; // The bit was set for this function only. | 4134 parenthesized_function_ = false; // The bit was set for this function only. |
4135 | 4135 |
| 4136 // Eager or lazy parse? |
| 4137 // If is_lazily_parsed, we'll parse lazy. If we can set a bookmark, we'll |
| 4138 // pass it to SkipLazyFunctionBody, which may use it to abort lazy |
| 4139 // parsing if it suspect that wasn't a good idea. If so, or if we didn't |
| 4140 // try to lazy parse in the first place, we'll have to parse eagerly. |
| 4141 Scanner::BookmarkScope bookmark(scanner()); |
4136 if (is_lazily_parsed) { | 4142 if (is_lazily_parsed) { |
4137 for (Scope* s = scope_->outer_scope(); | 4143 for (Scope* s = scope_->outer_scope(); |
4138 s != nullptr && (s != s->DeclarationScope()); s = s->outer_scope()) { | 4144 s != nullptr && (s != s->DeclarationScope()); s = s->outer_scope()) { |
4139 s->ForceContextAllocation(); | 4145 s->ForceContextAllocation(); |
4140 } | 4146 } |
| 4147 |
| 4148 Scanner::BookmarkScope* maybe_bookmark = |
| 4149 bookmark.Set() ? &bookmark : nullptr; |
4141 SkipLazyFunctionBody(&materialized_literal_count, | 4150 SkipLazyFunctionBody(&materialized_literal_count, |
4142 &expected_property_count, CHECK_OK); | 4151 &expected_property_count, /*CHECK_OK*/ ok, |
4143 } else { | 4152 maybe_bookmark); |
| 4153 |
| 4154 if (bookmark.HasBeenReset()) { |
| 4155 // Trigger eager (re-)parsing, just below this block. |
| 4156 is_lazily_parsed = false; |
| 4157 |
| 4158 // Inform the compiler it should also eager-compile this function. |
| 4159 eager_compile_hint = FunctionLiteral::kShouldEagerCompile; |
| 4160 } |
| 4161 } |
| 4162 if (!is_lazily_parsed) { |
4144 body = ParseEagerFunctionBody(function_name, pos, fvar, fvar_init_op, | 4163 body = ParseEagerFunctionBody(function_name, pos, fvar, fvar_init_op, |
4145 kind, CHECK_OK); | 4164 kind, CHECK_OK); |
4146 materialized_literal_count = function_state.materialized_literal_count(); | 4165 materialized_literal_count = function_state.materialized_literal_count(); |
4147 expected_property_count = function_state.expected_property_count(); | 4166 expected_property_count = function_state.expected_property_count(); |
4148 handler_count = function_state.handler_count(); | 4167 handler_count = function_state.handler_count(); |
4149 | 4168 |
4150 if (is_strong(language_mode()) && IsSubclassConstructor(kind)) { | 4169 if (is_strong(language_mode()) && IsSubclassConstructor(kind)) { |
4151 if (!function_state.super_location().IsValid()) { | 4170 if (!function_state.super_location().IsValid()) { |
4152 ReportMessageAt(function_name_location, | 4171 ReportMessageAt(function_name_location, |
4153 "strong_super_call_missing", kReferenceError); | 4172 "strong_super_call_missing", kReferenceError); |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4188 // TODO(caitp): enable optimization of functions with rest params | 4207 // TODO(caitp): enable optimization of functions with rest params |
4189 function_literal->set_dont_optimize_reason(kRestParameter); | 4208 function_literal->set_dont_optimize_reason(kRestParameter); |
4190 } | 4209 } |
4191 | 4210 |
4192 if (fni_ != NULL && should_infer_name) fni_->AddFunction(function_literal); | 4211 if (fni_ != NULL && should_infer_name) fni_->AddFunction(function_literal); |
4193 return function_literal; | 4212 return function_literal; |
4194 } | 4213 } |
4195 | 4214 |
4196 | 4215 |
4197 void Parser::SkipLazyFunctionBody(int* materialized_literal_count, | 4216 void Parser::SkipLazyFunctionBody(int* materialized_literal_count, |
4198 int* expected_property_count, | 4217 int* expected_property_count, bool* ok, |
4199 bool* ok) { | 4218 Scanner::BookmarkScope* bookmark) { |
| 4219 DCHECK_IMPLIES(bookmark, bookmark->HasBeenSet()); |
4200 if (produce_cached_parse_data()) CHECK(log_); | 4220 if (produce_cached_parse_data()) CHECK(log_); |
4201 | 4221 |
4202 int function_block_pos = position(); | 4222 int function_block_pos = position(); |
4203 if (consume_cached_parse_data() && !cached_parse_data_->rejected()) { | 4223 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 | 4224 // 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. | 4225 // data contains the information we need to construct the lazy function. |
4206 FunctionEntry entry = | 4226 FunctionEntry entry = |
4207 cached_parse_data_->GetFunctionEntry(function_block_pos); | 4227 cached_parse_data_->GetFunctionEntry(function_block_pos); |
4208 // Check that cached data is valid. If not, mark it as invalid (the embedder | 4228 // 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, | 4229 // handles it). Note that end position greater than end of stream is safe, |
(...skipping 12 matching lines...) Expand all Loading... |
4222 scope_->SetLanguageMode(entry.language_mode()); | 4242 scope_->SetLanguageMode(entry.language_mode()); |
4223 if (entry.uses_super_property()) scope_->RecordSuperPropertyUsage(); | 4243 if (entry.uses_super_property()) scope_->RecordSuperPropertyUsage(); |
4224 return; | 4244 return; |
4225 } | 4245 } |
4226 cached_parse_data_->Reject(); | 4246 cached_parse_data_->Reject(); |
4227 } | 4247 } |
4228 // With no cached data, we partially parse the function, without building an | 4248 // With no cached data, we partially parse the function, without building an |
4229 // AST. This gathers the data needed to build a lazy function. | 4249 // AST. This gathers the data needed to build a lazy function. |
4230 SingletonLogger logger; | 4250 SingletonLogger logger; |
4231 PreParser::PreParseResult result = | 4251 PreParser::PreParseResult result = |
4232 ParseLazyFunctionBodyWithPreParser(&logger); | 4252 ParseLazyFunctionBodyWithPreParser(&logger, bookmark); |
| 4253 if (bookmark && bookmark->HasBeenReset()) { |
| 4254 return; // Return immediately if pre-parser devided to abort parsing. |
| 4255 } |
4233 if (result == PreParser::kPreParseStackOverflow) { | 4256 if (result == PreParser::kPreParseStackOverflow) { |
4234 // Propagate stack overflow. | 4257 // Propagate stack overflow. |
4235 set_stack_overflow(); | 4258 set_stack_overflow(); |
4236 *ok = false; | 4259 *ok = false; |
4237 return; | 4260 return; |
4238 } | 4261 } |
4239 if (logger.has_error()) { | 4262 if (logger.has_error()) { |
4240 ParserTraits::ReportMessageAt( | 4263 ParserTraits::ReportMessageAt( |
4241 Scanner::Location(logger.start(), logger.end()), logger.message(), | 4264 Scanner::Location(logger.start(), logger.end()), logger.message(), |
4242 logger.argument_opt(), logger.error_type()); | 4265 logger.argument_opt(), logger.error_type()); |
(...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4351 } | 4374 } |
4352 | 4375 |
4353 Expect(Token::RBRACE, CHECK_OK); | 4376 Expect(Token::RBRACE, CHECK_OK); |
4354 scope_->set_end_position(scanner()->location().end_pos); | 4377 scope_->set_end_position(scanner()->location().end_pos); |
4355 | 4378 |
4356 return body; | 4379 return body; |
4357 } | 4380 } |
4358 | 4381 |
4359 | 4382 |
4360 PreParser::PreParseResult Parser::ParseLazyFunctionBodyWithPreParser( | 4383 PreParser::PreParseResult Parser::ParseLazyFunctionBodyWithPreParser( |
4361 SingletonLogger* logger) { | 4384 SingletonLogger* logger, Scanner::BookmarkScope* bookmark) { |
4362 // This function may be called on a background thread too; record only the | 4385 // This function may be called on a background thread too; record only the |
4363 // main thread preparse times. | 4386 // main thread preparse times. |
4364 if (pre_parse_timer_ != NULL) { | 4387 if (pre_parse_timer_ != NULL) { |
4365 pre_parse_timer_->Start(); | 4388 pre_parse_timer_->Start(); |
4366 } | 4389 } |
4367 DCHECK_EQ(Token::LBRACE, scanner()->current_token()); | 4390 DCHECK_EQ(Token::LBRACE, scanner()->current_token()); |
4368 | 4391 |
4369 if (reusable_preparser_ == NULL) { | 4392 if (reusable_preparser_ == NULL) { |
4370 reusable_preparser_ = new PreParser(zone(), &scanner_, ast_value_factory(), | 4393 reusable_preparser_ = new PreParser(zone(), &scanner_, ast_value_factory(), |
4371 NULL, stack_limit_); | 4394 NULL, stack_limit_); |
(...skipping 11 matching lines...) Expand all Loading... |
4383 allow_harmony_computed_property_names()); | 4406 allow_harmony_computed_property_names()); |
4384 reusable_preparser_->set_allow_harmony_rest_params( | 4407 reusable_preparser_->set_allow_harmony_rest_params( |
4385 allow_harmony_rest_params()); | 4408 allow_harmony_rest_params()); |
4386 reusable_preparser_->set_allow_harmony_spreadcalls( | 4409 reusable_preparser_->set_allow_harmony_spreadcalls( |
4387 allow_harmony_spreadcalls()); | 4410 allow_harmony_spreadcalls()); |
4388 reusable_preparser_->set_allow_harmony_destructuring( | 4411 reusable_preparser_->set_allow_harmony_destructuring( |
4389 allow_harmony_destructuring()); | 4412 allow_harmony_destructuring()); |
4390 reusable_preparser_->set_allow_strong_mode(allow_strong_mode()); | 4413 reusable_preparser_->set_allow_strong_mode(allow_strong_mode()); |
4391 } | 4414 } |
4392 PreParser::PreParseResult result = reusable_preparser_->PreParseLazyFunction( | 4415 PreParser::PreParseResult result = reusable_preparser_->PreParseLazyFunction( |
4393 language_mode(), function_state_->kind(), logger); | 4416 language_mode(), function_state_->kind(), logger, bookmark); |
4394 if (pre_parse_timer_ != NULL) { | 4417 if (pre_parse_timer_ != NULL) { |
4395 pre_parse_timer_->Stop(); | 4418 pre_parse_timer_->Stop(); |
4396 } | 4419 } |
4397 return result; | 4420 return result; |
4398 } | 4421 } |
4399 | 4422 |
4400 | 4423 |
4401 ClassLiteral* Parser::ParseClassLiteral(const AstRawString* name, | 4424 ClassLiteral* Parser::ParseClassLiteral(const AstRawString* name, |
4402 Scanner::Location class_name_location, | 4425 Scanner::Location class_name_location, |
4403 bool name_is_strict_reserved, int pos, | 4426 bool name_is_strict_reserved, int pos, |
(...skipping 1487 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5891 | 5914 |
5892 Expression* Parser::SpreadCallNew(Expression* function, | 5915 Expression* Parser::SpreadCallNew(Expression* function, |
5893 ZoneList<v8::internal::Expression*>* args, | 5916 ZoneList<v8::internal::Expression*>* args, |
5894 int pos) { | 5917 int pos) { |
5895 args->InsertAt(0, function, zone()); | 5918 args->InsertAt(0, function, zone()); |
5896 | 5919 |
5897 return factory()->NewCallRuntime( | 5920 return factory()->NewCallRuntime( |
5898 ast_value_factory()->reflect_construct_string(), NULL, args, pos); | 5921 ast_value_factory()->reflect_construct_string(), NULL, args, pos); |
5899 } | 5922 } |
5900 } } // namespace v8::internal | 5923 } } // namespace v8::internal |
OLD | NEW |