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 |