| 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 4058 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4069 // possible reference to the variable in foo's scope. However, it's possible | 4069 // possible reference to the variable in foo's scope. However, it's possible |
| 4070 // that it will be compiled lazily. | 4070 // that it will be compiled lazily. |
| 4071 | 4071 |
| 4072 // To make this additional case work, both Parser and PreParser implement a | 4072 // To make this additional case work, both Parser and PreParser implement a |
| 4073 // logic where only top-level functions will be parsed lazily. | 4073 // logic where only top-level functions will be parsed lazily. |
| 4074 bool is_lazily_parsed = (mode() == PARSE_LAZILY && | 4074 bool is_lazily_parsed = (mode() == PARSE_LAZILY && |
| 4075 scope_->AllowsLazyCompilation() && | 4075 scope_->AllowsLazyCompilation() && |
| 4076 !parenthesized_function_); | 4076 !parenthesized_function_); |
| 4077 parenthesized_function_ = false; // The bit was set for this function only. | 4077 parenthesized_function_ = false; // The bit was set for this function only. |
| 4078 | 4078 |
| 4079 // Eager or lazy parse? |
| 4080 // If is_lazily_parsed, we'll parse lazy. If we can set a bookmark, we'll |
| 4081 // pass it to SkipLazyFunctionBody, which may use it to abort lazy |
| 4082 // parsing if it suspect that wasn't a good idea. If so, or if we didn't |
| 4083 // try to lazy parse in the first place, we'll have to parse eagerly. |
| 4084 Scanner::BookmarkScope bookmark(scanner()); |
| 4079 if (is_lazily_parsed) { | 4085 if (is_lazily_parsed) { |
| 4080 for (Scope* s = scope_->outer_scope(); | 4086 for (Scope* s = scope_->outer_scope(); |
| 4081 s != nullptr && (s != s->DeclarationScope()); s = s->outer_scope()) { | 4087 s != nullptr && (s != s->DeclarationScope()); s = s->outer_scope()) { |
| 4082 s->ForceContextAllocation(); | 4088 s->ForceContextAllocation(); |
| 4083 } | 4089 } |
| 4090 |
| 4091 Scanner::BookmarkScope* maybe_bookmark = |
| 4092 bookmark.Set() ? &bookmark : nullptr; |
| 4084 SkipLazyFunctionBody(&materialized_literal_count, | 4093 SkipLazyFunctionBody(&materialized_literal_count, |
| 4085 &expected_property_count, CHECK_OK); | 4094 &expected_property_count, /*CHECK_OK*/ ok, |
| 4086 } else { | 4095 maybe_bookmark); |
| 4096 |
| 4097 if (bookmark.HasBeenReset()) { |
| 4098 // Trigger eager (re-)parsing, just below this block. |
| 4099 is_lazily_parsed = false; |
| 4100 |
| 4101 // Inform the compiler it should also eager-compile this function. |
| 4102 eager_compile_hint = FunctionLiteral::kShouldEagerCompile; |
| 4103 } |
| 4104 } |
| 4105 if (!is_lazily_parsed) { |
| 4087 body = ParseEagerFunctionBody(function_name, pos, fvar, fvar_init_op, | 4106 body = ParseEagerFunctionBody(function_name, pos, fvar, fvar_init_op, |
| 4088 kind, CHECK_OK); | 4107 kind, CHECK_OK); |
| 4089 materialized_literal_count = function_state.materialized_literal_count(); | 4108 materialized_literal_count = function_state.materialized_literal_count(); |
| 4090 expected_property_count = function_state.expected_property_count(); | 4109 expected_property_count = function_state.expected_property_count(); |
| 4091 handler_count = function_state.handler_count(); | 4110 handler_count = function_state.handler_count(); |
| 4092 | 4111 |
| 4093 if (is_strong(language_mode()) && IsSubclassConstructor(kind)) { | 4112 if (is_strong(language_mode()) && IsSubclassConstructor(kind)) { |
| 4094 if (!function_state.super_location().IsValid()) { | 4113 if (!function_state.super_location().IsValid()) { |
| 4095 ReportMessageAt(function_name_location, | 4114 ReportMessageAt(function_name_location, |
| 4096 "strong_super_call_missing", kReferenceError); | 4115 "strong_super_call_missing", kReferenceError); |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4131 // TODO(caitp): enable optimization of functions with rest params | 4150 // TODO(caitp): enable optimization of functions with rest params |
| 4132 function_literal->set_dont_optimize_reason(kRestParameter); | 4151 function_literal->set_dont_optimize_reason(kRestParameter); |
| 4133 } | 4152 } |
| 4134 | 4153 |
| 4135 if (fni_ != NULL && should_infer_name) fni_->AddFunction(function_literal); | 4154 if (fni_ != NULL && should_infer_name) fni_->AddFunction(function_literal); |
| 4136 return function_literal; | 4155 return function_literal; |
| 4137 } | 4156 } |
| 4138 | 4157 |
| 4139 | 4158 |
| 4140 void Parser::SkipLazyFunctionBody(int* materialized_literal_count, | 4159 void Parser::SkipLazyFunctionBody(int* materialized_literal_count, |
| 4141 int* expected_property_count, | 4160 int* expected_property_count, bool* ok, |
| 4142 bool* ok) { | 4161 Scanner::BookmarkScope* bookmark) { |
| 4162 DCHECK_IMPLIES(bookmark, bookmark->HasBeenSet()); |
| 4143 if (produce_cached_parse_data()) CHECK(log_); | 4163 if (produce_cached_parse_data()) CHECK(log_); |
| 4144 | 4164 |
| 4145 int function_block_pos = position(); | 4165 int function_block_pos = position(); |
| 4146 if (consume_cached_parse_data() && !cached_parse_data_->rejected()) { | 4166 if (consume_cached_parse_data() && !cached_parse_data_->rejected()) { |
| 4147 // If we have cached data, we use it to skip parsing the function body. The | 4167 // If we have cached data, we use it to skip parsing the function body. The |
| 4148 // data contains the information we need to construct the lazy function. | 4168 // data contains the information we need to construct the lazy function. |
| 4149 FunctionEntry entry = | 4169 FunctionEntry entry = |
| 4150 cached_parse_data_->GetFunctionEntry(function_block_pos); | 4170 cached_parse_data_->GetFunctionEntry(function_block_pos); |
| 4151 // Check that cached data is valid. If not, mark it as invalid (the embedder | 4171 // Check that cached data is valid. If not, mark it as invalid (the embedder |
| 4152 // handles it). Note that end position greater than end of stream is safe, | 4172 // handles it). Note that end position greater than end of stream is safe, |
| (...skipping 12 matching lines...) Expand all Loading... |
| 4165 scope_->SetLanguageMode(entry.language_mode()); | 4185 scope_->SetLanguageMode(entry.language_mode()); |
| 4166 if (entry.uses_super_property()) scope_->RecordSuperPropertyUsage(); | 4186 if (entry.uses_super_property()) scope_->RecordSuperPropertyUsage(); |
| 4167 return; | 4187 return; |
| 4168 } | 4188 } |
| 4169 cached_parse_data_->Reject(); | 4189 cached_parse_data_->Reject(); |
| 4170 } | 4190 } |
| 4171 // With no cached data, we partially parse the function, without building an | 4191 // With no cached data, we partially parse the function, without building an |
| 4172 // AST. This gathers the data needed to build a lazy function. | 4192 // AST. This gathers the data needed to build a lazy function. |
| 4173 SingletonLogger logger; | 4193 SingletonLogger logger; |
| 4174 PreParser::PreParseResult result = | 4194 PreParser::PreParseResult result = |
| 4175 ParseLazyFunctionBodyWithPreParser(&logger); | 4195 ParseLazyFunctionBodyWithPreParser(&logger, bookmark); |
| 4196 if (bookmark && bookmark->HasBeenReset()) { |
| 4197 return; // Return immediately if pre-parser devided to abort parsing. |
| 4198 } |
| 4176 if (result == PreParser::kPreParseStackOverflow) { | 4199 if (result == PreParser::kPreParseStackOverflow) { |
| 4177 // Propagate stack overflow. | 4200 // Propagate stack overflow. |
| 4178 set_stack_overflow(); | 4201 set_stack_overflow(); |
| 4179 *ok = false; | 4202 *ok = false; |
| 4180 return; | 4203 return; |
| 4181 } | 4204 } |
| 4182 if (logger.has_error()) { | 4205 if (logger.has_error()) { |
| 4183 ParserTraits::ReportMessageAt( | 4206 ParserTraits::ReportMessageAt( |
| 4184 Scanner::Location(logger.start(), logger.end()), logger.message(), | 4207 Scanner::Location(logger.start(), logger.end()), logger.message(), |
| 4185 logger.argument_opt(), logger.error_type()); | 4208 logger.argument_opt(), logger.error_type()); |
| (...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4294 } | 4317 } |
| 4295 | 4318 |
| 4296 Expect(Token::RBRACE, CHECK_OK); | 4319 Expect(Token::RBRACE, CHECK_OK); |
| 4297 scope_->set_end_position(scanner()->location().end_pos); | 4320 scope_->set_end_position(scanner()->location().end_pos); |
| 4298 | 4321 |
| 4299 return body; | 4322 return body; |
| 4300 } | 4323 } |
| 4301 | 4324 |
| 4302 | 4325 |
| 4303 PreParser::PreParseResult Parser::ParseLazyFunctionBodyWithPreParser( | 4326 PreParser::PreParseResult Parser::ParseLazyFunctionBodyWithPreParser( |
| 4304 SingletonLogger* logger) { | 4327 SingletonLogger* logger, Scanner::BookmarkScope* bookmark) { |
| 4305 // This function may be called on a background thread too; record only the | 4328 // This function may be called on a background thread too; record only the |
| 4306 // main thread preparse times. | 4329 // main thread preparse times. |
| 4307 if (pre_parse_timer_ != NULL) { | 4330 if (pre_parse_timer_ != NULL) { |
| 4308 pre_parse_timer_->Start(); | 4331 pre_parse_timer_->Start(); |
| 4309 } | 4332 } |
| 4310 DCHECK_EQ(Token::LBRACE, scanner()->current_token()); | 4333 DCHECK_EQ(Token::LBRACE, scanner()->current_token()); |
| 4311 | 4334 |
| 4312 if (reusable_preparser_ == NULL) { | 4335 if (reusable_preparser_ == NULL) { |
| 4313 reusable_preparser_ = new PreParser(zone(), &scanner_, ast_value_factory(), | 4336 reusable_preparser_ = new PreParser(zone(), &scanner_, ast_value_factory(), |
| 4314 NULL, stack_limit_); | 4337 NULL, stack_limit_); |
| 4315 reusable_preparser_->set_allow_lazy(true); | 4338 reusable_preparser_->set_allow_lazy(true); |
| 4316 reusable_preparser_->set_allow_natives(allow_natives()); | 4339 reusable_preparser_->set_allow_natives(allow_natives()); |
| 4317 reusable_preparser_->set_allow_harmony_modules(allow_harmony_modules()); | 4340 reusable_preparser_->set_allow_harmony_modules(allow_harmony_modules()); |
| 4318 reusable_preparser_->set_allow_harmony_arrow_functions( | 4341 reusable_preparser_->set_allow_harmony_arrow_functions( |
| 4319 allow_harmony_arrow_functions()); | 4342 allow_harmony_arrow_functions()); |
| 4320 reusable_preparser_->set_allow_harmony_classes(allow_harmony_classes()); | 4343 reusable_preparser_->set_allow_harmony_classes(allow_harmony_classes()); |
| 4321 reusable_preparser_->set_allow_harmony_object_literals( | 4344 reusable_preparser_->set_allow_harmony_object_literals( |
| 4322 allow_harmony_object_literals()); | 4345 allow_harmony_object_literals()); |
| 4323 reusable_preparser_->set_allow_harmony_sloppy(allow_harmony_sloppy()); | 4346 reusable_preparser_->set_allow_harmony_sloppy(allow_harmony_sloppy()); |
| 4324 reusable_preparser_->set_allow_harmony_unicode(allow_harmony_unicode()); | 4347 reusable_preparser_->set_allow_harmony_unicode(allow_harmony_unicode()); |
| 4325 reusable_preparser_->set_allow_harmony_computed_property_names( | 4348 reusable_preparser_->set_allow_harmony_computed_property_names( |
| 4326 allow_harmony_computed_property_names()); | 4349 allow_harmony_computed_property_names()); |
| 4327 reusable_preparser_->set_allow_harmony_rest_params( | 4350 reusable_preparser_->set_allow_harmony_rest_params( |
| 4328 allow_harmony_rest_params()); | 4351 allow_harmony_rest_params()); |
| 4329 reusable_preparser_->set_allow_harmony_spreadcalls( | 4352 reusable_preparser_->set_allow_harmony_spreadcalls( |
| 4330 allow_harmony_spreadcalls()); | 4353 allow_harmony_spreadcalls()); |
| 4331 reusable_preparser_->set_allow_strong_mode(allow_strong_mode()); | 4354 reusable_preparser_->set_allow_strong_mode(allow_strong_mode()); |
| 4332 } | 4355 } |
| 4333 PreParser::PreParseResult result = reusable_preparser_->PreParseLazyFunction( | 4356 PreParser::PreParseResult result = reusable_preparser_->PreParseLazyFunction( |
| 4334 language_mode(), function_state_->kind(), logger); | 4357 language_mode(), function_state_->kind(), logger, bookmark); |
| 4335 if (pre_parse_timer_ != NULL) { | 4358 if (pre_parse_timer_ != NULL) { |
| 4336 pre_parse_timer_->Stop(); | 4359 pre_parse_timer_->Stop(); |
| 4337 } | 4360 } |
| 4338 return result; | 4361 return result; |
| 4339 } | 4362 } |
| 4340 | 4363 |
| 4341 | 4364 |
| 4342 ClassLiteral* Parser::ParseClassLiteral(const AstRawString* name, | 4365 ClassLiteral* Parser::ParseClassLiteral(const AstRawString* name, |
| 4343 Scanner::Location class_name_location, | 4366 Scanner::Location class_name_location, |
| 4344 bool name_is_strict_reserved, int pos, | 4367 bool name_is_strict_reserved, int pos, |
| (...skipping 1487 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5832 | 5855 |
| 5833 Expression* Parser::SpreadCallNew(Expression* function, | 5856 Expression* Parser::SpreadCallNew(Expression* function, |
| 5834 ZoneList<v8::internal::Expression*>* args, | 5857 ZoneList<v8::internal::Expression*>* args, |
| 5835 int pos) { | 5858 int pos) { |
| 5836 args->InsertAt(0, function, zone()); | 5859 args->InsertAt(0, function, zone()); |
| 5837 | 5860 |
| 5838 return factory()->NewCallRuntime( | 5861 return factory()->NewCallRuntime( |
| 5839 ast_value_factory()->reflect_construct_string(), NULL, args, pos); | 5862 ast_value_factory()->reflect_construct_string(), NULL, args, pos); |
| 5840 } | 5863 } |
| 5841 } } // namespace v8::internal | 5864 } } // namespace v8::internal |
| OLD | NEW |