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 void Reset() { | 130 ~DiscardableZoneScope() { |
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(); | |
137 } | 136 } |
138 ~DiscardableZoneScope() { Reset(); } | |
139 | 137 |
140 private: | 138 private: |
141 AstNodeFactory::BodyScope ast_node_factory_scope_; | 139 AstNodeFactory::BodyScope ast_node_factory_scope_; |
142 FuncNameInferrer fni_; | 140 FuncNameInferrer fni_; |
143 Parser* parser_; | 141 Parser* parser_; |
144 FuncNameInferrer* prev_fni_; | 142 FuncNameInferrer* prev_fni_; |
145 Zone* prev_zone_; | 143 Zone* prev_zone_; |
146 | 144 |
147 DISALLOW_COPY_AND_ASSIGN(DiscardableZoneScope); | 145 DISALLOW_COPY_AND_ASSIGN(DiscardableZoneScope); |
148 }; | 146 }; |
(...skipping 2526 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2675 // FunctionExpression; even without enclosing parentheses it might be | 2673 // FunctionExpression; even without enclosing parentheses it might be |
2676 // immediately invoked. | 2674 // immediately invoked. |
2677 // - The function literal shouldn't be hinted to eagerly compile. | 2675 // - The function literal shouldn't be hinted to eagerly compile. |
2678 // - For asm.js functions the body needs to be available when module | 2676 // - For asm.js functions the body needs to be available when module |
2679 // validation is active, because we examine the entire module at once. | 2677 // validation is active, because we examine the entire module at once. |
2680 | 2678 |
2681 // Inner functions will be parsed using a temporary Zone. After parsing, we | 2679 // Inner functions will be parsed using a temporary Zone. After parsing, we |
2682 // will migrate unresolved variable into a Scope in the main Zone. | 2680 // will migrate unresolved variable into a Scope in the main Zone. |
2683 // TODO(marja): Refactor parsing modes: simplify this. | 2681 // TODO(marja): Refactor parsing modes: simplify this. |
2684 bool use_temp_zone = | 2682 bool use_temp_zone = |
2685 allow_lazy() && function_type == FunctionLiteral::kDeclaration && | 2683 !is_lazy_top_level_function && allow_lazy() && |
| 2684 function_type == FunctionLiteral::kDeclaration && |
2686 eager_compile_hint != FunctionLiteral::kShouldEagerCompile && | 2685 eager_compile_hint != FunctionLiteral::kShouldEagerCompile && |
2687 !(FLAG_validate_asm && scope()->IsAsmModule()); | 2686 !(FLAG_validate_asm && scope()->IsAsmModule()); |
2688 bool is_lazy_inner_function = | 2687 bool is_lazy_inner_function = use_temp_zone && FLAG_lazy_inner_functions; |
2689 use_temp_zone && FLAG_lazy_inner_functions && !is_lazy_top_level_function; | |
2690 | 2688 |
2691 // This Scope lives in the main zone. We'll migrate data into that zone later. | 2689 // This Scope lives in the main zone. We'll migrate data into that zone later. |
2692 DeclarationScope* scope = NewFunctionScope(kind); | 2690 DeclarationScope* scope = NewFunctionScope(kind); |
2693 SetLanguageMode(scope, language_mode); | 2691 SetLanguageMode(scope, language_mode); |
2694 | 2692 |
2695 ZoneList<Statement*>* body = nullptr; | 2693 ZoneList<Statement*>* body = nullptr; |
2696 int arity = -1; | 2694 int arity = -1; |
2697 int materialized_literal_count = -1; | 2695 int materialized_literal_count = -1; |
2698 int expected_property_count = -1; | 2696 int expected_property_count = -1; |
2699 DuplicateFinder duplicate_finder(scanner()->unicode_cache()); | 2697 DuplicateFinder duplicate_finder(scanner()->unicode_cache()); |
2700 bool should_be_used_once_hint = false; | 2698 bool should_be_used_once_hint = false; |
2701 bool has_duplicate_parameters; | 2699 bool has_duplicate_parameters; |
2702 | 2700 |
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 | |
2742 { | 2701 { |
2743 // Temporary zones can nest. When we migrate free variables (see below), we | 2702 // Temporary zones can nest. When we migrate free variables (see below), we |
2744 // need to recreate them in the previous Zone. | 2703 // need to recreate them in the previous Zone. |
2745 AstNodeFactory previous_zone_ast_node_factory(ast_value_factory()); | 2704 AstNodeFactory previous_zone_ast_node_factory(ast_value_factory()); |
2746 previous_zone_ast_node_factory.set_zone(zone()); | 2705 previous_zone_ast_node_factory.set_zone(zone()); |
2747 | 2706 |
2748 // Open a new zone scope, which sets our AstNodeFactory to allocate in the | 2707 // Open a new zone scope, which sets our AstNodeFactory to allocate in the |
2749 // new temporary zone if the preconditions are satisfied, and ensures that | 2708 // new temporary zone if the preconditions are satisfied, and ensures that |
2750 // the previous zone is always restored after parsing the body. To be able | 2709 // the previous zone is always restored after parsing the body. To be able |
2751 // to do scope analysis correctly after full parsing, we migrate needed | 2710 // to do scope analysis correctly after full parsing, we migrate needed |
2752 // information when the function is parsed. | 2711 // information when the function is parsed. |
2753 Zone temp_zone(zone()->allocator()); | 2712 Zone temp_zone(zone()->allocator()); |
2754 DiscardableZoneScope zone_scope(this, &temp_zone, use_temp_zone); | 2713 DiscardableZoneScope zone_scope(this, &temp_zone, use_temp_zone); |
| 2714 |
| 2715 FunctionState function_state(&function_state_, &scope_state_, scope); |
2755 #ifdef DEBUG | 2716 #ifdef DEBUG |
| 2717 scope->SetScopeName(function_name); |
2756 if (use_temp_zone) scope->set_needs_migration(); | 2718 if (use_temp_zone) scope->set_needs_migration(); |
2757 #endif | 2719 #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--; |
2758 | 2753 |
2759 // Eager or lazy parse? If is_lazy_top_level_function, we'll parse | 2754 // Eager or lazy parse? If is_lazy_top_level_function, we'll parse |
2760 // lazily. We'll call SkipLazyFunctionBody, which may decide to abort lazy | 2755 // lazily. We'll call SkipLazyFunctionBody, which may decide to abort lazy |
2761 // parsing if it suspects that wasn't a good idea. If so (in which case the | 2756 // parsing if it suspects that wasn't a good idea. If so (in which case the |
2762 // parser is expected to have backtracked), or if we didn't try to lazy | 2757 // parser is expected to have backtracked), or if we didn't try to lazy |
2763 // parse in the first place, we'll have to parse eagerly. | 2758 // parse in the first place, we'll have to parse eagerly. |
2764 if (is_lazy_top_level_function || is_lazy_inner_function) { | 2759 if (is_lazy_top_level_function || is_lazy_inner_function) { |
2765 Scanner::BookmarkScope bookmark(scanner()); | 2760 Scanner::BookmarkScope bookmark(scanner()); |
2766 bookmark.Set(); | 2761 bookmark.Set(); |
2767 LazyParsingResult result = SkipLazyFunctionBody( | 2762 LazyParsingResult result = SkipLazyFunctionBody( |
2768 &materialized_literal_count, &expected_property_count, | 2763 &materialized_literal_count, &expected_property_count, |
2769 is_lazy_inner_function, is_lazy_top_level_function, CHECK_OK); | 2764 is_lazy_inner_function, is_lazy_top_level_function, CHECK_OK); |
2770 | 2765 |
2771 materialized_literal_count += formals.materialized_literals_count + | 2766 materialized_literal_count += formals.materialized_literals_count + |
2772 function_state.materialized_literal_count(); | 2767 function_state.materialized_literal_count(); |
2773 | 2768 |
2774 if (result == kLazyParsingAborted) { | 2769 if (result == kLazyParsingAborted) { |
2775 DCHECK(is_lazy_top_level_function); | 2770 DCHECK(is_lazy_top_level_function); |
2776 bookmark.Apply(); | 2771 bookmark.Apply(); |
2777 // Trigger eager (re-)parsing, just below this block. | 2772 // Trigger eager (re-)parsing, just below this block. |
2778 is_lazy_top_level_function = false; | 2773 is_lazy_top_level_function = false; |
2779 | 2774 |
2780 // This is probably an initialization function. Inform the compiler it | 2775 // This is probably an initialization function. Inform the compiler it |
2781 // should also eager-compile this function, and that we expect it to be | 2776 // should also eager-compile this function, and that we expect it to be |
2782 // used once. | 2777 // used once. |
2783 eager_compile_hint = FunctionLiteral::kShouldEagerCompile; | 2778 eager_compile_hint = FunctionLiteral::kShouldEagerCompile; |
2784 should_be_used_once_hint = true; | 2779 should_be_used_once_hint = true; |
2785 scope->ResetAfterPreparsing(true); | 2780 scope->ResetAfterPreparsing(true); |
2786 zone_scope.Reset(); | |
2787 use_temp_zone = false; | |
2788 } | 2781 } |
2789 } | 2782 } |
2790 | 2783 |
2791 if (!is_lazy_top_level_function && !is_lazy_inner_function) { | 2784 if (!is_lazy_top_level_function && !is_lazy_inner_function) { |
2792 body = ParseEagerFunctionBody(function_name, pos, formals, kind, | 2785 body = ParseEagerFunctionBody(function_name, pos, formals, kind, |
2793 function_type, CHECK_OK); | 2786 function_type, CHECK_OK); |
2794 | 2787 |
2795 materialized_literal_count = function_state.materialized_literal_count(); | 2788 materialized_literal_count = function_state.materialized_literal_count(); |
2796 expected_property_count = function_state.expected_property_count(); | 2789 expected_property_count = function_state.expected_property_count(); |
2797 } | 2790 } |
(...skipping 2751 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5549 | 5542 |
5550 return final_loop; | 5543 return final_loop; |
5551 } | 5544 } |
5552 | 5545 |
5553 #undef CHECK_OK | 5546 #undef CHECK_OK |
5554 #undef CHECK_OK_VOID | 5547 #undef CHECK_OK_VOID |
5555 #undef CHECK_FAILED | 5548 #undef CHECK_FAILED |
5556 | 5549 |
5557 } // namespace internal | 5550 } // namespace internal |
5558 } // namespace v8 | 5551 } // namespace v8 |
OLD | NEW |