Chromium Code Reviews| 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 104 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 |
| OLD | NEW |