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 2723 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2734 // Inner functions will be parsed using a temporary Zone. After parsing, we | 2734 // Inner functions will be parsed using a temporary Zone. After parsing, we |
2735 // will migrate unresolved variable into a Scope in the main Zone. | 2735 // will migrate unresolved variable into a Scope in the main Zone. |
2736 // TODO(marja): Refactor parsing modes: simplify this. | 2736 // TODO(marja): Refactor parsing modes: simplify this. |
2737 bool use_temp_zone = | 2737 bool use_temp_zone = |
2738 !is_lazy_top_level_function && allow_lazy() && | 2738 !is_lazy_top_level_function && allow_lazy() && |
2739 function_type == FunctionLiteral::kDeclaration && | 2739 function_type == FunctionLiteral::kDeclaration && |
2740 eager_compile_hint != FunctionLiteral::kShouldEagerCompile && | 2740 eager_compile_hint != FunctionLiteral::kShouldEagerCompile && |
2741 !(FLAG_validate_asm && scope()->IsAsmModule()); | 2741 !(FLAG_validate_asm && scope()->IsAsmModule()); |
2742 bool is_lazy_inner_function = use_temp_zone && FLAG_lazy_inner_functions; | 2742 bool is_lazy_inner_function = use_temp_zone && FLAG_lazy_inner_functions; |
2743 | 2743 |
2744 DeclarationScope* main_scope = nullptr; | 2744 // This Scope lives in the main zone. We'll migrate data into that zone later. |
2745 if (use_temp_zone) { | 2745 DeclarationScope* scope = NewFunctionScope(kind); |
2746 // This Scope lives in the main Zone; we'll migrate data into it later. | 2746 SetLanguageMode(scope, language_mode); |
2747 main_scope = NewFunctionScope(kind); | |
2748 } | |
2749 | 2747 |
2750 ZoneList<Statement*>* body = nullptr; | 2748 ZoneList<Statement*>* body = nullptr; |
2751 int arity = -1; | 2749 int arity = -1; |
2752 int materialized_literal_count = -1; | 2750 int materialized_literal_count = -1; |
2753 int expected_property_count = -1; | 2751 int expected_property_count = -1; |
2754 DuplicateFinder duplicate_finder(scanner()->unicode_cache()); | 2752 DuplicateFinder duplicate_finder(scanner()->unicode_cache()); |
2755 bool should_be_used_once_hint = false; | 2753 bool should_be_used_once_hint = false; |
2756 bool has_duplicate_parameters; | 2754 bool has_duplicate_parameters; |
2757 | 2755 |
2758 { | 2756 { |
2759 // Temporary zones can nest. When we migrate free variables (see below), we | 2757 // Temporary zones can nest. When we migrate free variables (see below), we |
2760 // need to recreate them in the previous Zone. | 2758 // need to recreate them in the previous Zone. |
2761 AstNodeFactory previous_zone_ast_node_factory(ast_value_factory()); | 2759 AstNodeFactory previous_zone_ast_node_factory(ast_value_factory()); |
2762 previous_zone_ast_node_factory.set_zone(zone()); | 2760 previous_zone_ast_node_factory.set_zone(zone()); |
2763 | 2761 |
2764 // Open a new zone scope, which sets our AstNodeFactory to allocate in the | 2762 // Open a new zone scope, which sets our AstNodeFactory to allocate in the |
2765 // new temporary zone if the preconditions are satisfied, and ensures that | 2763 // new temporary zone if the preconditions are satisfied, and ensures that |
2766 // the previous zone is always restored after parsing the body. To be able | 2764 // the previous zone is always restored after parsing the body. To be able |
2767 // to do scope analysis correctly after full parsing, we migrate needed | 2765 // to do scope analysis correctly after full parsing, we migrate needed |
2768 // information from scope into main_scope when the function has been parsed. | 2766 // information when the function is parsed. |
2769 Zone temp_zone(zone()->allocator()); | 2767 Zone temp_zone(zone()->allocator()); |
2770 DiscardableZoneScope zone_scope(this, &temp_zone, use_temp_zone); | 2768 DiscardableZoneScope zone_scope(this, &temp_zone, use_temp_zone); |
2771 | 2769 |
2772 DeclarationScope* scope = NewFunctionScope(kind); | |
2773 SetLanguageMode(scope, language_mode); | |
2774 if (!use_temp_zone) { | |
2775 main_scope = scope; | |
2776 } else { | |
2777 DCHECK(main_scope->zone() != scope->zone()); | |
2778 } | |
2779 | |
2780 FunctionState function_state(&function_state_, &scope_state_, scope); | 2770 FunctionState function_state(&function_state_, &scope_state_, scope); |
2781 #ifdef DEBUG | 2771 #ifdef DEBUG |
2782 scope->SetScopeName(function_name); | 2772 scope->SetScopeName(function_name); |
2783 #endif | 2773 #endif |
2784 ExpressionClassifier formals_classifier(this, &duplicate_finder); | 2774 ExpressionClassifier formals_classifier(this, &duplicate_finder); |
2785 | 2775 |
2786 if (is_generator) { | 2776 if (is_generator) { |
2787 // For generators, allocating variables in contexts is currently a win | 2777 // For generators, allocating variables in contexts is currently a win |
2788 // because it minimizes the work needed to suspend and resume an | 2778 // because it minimizes the work needed to suspend and resume an |
2789 // activation. The machine code produced for generators (by full-codegen) | 2779 // activation. The machine code produced for generators (by full-codegen) |
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2834 DCHECK(is_lazy_top_level_function); | 2824 DCHECK(is_lazy_top_level_function); |
2835 bookmark.Apply(); | 2825 bookmark.Apply(); |
2836 // Trigger eager (re-)parsing, just below this block. | 2826 // Trigger eager (re-)parsing, just below this block. |
2837 is_lazy_top_level_function = false; | 2827 is_lazy_top_level_function = false; |
2838 | 2828 |
2839 // This is probably an initialization function. Inform the compiler it | 2829 // This is probably an initialization function. Inform the compiler it |
2840 // should also eager-compile this function, and that we expect it to be | 2830 // should also eager-compile this function, and that we expect it to be |
2841 // used once. | 2831 // used once. |
2842 eager_compile_hint = FunctionLiteral::kShouldEagerCompile; | 2832 eager_compile_hint = FunctionLiteral::kShouldEagerCompile; |
2843 should_be_used_once_hint = true; | 2833 should_be_used_once_hint = true; |
2844 } else if (is_lazy_inner_function) { | 2834 scope->ResetAfterPreparsing(); |
2845 DCHECK(main_scope != scope); | |
2846 scope->AnalyzePartially(main_scope, &previous_zone_ast_node_factory); | |
2847 } | 2835 } |
2848 } | 2836 } |
2837 | |
2849 if (!is_lazy_top_level_function && !is_lazy_inner_function) { | 2838 if (!is_lazy_top_level_function && !is_lazy_inner_function) { |
2850 body = ParseEagerFunctionBody(function_name, pos, formals, kind, | 2839 body = ParseEagerFunctionBody(function_name, pos, formals, kind, |
2851 function_type, CHECK_OK); | 2840 function_type, CHECK_OK); |
2852 | 2841 |
2853 materialized_literal_count = function_state.materialized_literal_count(); | 2842 materialized_literal_count = function_state.materialized_literal_count(); |
2854 expected_property_count = function_state.expected_property_count(); | 2843 expected_property_count = function_state.expected_property_count(); |
2855 if (use_temp_zone) { | 2844 } |
2856 // If the preconditions are correct the function body should never be | 2845 |
2857 // accessed, but do this anyway for better behaviour if they're wrong. | 2846 if (use_temp_zone || is_lazy_top_level_function) { |
marja
2016/09/27 07:14:03
This sounds wrong... is_lazy_inner_function maybe?
marja
2016/09/27 11:17:34
.... and I was confused; use_temp_zone contains th
| |
2858 body = nullptr; | 2847 // If the preconditions are correct the function body should never be |
2859 DCHECK(main_scope != scope); | 2848 // accessed, but do this anyway for better behaviour if they're wrong. |
2860 scope->AnalyzePartially(main_scope, &previous_zone_ast_node_factory); | 2849 body = nullptr; |
2861 } | 2850 scope->AnalyzePartially(&previous_zone_ast_node_factory); |
2862 } | 2851 } |
2863 | 2852 |
2864 // Parsing the body may change the language mode in our scope. | 2853 // Parsing the body may change the language mode in our scope. |
2865 language_mode = scope->language_mode(); | 2854 language_mode = scope->language_mode(); |
2866 | 2855 |
2867 // Validate name and parameter names. We can do this only after parsing the | 2856 // Validate name and parameter names. We can do this only after parsing the |
2868 // function, since the function can declare itself strict. | 2857 // function, since the function can declare itself strict. |
2869 CheckFunctionName(language_mode, function_name, function_name_validity, | 2858 CheckFunctionName(language_mode, function_name, function_name_validity, |
2870 function_name_location, CHECK_OK); | 2859 function_name_location, CHECK_OK); |
2871 const bool allow_duplicate_parameters = | 2860 const bool allow_duplicate_parameters = |
(...skipping 16 matching lines...) Expand all Loading... | |
2888 has_duplicate_parameters = | 2877 has_duplicate_parameters = |
2889 !classifier()->is_valid_formal_parameter_list_without_duplicates(); | 2878 !classifier()->is_valid_formal_parameter_list_without_duplicates(); |
2890 } // DiscardableZoneScope goes out of scope. | 2879 } // DiscardableZoneScope goes out of scope. |
2891 | 2880 |
2892 FunctionLiteral::ParameterFlag duplicate_parameters = | 2881 FunctionLiteral::ParameterFlag duplicate_parameters = |
2893 has_duplicate_parameters ? FunctionLiteral::kHasDuplicateParameters | 2882 has_duplicate_parameters ? FunctionLiteral::kHasDuplicateParameters |
2894 : FunctionLiteral::kNoDuplicateParameters; | 2883 : FunctionLiteral::kNoDuplicateParameters; |
2895 | 2884 |
2896 // Note that the FunctionLiteral needs to be created in the main Zone again. | 2885 // Note that the FunctionLiteral needs to be created in the main Zone again. |
2897 FunctionLiteral* function_literal = factory()->NewFunctionLiteral( | 2886 FunctionLiteral* function_literal = factory()->NewFunctionLiteral( |
2898 function_name, main_scope, body, materialized_literal_count, | 2887 function_name, scope, body, materialized_literal_count, |
2899 expected_property_count, arity, duplicate_parameters, function_type, | 2888 expected_property_count, arity, duplicate_parameters, function_type, |
2900 eager_compile_hint, kind, pos); | 2889 eager_compile_hint, kind, pos); |
2901 function_literal->set_function_token_position(function_token_pos); | 2890 function_literal->set_function_token_position(function_token_pos); |
2902 if (should_be_used_once_hint) | 2891 if (should_be_used_once_hint) |
2903 function_literal->set_should_be_used_once_hint(); | 2892 function_literal->set_should_be_used_once_hint(); |
2904 | 2893 |
2905 if (should_infer_name) { | 2894 if (should_infer_name) { |
2906 DCHECK_NOT_NULL(fni_); | 2895 DCHECK_NOT_NULL(fni_); |
2907 fni_->AddFunction(function_literal); | 2896 fni_->AddFunction(function_literal); |
2908 } | 2897 } |
(...skipping 564 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3473 #undef SET_ALLOW | 3462 #undef SET_ALLOW |
3474 } | 3463 } |
3475 // Aborting inner function preparsing would leave scopes in an inconsistent | 3464 // Aborting inner function preparsing would leave scopes in an inconsistent |
3476 // state; we don't parse inner functions in the abortable mode anyway. | 3465 // state; we don't parse inner functions in the abortable mode anyway. |
3477 DCHECK(!is_inner_function || !may_abort); | 3466 DCHECK(!is_inner_function || !may_abort); |
3478 | 3467 |
3479 DeclarationScope* function_scope = function_state_->scope(); | 3468 DeclarationScope* function_scope = function_state_->scope(); |
3480 PreParser::PreParseResult result = reusable_preparser_->PreParseLazyFunction( | 3469 PreParser::PreParseResult result = reusable_preparser_->PreParseLazyFunction( |
3481 function_scope, parsing_module_, logger, is_inner_function, may_abort, | 3470 function_scope, parsing_module_, logger, is_inner_function, may_abort, |
3482 use_counts_); | 3471 use_counts_); |
3483 // Detaching the scopes created by PreParser from the Scope chain must be done | |
3484 // above (see ParseFunctionLiteral & AnalyzePartially). | |
3485 if (!is_inner_function) function_scope->ResetAfterPreparsing(); | |
3486 if (pre_parse_timer_ != NULL) { | 3472 if (pre_parse_timer_ != NULL) { |
3487 pre_parse_timer_->Stop(); | 3473 pre_parse_timer_->Stop(); |
3488 } | 3474 } |
3489 return result; | 3475 return result; |
3490 } | 3476 } |
3491 | 3477 |
3492 Expression* Parser::InstallHomeObject(Expression* function_literal, | 3478 Expression* Parser::InstallHomeObject(Expression* function_literal, |
3493 Expression* home_object) { | 3479 Expression* home_object) { |
3494 Block* do_block = factory()->NewBlock(nullptr, 1, false, kNoSourcePosition); | 3480 Block* do_block = factory()->NewBlock(nullptr, 1, false, kNoSourcePosition); |
3495 Variable* result_var = | 3481 Variable* result_var = |
(...skipping 2103 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
5599 | 5585 |
5600 return final_loop; | 5586 return final_loop; |
5601 } | 5587 } |
5602 | 5588 |
5603 #undef CHECK_OK | 5589 #undef CHECK_OK |
5604 #undef CHECK_OK_VOID | 5590 #undef CHECK_OK_VOID |
5605 #undef CHECK_FAILED | 5591 #undef CHECK_FAILED |
5606 | 5592 |
5607 } // namespace internal | 5593 } // namespace internal |
5608 } // namespace v8 | 5594 } // namespace v8 |
OLD | NEW |