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/parsing/parser.h" | 5 #include "src/parsing/parser.h" |
6 | 6 |
7 #include "src/api.h" | 7 #include "src/api.h" |
8 #include "src/ast/ast.h" | 8 #include "src/ast/ast.h" |
9 #include "src/ast/ast-expression-visitor.h" | 9 #include "src/ast/ast-expression-visitor.h" |
10 #include "src/ast/ast-literal-reindexer.h" | 10 #include "src/ast/ast-literal-reindexer.h" |
(...skipping 4098 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4109 expr = right; | 4109 expr = right; |
4110 } | 4110 } |
4111 | 4111 |
4112 // Only the right-most expression may be a rest parameter. | 4112 // Only the right-most expression may be a rest parameter. |
4113 DCHECK(!parameters->has_rest); | 4113 DCHECK(!parameters->has_rest); |
4114 | 4114 |
4115 bool is_rest = expr->IsSpread(); | 4115 bool is_rest = expr->IsSpread(); |
4116 if (is_rest) { | 4116 if (is_rest) { |
4117 expr = expr->AsSpread()->expression(); | 4117 expr = expr->AsSpread()->expression(); |
4118 parameters->has_rest = true; | 4118 parameters->has_rest = true; |
4119 parameters->rest_array_literal_index = | |
4120 parser_->function_state_->NextMaterializedLiteralIndex(); | |
4121 ++parameters->materialized_literals_count; | |
4122 } | 4119 } |
4123 if (parameters->is_simple) { | 4120 if (parameters->is_simple) { |
4124 parameters->is_simple = !is_rest && expr->IsVariableProxy(); | 4121 parameters->is_simple = !is_rest && expr->IsVariableProxy(); |
4125 } | 4122 } |
4126 | 4123 |
4127 Expression* initializer = nullptr; | 4124 Expression* initializer = nullptr; |
4128 if (expr->IsVariableProxy()) { | 4125 if (expr->IsVariableProxy()) { |
4129 // When the formal parameter was originally seen, it was parsed as a | 4126 // When the formal parameter was originally seen, it was parsed as a |
4130 // VariableProxy and recorded as unresolved in the scope. Here we undo that | 4127 // VariableProxy and recorded as unresolved in the scope. Here we undo that |
4131 // parse-time side-effect for parameters that are single-names (not | 4128 // parse-time side-effect for parameters that are single-names (not |
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4196 | 4193 |
4197 void ParserTraits::ReindexLiterals(const ParserFormalParameters& parameters) { | 4194 void ParserTraits::ReindexLiterals(const ParserFormalParameters& parameters) { |
4198 if (parser_->function_state_->materialized_literal_count() > 0) { | 4195 if (parser_->function_state_->materialized_literal_count() > 0) { |
4199 AstLiteralReindexer reindexer; | 4196 AstLiteralReindexer reindexer; |
4200 | 4197 |
4201 for (const auto p : parameters.params) { | 4198 for (const auto p : parameters.params) { |
4202 if (p.pattern != nullptr) reindexer.Reindex(p.pattern); | 4199 if (p.pattern != nullptr) reindexer.Reindex(p.pattern); |
4203 if (p.initializer != nullptr) reindexer.Reindex(p.initializer); | 4200 if (p.initializer != nullptr) reindexer.Reindex(p.initializer); |
4204 } | 4201 } |
4205 | 4202 |
4206 if (parameters.has_rest) { | |
4207 parameters.rest_array_literal_index = reindexer.NextIndex(); | |
4208 } | |
4209 | |
4210 DCHECK(reindexer.count() <= | 4203 DCHECK(reindexer.count() <= |
4211 parser_->function_state_->materialized_literal_count()); | 4204 parser_->function_state_->materialized_literal_count()); |
4212 } | 4205 } |
4213 } | 4206 } |
4214 | 4207 |
4215 | 4208 |
4216 FunctionLiteral* Parser::ParseFunctionLiteral( | 4209 FunctionLiteral* Parser::ParseFunctionLiteral( |
4217 const AstRawString* function_name, Scanner::Location function_name_location, | 4210 const AstRawString* function_name, Scanner::Location function_name_location, |
4218 FunctionNameValidity function_name_validity, FunctionKind kind, | 4211 FunctionNameValidity function_name_validity, FunctionKind kind, |
4219 int function_token_pos, FunctionLiteral::FunctionType function_type, | 4212 int function_token_pos, FunctionLiteral::FunctionType function_type, |
(...skipping 259 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4479 | 4472 |
4480 FunctionLiteral* function_literal = factory()->NewFunctionLiteral( | 4473 FunctionLiteral* function_literal = factory()->NewFunctionLiteral( |
4481 function_name, ast_value_factory(), scope, body, | 4474 function_name, ast_value_factory(), scope, body, |
4482 materialized_literal_count, expected_property_count, arity, | 4475 materialized_literal_count, expected_property_count, arity, |
4483 duplicate_parameters, function_type, FunctionLiteral::kIsFunction, | 4476 duplicate_parameters, function_type, FunctionLiteral::kIsFunction, |
4484 eager_compile_hint, kind, pos); | 4477 eager_compile_hint, kind, pos); |
4485 function_literal->set_function_token_position(function_token_pos); | 4478 function_literal->set_function_token_position(function_token_pos); |
4486 if (should_be_used_once_hint) | 4479 if (should_be_used_once_hint) |
4487 function_literal->set_should_be_used_once_hint(); | 4480 function_literal->set_should_be_used_once_hint(); |
4488 | 4481 |
| 4482 if (scope->has_rest_parameter()) { |
| 4483 function_literal->set_dont_optimize_reason(kRestParameter); |
| 4484 } |
| 4485 |
4489 if (fni_ != NULL && should_infer_name) fni_->AddFunction(function_literal); | 4486 if (fni_ != NULL && should_infer_name) fni_->AddFunction(function_literal); |
4490 return function_literal; | 4487 return function_literal; |
4491 } | 4488 } |
4492 | 4489 |
4493 | 4490 |
4494 void Parser::SkipLazyFunctionBody(int* materialized_literal_count, | 4491 void Parser::SkipLazyFunctionBody(int* materialized_literal_count, |
4495 int* expected_property_count, bool* ok, | 4492 int* expected_property_count, bool* ok, |
4496 Scanner::BookmarkScope* bookmark) { | 4493 Scanner::BookmarkScope* bookmark) { |
4497 DCHECK_IMPLIES(bookmark, bookmark->HasBeenSet()); | 4494 DCHECK_IMPLIES(bookmark, bookmark->HasBeenSet()); |
4498 if (produce_cached_parse_data()) CHECK(log_); | 4495 if (produce_cached_parse_data()) CHECK(log_); |
(...skipping 129 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4628 | 4625 |
4629 | 4626 |
4630 Block* Parser::BuildParameterInitializationBlock( | 4627 Block* Parser::BuildParameterInitializationBlock( |
4631 const ParserFormalParameters& parameters, bool* ok) { | 4628 const ParserFormalParameters& parameters, bool* ok) { |
4632 DCHECK(!parameters.is_simple); | 4629 DCHECK(!parameters.is_simple); |
4633 DCHECK(scope_->is_function_scope()); | 4630 DCHECK(scope_->is_function_scope()); |
4634 Block* init_block = | 4631 Block* init_block = |
4635 factory()->NewBlock(NULL, 1, true, RelocInfo::kNoPosition); | 4632 factory()->NewBlock(NULL, 1, true, RelocInfo::kNoPosition); |
4636 for (int i = 0; i < parameters.params.length(); ++i) { | 4633 for (int i = 0; i < parameters.params.length(); ++i) { |
4637 auto parameter = parameters.params[i]; | 4634 auto parameter = parameters.params[i]; |
| 4635 if (parameter.is_rest) break; |
4638 DeclarationDescriptor descriptor; | 4636 DeclarationDescriptor descriptor; |
4639 descriptor.declaration_kind = DeclarationDescriptor::PARAMETER; | 4637 descriptor.declaration_kind = DeclarationDescriptor::PARAMETER; |
4640 descriptor.parser = this; | 4638 descriptor.parser = this; |
4641 descriptor.scope = scope_; | 4639 descriptor.scope = scope_; |
4642 descriptor.hoist_scope = nullptr; | 4640 descriptor.hoist_scope = nullptr; |
4643 descriptor.mode = LET; | 4641 descriptor.mode = LET; |
4644 descriptor.needs_init = true; | 4642 descriptor.needs_init = true; |
4645 descriptor.declaration_pos = parameter.pattern->position(); | 4643 descriptor.declaration_pos = parameter.pattern->position(); |
4646 // The position that will be used by the AssignmentExpression | 4644 // The position that will be used by the AssignmentExpression |
4647 // which copies from the temp parameter to the pattern. | 4645 // which copies from the temp parameter to the pattern. |
4648 // | 4646 // |
4649 // TODO(adamk): Should this be RelocInfo::kNoPosition, since | 4647 // TODO(adamk): Should this be RelocInfo::kNoPosition, since |
4650 // it's just copying from a temp var to the real param var? | 4648 // it's just copying from a temp var to the real param var? |
4651 descriptor.initialization_pos = parameter.pattern->position(); | 4649 descriptor.initialization_pos = parameter.pattern->position(); |
4652 // The initializer position which will end up in, | 4650 // The initializer position which will end up in, |
4653 // Variable::initializer_position(), used for hole check elimination. | 4651 // Variable::initializer_position(), used for hole check elimination. |
4654 int initializer_position = parameter.pattern->position(); | 4652 int initializer_position = parameter.pattern->position(); |
4655 Expression* initial_value = | 4653 Expression* initial_value = |
4656 factory()->NewVariableProxy(parameters.scope->parameter(i)); | 4654 factory()->NewVariableProxy(parameters.scope->parameter(i)); |
4657 if (parameter.initializer != nullptr) { | 4655 if (parameter.initializer != nullptr) { |
4658 // IS_UNDEFINED($param) ? initializer : $param | 4656 // IS_UNDEFINED($param) ? initializer : $param |
4659 DCHECK(!parameter.is_rest); | |
4660 | 4657 |
4661 // Ensure initializer is rewritten | 4658 // Ensure initializer is rewritten |
4662 RewriteParameterInitializer(parameter.initializer, scope_); | 4659 RewriteParameterInitializer(parameter.initializer, scope_); |
4663 | 4660 |
4664 auto condition = factory()->NewCompareOperation( | 4661 auto condition = factory()->NewCompareOperation( |
4665 Token::EQ_STRICT, | 4662 Token::EQ_STRICT, |
4666 factory()->NewVariableProxy(parameters.scope->parameter(i)), | 4663 factory()->NewVariableProxy(parameters.scope->parameter(i)), |
4667 factory()->NewUndefinedLiteral(RelocInfo::kNoPosition), | 4664 factory()->NewUndefinedLiteral(RelocInfo::kNoPosition), |
4668 RelocInfo::kNoPosition); | 4665 RelocInfo::kNoPosition); |
4669 initial_value = factory()->NewConditional( | 4666 initial_value = factory()->NewConditional( |
4670 condition, parameter.initializer, initial_value, | 4667 condition, parameter.initializer, initial_value, |
4671 RelocInfo::kNoPosition); | 4668 RelocInfo::kNoPosition); |
4672 descriptor.initialization_pos = parameter.initializer->position(); | 4669 descriptor.initialization_pos = parameter.initializer->position(); |
4673 initializer_position = parameter.initializer_end_position; | 4670 initializer_position = parameter.initializer_end_position; |
4674 } else if (parameter.is_rest) { | |
4675 // $rest = []; | |
4676 // for (var $argument_index = $rest_index; | |
4677 // $argument_index < %_ArgumentsLength(); | |
4678 // ++$argument_index) { | |
4679 // %AppendElement($rest, %_Arguments($argument_index)); | |
4680 // } | |
4681 // let <param> = $rest; | |
4682 DCHECK(parameter.pattern->IsVariableProxy()); | |
4683 DCHECK_EQ(i, parameters.params.length() - 1); | |
4684 | |
4685 Variable* temp_var = parameters.scope->parameter(i); | |
4686 auto empty_values = new (zone()) ZoneList<Expression*>(0, zone()); | |
4687 auto empty_array = factory()->NewArrayLiteral( | |
4688 empty_values, parameters.rest_array_literal_index, | |
4689 is_strong(language_mode()), RelocInfo::kNoPosition); | |
4690 | |
4691 auto init_array = factory()->NewAssignment( | |
4692 Token::INIT, factory()->NewVariableProxy(temp_var), empty_array, | |
4693 RelocInfo::kNoPosition); | |
4694 | |
4695 auto loop = factory()->NewForStatement(NULL, RelocInfo::kNoPosition); | |
4696 | |
4697 auto argument_index = | |
4698 parameters.scope->NewTemporary(ast_value_factory()->empty_string()); | |
4699 auto init = factory()->NewExpressionStatement( | |
4700 factory()->NewAssignment( | |
4701 Token::INIT, factory()->NewVariableProxy(argument_index), | |
4702 factory()->NewSmiLiteral(i, RelocInfo::kNoPosition), | |
4703 RelocInfo::kNoPosition), | |
4704 RelocInfo::kNoPosition); | |
4705 | |
4706 auto empty_arguments = new (zone()) ZoneList<Expression*>(0, zone()); | |
4707 | |
4708 // $arguments_index < arguments.length | |
4709 auto cond = factory()->NewCompareOperation( | |
4710 Token::LT, factory()->NewVariableProxy(argument_index), | |
4711 factory()->NewCallRuntime(Runtime::kInlineArgumentsLength, | |
4712 empty_arguments, RelocInfo::kNoPosition), | |
4713 RelocInfo::kNoPosition); | |
4714 | |
4715 // ++argument_index | |
4716 auto next = factory()->NewExpressionStatement( | |
4717 factory()->NewCountOperation( | |
4718 Token::INC, true, factory()->NewVariableProxy(argument_index), | |
4719 RelocInfo::kNoPosition), | |
4720 RelocInfo::kNoPosition); | |
4721 | |
4722 // %_Arguments($arguments_index) | |
4723 auto arguments_args = new (zone()) ZoneList<Expression*>(1, zone()); | |
4724 arguments_args->Add(factory()->NewVariableProxy(argument_index), zone()); | |
4725 | |
4726 // %AppendElement($rest, %_Arguments($arguments_index)) | |
4727 auto append_element_args = new (zone()) ZoneList<Expression*>(2, zone()); | |
4728 | |
4729 append_element_args->Add(factory()->NewVariableProxy(temp_var), zone()); | |
4730 append_element_args->Add( | |
4731 factory()->NewCallRuntime(Runtime::kInlineArguments, arguments_args, | |
4732 RelocInfo::kNoPosition), | |
4733 zone()); | |
4734 | |
4735 auto body = factory()->NewExpressionStatement( | |
4736 factory()->NewCallRuntime(Runtime::kAppendElement, | |
4737 append_element_args, | |
4738 RelocInfo::kNoPosition), | |
4739 RelocInfo::kNoPosition); | |
4740 | |
4741 loop->Initialize(init, cond, next, body); | |
4742 | |
4743 init_block->statements()->Add( | |
4744 factory()->NewExpressionStatement(init_array, RelocInfo::kNoPosition), | |
4745 zone()); | |
4746 | |
4747 init_block->statements()->Add(loop, zone()); | |
4748 } | 4671 } |
4749 | 4672 |
4750 Scope* param_scope = scope_; | 4673 Scope* param_scope = scope_; |
4751 Block* param_block = init_block; | 4674 Block* param_block = init_block; |
4752 if (!parameter.is_simple() && scope_->calls_sloppy_eval()) { | 4675 if (!parameter.is_simple() && scope_->calls_sloppy_eval()) { |
4753 param_scope = NewScope(scope_, BLOCK_SCOPE); | 4676 param_scope = NewScope(scope_, BLOCK_SCOPE); |
4754 param_scope->set_is_declaration_scope(); | 4677 param_scope->set_is_declaration_scope(); |
4755 param_scope->set_start_position(parameter.pattern->position()); | 4678 param_scope->set_start_position(parameter.pattern->position()); |
4756 param_scope->set_end_position(RelocInfo::kNoPosition); | 4679 param_scope->set_end_position(RelocInfo::kNoPosition); |
4757 param_scope->RecordEvalCall(); | 4680 param_scope->RecordEvalCall(); |
(...skipping 1836 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6594 | 6517 |
6595 void ParserTraits::QueueDestructuringAssignmentForRewriting(Expression* expr) { | 6518 void ParserTraits::QueueDestructuringAssignmentForRewriting(Expression* expr) { |
6596 DCHECK(expr->IsRewritableAssignmentExpression()); | 6519 DCHECK(expr->IsRewritableAssignmentExpression()); |
6597 parser_->function_state_->AddDestructuringAssignment( | 6520 parser_->function_state_->AddDestructuringAssignment( |
6598 Parser::DestructuringAssignment(expr, parser_->scope_)); | 6521 Parser::DestructuringAssignment(expr, parser_->scope_)); |
6599 } | 6522 } |
6600 | 6523 |
6601 | 6524 |
6602 } // namespace internal | 6525 } // namespace internal |
6603 } // namespace v8 | 6526 } // namespace v8 |
OLD | NEW |