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