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 <memory> | 7 #include <memory> |
8 | 8 |
9 #include "src/api.h" | 9 #include "src/api.h" |
10 #include "src/ast/ast-expression-rewriter.h" | 10 #include "src/ast/ast-expression-rewriter.h" |
(...skipping 109 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
120 prev_fni_(parser->fni_), | 120 prev_fni_(parser->fni_), |
121 prev_zone_(parser->zone_) { | 121 prev_zone_(parser->zone_) { |
122 if (use_temp_zone) { | 122 if (use_temp_zone) { |
123 parser_->fni_ = &fni_; | 123 parser_->fni_ = &fni_; |
124 parser_->zone_ = temp_zone; | 124 parser_->zone_ = temp_zone; |
125 if (parser_->reusable_preparser_ != nullptr) { | 125 if (parser_->reusable_preparser_ != nullptr) { |
126 parser_->reusable_preparser_->zone_ = temp_zone; | 126 parser_->reusable_preparser_->zone_ = temp_zone; |
127 } | 127 } |
128 } | 128 } |
129 } | 129 } |
130 ~DiscardableZoneScope() { | 130 void Reset() { |
131 parser_->fni_ = prev_fni_; | 131 parser_->fni_ = prev_fni_; |
132 parser_->zone_ = prev_zone_; | 132 parser_->zone_ = prev_zone_; |
133 if (parser_->reusable_preparser_ != nullptr) { | 133 if (parser_->reusable_preparser_ != nullptr) { |
134 parser_->reusable_preparser_->zone_ = prev_zone_; | 134 parser_->reusable_preparser_->zone_ = prev_zone_; |
135 } | 135 } |
| 136 ast_node_factory_scope_.Reset(); |
136 } | 137 } |
| 138 ~DiscardableZoneScope() { Reset(); } |
137 | 139 |
138 private: | 140 private: |
139 AstNodeFactory::BodyScope ast_node_factory_scope_; | 141 AstNodeFactory::BodyScope ast_node_factory_scope_; |
140 FuncNameInferrer fni_; | 142 FuncNameInferrer fni_; |
141 Parser* parser_; | 143 Parser* parser_; |
142 FuncNameInferrer* prev_fni_; | 144 FuncNameInferrer* prev_fni_; |
143 Zone* prev_zone_; | 145 Zone* prev_zone_; |
144 | 146 |
145 DISALLOW_COPY_AND_ASSIGN(DiscardableZoneScope); | 147 DISALLOW_COPY_AND_ASSIGN(DiscardableZoneScope); |
146 }; | 148 }; |
(...skipping 2526 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2673 // FunctionExpression; even without enclosing parentheses it might be | 2675 // FunctionExpression; even without enclosing parentheses it might be |
2674 // immediately invoked. | 2676 // immediately invoked. |
2675 // - The function literal shouldn't be hinted to eagerly compile. | 2677 // - The function literal shouldn't be hinted to eagerly compile. |
2676 // - For asm.js functions the body needs to be available when module | 2678 // - For asm.js functions the body needs to be available when module |
2677 // validation is active, because we examine the entire module at once. | 2679 // validation is active, because we examine the entire module at once. |
2678 | 2680 |
2679 // Inner functions will be parsed using a temporary Zone. After parsing, we | 2681 // Inner functions will be parsed using a temporary Zone. After parsing, we |
2680 // will migrate unresolved variable into a Scope in the main Zone. | 2682 // will migrate unresolved variable into a Scope in the main Zone. |
2681 // TODO(marja): Refactor parsing modes: simplify this. | 2683 // TODO(marja): Refactor parsing modes: simplify this. |
2682 bool use_temp_zone = | 2684 bool use_temp_zone = |
2683 !is_lazy_top_level_function && allow_lazy() && | 2685 allow_lazy() && function_type == FunctionLiteral::kDeclaration && |
2684 function_type == FunctionLiteral::kDeclaration && | |
2685 eager_compile_hint != FunctionLiteral::kShouldEagerCompile && | 2686 eager_compile_hint != FunctionLiteral::kShouldEagerCompile && |
2686 !(FLAG_validate_asm && scope()->IsAsmModule()); | 2687 !(FLAG_validate_asm && scope()->IsAsmModule()); |
2687 bool is_lazy_inner_function = use_temp_zone && FLAG_lazy_inner_functions; | 2688 bool is_lazy_inner_function = |
| 2689 use_temp_zone && FLAG_lazy_inner_functions && !is_lazy_top_level_function; |
2688 | 2690 |
2689 // This Scope lives in the main zone. We'll migrate data into that zone later. | 2691 // This Scope lives in the main zone. We'll migrate data into that zone later. |
2690 DeclarationScope* scope = NewFunctionScope(kind); | 2692 DeclarationScope* scope = NewFunctionScope(kind); |
2691 SetLanguageMode(scope, language_mode); | 2693 SetLanguageMode(scope, language_mode); |
2692 | 2694 |
2693 ZoneList<Statement*>* body = nullptr; | 2695 ZoneList<Statement*>* body = nullptr; |
2694 int arity = -1; | 2696 int arity = -1; |
2695 int materialized_literal_count = -1; | 2697 int materialized_literal_count = -1; |
2696 int expected_property_count = -1; | 2698 int expected_property_count = -1; |
2697 DuplicateFinder duplicate_finder(scanner()->unicode_cache()); | 2699 DuplicateFinder duplicate_finder(scanner()->unicode_cache()); |
2698 bool should_be_used_once_hint = false; | 2700 bool should_be_used_once_hint = false; |
2699 bool has_duplicate_parameters; | 2701 bool has_duplicate_parameters; |
2700 | 2702 |
| 2703 FunctionState function_state(&function_state_, &scope_state_, scope); |
| 2704 #ifdef DEBUG |
| 2705 scope->SetScopeName(function_name); |
| 2706 #endif |
| 2707 |
| 2708 ExpressionClassifier formals_classifier(this, &duplicate_finder); |
| 2709 |
| 2710 if (is_generator) { |
| 2711 // For generators, allocating variables in contexts is currently a win |
| 2712 // because it minimizes the work needed to suspend and resume an |
| 2713 // activation. The machine code produced for generators (by full-codegen) |
| 2714 // relies on this forced context allocation, but not in an essential way. |
| 2715 this->scope()->ForceContextAllocation(); |
| 2716 |
| 2717 // Calling a generator returns a generator object. That object is stored |
| 2718 // in a temporary variable, a definition that is used by "yield" |
| 2719 // expressions. This also marks the FunctionState as a generator. |
| 2720 Variable* temp = |
| 2721 NewTemporary(ast_value_factory()->dot_generator_object_string()); |
| 2722 function_state.set_generator_object_variable(temp); |
| 2723 } |
| 2724 |
| 2725 Expect(Token::LPAREN, CHECK_OK); |
| 2726 int start_position = scanner()->location().beg_pos; |
| 2727 this->scope()->set_start_position(start_position); |
| 2728 ParserFormalParameters formals(scope); |
| 2729 ParseFormalParameterList(&formals, CHECK_OK); |
| 2730 arity = formals.Arity(); |
| 2731 Expect(Token::RPAREN, CHECK_OK); |
| 2732 int formals_end_position = scanner()->location().end_pos; |
| 2733 |
| 2734 CheckArityRestrictions(arity, kind, formals.has_rest, start_position, |
| 2735 formals_end_position, CHECK_OK); |
| 2736 Expect(Token::LBRACE, CHECK_OK); |
| 2737 // Don't include the rest parameter into the function's formal parameter |
| 2738 // count (esp. the SharedFunctionInfo::internal_formal_parameter_count, |
| 2739 // which says whether we need to create an arguments adaptor frame). |
| 2740 if (formals.has_rest) arity--; |
| 2741 |
2701 { | 2742 { |
2702 // Temporary zones can nest. When we migrate free variables (see below), we | 2743 // Temporary zones can nest. When we migrate free variables (see below), we |
2703 // need to recreate them in the previous Zone. | 2744 // need to recreate them in the previous Zone. |
2704 AstNodeFactory previous_zone_ast_node_factory(ast_value_factory()); | 2745 AstNodeFactory previous_zone_ast_node_factory(ast_value_factory()); |
2705 previous_zone_ast_node_factory.set_zone(zone()); | 2746 previous_zone_ast_node_factory.set_zone(zone()); |
2706 | 2747 |
2707 // Open a new zone scope, which sets our AstNodeFactory to allocate in the | 2748 // Open a new zone scope, which sets our AstNodeFactory to allocate in the |
2708 // new temporary zone if the preconditions are satisfied, and ensures that | 2749 // new temporary zone if the preconditions are satisfied, and ensures that |
2709 // the previous zone is always restored after parsing the body. To be able | 2750 // the previous zone is always restored after parsing the body. To be able |
2710 // to do scope analysis correctly after full parsing, we migrate needed | 2751 // to do scope analysis correctly after full parsing, we migrate needed |
2711 // information when the function is parsed. | 2752 // information when the function is parsed. |
2712 Zone temp_zone(zone()->allocator()); | 2753 Zone temp_zone(zone()->allocator()); |
2713 DiscardableZoneScope zone_scope(this, &temp_zone, use_temp_zone); | 2754 DiscardableZoneScope zone_scope(this, &temp_zone, use_temp_zone); |
2714 | |
2715 FunctionState function_state(&function_state_, &scope_state_, scope); | |
2716 #ifdef DEBUG | 2755 #ifdef DEBUG |
2717 scope->SetScopeName(function_name); | |
2718 if (use_temp_zone) scope->set_needs_migration(); | 2756 if (use_temp_zone) scope->set_needs_migration(); |
2719 #endif | 2757 #endif |
2720 ExpressionClassifier formals_classifier(this, &duplicate_finder); | |
2721 | |
2722 if (is_generator) { | |
2723 // For generators, allocating variables in contexts is currently a win | |
2724 // because it minimizes the work needed to suspend and resume an | |
2725 // activation. The machine code produced for generators (by full-codegen) | |
2726 // relies on this forced context allocation, but not in an essential way. | |
2727 this->scope()->ForceContextAllocation(); | |
2728 | |
2729 // Calling a generator returns a generator object. That object is stored | |
2730 // in a temporary variable, a definition that is used by "yield" | |
2731 // expressions. This also marks the FunctionState as a generator. | |
2732 Variable* temp = | |
2733 NewTemporary(ast_value_factory()->dot_generator_object_string()); | |
2734 function_state.set_generator_object_variable(temp); | |
2735 } | |
2736 | |
2737 Expect(Token::LPAREN, CHECK_OK); | |
2738 int start_position = scanner()->location().beg_pos; | |
2739 this->scope()->set_start_position(start_position); | |
2740 ParserFormalParameters formals(scope); | |
2741 ParseFormalParameterList(&formals, CHECK_OK); | |
2742 arity = formals.Arity(); | |
2743 Expect(Token::RPAREN, CHECK_OK); | |
2744 int formals_end_position = scanner()->location().end_pos; | |
2745 | |
2746 CheckArityRestrictions(arity, kind, formals.has_rest, start_position, | |
2747 formals_end_position, CHECK_OK); | |
2748 Expect(Token::LBRACE, CHECK_OK); | |
2749 // Don't include the rest parameter into the function's formal parameter | |
2750 // count (esp. the SharedFunctionInfo::internal_formal_parameter_count, | |
2751 // which says whether we need to create an arguments adaptor frame). | |
2752 if (formals.has_rest) arity--; | |
2753 | 2758 |
2754 // Eager or lazy parse? If is_lazy_top_level_function, we'll parse | 2759 // Eager or lazy parse? If is_lazy_top_level_function, we'll parse |
2755 // lazily. We'll call SkipLazyFunctionBody, which may decide to abort lazy | 2760 // lazily. We'll call SkipLazyFunctionBody, which may decide to abort lazy |
2756 // parsing if it suspects that wasn't a good idea. If so (in which case the | 2761 // parsing if it suspects that wasn't a good idea. If so (in which case the |
2757 // parser is expected to have backtracked), or if we didn't try to lazy | 2762 // parser is expected to have backtracked), or if we didn't try to lazy |
2758 // parse in the first place, we'll have to parse eagerly. | 2763 // parse in the first place, we'll have to parse eagerly. |
2759 if (is_lazy_top_level_function || is_lazy_inner_function) { | 2764 if (is_lazy_top_level_function || is_lazy_inner_function) { |
2760 Scanner::BookmarkScope bookmark(scanner()); | 2765 Scanner::BookmarkScope bookmark(scanner()); |
2761 bookmark.Set(); | 2766 bookmark.Set(); |
2762 LazyParsingResult result = SkipLazyFunctionBody( | 2767 LazyParsingResult result = SkipLazyFunctionBody( |
2763 &materialized_literal_count, &expected_property_count, | 2768 &materialized_literal_count, &expected_property_count, |
2764 is_lazy_inner_function, is_lazy_top_level_function, CHECK_OK); | 2769 is_lazy_inner_function, is_lazy_top_level_function, CHECK_OK); |
2765 | 2770 |
2766 materialized_literal_count += formals.materialized_literals_count + | 2771 materialized_literal_count += formals.materialized_literals_count + |
2767 function_state.materialized_literal_count(); | 2772 function_state.materialized_literal_count(); |
2768 | 2773 |
2769 if (result == kLazyParsingAborted) { | 2774 if (result == kLazyParsingAborted) { |
2770 DCHECK(is_lazy_top_level_function); | 2775 DCHECK(is_lazy_top_level_function); |
2771 bookmark.Apply(); | 2776 bookmark.Apply(); |
2772 // Trigger eager (re-)parsing, just below this block. | 2777 // Trigger eager (re-)parsing, just below this block. |
2773 is_lazy_top_level_function = false; | 2778 is_lazy_top_level_function = false; |
2774 | 2779 |
2775 // This is probably an initialization function. Inform the compiler it | 2780 // This is probably an initialization function. Inform the compiler it |
2776 // should also eager-compile this function, and that we expect it to be | 2781 // should also eager-compile this function, and that we expect it to be |
2777 // used once. | 2782 // used once. |
2778 eager_compile_hint = FunctionLiteral::kShouldEagerCompile; | 2783 eager_compile_hint = FunctionLiteral::kShouldEagerCompile; |
2779 should_be_used_once_hint = true; | 2784 should_be_used_once_hint = true; |
2780 scope->ResetAfterPreparsing(true); | 2785 scope->ResetAfterPreparsing(true); |
| 2786 zone_scope.Reset(); |
| 2787 use_temp_zone = false; |
2781 } | 2788 } |
2782 } | 2789 } |
2783 | 2790 |
2784 if (!is_lazy_top_level_function && !is_lazy_inner_function) { | 2791 if (!is_lazy_top_level_function && !is_lazy_inner_function) { |
2785 body = ParseEagerFunctionBody(function_name, pos, formals, kind, | 2792 body = ParseEagerFunctionBody(function_name, pos, formals, kind, |
2786 function_type, CHECK_OK); | 2793 function_type, CHECK_OK); |
2787 | 2794 |
2788 materialized_literal_count = function_state.materialized_literal_count(); | 2795 materialized_literal_count = function_state.materialized_literal_count(); |
2789 expected_property_count = function_state.expected_property_count(); | 2796 expected_property_count = function_state.expected_property_count(); |
2790 } | 2797 } |
(...skipping 2745 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5536 | 5543 |
5537 return final_loop; | 5544 return final_loop; |
5538 } | 5545 } |
5539 | 5546 |
5540 #undef CHECK_OK | 5547 #undef CHECK_OK |
5541 #undef CHECK_OK_VOID | 5548 #undef CHECK_OK_VOID |
5542 #undef CHECK_FAILED | 5549 #undef CHECK_FAILED |
5543 | 5550 |
5544 } // namespace internal | 5551 } // namespace internal |
5545 } // namespace v8 | 5552 } // namespace v8 |
OLD | NEW |