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 2668 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2679 // Inner functions will be parsed using a temporary Zone. After parsing, we | 2679 // Inner functions will be parsed using a temporary Zone. After parsing, we |
2680 // will migrate unresolved variable into a Scope in the main Zone. | 2680 // will migrate unresolved variable into a Scope in the main Zone. |
2681 // TODO(marja): Refactor parsing modes: simplify this. | 2681 // TODO(marja): Refactor parsing modes: simplify this. |
2682 bool use_temp_zone = | 2682 bool use_temp_zone = |
2683 !is_lazy_top_level_function && allow_lazy() && | 2683 !is_lazy_top_level_function && allow_lazy() && |
2684 function_type == FunctionLiteral::kDeclaration && | 2684 function_type == FunctionLiteral::kDeclaration && |
2685 eager_compile_hint != FunctionLiteral::kShouldEagerCompile && | 2685 eager_compile_hint != FunctionLiteral::kShouldEagerCompile && |
2686 !(FLAG_validate_asm && scope()->IsAsmModule()); | 2686 !(FLAG_validate_asm && scope()->IsAsmModule()); |
2687 bool is_lazy_inner_function = use_temp_zone && FLAG_lazy_inner_functions; | 2687 bool is_lazy_inner_function = use_temp_zone && FLAG_lazy_inner_functions; |
2688 | 2688 |
2689 DeclarationScope* main_scope = nullptr; | 2689 // This Scope lives in the main zone. We'll migrate data into that zone later. |
2690 if (use_temp_zone) { | 2690 DeclarationScope* scope = NewFunctionScope(kind); |
2691 // This Scope lives in the main Zone; we'll migrate data into it later. | 2691 SetLanguageMode(scope, language_mode); |
2692 main_scope = NewFunctionScope(kind); | |
2693 } | |
2694 | 2692 |
2695 ZoneList<Statement*>* body = nullptr; | 2693 ZoneList<Statement*>* body = nullptr; |
2696 int arity = -1; | 2694 int arity = -1; |
2697 int materialized_literal_count = -1; | 2695 int materialized_literal_count = -1; |
2698 int expected_property_count = -1; | 2696 int expected_property_count = -1; |
2699 DuplicateFinder duplicate_finder(scanner()->unicode_cache()); | 2697 DuplicateFinder duplicate_finder(scanner()->unicode_cache()); |
2700 bool should_be_used_once_hint = false; | 2698 bool should_be_used_once_hint = false; |
2701 bool has_duplicate_parameters; | 2699 bool has_duplicate_parameters; |
2702 | 2700 |
2703 { | 2701 { |
2704 // Temporary zones can nest. When we migrate free variables (see below), we | 2702 // Temporary zones can nest. When we migrate free variables (see below), we |
2705 // need to recreate them in the previous Zone. | 2703 // need to recreate them in the previous Zone. |
2706 AstNodeFactory previous_zone_ast_node_factory(ast_value_factory()); | 2704 AstNodeFactory previous_zone_ast_node_factory(ast_value_factory()); |
2707 previous_zone_ast_node_factory.set_zone(zone()); | 2705 previous_zone_ast_node_factory.set_zone(zone()); |
2708 | 2706 |
2709 // Open a new zone scope, which sets our AstNodeFactory to allocate in the | 2707 // Open a new zone scope, which sets our AstNodeFactory to allocate in the |
2710 // new temporary zone if the preconditions are satisfied, and ensures that | 2708 // new temporary zone if the preconditions are satisfied, and ensures that |
2711 // the previous zone is always restored after parsing the body. To be able | 2709 // the previous zone is always restored after parsing the body. To be able |
2712 // to do scope analysis correctly after full parsing, we migrate needed | 2710 // to do scope analysis correctly after full parsing, we migrate needed |
2713 // information from scope into main_scope when the function has been parsed. | 2711 // information when the function is parsed. |
2714 Zone temp_zone(zone()->allocator()); | 2712 Zone temp_zone(zone()->allocator()); |
2715 DiscardableZoneScope zone_scope(this, &temp_zone, use_temp_zone); | 2713 DiscardableZoneScope zone_scope(this, &temp_zone, use_temp_zone); |
2716 | 2714 |
2717 DeclarationScope* scope = NewFunctionScope(kind); | |
2718 SetLanguageMode(scope, language_mode); | |
2719 if (!use_temp_zone) { | |
2720 main_scope = scope; | |
2721 } else { | |
2722 DCHECK(main_scope->zone() != scope->zone()); | |
2723 } | |
2724 | |
2725 FunctionState function_state(&function_state_, &scope_state_, scope); | 2715 FunctionState function_state(&function_state_, &scope_state_, scope); |
2726 #ifdef DEBUG | 2716 #ifdef DEBUG |
2727 scope->SetScopeName(function_name); | 2717 scope->SetScopeName(function_name); |
| 2718 if (use_temp_zone) scope->set_needs_migration(); |
2728 #endif | 2719 #endif |
2729 ExpressionClassifier formals_classifier(this, &duplicate_finder); | 2720 ExpressionClassifier formals_classifier(this, &duplicate_finder); |
2730 | 2721 |
2731 if (is_generator) { | 2722 if (is_generator) { |
2732 // For generators, allocating variables in contexts is currently a win | 2723 // For generators, allocating variables in contexts is currently a win |
2733 // because it minimizes the work needed to suspend and resume an | 2724 // because it minimizes the work needed to suspend and resume an |
2734 // activation. The machine code produced for generators (by full-codegen) | 2725 // activation. The machine code produced for generators (by full-codegen) |
2735 // relies on this forced context allocation, but not in an essential way. | 2726 // relies on this forced context allocation, but not in an essential way. |
2736 this->scope()->ForceContextAllocation(); | 2727 this->scope()->ForceContextAllocation(); |
2737 | 2728 |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2779 DCHECK(is_lazy_top_level_function); | 2770 DCHECK(is_lazy_top_level_function); |
2780 bookmark.Apply(); | 2771 bookmark.Apply(); |
2781 // Trigger eager (re-)parsing, just below this block. | 2772 // Trigger eager (re-)parsing, just below this block. |
2782 is_lazy_top_level_function = false; | 2773 is_lazy_top_level_function = false; |
2783 | 2774 |
2784 // This is probably an initialization function. Inform the compiler it | 2775 // This is probably an initialization function. Inform the compiler it |
2785 // should also eager-compile this function, and that we expect it to be | 2776 // should also eager-compile this function, and that we expect it to be |
2786 // used once. | 2777 // used once. |
2787 eager_compile_hint = FunctionLiteral::kShouldEagerCompile; | 2778 eager_compile_hint = FunctionLiteral::kShouldEagerCompile; |
2788 should_be_used_once_hint = true; | 2779 should_be_used_once_hint = true; |
2789 } else if (is_lazy_inner_function) { | 2780 scope->ResetAfterPreparsing(true); |
2790 DCHECK(main_scope != scope); | |
2791 scope->AnalyzePartially(main_scope, &previous_zone_ast_node_factory); | |
2792 } | 2781 } |
2793 } | 2782 } |
| 2783 |
2794 if (!is_lazy_top_level_function && !is_lazy_inner_function) { | 2784 if (!is_lazy_top_level_function && !is_lazy_inner_function) { |
2795 body = ParseEagerFunctionBody(function_name, pos, formals, kind, | 2785 body = ParseEagerFunctionBody(function_name, pos, formals, kind, |
2796 function_type, CHECK_OK); | 2786 function_type, CHECK_OK); |
2797 | 2787 |
2798 materialized_literal_count = function_state.materialized_literal_count(); | 2788 materialized_literal_count = function_state.materialized_literal_count(); |
2799 expected_property_count = function_state.expected_property_count(); | 2789 expected_property_count = function_state.expected_property_count(); |
2800 if (use_temp_zone) { | 2790 } |
2801 // If the preconditions are correct the function body should never be | 2791 |
2802 // accessed, but do this anyway for better behaviour if they're wrong. | 2792 if (use_temp_zone || is_lazy_top_level_function) { |
2803 body = nullptr; | 2793 // If the preconditions are correct the function body should never be |
2804 DCHECK(main_scope != scope); | 2794 // accessed, but do this anyway for better behaviour if they're wrong. |
2805 scope->AnalyzePartially(main_scope, &previous_zone_ast_node_factory); | 2795 body = nullptr; |
2806 } | 2796 scope->AnalyzePartially(&previous_zone_ast_node_factory); |
2807 } | 2797 } |
2808 | 2798 |
2809 // Parsing the body may change the language mode in our scope. | 2799 // Parsing the body may change the language mode in our scope. |
2810 language_mode = scope->language_mode(); | 2800 language_mode = scope->language_mode(); |
2811 | 2801 |
2812 // Validate name and parameter names. We can do this only after parsing the | 2802 // Validate name and parameter names. We can do this only after parsing the |
2813 // function, since the function can declare itself strict. | 2803 // function, since the function can declare itself strict. |
2814 CheckFunctionName(language_mode, function_name, function_name_validity, | 2804 CheckFunctionName(language_mode, function_name, function_name_validity, |
2815 function_name_location, CHECK_OK); | 2805 function_name_location, CHECK_OK); |
2816 const bool allow_duplicate_parameters = | 2806 const bool allow_duplicate_parameters = |
(...skipping 16 matching lines...) Expand all Loading... |
2833 has_duplicate_parameters = | 2823 has_duplicate_parameters = |
2834 !classifier()->is_valid_formal_parameter_list_without_duplicates(); | 2824 !classifier()->is_valid_formal_parameter_list_without_duplicates(); |
2835 } // DiscardableZoneScope goes out of scope. | 2825 } // DiscardableZoneScope goes out of scope. |
2836 | 2826 |
2837 FunctionLiteral::ParameterFlag duplicate_parameters = | 2827 FunctionLiteral::ParameterFlag duplicate_parameters = |
2838 has_duplicate_parameters ? FunctionLiteral::kHasDuplicateParameters | 2828 has_duplicate_parameters ? FunctionLiteral::kHasDuplicateParameters |
2839 : FunctionLiteral::kNoDuplicateParameters; | 2829 : FunctionLiteral::kNoDuplicateParameters; |
2840 | 2830 |
2841 // Note that the FunctionLiteral needs to be created in the main Zone again. | 2831 // Note that the FunctionLiteral needs to be created in the main Zone again. |
2842 FunctionLiteral* function_literal = factory()->NewFunctionLiteral( | 2832 FunctionLiteral* function_literal = factory()->NewFunctionLiteral( |
2843 function_name, main_scope, body, materialized_literal_count, | 2833 function_name, scope, body, materialized_literal_count, |
2844 expected_property_count, arity, duplicate_parameters, function_type, | 2834 expected_property_count, arity, duplicate_parameters, function_type, |
2845 eager_compile_hint, pos); | 2835 eager_compile_hint, pos); |
2846 function_literal->set_function_token_position(function_token_pos); | 2836 function_literal->set_function_token_position(function_token_pos); |
2847 if (should_be_used_once_hint) | 2837 if (should_be_used_once_hint) |
2848 function_literal->set_should_be_used_once_hint(); | 2838 function_literal->set_should_be_used_once_hint(); |
2849 | 2839 |
2850 if (should_infer_name) { | 2840 if (should_infer_name) { |
2851 DCHECK_NOT_NULL(fni_); | 2841 DCHECK_NOT_NULL(fni_); |
2852 fni_->AddFunction(function_literal); | 2842 fni_->AddFunction(function_literal); |
2853 } | 2843 } |
2854 return function_literal; | 2844 return function_literal; |
2855 } | 2845 } |
2856 | 2846 |
2857 Parser::LazyParsingResult Parser::SkipLazyFunctionBody( | 2847 Parser::LazyParsingResult Parser::SkipLazyFunctionBody( |
2858 int* materialized_literal_count, int* expected_property_count, | 2848 int* materialized_literal_count, int* expected_property_count, |
2859 bool is_inner_function, bool may_abort, bool* ok) { | 2849 bool is_inner_function, bool may_abort, bool* ok) { |
2860 if (produce_cached_parse_data()) CHECK(log_); | 2850 if (produce_cached_parse_data()) CHECK(log_); |
2861 | 2851 |
2862 int function_block_pos = position(); | 2852 int function_block_pos = position(); |
2863 DeclarationScope* scope = function_state_->scope(); | 2853 DeclarationScope* scope = function_state_->scope(); |
2864 DCHECK(scope->is_function_scope()); | 2854 DCHECK(scope->is_function_scope()); |
2865 scope->set_is_lazily_parsed(true); | |
2866 // Inner functions are not part of the cached data. | 2855 // Inner functions are not part of the cached data. |
2867 if (!is_inner_function && consume_cached_parse_data() && | 2856 if (!is_inner_function && consume_cached_parse_data() && |
2868 !cached_parse_data_->rejected()) { | 2857 !cached_parse_data_->rejected()) { |
2869 // If we have cached data, we use it to skip parsing the function body. The | 2858 // If we have cached data, we use it to skip parsing the function body. The |
2870 // data contains the information we need to construct the lazy function. | 2859 // data contains the information we need to construct the lazy function. |
2871 FunctionEntry entry = | 2860 FunctionEntry entry = |
2872 cached_parse_data_->GetFunctionEntry(function_block_pos); | 2861 cached_parse_data_->GetFunctionEntry(function_block_pos); |
2873 // Check that cached data is valid. If not, mark it as invalid (the embedder | 2862 // Check that cached data is valid. If not, mark it as invalid (the embedder |
2874 // handles it). Note that end position greater than end of stream is safe, | 2863 // handles it). Note that end position greater than end of stream is safe, |
2875 // and hard to check. | 2864 // and hard to check. |
(...skipping 12 matching lines...) Expand all Loading... |
2888 } | 2877 } |
2889 cached_parse_data_->Reject(); | 2878 cached_parse_data_->Reject(); |
2890 } | 2879 } |
2891 // With no cached data, we partially parse the function, without building an | 2880 // With no cached data, we partially parse the function, without building an |
2892 // AST. This gathers the data needed to build a lazy function. | 2881 // AST. This gathers the data needed to build a lazy function. |
2893 SingletonLogger logger; | 2882 SingletonLogger logger; |
2894 PreParser::PreParseResult result = | 2883 PreParser::PreParseResult result = |
2895 ParseLazyFunctionBodyWithPreParser(&logger, is_inner_function, may_abort); | 2884 ParseLazyFunctionBodyWithPreParser(&logger, is_inner_function, may_abort); |
2896 | 2885 |
2897 // Return immediately if pre-parser decided to abort parsing. | 2886 // Return immediately if pre-parser decided to abort parsing. |
2898 if (result == PreParser::kPreParseAbort) { | 2887 if (result == PreParser::kPreParseAbort) return kLazyParsingAborted; |
2899 scope->set_is_lazily_parsed(false); | |
2900 return kLazyParsingAborted; | |
2901 } | |
2902 if (result == PreParser::kPreParseStackOverflow) { | 2888 if (result == PreParser::kPreParseStackOverflow) { |
2903 // Propagate stack overflow. | 2889 // Propagate stack overflow. |
2904 set_stack_overflow(); | 2890 set_stack_overflow(); |
2905 *ok = false; | 2891 *ok = false; |
2906 return kLazyParsingComplete; | 2892 return kLazyParsingComplete; |
2907 } | 2893 } |
2908 if (logger.has_error()) { | 2894 if (logger.has_error()) { |
2909 ReportMessageAt(Scanner::Location(logger.start(), logger.end()), | 2895 ReportMessageAt(Scanner::Location(logger.start(), logger.end()), |
2910 logger.message(), logger.argument_opt(), | 2896 logger.message(), logger.argument_opt(), |
2911 logger.error_type()); | 2897 logger.error_type()); |
(...skipping 479 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3391 #undef SET_ALLOW | 3377 #undef SET_ALLOW |
3392 } | 3378 } |
3393 // Aborting inner function preparsing would leave scopes in an inconsistent | 3379 // Aborting inner function preparsing would leave scopes in an inconsistent |
3394 // state; we don't parse inner functions in the abortable mode anyway. | 3380 // state; we don't parse inner functions in the abortable mode anyway. |
3395 DCHECK(!is_inner_function || !may_abort); | 3381 DCHECK(!is_inner_function || !may_abort); |
3396 | 3382 |
3397 DeclarationScope* function_scope = function_state_->scope(); | 3383 DeclarationScope* function_scope = function_state_->scope(); |
3398 PreParser::PreParseResult result = reusable_preparser_->PreParseLazyFunction( | 3384 PreParser::PreParseResult result = reusable_preparser_->PreParseLazyFunction( |
3399 function_scope, parsing_module_, logger, is_inner_function, may_abort, | 3385 function_scope, parsing_module_, logger, is_inner_function, may_abort, |
3400 use_counts_); | 3386 use_counts_); |
3401 // Detaching the scopes created by PreParser from the Scope chain must be done | |
3402 // above (see ParseFunctionLiteral & AnalyzePartially). | |
3403 if (!is_inner_function) { | |
3404 function_scope->ResetAfterPreparsing(result == PreParser::kPreParseAbort); | |
3405 } | |
3406 if (pre_parse_timer_ != NULL) { | 3387 if (pre_parse_timer_ != NULL) { |
3407 pre_parse_timer_->Stop(); | 3388 pre_parse_timer_->Stop(); |
3408 } | 3389 } |
3409 return result; | 3390 return result; |
3410 } | 3391 } |
3411 | 3392 |
3412 Expression* Parser::InstallHomeObject(Expression* function_literal, | 3393 Expression* Parser::InstallHomeObject(Expression* function_literal, |
3413 Expression* home_object) { | 3394 Expression* home_object) { |
3414 Block* do_block = factory()->NewBlock(nullptr, 1, false, kNoSourcePosition); | 3395 Block* do_block = factory()->NewBlock(nullptr, 1, false, kNoSourcePosition); |
3415 Variable* result_var = | 3396 Variable* result_var = |
(...skipping 125 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3541 MessageTemplate::kUnexpectedStrictReserved); | 3522 MessageTemplate::kUnexpectedStrictReserved); |
3542 *ok = false; | 3523 *ok = false; |
3543 return nullptr; | 3524 return nullptr; |
3544 } | 3525 } |
3545 if (IsEvalOrArguments(name)) { | 3526 if (IsEvalOrArguments(name)) { |
3546 ReportMessageAt(class_name_location, MessageTemplate::kStrictEvalArguments); | 3527 ReportMessageAt(class_name_location, MessageTemplate::kStrictEvalArguments); |
3547 *ok = false; | 3528 *ok = false; |
3548 return nullptr; | 3529 return nullptr; |
3549 } | 3530 } |
3550 | 3531 |
3551 BlockState block_state(&scope_state_); | 3532 BlockState block_state(zone(), &scope_state_); |
3552 RaiseLanguageMode(STRICT); | 3533 RaiseLanguageMode(STRICT); |
3553 #ifdef DEBUG | 3534 #ifdef DEBUG |
3554 scope()->SetScopeName(name); | 3535 scope()->SetScopeName(name); |
3555 #endif | 3536 #endif |
3556 | 3537 |
3557 VariableProxy* proxy = nullptr; | 3538 VariableProxy* proxy = nullptr; |
3558 if (name != nullptr) { | 3539 if (name != nullptr) { |
3559 proxy = factory()->NewVariableProxy(name, NORMAL_VARIABLE); | 3540 proxy = factory()->NewVariableProxy(name, NORMAL_VARIABLE); |
3560 // TODO(verwaest): declare via block_state. | 3541 // TODO(verwaest): declare via block_state. |
3561 Declaration* declaration = | 3542 Declaration* declaration = |
(...skipping 1993 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5555 | 5536 |
5556 return final_loop; | 5537 return final_loop; |
5557 } | 5538 } |
5558 | 5539 |
5559 #undef CHECK_OK | 5540 #undef CHECK_OK |
5560 #undef CHECK_OK_VOID | 5541 #undef CHECK_OK_VOID |
5561 #undef CHECK_FAILED | 5542 #undef CHECK_FAILED |
5562 | 5543 |
5563 } // namespace internal | 5544 } // namespace internal |
5564 } // namespace v8 | 5545 } // namespace v8 |
OLD | NEW |