| 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 |