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

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

Issue 2352593002: Preparse inner functions (new try) (Closed)
Patch Set: style & cleanup 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
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 104 matching lines...) Expand 10 before | Expand all | Expand 10 after
115 public: 115 public:
116 DiscardableZoneScope(Parser* parser, Zone* temp_zone, bool use_temp_zone) 116 DiscardableZoneScope(Parser* parser, Zone* temp_zone, bool use_temp_zone)
117 : ast_node_factory_scope_(parser->factory(), temp_zone, use_temp_zone), 117 : ast_node_factory_scope_(parser->factory(), temp_zone, use_temp_zone),
118 fni_(parser->ast_value_factory_, temp_zone), 118 fni_(parser->ast_value_factory_, temp_zone),
119 parser_(parser), 119 parser_(parser),
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) {
126 parser_->reusable_preparser_->zone_ = temp_zone;
127 }
125 } 128 }
126 } 129 }
127 ~DiscardableZoneScope() { 130 ~DiscardableZoneScope() {
128 parser_->fni_ = prev_fni_; 131 parser_->fni_ = prev_fni_;
129 parser_->zone_ = prev_zone_; 132 parser_->zone_ = prev_zone_;
133 if (parser_->reusable_preparser_ != nullptr) {
134 parser_->reusable_preparser_->zone_ = prev_zone_;
135 }
130 } 136 }
131 137
132 private: 138 private:
133 AstNodeFactory::BodyScope ast_node_factory_scope_; 139 AstNodeFactory::BodyScope ast_node_factory_scope_;
134 FuncNameInferrer fni_; 140 FuncNameInferrer fni_;
135 Parser* parser_; 141 Parser* parser_;
136 FuncNameInferrer* prev_fni_; 142 FuncNameInferrer* prev_fni_;
137 Zone* prev_zone_; 143 Zone* prev_zone_;
138 144
139 DISALLOW_COPY_AND_ASSIGN(DiscardableZoneScope); 145 DISALLOW_COPY_AND_ASSIGN(DiscardableZoneScope);
(...skipping 2535 matching lines...) Expand 10 before | Expand all | Expand 10 after
2675 // - It must not have been prohibited by the caller to Parse (some callers 2681 // - It must not have been prohibited by the caller to Parse (some callers
2676 // need a full AST). 2682 // need a full AST).
2677 // - The outer scope must allow lazy compilation of inner functions. 2683 // - The outer scope must allow lazy compilation of inner functions.
2678 // - The function mustn't be a function expression with an open parenthesis 2684 // - The function mustn't be a function expression with an open parenthesis
2679 // before; we consider that a hint that the function will be called 2685 // before; we consider that a hint that the function will be called
2680 // immediately, and it would be a waste of time to make it lazily 2686 // immediately, and it would be a waste of time to make it lazily
2681 // compiled. 2687 // compiled.
2682 // These are all things we can know at this point, without looking at the 2688 // These are all things we can know at this point, without looking at the
2683 // function itself. 2689 // function itself.
2684 2690
2685 // In addition, we need to distinguish between these cases: 2691 // We separate between lazy parsing top level functions and lazy parsing inner
2692 // functions, because the latter needs to do more work. In particular, we need
2693 // to track unresolved variables to distinguish between these cases:
2686 // (function foo() { 2694 // (function foo() {
2687 // bar = function() { return 1; } 2695 // bar = function() { return 1; }
2688 // })(); 2696 // })();
2689 // and 2697 // and
2690 // (function foo() { 2698 // (function foo() {
2691 // var a = 1; 2699 // var a = 1;
2692 // bar = function() { return a; } 2700 // bar = function() { return a; }
2693 // })(); 2701 // })();
2694 2702
2695 // Now foo will be parsed eagerly and compiled eagerly (optimization: assume 2703 // Now foo will be parsed eagerly and compiled eagerly (optimization: assume
2696 // parenthesis before the function means that it will be called 2704 // parenthesis before the function means that it will be called
2697 // immediately). The inner function *must* be parsed eagerly to resolve the 2705 // immediately). bar can be parsed lazily, but we need to parse it in a mode
2698 // possible reference to the variable in foo's scope. However, it's possible 2706 // that tracks unresolved variables.
2699 // that it will be compiled lazily. 2707 DCHECK_IMPLIES(mode() == PARSE_LAZILY, FLAG_lazy);
2708 DCHECK_IMPLIES(mode() == PARSE_LAZILY, allow_lazy());
2709 DCHECK_IMPLIES(mode() == PARSE_LAZILY, extension_ == nullptr);
2700 2710
2701 // To make this additional case work, both Parser and PreParser implement a 2711 bool is_lazy_top_level_function =
2702 // logic where only top-level functions will be parsed lazily. 2712 mode() == PARSE_LAZILY &&
2703 bool is_lazily_parsed = mode() == PARSE_LAZILY && 2713 eager_compile_hint == FunctionLiteral::kShouldLazyCompile &&
2704 scope()->AllowsLazyParsing() && 2714 scope()->AllowsLazyParsingWithoutUnresolvedVariables();
2705 !function_state_->next_function_is_parenthesized();
2706 2715
2707 // Determine whether the function body can be discarded after parsing. 2716 // Determine whether we can still do the inner function lazy parsing.
Toon Verwaest 2016/09/23 11:51:18 Determine whether we can still lazy parse the inne
marja 2016/09/23 14:26:52 Done.
2708 // The preconditions are: 2717 // The preconditions are:
2709 // - Lazy compilation has to be enabled. 2718 // - Lazy compilation has to be enabled.
2710 // - Neither V8 natives nor native function declarations can be allowed, 2719 // - Neither V8 natives nor native function declarations can be allowed,
2711 // since parsing one would retroactively force the function to be 2720 // since parsing one would retroactively force the function to be
2712 // eagerly compiled. 2721 // eagerly compiled.
2713 // - The invoker of this parser can't depend on the AST being eagerly 2722 // - The invoker of this parser can't depend on the AST being eagerly
2714 // built (either because the function is about to be compiled, or 2723 // built (either because the function is about to be compiled, or
2715 // because the AST is going to be inspected for some reason). 2724 // because the AST is going to be inspected for some reason).
2716 // - Because of the above, we can't be attempting to parse a 2725 // - Because of the above, we can't be attempting to parse a
2717 // FunctionExpression; even without enclosing parentheses it might be 2726 // FunctionExpression; even without enclosing parentheses it might be
2718 // immediately invoked. 2727 // immediately invoked.
2719 // - The function literal shouldn't be hinted to eagerly compile. 2728 // - The function literal shouldn't be hinted to eagerly compile.
2720 // - For asm.js functions the body needs to be available when module 2729 // - For asm.js functions the body needs to be available when module
2721 // validation is active, because we examine the entire module at once. 2730 // validation is active, because we examine the entire module at once.
2722 bool use_temp_zone = 2731
2723 !is_lazily_parsed && allow_lazy() && 2732 // Inner functions will be parsed by using a temporary Zone. After parsing, we
Toon Verwaest 2016/09/23 11:51:18 parsed using
marja 2016/09/23 14:26:52 Done.
2733 // will migrate unresolved variable into a Scope in the main Zone.
2734 // TODO(marja): Refactor parsing modes: simplify this.
2735 bool is_lazy_inner_function =
2736 !is_lazy_top_level_function && allow_lazy() &&
2724 function_type == FunctionLiteral::kDeclaration && 2737 function_type == FunctionLiteral::kDeclaration &&
2725 eager_compile_hint != FunctionLiteral::kShouldEagerCompile && 2738 eager_compile_hint != FunctionLiteral::kShouldEagerCompile &&
2726 !(FLAG_validate_asm && scope()->IsAsmModule()); 2739 !(FLAG_validate_asm && scope()->IsAsmModule());
2727 2740
2728 DeclarationScope* main_scope = nullptr; 2741 DeclarationScope* main_scope = nullptr;
2729 if (use_temp_zone) { 2742 if (is_lazy_inner_function) {
2730 // This Scope lives in the main Zone; we'll migrate data into it later. 2743 // This Scope lives in the main Zone; we'll migrate data into it later.
2731 main_scope = NewFunctionScope(kind); 2744 main_scope = NewFunctionScope(kind);
2732 } 2745 }
2733 2746
2734 ZoneList<Statement*>* body = nullptr; 2747 ZoneList<Statement*>* body = nullptr;
2735 int arity = -1; 2748 int arity = -1;
2736 int materialized_literal_count = -1; 2749 int materialized_literal_count = -1;
2737 int expected_property_count = -1; 2750 int expected_property_count = -1;
2738 DuplicateFinder duplicate_finder(scanner()->unicode_cache()); 2751 DuplicateFinder duplicate_finder(scanner()->unicode_cache());
2739 bool should_be_used_once_hint = false; 2752 bool should_be_used_once_hint = false;
2740 bool has_duplicate_parameters; 2753 bool has_duplicate_parameters;
2741 2754
2742 { 2755 {
2743 // Temporary zones can nest. When we migrate free variables (see below), we 2756 // Temporary zones can nest. When we migrate free variables (see below), we
2744 // need to recreate them in the previous Zone. 2757 // need to recreate them in the previous Zone.
2745 AstNodeFactory previous_zone_ast_node_factory(ast_value_factory()); 2758 AstNodeFactory previous_zone_ast_node_factory(ast_value_factory());
2746 previous_zone_ast_node_factory.set_zone(zone()); 2759 previous_zone_ast_node_factory.set_zone(zone());
2747 2760
2748 // Open a new zone scope, which sets our AstNodeFactory to allocate in the 2761 // 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 2762 // 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 2763 // 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 2764 // to do scope analysis correctly after full parsing, we migrate needed
2752 // information from scope into main_scope when the function has been parsed. 2765 // information from scope into main_scope when the function has been parsed.
2753 Zone temp_zone(zone()->allocator()); 2766 Zone temp_zone(zone()->allocator());
2754 DiscardableZoneScope zone_scope(this, &temp_zone, use_temp_zone); 2767 DiscardableZoneScope zone_scope(this, &temp_zone, is_lazy_inner_function);
2755 2768
2756 DeclarationScope* scope = NewFunctionScope(kind); 2769 DeclarationScope* scope = NewFunctionScope(kind);
2757 SetLanguageMode(scope, language_mode); 2770 SetLanguageMode(scope, language_mode);
2758 if (!use_temp_zone) { 2771 if (!is_lazy_inner_function) {
2759 main_scope = scope; 2772 main_scope = scope;
2760 } else { 2773 } else {
2761 DCHECK(main_scope->zone() != scope->zone()); 2774 DCHECK(main_scope->zone() != scope->zone());
2762 } 2775 }
2763 2776
2764 FunctionState function_state(&function_state_, &scope_state_, scope, kind); 2777 FunctionState function_state(&function_state_, &scope_state_, scope, kind);
2765 #ifdef DEBUG 2778 #ifdef DEBUG
2766 scope->SetScopeName(function_name); 2779 scope->SetScopeName(function_name);
2767 #endif 2780 #endif
2768 ExpressionClassifier formals_classifier(this, &duplicate_finder); 2781 ExpressionClassifier formals_classifier(this, &duplicate_finder);
(...skipping 23 matching lines...) Expand all
2792 int formals_end_position = scanner()->location().end_pos; 2805 int formals_end_position = scanner()->location().end_pos;
2793 2806
2794 CheckArityRestrictions(arity, kind, formals.has_rest, start_position, 2807 CheckArityRestrictions(arity, kind, formals.has_rest, start_position,
2795 formals_end_position, CHECK_OK); 2808 formals_end_position, CHECK_OK);
2796 Expect(Token::LBRACE, CHECK_OK); 2809 Expect(Token::LBRACE, CHECK_OK);
2797 // Don't include the rest parameter into the function's formal parameter 2810 // Don't include the rest parameter into the function's formal parameter
2798 // count (esp. the SharedFunctionInfo::internal_formal_parameter_count, 2811 // count (esp. the SharedFunctionInfo::internal_formal_parameter_count,
2799 // which says whether we need to create an arguments adaptor frame). 2812 // which says whether we need to create an arguments adaptor frame).
2800 if (formals.has_rest) arity--; 2813 if (formals.has_rest) arity--;
2801 2814
2802 // Eager or lazy parse? 2815 // Eager or lazy parse? If is_lazy_top_level_function, we'll parse
2803 // If is_lazily_parsed, we'll parse lazily. We'll call SkipLazyFunctionBody, 2816 // lazily. We'll call SkipLazyFunctionBody, which may decide to abort lazy
2804 // which may decide to abort lazy parsing if it suspects that wasn't a good 2817 // parsing if it suspects that wasn't a good idea. If so (in which case the
2805 // idea. If so (in which case the parser is expected to have backtracked), 2818 // parser is expected to have backtracked), or if we didn't try to lazy
2806 // or if we didn't try to lazy parse in the first place, we'll have to parse 2819 // parse in the first place, we'll have to parse eagerly.
2807 // eagerly. 2820 if (is_lazy_top_level_function) {
Toon Verwaest 2016/09/23 11:51:18 What about just merging this with the is_lazy_inne
marja 2016/09/26 07:14:41 Done - but in the new version is much more difficu
2808 if (is_lazily_parsed) {
2809 Scanner::BookmarkScope bookmark(scanner()); 2821 Scanner::BookmarkScope bookmark(scanner());
2810 bookmark.Set(); 2822 bookmark.Set();
2811 LazyParsingResult result = 2823 LazyParsingResult result =
2812 SkipLazyFunctionBody(&materialized_literal_count, 2824 SkipLazyFunctionBody(&materialized_literal_count,
2813 &expected_property_count, true, CHECK_OK); 2825 &expected_property_count, false, true, CHECK_OK);
2814 2826
2815 materialized_literal_count += formals.materialized_literals_count + 2827 materialized_literal_count += formals.materialized_literals_count +
2816 function_state.materialized_literal_count(); 2828 function_state.materialized_literal_count();
2817 2829
2818 if (result == kLazyParsingAborted) { 2830 if (result == kLazyParsingAborted) {
2819 bookmark.Apply(); 2831 bookmark.Apply();
2820 // Trigger eager (re-)parsing, just below this block. 2832 // Trigger eager (re-)parsing, just below this block.
2821 is_lazily_parsed = false; 2833 is_lazy_top_level_function = false;
2822 2834
2823 // This is probably an initialization function. Inform the compiler it 2835 // This is probably an initialization function. Inform the compiler it
2824 // should also eager-compile this function, and that we expect it to be 2836 // should also eager-compile this function, and that we expect it to be
2825 // used once. 2837 // used once.
2826 eager_compile_hint = FunctionLiteral::kShouldEagerCompile; 2838 eager_compile_hint = FunctionLiteral::kShouldEagerCompile;
2827 should_be_used_once_hint = true; 2839 should_be_used_once_hint = true;
2828 } 2840 }
2829 } 2841 }
2830 if (!is_lazily_parsed) { 2842 if (is_lazy_inner_function) {
2843 if (FLAG_lazy_inner_functions) {
2844 LazyParsingResult result = SkipLazyFunctionBody(
2845 &materialized_literal_count, &expected_property_count, true, false,
2846 CHECK_OK);
2847 materialized_literal_count +=
2848 formals.materialized_literals_count +
2849 function_state.materialized_literal_count();
2850 DCHECK(result != kLazyParsingAborted);
2851 USE(result);
2852 } else {
2853 ParseEagerFunctionBody(function_name, pos, formals, kind, function_type,
2854 CHECK_OK);
2855 materialized_literal_count =
2856 function_state.materialized_literal_count();
2857 expected_property_count = function_state.expected_property_count();
2858 }
2859 } else if (!is_lazy_top_level_function) {
2831 body = ParseEagerFunctionBody(function_name, pos, formals, kind, 2860 body = ParseEagerFunctionBody(function_name, pos, formals, kind,
2832 function_type, CHECK_OK); 2861 function_type, CHECK_OK);
2833 2862
2834 materialized_literal_count = function_state.materialized_literal_count(); 2863 materialized_literal_count = function_state.materialized_literal_count();
2835 expected_property_count = function_state.expected_property_count(); 2864 expected_property_count = function_state.expected_property_count();
2836 if (use_temp_zone) {
2837 // If the preconditions are correct the function body should never be
2838 // accessed, but do this anyway for better behaviour if they're wrong.
2839 body = nullptr;
2840 }
2841 } 2865 }
2842 2866
2843 // Parsing the body may change the language mode in our scope. 2867 // Parsing the body may change the language mode in our scope.
2844 language_mode = scope->language_mode(); 2868 language_mode = scope->language_mode();
2845 scope->DeclareArguments(ast_value_factory()); 2869 scope->DeclareArguments(ast_value_factory());
2846 if (main_scope != scope) { 2870 if (main_scope != scope) {
2847 main_scope->DeclareArguments(ast_value_factory()); 2871 main_scope->DeclareArguments(ast_value_factory());
2848 } 2872 }
2849 2873
2850 // Validate name and parameter names. We can do this only after parsing the 2874 // Validate name and parameter names. We can do this only after parsing the
(...skipping 13 matching lines...) Expand all
2864 } 2888 }
2865 CheckConflictingVarDeclarations(scope, CHECK_OK); 2889 CheckConflictingVarDeclarations(scope, CHECK_OK);
2866 2890
2867 if (body) { 2891 if (body) {
2868 // If body can be inspected, rewrite queued destructuring assignments 2892 // If body can be inspected, rewrite queued destructuring assignments
2869 RewriteDestructuringAssignments(); 2893 RewriteDestructuringAssignments();
2870 } 2894 }
2871 has_duplicate_parameters = 2895 has_duplicate_parameters =
2872 !classifier()->is_valid_formal_parameter_list_without_duplicates(); 2896 !classifier()->is_valid_formal_parameter_list_without_duplicates();
2873 2897
2874 if (use_temp_zone) { 2898 if (is_lazy_inner_function) {
Toon Verwaest 2016/09/23 11:51:18 This can be dropped if you handle it as described
marja 2016/09/26 07:14:41 Done.
2875 DCHECK(main_scope != scope); 2899 DCHECK(main_scope != scope);
2876 scope->AnalyzePartially(main_scope, &previous_zone_ast_node_factory); 2900 scope->AnalyzePartially(main_scope, &previous_zone_ast_node_factory);
2877 } 2901 }
2878 } // DiscardableZoneScope goes out of scope. 2902 } // DiscardableZoneScope goes out of scope.
2879 2903
2880 FunctionLiteral::ParameterFlag duplicate_parameters = 2904 FunctionLiteral::ParameterFlag duplicate_parameters =
2881 has_duplicate_parameters ? FunctionLiteral::kHasDuplicateParameters 2905 has_duplicate_parameters ? FunctionLiteral::kHasDuplicateParameters
2882 : FunctionLiteral::kNoDuplicateParameters; 2906 : FunctionLiteral::kNoDuplicateParameters;
2883 2907
2884 // Note that the FunctionLiteral needs to be created in the main Zone again. 2908 // Note that the FunctionLiteral needs to be created in the main Zone again.
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
2918 } 2942 }
2919 return ParseFunctionLiteral(name, scanner()->location(), 2943 return ParseFunctionLiteral(name, scanner()->location(),
2920 is_strict_reserved ? kFunctionNameIsStrictReserved 2944 is_strict_reserved ? kFunctionNameIsStrictReserved
2921 : kFunctionNameValidityUnknown, 2945 : kFunctionNameValidityUnknown,
2922 FunctionKind::kAsyncFunction, pos, type, 2946 FunctionKind::kAsyncFunction, pos, type,
2923 language_mode(), CHECK_OK); 2947 language_mode(), CHECK_OK);
2924 } 2948 }
2925 2949
2926 Parser::LazyParsingResult Parser::SkipLazyFunctionBody( 2950 Parser::LazyParsingResult Parser::SkipLazyFunctionBody(
2927 int* materialized_literal_count, int* expected_property_count, 2951 int* materialized_literal_count, int* expected_property_count,
2928 bool may_abort, bool* ok) { 2952 bool is_inner_function, bool may_abort, bool* ok) {
2929 if (produce_cached_parse_data()) CHECK(log_); 2953 if (produce_cached_parse_data()) CHECK(log_);
2930 2954
2931 int function_block_pos = position(); 2955 int function_block_pos = position();
2932 DeclarationScope* scope = this->scope()->AsDeclarationScope(); 2956 DeclarationScope* scope = this->scope()->AsDeclarationScope();
2933 DCHECK(scope->is_function_scope()); 2957 DCHECK(scope->is_function_scope());
2934 scope->set_is_lazily_parsed(true); 2958 scope->set_is_lazily_parsed(true);
2935 if (consume_cached_parse_data() && !cached_parse_data_->rejected()) { 2959 // Inner functions are not part of the cached data.
2960 if (!is_inner_function && consume_cached_parse_data() &&
2961 !cached_parse_data_->rejected()) {
2936 // If we have cached data, we use it to skip parsing the function body. The 2962 // If we have cached data, we use it to skip parsing the function body. The
2937 // data contains the information we need to construct the lazy function. 2963 // data contains the information we need to construct the lazy function.
2938 FunctionEntry entry = 2964 FunctionEntry entry =
2939 cached_parse_data_->GetFunctionEntry(function_block_pos); 2965 cached_parse_data_->GetFunctionEntry(function_block_pos);
2940 // Check that cached data is valid. If not, mark it as invalid (the embedder 2966 // Check that cached data is valid. If not, mark it as invalid (the embedder
2941 // handles it). Note that end position greater than end of stream is safe, 2967 // handles it). Note that end position greater than end of stream is safe,
2942 // and hard to check. 2968 // and hard to check.
2943 if (entry.is_valid() && entry.end_pos() > function_block_pos) { 2969 if (entry.is_valid() && entry.end_pos() > function_block_pos) {
2944 scanner()->SeekForward(entry.end_pos() - 1); 2970 scanner()->SeekForward(entry.end_pos() - 1);
2945 2971
2946 scope->set_end_position(entry.end_pos()); 2972 scope->set_end_position(entry.end_pos());
2947 Expect(Token::RBRACE, CHECK_OK_VALUE(kLazyParsingComplete)); 2973 Expect(Token::RBRACE, CHECK_OK_VALUE(kLazyParsingComplete));
2948 total_preparse_skipped_ += scope->end_position() - function_block_pos; 2974 total_preparse_skipped_ += scope->end_position() - function_block_pos;
2949 *materialized_literal_count = entry.literal_count(); 2975 *materialized_literal_count = entry.literal_count();
2950 *expected_property_count = entry.property_count(); 2976 *expected_property_count = entry.property_count();
2951 SetLanguageMode(scope, entry.language_mode()); 2977 SetLanguageMode(scope, entry.language_mode());
2952 if (entry.uses_super_property()) scope->RecordSuperPropertyUsage(); 2978 if (entry.uses_super_property()) scope->RecordSuperPropertyUsage();
2953 if (entry.calls_eval()) scope->RecordEvalCall(); 2979 if (entry.calls_eval()) scope->RecordEvalCall();
2954 return kLazyParsingComplete; 2980 return kLazyParsingComplete;
2955 } 2981 }
2956 cached_parse_data_->Reject(); 2982 cached_parse_data_->Reject();
2957 } 2983 }
2958 // With no cached data, we partially parse the function, without building an 2984 // With no cached data, we partially parse the function, without building an
2959 // AST. This gathers the data needed to build a lazy function. 2985 // AST. This gathers the data needed to build a lazy function.
2960 SingletonLogger logger; 2986 SingletonLogger logger;
2961 PreParser::PreParseResult result = 2987 PreParser::PreParseResult result =
2962 ParseLazyFunctionBodyWithPreParser(&logger, may_abort); 2988 ParseLazyFunctionBodyWithPreParser(&logger, is_inner_function, may_abort);
2963 // Return immediately if pre-parser decided to abort parsing. 2989 // Return immediately if pre-parser decided to abort parsing.
2964 if (result == PreParser::kPreParseAbort) { 2990 if (result == PreParser::kPreParseAbort) {
2965 scope->set_is_lazily_parsed(false); 2991 scope->set_is_lazily_parsed(false);
2966 return kLazyParsingAborted; 2992 return kLazyParsingAborted;
2967 } 2993 }
2968 if (result == PreParser::kPreParseStackOverflow) { 2994 if (result == PreParser::kPreParseStackOverflow) {
2969 // Propagate stack overflow. 2995 // Propagate stack overflow.
2970 set_stack_overflow(); 2996 set_stack_overflow();
2971 *ok = false; 2997 *ok = false;
2972 return kLazyParsingComplete; 2998 return kLazyParsingComplete;
2973 } 2999 }
2974 if (logger.has_error()) { 3000 if (logger.has_error()) {
2975 ReportMessageAt(Scanner::Location(logger.start(), logger.end()), 3001 ReportMessageAt(Scanner::Location(logger.start(), logger.end()),
2976 logger.message(), logger.argument_opt(), 3002 logger.message(), logger.argument_opt(),
2977 logger.error_type()); 3003 logger.error_type());
2978 *ok = false; 3004 *ok = false;
2979 return kLazyParsingComplete; 3005 return kLazyParsingComplete;
2980 } 3006 }
2981 scope->set_end_position(logger.end()); 3007 scope->set_end_position(logger.end());
2982 Expect(Token::RBRACE, CHECK_OK_VALUE(kLazyParsingComplete)); 3008 Expect(Token::RBRACE, CHECK_OK_VALUE(kLazyParsingComplete));
2983 total_preparse_skipped_ += scope->end_position() - function_block_pos; 3009 total_preparse_skipped_ += scope->end_position() - function_block_pos;
2984 *materialized_literal_count = logger.literals(); 3010 *materialized_literal_count = logger.literals();
2985 *expected_property_count = logger.properties(); 3011 *expected_property_count = logger.properties();
2986 SetLanguageMode(scope, logger.language_mode()); 3012 SetLanguageMode(scope, logger.language_mode());
2987 if (logger.uses_super_property()) scope->RecordSuperPropertyUsage(); 3013 if (logger.uses_super_property()) scope->RecordSuperPropertyUsage();
2988 if (logger.calls_eval()) scope->RecordEvalCall(); 3014 if (logger.calls_eval()) scope->RecordEvalCall();
2989 if (produce_cached_parse_data()) { 3015 if (!is_inner_function && produce_cached_parse_data()) {
2990 DCHECK(log_); 3016 DCHECK(log_);
2991 // Position right after terminal '}'. 3017 // Position right after terminal '}'.
2992 int body_end = scanner()->location().end_pos; 3018 int body_end = scanner()->location().end_pos;
2993 log_->LogFunction(function_block_pos, body_end, *materialized_literal_count, 3019 log_->LogFunction(function_block_pos, body_end, *materialized_literal_count,
2994 *expected_property_count, language_mode(), 3020 *expected_property_count, language_mode(),
2995 scope->uses_super_property(), scope->calls_eval()); 3021 scope->uses_super_property(), scope->calls_eval());
2996 } 3022 }
2997 return kLazyParsingComplete; 3023 return kLazyParsingComplete;
2998 } 3024 }
2999 3025
(...skipping 286 matching lines...) Expand 10 before | Expand all | Expand 10 after
3286 promise = scope()->NewTemporary(ast_value_factory()->empty_string()); 3312 promise = scope()->NewTemporary(ast_value_factory()->empty_string());
3287 function_state_->set_promise_variable(promise); 3313 function_state_->set_promise_variable(promise);
3288 } 3314 }
3289 return promise; 3315 return promise;
3290 } 3316 }
3291 3317
3292 ZoneList<Statement*>* Parser::ParseEagerFunctionBody( 3318 ZoneList<Statement*>* Parser::ParseEagerFunctionBody(
3293 const AstRawString* function_name, int pos, 3319 const AstRawString* function_name, int pos,
3294 const ParserFormalParameters& parameters, FunctionKind kind, 3320 const ParserFormalParameters& parameters, FunctionKind kind,
3295 FunctionLiteral::FunctionType function_type, bool* ok) { 3321 FunctionLiteral::FunctionType function_type, bool* ok) {
3296 // Everything inside an eagerly parsed function will be parsed eagerly 3322 // Everything inside an eagerly parsed function will be parsed eagerly (see
3297 // (see comment above). 3323 // comment above). Lazy inner functions are handled separately and they won't
3324 // require the mode to be PARSE_LAZILY (see ParseFunctionLiteral).
3325 // TODO(marja): Refactor parsing modes: remove this.
3298 ParsingModeScope parsing_mode(this, PARSE_EAGERLY); 3326 ParsingModeScope parsing_mode(this, PARSE_EAGERLY);
3299 ZoneList<Statement*>* result = new(zone()) ZoneList<Statement*>(8, zone()); 3327 ZoneList<Statement*>* result = new(zone()) ZoneList<Statement*>(8, zone());
3300 3328
3301 static const int kFunctionNameAssignmentIndex = 0; 3329 static const int kFunctionNameAssignmentIndex = 0;
3302 if (function_type == FunctionLiteral::kNamedExpression) { 3330 if (function_type == FunctionLiteral::kNamedExpression) {
3303 DCHECK(function_name != NULL); 3331 DCHECK(function_name != NULL);
3304 // If we have a named function expression, we add a local variable 3332 // If we have a named function expression, we add a local variable
3305 // declaration to the body of the function with the name of the 3333 // declaration to the body of the function with the name of the
3306 // function and let it refer to the function itself (closure). 3334 // function and let it refer to the function itself (closure).
3307 // Not having parsed the function body, the language mode may still change, 3335 // Not having parsed the function body, the language mode may still change,
(...skipping 143 matching lines...) Expand 10 before | Expand all | Expand 10 after
3451 statement = factory()->NewEmptyStatement(kNoSourcePosition); 3479 statement = factory()->NewEmptyStatement(kNoSourcePosition);
3452 } 3480 }
3453 result->Set(kFunctionNameAssignmentIndex, statement); 3481 result->Set(kFunctionNameAssignmentIndex, statement);
3454 } 3482 }
3455 3483
3456 MarkCollectedTailCallExpressions(); 3484 MarkCollectedTailCallExpressions();
3457 return result; 3485 return result;
3458 } 3486 }
3459 3487
3460 PreParser::PreParseResult Parser::ParseLazyFunctionBodyWithPreParser( 3488 PreParser::PreParseResult Parser::ParseLazyFunctionBodyWithPreParser(
3461 SingletonLogger* logger, bool may_abort) { 3489 SingletonLogger* logger, bool is_inner_function, bool may_abort) {
3462 // This function may be called on a background thread too; record only the 3490 // This function may be called on a background thread too; record only the
3463 // main thread preparse times. 3491 // main thread preparse times.
3464 if (pre_parse_timer_ != NULL) { 3492 if (pre_parse_timer_ != NULL) {
3465 pre_parse_timer_->Start(); 3493 pre_parse_timer_->Start();
3466 } 3494 }
3467 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8.compile"), "V8.PreParse"); 3495 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8.compile"), "V8.PreParse");
3468 3496
3469 DCHECK_EQ(Token::LBRACE, scanner()->current_token()); 3497 DCHECK_EQ(Token::LBRACE, scanner()->current_token());
3470 3498
3471 if (reusable_preparser_ == NULL) { 3499 if (reusable_preparser_ == NULL) {
3472 reusable_preparser_ = new PreParser(zone(), &scanner_, ast_value_factory(), 3500 reusable_preparser_ = new PreParser(zone(), &scanner_, ast_value_factory(),
3473 NULL, stack_limit_); 3501 NULL, stack_limit_);
3474 reusable_preparser_->set_allow_lazy(true); 3502 reusable_preparser_->set_allow_lazy(true);
3475 #define SET_ALLOW(name) reusable_preparser_->set_allow_##name(allow_##name()); 3503 #define SET_ALLOW(name) reusable_preparser_->set_allow_##name(allow_##name());
3476 SET_ALLOW(natives); 3504 SET_ALLOW(natives);
3477 SET_ALLOW(harmony_do_expressions); 3505 SET_ALLOW(harmony_do_expressions);
3478 SET_ALLOW(harmony_for_in); 3506 SET_ALLOW(harmony_for_in);
3479 SET_ALLOW(harmony_function_sent); 3507 SET_ALLOW(harmony_function_sent);
3480 SET_ALLOW(harmony_restrictive_declarations); 3508 SET_ALLOW(harmony_restrictive_declarations);
3481 SET_ALLOW(harmony_async_await); 3509 SET_ALLOW(harmony_async_await);
3482 SET_ALLOW(harmony_trailing_commas); 3510 SET_ALLOW(harmony_trailing_commas);
3483 SET_ALLOW(harmony_class_fields); 3511 SET_ALLOW(harmony_class_fields);
3484 #undef SET_ALLOW 3512 #undef SET_ALLOW
3485 } 3513 }
3486 PreParser::PreParseResult result = reusable_preparser_->PreParseLazyFunction( 3514 // Aborting inner function preparsing would leave scopes in an inconsistent
3487 language_mode(), function_state_->kind(), 3515 // state; we don't parse inner functions in the abortable mode anyway.
3488 scope()->AsDeclarationScope()->has_simple_parameters(), parsing_module_, 3516 DCHECK(!is_inner_function || !may_abort);
3489 logger, may_abort, use_counts_); 3517
3518 FunctionKind kind = function_state_->kind();
3519 PreParser::PreParseResult result;
3520 if (!is_inner_function) {
3521 // If we don't need to look at the scope, construct a dummy scope chain
Toon Verwaest 2016/09/23 11:51:18 I don't see why this is necessary now but wasn't b
marja 2016/09/26 07:14:41 This code was moved from PreParser::PreParseLazyFu
3522 // which is not connected to the real scope chain.
3523 LanguageMode mode = language_mode();
3524 bool has_simple_parameters =
3525 scope()->AsDeclarationScope()->has_simple_parameters();
3526 DeclarationScope* top_scope = NewScriptScope();
3527 top_scope->SetLanguageMode(mode);
3528 FunctionState top_state(&function_state_, &scope_state_, top_scope,
3529 kNormalFunction);
3530 DeclarationScope* function_scope = NewFunctionScope(kind);
3531 if (!has_simple_parameters) {
3532 function_scope->SetHasNonSimpleParameters();
3533 }
3534 result = reusable_preparser_->PreParseLazyFunction(
3535 kind, function_scope, parsing_module_, logger, is_inner_function,
3536 may_abort, use_counts_);
3537 } else {
3538 // Detaching the scopes created by PreParser from the Scope chain must be
3539 // done above (see ParseFunctionLiteral & AnalyzePartially).
3540 result = reusable_preparser_->PreParseLazyFunction(
3541 kind, scope()->AsDeclarationScope(), parsing_module_, logger,
3542 is_inner_function, may_abort, use_counts_);
3543 }
3490 if (pre_parse_timer_ != NULL) { 3544 if (pre_parse_timer_ != NULL) {
3491 pre_parse_timer_->Stop(); 3545 pre_parse_timer_->Stop();
3492 } 3546 }
3493 return result; 3547 return result;
3494 } 3548 }
3495 3549
3496 Expression* Parser::InstallHomeObject(Expression* function_literal, 3550 Expression* Parser::InstallHomeObject(Expression* function_literal,
3497 Expression* home_object) { 3551 Expression* home_object) {
3498 Block* do_block = factory()->NewBlock(nullptr, 1, false, kNoSourcePosition); 3552 Block* do_block = factory()->NewBlock(nullptr, 1, false, kNoSourcePosition);
3499 Variable* result_var = 3553 Variable* result_var =
(...skipping 2103 matching lines...) Expand 10 before | Expand all | Expand 10 after
5603 5657
5604 return final_loop; 5658 return final_loop;
5605 } 5659 }
5606 5660
5607 #undef CHECK_OK 5661 #undef CHECK_OK
5608 #undef CHECK_OK_VOID 5662 #undef CHECK_OK_VOID
5609 #undef CHECK_FAILED 5663 #undef CHECK_FAILED
5610 5664
5611 } // namespace internal 5665 } // namespace internal
5612 } // namespace v8 5666 } // namespace v8
OLDNEW
« src/ast/scopes.cc ('K') | « src/parsing/parser.h ('k') | src/parsing/parser-base.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698