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/ast-literal-reindexer.h" | 9 #include "src/ast-literal-reindexer.h" |
| 10 #include "src/bailout-reason.h" | 10 #include "src/bailout-reason.h" |
| (...skipping 4021 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 4032 ParserFormalParameters formals(scope); | 4032 ParserFormalParameters formals(scope); |
| 4033 arity = ParseFormalParameterList(&formals, &formals_classifier, CHECK_OK); | 4033 arity = ParseFormalParameterList(&formals, &formals_classifier, CHECK_OK); |
| 4034 Expect(Token::RPAREN, CHECK_OK); | 4034 Expect(Token::RPAREN, CHECK_OK); |
| 4035 int formals_end_position = scanner()->location().end_pos; | 4035 int formals_end_position = scanner()->location().end_pos; |
| 4036 | 4036 |
| 4037 CheckArityRestrictions(arity, arity_restriction, | 4037 CheckArityRestrictions(arity, arity_restriction, |
| 4038 formals.has_rest, start_position, | 4038 formals.has_rest, start_position, |
| 4039 formals_end_position, CHECK_OK); | 4039 formals_end_position, CHECK_OK); |
| 4040 Expect(Token::LBRACE, CHECK_OK); | 4040 Expect(Token::LBRACE, CHECK_OK); |
| 4041 | 4041 |
| 4042 // If we have a named function expression, we add a local variable | |
| 4043 // declaration to the body of the function with the name of the | |
| 4044 // function and let it refer to the function itself (closure). | |
| 4045 // NOTE: We create a proxy and resolve it here so that in the | |
| 4046 // future we can change the AST to only refer to VariableProxies | |
| 4047 // instead of Variables and Proxis as is the case now. | |
| 4048 Variable* fvar = NULL; | |
| 4049 Token::Value fvar_init_op = Token::INIT_CONST_LEGACY; | |
| 4050 if (function_type == FunctionLiteral::NAMED_EXPRESSION) { | |
| 4051 bool use_strict_const = is_strict(language_mode) || | |
| 4052 (!allow_legacy_const() && allow_harmony_sloppy()); | |
| 4053 if (use_strict_const) { | |
| 4054 fvar_init_op = Token::INIT_CONST; | |
| 4055 } | |
| 4056 VariableMode fvar_mode = use_strict_const ? CONST : CONST_LEGACY; | |
| 4057 DCHECK(function_name != NULL); | |
| 4058 fvar = new (zone()) | |
| 4059 Variable(scope_, function_name, fvar_mode, Variable::NORMAL, | |
| 4060 kCreatedInitialized, kNotAssigned); | |
| 4061 VariableProxy* proxy = factory()->NewVariableProxy(fvar); | |
| 4062 VariableDeclaration* fvar_declaration = factory()->NewVariableDeclaration( | |
| 4063 proxy, fvar_mode, scope_, RelocInfo::kNoPosition); | |
| 4064 scope_->DeclareFunctionVar(fvar_declaration); | |
| 4065 } | |
| 4066 | |
| 4067 // Determine if the function can be parsed lazily. Lazy parsing is different | 4042 // Determine if the function can be parsed lazily. Lazy parsing is different |
| 4068 // from lazy compilation; we need to parse more eagerly than we compile. | 4043 // from lazy compilation; we need to parse more eagerly than we compile. |
| 4069 | 4044 |
| 4070 // We can only parse lazily if we also compile lazily. The heuristics for | 4045 // We can only parse lazily if we also compile lazily. The heuristics for |
| 4071 // lazy compilation are: | 4046 // lazy compilation are: |
| 4072 // - It must not have been prohibited by the caller to Parse (some callers | 4047 // - It must not have been prohibited by the caller to Parse (some callers |
| 4073 // need a full AST). | 4048 // need a full AST). |
| 4074 // - The outer scope must allow lazy compilation of inner functions. | 4049 // - The outer scope must allow lazy compilation of inner functions. |
| 4075 // - The function mustn't be a function expression with an open parenthesis | 4050 // - The function mustn't be a function expression with an open parenthesis |
| 4076 // before; we consider that a hint that the function will be called | 4051 // before; we consider that a hint that the function will be called |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 4120 is_lazily_parsed = false; | 4095 is_lazily_parsed = false; |
| 4121 | 4096 |
| 4122 // This is probably an initialization function. Inform the compiler it | 4097 // This is probably an initialization function. Inform the compiler it |
| 4123 // should also eager-compile this function, and that we expect it to be | 4098 // should also eager-compile this function, and that we expect it to be |
| 4124 // used once. | 4099 // used once. |
| 4125 eager_compile_hint = FunctionLiteral::kShouldEagerCompile; | 4100 eager_compile_hint = FunctionLiteral::kShouldEagerCompile; |
| 4126 should_be_used_once_hint = true; | 4101 should_be_used_once_hint = true; |
| 4127 } | 4102 } |
| 4128 } | 4103 } |
| 4129 if (!is_lazily_parsed) { | 4104 if (!is_lazily_parsed) { |
| 4130 body = ParseEagerFunctionBody(function_name, pos, formals, fvar, | 4105 body = ParseEagerFunctionBody(function_name, pos, formals, kind, |
| 4131 fvar_init_op, kind, CHECK_OK); | 4106 function_type, CHECK_OK); |
| 4132 materialized_literal_count = function_state.materialized_literal_count(); | 4107 materialized_literal_count = function_state.materialized_literal_count(); |
| 4133 expected_property_count = function_state.expected_property_count(); | 4108 expected_property_count = function_state.expected_property_count(); |
| 4134 } | 4109 } |
| 4135 | 4110 |
| 4136 // Parsing the body may change the language mode in our scope. | 4111 // Parsing the body may change the language mode in our scope. |
| 4137 language_mode = scope->language_mode(); | 4112 language_mode = scope->language_mode(); |
| 4138 | 4113 |
| 4139 if (is_strong(language_mode) && IsSubclassConstructor(kind)) { | 4114 if (is_strong(language_mode) && IsSubclassConstructor(kind)) { |
| 4140 if (!function_state.super_location().IsValid()) { | 4115 if (!function_state.super_location().IsValid()) { |
| 4141 ReportMessageAt(function_name_location, | 4116 ReportMessageAt(function_name_location, |
| (...skipping 195 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 4337 factory()->NewVariableProxy(parameter.var)); | 4312 factory()->NewVariableProxy(parameter.var)); |
| 4338 PatternRewriter::DeclareAndInitializeVariables(init_block, &descriptor, | 4313 PatternRewriter::DeclareAndInitializeVariables(init_block, &descriptor, |
| 4339 &decl, nullptr, CHECK_OK); | 4314 &decl, nullptr, CHECK_OK); |
| 4340 } | 4315 } |
| 4341 return init_block; | 4316 return init_block; |
| 4342 } | 4317 } |
| 4343 | 4318 |
| 4344 | 4319 |
| 4345 ZoneList<Statement*>* Parser::ParseEagerFunctionBody( | 4320 ZoneList<Statement*>* Parser::ParseEagerFunctionBody( |
| 4346 const AstRawString* function_name, int pos, | 4321 const AstRawString* function_name, int pos, |
| 4347 const ParserFormalParameters& parameters, Variable* fvar, | 4322 const ParserFormalParameters& parameters, FunctionKind kind, |
| 4348 Token::Value fvar_init_op, FunctionKind kind, bool* ok) { | 4323 FunctionLiteral::FunctionType function_type, bool* ok) { |
| 4349 // Everything inside an eagerly parsed function will be parsed eagerly | 4324 // Everything inside an eagerly parsed function will be parsed eagerly |
| 4350 // (see comment above). | 4325 // (see comment above). |
| 4351 ParsingModeScope parsing_mode(this, PARSE_EAGERLY); | 4326 ParsingModeScope parsing_mode(this, PARSE_EAGERLY); |
| 4352 ZoneList<Statement*>* result = new(zone()) ZoneList<Statement*>(8, zone()); | 4327 ZoneList<Statement*>* result = new(zone()) ZoneList<Statement*>(8, zone()); |
| 4353 if (fvar != NULL) { | 4328 |
| 4354 VariableProxy* fproxy = scope_->NewUnresolved(factory(), function_name); | 4329 static const int kFunctionNameAssignmentIndex = 0; |
| 4355 fproxy->BindTo(fvar); | 4330 if (function_type == FunctionLiteral::NAMED_EXPRESSION) { |
| 4356 result->Add(factory()->NewExpressionStatement( | 4331 DCHECK(function_name != NULL); |
| 4357 factory()->NewAssignment(fvar_init_op, | 4332 // If we have a named function expression, we add a local variable |
| 4358 fproxy, | 4333 // declaration to the body of the function with the name of the |
| 4359 factory()->NewThisFunction(pos), | 4334 // function and let it refer to the function itself (closure). |
| 4360 RelocInfo::kNoPosition), | 4335 // Not having parsed the function body, the language mode may still change, |
| 4361 RelocInfo::kNoPosition), zone()); | 4336 // so we reserve a spot and create the actual const assignment later. |
| 4337 DCHECK_EQ(kFunctionNameAssignmentIndex, result->length()); | |
| 4338 result->Add(NULL, zone()); | |
| 4362 } | 4339 } |
| 4363 | 4340 |
| 4364 | |
| 4365 // For concise constructors, check that they are constructed, | 4341 // For concise constructors, check that they are constructed, |
| 4366 // not called. | 4342 // not called. |
| 4367 if (i::IsConstructor(kind)) { | 4343 if (i::IsConstructor(kind)) { |
| 4368 AddAssertIsConstruct(result, pos); | 4344 AddAssertIsConstruct(result, pos); |
| 4369 } | 4345 } |
| 4370 | 4346 |
| 4371 ZoneList<Statement*>* body = result; | 4347 ZoneList<Statement*>* body = result; |
| 4372 Scope* inner_scope = nullptr; | 4348 Scope* inner_scope = nullptr; |
| 4373 Block* inner_block = nullptr; | 4349 Block* inner_block = nullptr; |
| 4374 if (!parameters.is_simple) { | 4350 if (!parameters.is_simple) { |
| (...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 4438 inner_scope->set_end_position(scanner()->location().end_pos); | 4414 inner_scope->set_end_position(scanner()->location().end_pos); |
| 4439 inner_scope = inner_scope->FinalizeBlockScope(); | 4415 inner_scope = inner_scope->FinalizeBlockScope(); |
| 4440 if (inner_scope != nullptr) { | 4416 if (inner_scope != nullptr) { |
| 4441 CheckConflictingVarDeclarations(inner_scope, CHECK_OK); | 4417 CheckConflictingVarDeclarations(inner_scope, CHECK_OK); |
| 4442 } | 4418 } |
| 4443 | 4419 |
| 4444 result->Add(init_block, zone()); | 4420 result->Add(init_block, zone()); |
| 4445 result->Add(inner_block, zone()); | 4421 result->Add(inner_block, zone()); |
| 4446 } | 4422 } |
| 4447 | 4423 |
| 4424 if (function_type == FunctionLiteral::NAMED_EXPRESSION) { | |
| 4425 // Now that we know the language mode, we can create the const assignment | |
| 4426 // in the previously reserved spot. | |
| 4427 // NOTE: We create a proxy and resolve it here so that in the | |
| 4428 // future we can change the AST to only refer to VariableProxies | |
| 4429 // instead of Variables and Proxies as is the case now. | |
| 4430 Token::Value fvar_init_op = Token::INIT_CONST_LEGACY; | |
| 4431 bool use_strict_const = is_strict(scope_->language_mode()) || | |
| 4432 (!allow_legacy_const() && allow_harmony_sloppy()); | |
| 4433 if (use_strict_const) { | |
| 4434 fvar_init_op = Token::INIT_CONST; | |
| 4435 } | |
| 4436 VariableMode fvar_mode = use_strict_const ? CONST : CONST_LEGACY; | |
|
rossberg
2015/08/04 09:47:36
Wait, I thought the idea was that this should alwa
| |
| 4437 Variable* fvar = new (zone()) | |
| 4438 Variable(scope_, function_name, fvar_mode, Variable::NORMAL, | |
| 4439 kCreatedInitialized, kNotAssigned); | |
| 4440 VariableProxy* proxy = factory()->NewVariableProxy(fvar); | |
| 4441 VariableDeclaration* fvar_declaration = factory()->NewVariableDeclaration( | |
| 4442 proxy, fvar_mode, scope_, RelocInfo::kNoPosition); | |
| 4443 scope_->DeclareFunctionVar(fvar_declaration); | |
| 4444 | |
| 4445 VariableProxy* fproxy = scope_->NewUnresolved(factory(), function_name); | |
| 4446 fproxy->BindTo(fvar); | |
| 4447 result->Set(kFunctionNameAssignmentIndex, | |
| 4448 factory()->NewExpressionStatement( | |
| 4449 factory()->NewAssignment(fvar_init_op, fproxy, | |
| 4450 factory()->NewThisFunction(pos), | |
| 4451 RelocInfo::kNoPosition), | |
| 4452 RelocInfo::kNoPosition)); | |
| 4453 } | |
| 4454 | |
| 4448 return result; | 4455 return result; |
| 4449 } | 4456 } |
| 4450 | 4457 |
| 4451 | 4458 |
| 4452 PreParser::PreParseResult Parser::ParseLazyFunctionBodyWithPreParser( | 4459 PreParser::PreParseResult Parser::ParseLazyFunctionBodyWithPreParser( |
| 4453 SingletonLogger* logger, Scanner::BookmarkScope* bookmark) { | 4460 SingletonLogger* logger, Scanner::BookmarkScope* bookmark) { |
| 4454 // This function may be called on a background thread too; record only the | 4461 // This function may be called on a background thread too; record only the |
| 4455 // main thread preparse times. | 4462 // main thread preparse times. |
| 4456 if (pre_parse_timer_ != NULL) { | 4463 if (pre_parse_timer_ != NULL) { |
| 4457 pre_parse_timer_->Start(); | 4464 pre_parse_timer_->Start(); |
| (...skipping 1531 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 5989 Expression* Parser::SpreadCallNew(Expression* function, | 5996 Expression* Parser::SpreadCallNew(Expression* function, |
| 5990 ZoneList<v8::internal::Expression*>* args, | 5997 ZoneList<v8::internal::Expression*>* args, |
| 5991 int pos) { | 5998 int pos) { |
| 5992 args->InsertAt(0, function, zone()); | 5999 args->InsertAt(0, function, zone()); |
| 5993 | 6000 |
| 5994 return factory()->NewCallRuntime( | 6001 return factory()->NewCallRuntime( |
| 5995 ast_value_factory()->reflect_construct_string(), NULL, args, pos); | 6002 ast_value_factory()->reflect_construct_string(), NULL, args, pos); |
| 5996 } | 6003 } |
| 5997 } // namespace internal | 6004 } // namespace internal |
| 5998 } // namespace v8 | 6005 } // namespace v8 |
| OLD | NEW |