Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1)

Side by Side Diff: src/parsing/parser.cc

Issue 2374963002: Preparse top-level functions in discardable zones (Closed)
Patch Set: Rebase Created 4 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/ast/scopes.cc ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
OLDNEW
« no previous file with comments | « src/ast/scopes.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698