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 2727 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2738 // Inner functions will be parsed using a temporary Zone. After parsing, we | 2738 // Inner functions will be parsed using a temporary Zone. After parsing, we |
2739 // will migrate unresolved variable into a Scope in the main Zone. | 2739 // will migrate unresolved variable into a Scope in the main Zone. |
2740 // TODO(marja): Refactor parsing modes: simplify this. | 2740 // TODO(marja): Refactor parsing modes: simplify this. |
2741 bool use_temp_zone = | 2741 bool use_temp_zone = |
2742 !is_lazy_top_level_function && allow_lazy() && | 2742 !is_lazy_top_level_function && allow_lazy() && |
2743 function_type == FunctionLiteral::kDeclaration && | 2743 function_type == FunctionLiteral::kDeclaration && |
2744 eager_compile_hint != FunctionLiteral::kShouldEagerCompile && | 2744 eager_compile_hint != FunctionLiteral::kShouldEagerCompile && |
2745 !(FLAG_validate_asm && scope()->IsAsmModule()); | 2745 !(FLAG_validate_asm && scope()->IsAsmModule()); |
2746 bool is_lazy_inner_function = use_temp_zone && FLAG_lazy_inner_functions; | 2746 bool is_lazy_inner_function = use_temp_zone && FLAG_lazy_inner_functions; |
2747 | 2747 |
2748 DeclarationScope* main_scope = nullptr; | 2748 // This Scope lives in the main zone. We'll migrate data into that zone later. |
2749 if (use_temp_zone) { | 2749 DeclarationScope* scope = NewFunctionScope(kind); |
2750 // This Scope lives in the main Zone; we'll migrate data into it later. | 2750 SetLanguageMode(scope, language_mode); |
2751 main_scope = NewFunctionScope(kind); | |
2752 } | |
2753 | 2751 |
2754 ZoneList<Statement*>* body = nullptr; | 2752 ZoneList<Statement*>* body = nullptr; |
2755 int arity = -1; | 2753 int arity = -1; |
2756 int materialized_literal_count = -1; | 2754 int materialized_literal_count = -1; |
2757 int expected_property_count = -1; | 2755 int expected_property_count = -1; |
2758 DuplicateFinder duplicate_finder(scanner()->unicode_cache()); | 2756 DuplicateFinder duplicate_finder(scanner()->unicode_cache()); |
2759 bool should_be_used_once_hint = false; | 2757 bool should_be_used_once_hint = false; |
2760 bool has_duplicate_parameters; | 2758 bool has_duplicate_parameters; |
2761 | 2759 |
2762 { | 2760 { |
2763 // Temporary zones can nest. When we migrate free variables (see below), we | 2761 // Temporary zones can nest. When we migrate free variables (see below), we |
2764 // need to recreate them in the previous Zone. | 2762 // need to recreate them in the previous Zone. |
2765 AstNodeFactory previous_zone_ast_node_factory(ast_value_factory()); | 2763 AstNodeFactory previous_zone_ast_node_factory(ast_value_factory()); |
2766 previous_zone_ast_node_factory.set_zone(zone()); | 2764 previous_zone_ast_node_factory.set_zone(zone()); |
2767 | 2765 |
2768 // Open a new zone scope, which sets our AstNodeFactory to allocate in the | 2766 // Open a new zone scope, which sets our AstNodeFactory to allocate in the |
2769 // new temporary zone if the preconditions are satisfied, and ensures that | 2767 // new temporary zone if the preconditions are satisfied, and ensures that |
2770 // the previous zone is always restored after parsing the body. To be able | 2768 // the previous zone is always restored after parsing the body. To be able |
2771 // to do scope analysis correctly after full parsing, we migrate needed | 2769 // to do scope analysis correctly after full parsing, we migrate needed |
2772 // information from scope into main_scope when the function has been parsed. | 2770 // information when the function is parsed. |
2773 Zone temp_zone(zone()->allocator()); | 2771 Zone temp_zone(zone()->allocator()); |
2774 DiscardableZoneScope zone_scope(this, &temp_zone, use_temp_zone); | 2772 DiscardableZoneScope zone_scope(this, &temp_zone, use_temp_zone); |
2775 | 2773 |
2776 DeclarationScope* scope = NewFunctionScope(kind); | |
2777 SetLanguageMode(scope, language_mode); | |
2778 if (!use_temp_zone) { | |
2779 main_scope = scope; | |
2780 } else { | |
2781 DCHECK(main_scope->zone() != scope->zone()); | |
2782 } | |
2783 | |
2784 FunctionState function_state(&function_state_, &scope_state_, scope); | 2774 FunctionState function_state(&function_state_, &scope_state_, scope); |
2785 #ifdef DEBUG | 2775 #ifdef DEBUG |
2786 scope->SetScopeName(function_name); | 2776 scope->SetScopeName(function_name); |
| 2777 if (use_temp_zone) scope->set_needs_migration(); |
2787 #endif | 2778 #endif |
2788 ExpressionClassifier formals_classifier(this, &duplicate_finder); | 2779 ExpressionClassifier formals_classifier(this, &duplicate_finder); |
2789 | 2780 |
2790 if (is_generator) { | 2781 if (is_generator) { |
2791 // For generators, allocating variables in contexts is currently a win | 2782 // For generators, allocating variables in contexts is currently a win |
2792 // because it minimizes the work needed to suspend and resume an | 2783 // because it minimizes the work needed to suspend and resume an |
2793 // activation. The machine code produced for generators (by full-codegen) | 2784 // activation. The machine code produced for generators (by full-codegen) |
2794 // relies on this forced context allocation, but not in an essential way. | 2785 // relies on this forced context allocation, but not in an essential way. |
2795 this->scope()->ForceContextAllocation(); | 2786 this->scope()->ForceContextAllocation(); |
2796 | 2787 |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2838 DCHECK(is_lazy_top_level_function); | 2829 DCHECK(is_lazy_top_level_function); |
2839 bookmark.Apply(); | 2830 bookmark.Apply(); |
2840 // Trigger eager (re-)parsing, just below this block. | 2831 // Trigger eager (re-)parsing, just below this block. |
2841 is_lazy_top_level_function = false; | 2832 is_lazy_top_level_function = false; |
2842 | 2833 |
2843 // This is probably an initialization function. Inform the compiler it | 2834 // This is probably an initialization function. Inform the compiler it |
2844 // should also eager-compile this function, and that we expect it to be | 2835 // should also eager-compile this function, and that we expect it to be |
2845 // used once. | 2836 // used once. |
2846 eager_compile_hint = FunctionLiteral::kShouldEagerCompile; | 2837 eager_compile_hint = FunctionLiteral::kShouldEagerCompile; |
2847 should_be_used_once_hint = true; | 2838 should_be_used_once_hint = true; |
2848 } else if (is_lazy_inner_function) { | 2839 scope->ResetAfterPreparsing(true); |
2849 DCHECK(main_scope != scope); | |
2850 scope->AnalyzePartially(main_scope, &previous_zone_ast_node_factory); | |
2851 } | 2840 } |
2852 } | 2841 } |
| 2842 |
2853 if (!is_lazy_top_level_function && !is_lazy_inner_function) { | 2843 if (!is_lazy_top_level_function && !is_lazy_inner_function) { |
2854 body = ParseEagerFunctionBody(function_name, pos, formals, kind, | 2844 body = ParseEagerFunctionBody(function_name, pos, formals, kind, |
2855 function_type, CHECK_OK); | 2845 function_type, CHECK_OK); |
2856 | 2846 |
2857 materialized_literal_count = function_state.materialized_literal_count(); | 2847 materialized_literal_count = function_state.materialized_literal_count(); |
2858 expected_property_count = function_state.expected_property_count(); | 2848 expected_property_count = function_state.expected_property_count(); |
2859 if (use_temp_zone) { | 2849 } |
2860 // If the preconditions are correct the function body should never be | 2850 |
2861 // accessed, but do this anyway for better behaviour if they're wrong. | 2851 if (use_temp_zone || is_lazy_top_level_function) { |
2862 body = nullptr; | 2852 // If the preconditions are correct the function body should never be |
2863 DCHECK(main_scope != scope); | 2853 // accessed, but do this anyway for better behaviour if they're wrong. |
2864 scope->AnalyzePartially(main_scope, &previous_zone_ast_node_factory); | 2854 body = nullptr; |
2865 } | 2855 scope->AnalyzePartially(&previous_zone_ast_node_factory); |
2866 } | 2856 } |
2867 | 2857 |
2868 // Parsing the body may change the language mode in our scope. | 2858 // Parsing the body may change the language mode in our scope. |
2869 language_mode = scope->language_mode(); | 2859 language_mode = scope->language_mode(); |
2870 | 2860 |
2871 // Validate name and parameter names. We can do this only after parsing the | 2861 // Validate name and parameter names. We can do this only after parsing the |
2872 // function, since the function can declare itself strict. | 2862 // function, since the function can declare itself strict. |
2873 CheckFunctionName(language_mode, function_name, function_name_validity, | 2863 CheckFunctionName(language_mode, function_name, function_name_validity, |
2874 function_name_location, CHECK_OK); | 2864 function_name_location, CHECK_OK); |
2875 const bool allow_duplicate_parameters = | 2865 const bool allow_duplicate_parameters = |
(...skipping 16 matching lines...) Expand all Loading... |
2892 has_duplicate_parameters = | 2882 has_duplicate_parameters = |
2893 !classifier()->is_valid_formal_parameter_list_without_duplicates(); | 2883 !classifier()->is_valid_formal_parameter_list_without_duplicates(); |
2894 } // DiscardableZoneScope goes out of scope. | 2884 } // DiscardableZoneScope goes out of scope. |
2895 | 2885 |
2896 FunctionLiteral::ParameterFlag duplicate_parameters = | 2886 FunctionLiteral::ParameterFlag duplicate_parameters = |
2897 has_duplicate_parameters ? FunctionLiteral::kHasDuplicateParameters | 2887 has_duplicate_parameters ? FunctionLiteral::kHasDuplicateParameters |
2898 : FunctionLiteral::kNoDuplicateParameters; | 2888 : FunctionLiteral::kNoDuplicateParameters; |
2899 | 2889 |
2900 // Note that the FunctionLiteral needs to be created in the main Zone again. | 2890 // Note that the FunctionLiteral needs to be created in the main Zone again. |
2901 FunctionLiteral* function_literal = factory()->NewFunctionLiteral( | 2891 FunctionLiteral* function_literal = factory()->NewFunctionLiteral( |
2902 function_name, main_scope, body, materialized_literal_count, | 2892 function_name, scope, body, materialized_literal_count, |
2903 expected_property_count, arity, duplicate_parameters, function_type, | 2893 expected_property_count, arity, duplicate_parameters, function_type, |
2904 eager_compile_hint, kind, pos); | 2894 eager_compile_hint, kind, pos); |
2905 function_literal->set_function_token_position(function_token_pos); | 2895 function_literal->set_function_token_position(function_token_pos); |
2906 if (should_be_used_once_hint) | 2896 if (should_be_used_once_hint) |
2907 function_literal->set_should_be_used_once_hint(); | 2897 function_literal->set_should_be_used_once_hint(); |
2908 | 2898 |
2909 if (should_infer_name) { | 2899 if (should_infer_name) { |
2910 DCHECK_NOT_NULL(fni_); | 2900 DCHECK_NOT_NULL(fni_); |
2911 fni_->AddFunction(function_literal); | 2901 fni_->AddFunction(function_literal); |
2912 } | 2902 } |
(...skipping 27 matching lines...) Expand all Loading... |
2940 } | 2930 } |
2941 | 2931 |
2942 Parser::LazyParsingResult Parser::SkipLazyFunctionBody( | 2932 Parser::LazyParsingResult Parser::SkipLazyFunctionBody( |
2943 int* materialized_literal_count, int* expected_property_count, | 2933 int* materialized_literal_count, int* expected_property_count, |
2944 bool is_inner_function, bool may_abort, bool* ok) { | 2934 bool is_inner_function, bool may_abort, bool* ok) { |
2945 if (produce_cached_parse_data()) CHECK(log_); | 2935 if (produce_cached_parse_data()) CHECK(log_); |
2946 | 2936 |
2947 int function_block_pos = position(); | 2937 int function_block_pos = position(); |
2948 DeclarationScope* scope = function_state_->scope(); | 2938 DeclarationScope* scope = function_state_->scope(); |
2949 DCHECK(scope->is_function_scope()); | 2939 DCHECK(scope->is_function_scope()); |
2950 scope->set_is_lazily_parsed(true); | |
2951 // Inner functions are not part of the cached data. | 2940 // Inner functions are not part of the cached data. |
2952 if (!is_inner_function && consume_cached_parse_data() && | 2941 if (!is_inner_function && consume_cached_parse_data() && |
2953 !cached_parse_data_->rejected()) { | 2942 !cached_parse_data_->rejected()) { |
2954 // If we have cached data, we use it to skip parsing the function body. The | 2943 // If we have cached data, we use it to skip parsing the function body. The |
2955 // data contains the information we need to construct the lazy function. | 2944 // data contains the information we need to construct the lazy function. |
2956 FunctionEntry entry = | 2945 FunctionEntry entry = |
2957 cached_parse_data_->GetFunctionEntry(function_block_pos); | 2946 cached_parse_data_->GetFunctionEntry(function_block_pos); |
2958 // Check that cached data is valid. If not, mark it as invalid (the embedder | 2947 // Check that cached data is valid. If not, mark it as invalid (the embedder |
2959 // handles it). Note that end position greater than end of stream is safe, | 2948 // handles it). Note that end position greater than end of stream is safe, |
2960 // and hard to check. | 2949 // and hard to check. |
(...skipping 12 matching lines...) Expand all Loading... |
2973 } | 2962 } |
2974 cached_parse_data_->Reject(); | 2963 cached_parse_data_->Reject(); |
2975 } | 2964 } |
2976 // With no cached data, we partially parse the function, without building an | 2965 // With no cached data, we partially parse the function, without building an |
2977 // AST. This gathers the data needed to build a lazy function. | 2966 // AST. This gathers the data needed to build a lazy function. |
2978 SingletonLogger logger; | 2967 SingletonLogger logger; |
2979 PreParser::PreParseResult result = | 2968 PreParser::PreParseResult result = |
2980 ParseLazyFunctionBodyWithPreParser(&logger, is_inner_function, may_abort); | 2969 ParseLazyFunctionBodyWithPreParser(&logger, is_inner_function, may_abort); |
2981 | 2970 |
2982 // Return immediately if pre-parser decided to abort parsing. | 2971 // Return immediately if pre-parser decided to abort parsing. |
2983 if (result == PreParser::kPreParseAbort) { | 2972 if (result == PreParser::kPreParseAbort) return kLazyParsingAborted; |
2984 scope->set_is_lazily_parsed(false); | |
2985 return kLazyParsingAborted; | |
2986 } | |
2987 if (result == PreParser::kPreParseStackOverflow) { | 2973 if (result == PreParser::kPreParseStackOverflow) { |
2988 // Propagate stack overflow. | 2974 // Propagate stack overflow. |
2989 set_stack_overflow(); | 2975 set_stack_overflow(); |
2990 *ok = false; | 2976 *ok = false; |
2991 return kLazyParsingComplete; | 2977 return kLazyParsingComplete; |
2992 } | 2978 } |
2993 if (logger.has_error()) { | 2979 if (logger.has_error()) { |
2994 ReportMessageAt(Scanner::Location(logger.start(), logger.end()), | 2980 ReportMessageAt(Scanner::Location(logger.start(), logger.end()), |
2995 logger.message(), logger.argument_opt(), | 2981 logger.message(), logger.argument_opt(), |
2996 logger.error_type()); | 2982 logger.error_type()); |
(...skipping 480 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3477 #undef SET_ALLOW | 3463 #undef SET_ALLOW |
3478 } | 3464 } |
3479 // Aborting inner function preparsing would leave scopes in an inconsistent | 3465 // Aborting inner function preparsing would leave scopes in an inconsistent |
3480 // state; we don't parse inner functions in the abortable mode anyway. | 3466 // state; we don't parse inner functions in the abortable mode anyway. |
3481 DCHECK(!is_inner_function || !may_abort); | 3467 DCHECK(!is_inner_function || !may_abort); |
3482 | 3468 |
3483 DeclarationScope* function_scope = function_state_->scope(); | 3469 DeclarationScope* function_scope = function_state_->scope(); |
3484 PreParser::PreParseResult result = reusable_preparser_->PreParseLazyFunction( | 3470 PreParser::PreParseResult result = reusable_preparser_->PreParseLazyFunction( |
3485 function_scope, parsing_module_, logger, is_inner_function, may_abort, | 3471 function_scope, parsing_module_, logger, is_inner_function, may_abort, |
3486 use_counts_); | 3472 use_counts_); |
3487 // Detaching the scopes created by PreParser from the Scope chain must be done | |
3488 // above (see ParseFunctionLiteral & AnalyzePartially). | |
3489 if (!is_inner_function) { | |
3490 function_scope->ResetAfterPreparsing(result == PreParser::kPreParseAbort); | |
3491 } | |
3492 if (pre_parse_timer_ != NULL) { | 3473 if (pre_parse_timer_ != NULL) { |
3493 pre_parse_timer_->Stop(); | 3474 pre_parse_timer_->Stop(); |
3494 } | 3475 } |
3495 return result; | 3476 return result; |
3496 } | 3477 } |
3497 | 3478 |
3498 Expression* Parser::InstallHomeObject(Expression* function_literal, | 3479 Expression* Parser::InstallHomeObject(Expression* function_literal, |
3499 Expression* home_object) { | 3480 Expression* home_object) { |
3500 Block* do_block = factory()->NewBlock(nullptr, 1, false, kNoSourcePosition); | 3481 Block* do_block = factory()->NewBlock(nullptr, 1, false, kNoSourcePosition); |
3501 Variable* result_var = | 3482 Variable* result_var = |
(...skipping 126 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3628 MessageTemplate::kUnexpectedStrictReserved); | 3609 MessageTemplate::kUnexpectedStrictReserved); |
3629 *ok = false; | 3610 *ok = false; |
3630 return nullptr; | 3611 return nullptr; |
3631 } | 3612 } |
3632 if (IsEvalOrArguments(name)) { | 3613 if (IsEvalOrArguments(name)) { |
3633 ReportMessageAt(class_name_location, MessageTemplate::kStrictEvalArguments); | 3614 ReportMessageAt(class_name_location, MessageTemplate::kStrictEvalArguments); |
3634 *ok = false; | 3615 *ok = false; |
3635 return nullptr; | 3616 return nullptr; |
3636 } | 3617 } |
3637 | 3618 |
3638 BlockState block_state(&scope_state_); | 3619 BlockState block_state(zone(), &scope_state_); |
3639 RaiseLanguageMode(STRICT); | 3620 RaiseLanguageMode(STRICT); |
3640 #ifdef DEBUG | 3621 #ifdef DEBUG |
3641 scope()->SetScopeName(name); | 3622 scope()->SetScopeName(name); |
3642 #endif | 3623 #endif |
3643 | 3624 |
3644 VariableProxy* proxy = nullptr; | 3625 VariableProxy* proxy = nullptr; |
3645 if (name != nullptr) { | 3626 if (name != nullptr) { |
3646 proxy = factory()->NewVariableProxy(name, NORMAL_VARIABLE); | 3627 proxy = factory()->NewVariableProxy(name, NORMAL_VARIABLE); |
3647 // TODO(verwaest): declare via block_state. | 3628 // TODO(verwaest): declare via block_state. |
3648 Declaration* declaration = | 3629 Declaration* declaration = |
(...skipping 1956 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5605 | 5586 |
5606 return final_loop; | 5587 return final_loop; |
5607 } | 5588 } |
5608 | 5589 |
5609 #undef CHECK_OK | 5590 #undef CHECK_OK |
5610 #undef CHECK_OK_VOID | 5591 #undef CHECK_OK_VOID |
5611 #undef CHECK_FAILED | 5592 #undef CHECK_FAILED |
5612 | 5593 |
5613 } // namespace internal | 5594 } // namespace internal |
5614 } // namespace v8 | 5595 } // namespace v8 |
OLD | NEW |