Chromium Code Reviews| 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 4019 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 |
| OLD | NEW |