Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(462)

Side by Side Diff: src/parsing/parser.cc

Issue 2368313002: Don't use different function scopes when parsing with temp zones (Closed)
Patch Set: Make sure arguments_ is properly analyzed as well, since it's used as a signal for optimization Created 4 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/ast/scopes.cc ('k') | src/parsing/parser-base.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
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
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
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
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
OLDNEW
« no previous file with comments | « src/ast/scopes.cc ('k') | src/parsing/parser-base.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698