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