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

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

Issue 2411793003: Preparse lazy function parameters (Closed)
Patch Set: rebased Created 4 years, 1 month 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/parsing/parser.h ('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 2514 matching lines...) Expand 10 before | Expand all | Expand 10 after
2525 // 2525 //
2526 // Getter :: 2526 // Getter ::
2527 // '(' ')' '{' FunctionBody '}' 2527 // '(' ')' '{' FunctionBody '}'
2528 // 2528 //
2529 // Setter :: 2529 // Setter ::
2530 // '(' PropertySetParameterList ')' '{' FunctionBody '}' 2530 // '(' PropertySetParameterList ')' '{' FunctionBody '}'
2531 2531
2532 int pos = function_token_pos == kNoSourcePosition ? peek_position() 2532 int pos = function_token_pos == kNoSourcePosition ? peek_position()
2533 : function_token_pos; 2533 : function_token_pos;
2534 2534
2535 bool is_generator = IsGeneratorFunction(kind);
2536
2537 // Anonymous functions were passed either the empty symbol or a null 2535 // Anonymous functions were passed either the empty symbol or a null
2538 // handle as the function name. Remember if we were passed a non-empty 2536 // handle as the function name. Remember if we were passed a non-empty
2539 // handle to decide whether to invoke function name inference. 2537 // handle to decide whether to invoke function name inference.
2540 bool should_infer_name = function_name == NULL; 2538 bool should_infer_name = function_name == NULL;
2541 2539
2542 // We want a non-null handle as the function name. 2540 // We want a non-null handle as the function name.
2543 if (should_infer_name) { 2541 if (should_infer_name) {
2544 function_name = ast_value_factory()->empty_string(); 2542 function_name = ast_value_factory()->empty_string();
2545 } 2543 }
2546 2544
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after
2616 : (is_lazy_top_level_function || 2614 : (is_lazy_top_level_function ||
2617 (allow_lazy() && function_type == FunctionLiteral::kDeclaration && 2615 (allow_lazy() && function_type == FunctionLiteral::kDeclaration &&
2618 eager_compile_hint == FunctionLiteral::kShouldLazyCompile))) && 2616 eager_compile_hint == FunctionLiteral::kShouldLazyCompile))) &&
2619 !(FLAG_validate_asm && scope()->IsAsmModule()); 2617 !(FLAG_validate_asm && scope()->IsAsmModule());
2620 bool is_lazy_inner_function = 2618 bool is_lazy_inner_function =
2621 use_temp_zone && FLAG_lazy_inner_functions && !is_lazy_top_level_function; 2619 use_temp_zone && FLAG_lazy_inner_functions && !is_lazy_top_level_function;
2622 2620
2623 // This Scope lives in the main zone. We'll migrate data into that zone later. 2621 // This Scope lives in the main zone. We'll migrate data into that zone later.
2624 DeclarationScope* scope = NewFunctionScope(kind); 2622 DeclarationScope* scope = NewFunctionScope(kind);
2625 SetLanguageMode(scope, language_mode); 2623 SetLanguageMode(scope, language_mode);
2624 #ifdef DEBUG
2625 scope->SetScopeName(function_name);
2626 #endif
2626 2627
2627 ZoneList<Statement*>* body = nullptr; 2628 ZoneList<Statement*>* body = nullptr;
2628 int materialized_literal_count = -1; 2629 int materialized_literal_count = -1;
2629 int expected_property_count = -1; 2630 int expected_property_count = -1;
2630 DuplicateFinder duplicate_finder(scanner()->unicode_cache());
2631 bool should_be_used_once_hint = false; 2631 bool should_be_used_once_hint = false;
2632 bool has_duplicate_parameters; 2632 int num_parameters = -1;
2633 2633 int function_length = -1;
2634 FunctionState function_state(&function_state_, &scope_state_, scope); 2634 bool has_duplicate_parameters = false;
2635 #ifdef DEBUG
2636 scope->SetScopeName(function_name);
2637 #endif
2638
2639 ExpressionClassifier formals_classifier(this, &duplicate_finder);
2640
2641 if (is_generator) PrepareGeneratorVariables(&function_state);
2642
2643 Expect(Token::LPAREN, CHECK_OK);
2644 int start_position = scanner()->location().beg_pos;
2645 this->scope()->set_start_position(start_position);
2646 ParserFormalParameters formals(scope);
2647 ParseFormalParameterList(&formals, CHECK_OK);
2648 Expect(Token::RPAREN, CHECK_OK);
2649 int formals_end_position = scanner()->location().end_pos;
2650
2651 CheckArityRestrictions(formals.arity, kind, formals.has_rest, start_position,
2652 formals_end_position, CHECK_OK);
2653 Expect(Token::LBRACE, CHECK_OK);
2654 2635
2655 { 2636 {
2656 // Temporary zones can nest. When we migrate free variables (see below), we 2637 // Temporary zones can nest. When we migrate free variables (see below), we
2657 // need to recreate them in the previous Zone. 2638 // need to recreate them in the previous Zone.
2658 AstNodeFactory previous_zone_ast_node_factory(ast_value_factory()); 2639 AstNodeFactory previous_zone_ast_node_factory(ast_value_factory());
2659 previous_zone_ast_node_factory.set_zone(zone()); 2640 previous_zone_ast_node_factory.set_zone(zone());
2660 2641
2661 // Open a new zone scope, which sets our AstNodeFactory to allocate in the 2642 // Open a new zone scope, which sets our AstNodeFactory to allocate in the
2662 // new temporary zone if the preconditions are satisfied, and ensures that 2643 // new temporary zone if the preconditions are satisfied, and ensures that
2663 // the previous zone is always restored after parsing the body. To be able 2644 // the previous zone is always restored after parsing the body. To be able
2664 // to do scope analysis correctly after full parsing, we migrate needed 2645 // to do scope analysis correctly after full parsing, we migrate needed
2665 // information when the function is parsed. 2646 // information when the function is parsed.
2666 Zone temp_zone(zone()->allocator(), ZONE_NAME); 2647 Zone temp_zone(zone()->allocator(), ZONE_NAME);
2667 DiscardableZoneScope zone_scope(this, &temp_zone, use_temp_zone); 2648 DiscardableZoneScope zone_scope(this, &temp_zone, use_temp_zone);
2668 #ifdef DEBUG 2649 #ifdef DEBUG
2669 if (use_temp_zone) scope->set_needs_migration(); 2650 if (use_temp_zone) scope->set_needs_migration();
2670 #endif 2651 #endif
2671 2652
2672 // Eager or lazy parse? If is_lazy_top_level_function, we'll parse 2653 // Eager or lazy parse? If is_lazy_top_level_function, we'll parse
2673 // lazily. We'll call SkipLazyFunctionBody, which may decide to abort lazy 2654 // lazily. We'll call SkipLazyFunction, which may decide to
2674 // parsing if it suspects that wasn't a good idea. If so (in which case the 2655 // abort lazy parsing if it suspects that wasn't a good idea. If so (in
2675 // parser is expected to have backtracked), or if we didn't try to lazy 2656 // which case the parser is expected to have backtracked), or if we didn't
2676 // parse in the first place, we'll have to parse eagerly. 2657 // try to lazy parse in the first place, we'll have to parse eagerly.
2677 if (is_lazy_top_level_function || is_lazy_inner_function) { 2658 if (is_lazy_top_level_function || is_lazy_inner_function) {
2678 Scanner::BookmarkScope bookmark(scanner()); 2659 Scanner::BookmarkScope bookmark(scanner());
2679 bookmark.Set(); 2660 bookmark.Set();
2680 LazyParsingResult result = SkipLazyFunctionBody( 2661 LazyParsingResult result = SkipLazyFunction(
2681 &materialized_literal_count, &expected_property_count, 2662 kind, scope, &num_parameters, &function_length,
2682 is_lazy_inner_function, is_lazy_top_level_function, CHECK_OK); 2663 &has_duplicate_parameters, &materialized_literal_count,
2683 2664 &expected_property_count, is_lazy_inner_function,
2684 materialized_literal_count += formals.materialized_literals_count + 2665 is_lazy_top_level_function, CHECK_OK);
2685 function_state.materialized_literal_count();
2686 2666
2687 if (result == kLazyParsingAborted) { 2667 if (result == kLazyParsingAborted) {
2688 DCHECK(is_lazy_top_level_function); 2668 DCHECK(is_lazy_top_level_function);
2689 bookmark.Apply(); 2669 bookmark.Apply();
2690 // Trigger eager (re-)parsing, just below this block. 2670 // Trigger eager (re-)parsing, just below this block.
2691 is_lazy_top_level_function = false; 2671 is_lazy_top_level_function = false;
2692 2672
2693 // This is probably an initialization function. Inform the compiler it 2673 // This is probably an initialization function. Inform the compiler it
2694 // should also eager-compile this function, and that we expect it to be 2674 // should also eager-compile this function, and that we expect it to be
2695 // used once. 2675 // used once.
2696 eager_compile_hint = FunctionLiteral::kShouldEagerCompile; 2676 eager_compile_hint = FunctionLiteral::kShouldEagerCompile;
2697 should_be_used_once_hint = true; 2677 should_be_used_once_hint = true;
2698 scope->ResetAfterPreparsing(ast_value_factory(), true); 2678 scope->ResetAfterPreparsing(ast_value_factory(), true);
2699 zone_scope.Reset(); 2679 zone_scope.Reset();
2700 use_temp_zone = false; 2680 use_temp_zone = false;
2701 } 2681 }
2702 } 2682 }
2703 2683
2704 if (!is_lazy_top_level_function && !is_lazy_inner_function) { 2684 if (!is_lazy_top_level_function && !is_lazy_inner_function) {
2705 body = ParseEagerFunctionBody(function_name, pos, formals, kind, 2685 body = ParseFunctionParametersAndBodyEagerly(
2706 function_type, CHECK_OK); 2686 function_name, pos, kind, function_type, scope, &num_parameters,
2707 2687 &function_length, &has_duplicate_parameters,
2708 materialized_literal_count = function_state.materialized_literal_count(); 2688 &materialized_literal_count, &expected_property_count, CHECK_OK);
2709 expected_property_count = function_state.expected_property_count();
2710 } 2689 }
2711 2690
2712 DCHECK(use_temp_zone || !is_lazy_top_level_function); 2691 DCHECK(use_temp_zone || !is_lazy_top_level_function);
2713 if (use_temp_zone) { 2692 if (use_temp_zone) {
2714 // If the preconditions are correct the function body should never be 2693 // If the preconditions are correct the function body should never be
2715 // accessed, but do this anyway for better behaviour if they're wrong. 2694 // accessed, but do this anyway for better behaviour if they're wrong.
2716 body = nullptr; 2695 body = nullptr;
2717 scope->AnalyzePartially(&previous_zone_ast_node_factory); 2696 scope->AnalyzePartially(&previous_zone_ast_node_factory);
2718 } 2697 }
2719 2698
2720 if (FLAG_trace_preparse) { 2699 if (FLAG_trace_preparse) {
2721 PrintF(" [%s]: %i-%i %.*s\n", 2700 PrintF(" [%s]: %i-%i %.*s\n",
2722 is_lazy_top_level_function 2701 is_lazy_top_level_function
2723 ? "Preparse no-resolution" 2702 ? "Preparse no-resolution"
2724 : (use_temp_zone ? "Preparse resolution" : "Full parse"), 2703 : (use_temp_zone ? "Preparse resolution" : "Full parse"),
2725 scope->start_position(), scope->end_position(), 2704 scope->start_position(), scope->end_position(),
2726 function_name->byte_length(), function_name->raw_data()); 2705 function_name->byte_length(), function_name->raw_data());
2727 } 2706 }
2728 2707
2729 // Parsing the body may change the language mode in our scope. 2708 // Validate function name. We can do this only after parsing the function,
2709 // since the function can declare itself strict.
2730 language_mode = scope->language_mode(); 2710 language_mode = scope->language_mode();
2731
2732 // Validate name and parameter names. We can do this only after parsing the
2733 // function, since the function can declare itself strict.
2734 CheckFunctionName(language_mode, function_name, function_name_validity, 2711 CheckFunctionName(language_mode, function_name, function_name_validity,
2735 function_name_location, CHECK_OK); 2712 function_name_location, CHECK_OK);
2736 const bool allow_duplicate_parameters =
2737 is_sloppy(language_mode) && formals.is_simple && !IsConciseMethod(kind);
2738 ValidateFormalParameters(language_mode, allow_duplicate_parameters,
2739 CHECK_OK);
2740 2713
2741 if (is_strict(language_mode)) { 2714 if (is_strict(language_mode)) {
2742 CheckStrictOctalLiteral(scope->start_position(), scope->end_position(), 2715 CheckStrictOctalLiteral(scope->start_position(), scope->end_position(),
2743 CHECK_OK); 2716 CHECK_OK);
2744 CheckDecimalLiteralWithLeadingZero(scope->start_position(), 2717 CheckDecimalLiteralWithLeadingZero(scope->start_position(),
2745 scope->end_position()); 2718 scope->end_position());
2746 } 2719 }
2747 CheckConflictingVarDeclarations(scope, CHECK_OK); 2720 CheckConflictingVarDeclarations(scope, CHECK_OK);
2748
2749 if (body) {
2750 // If body can be inspected, rewrite queued destructuring assignments
2751 RewriteDestructuringAssignments();
2752 }
2753 has_duplicate_parameters =
2754 !classifier()->is_valid_formal_parameter_list_without_duplicates();
2755 } // DiscardableZoneScope goes out of scope. 2721 } // DiscardableZoneScope goes out of scope.
2756 2722
2757 FunctionLiteral::ParameterFlag duplicate_parameters = 2723 FunctionLiteral::ParameterFlag duplicate_parameters =
2758 has_duplicate_parameters ? FunctionLiteral::kHasDuplicateParameters 2724 has_duplicate_parameters ? FunctionLiteral::kHasDuplicateParameters
2759 : FunctionLiteral::kNoDuplicateParameters; 2725 : FunctionLiteral::kNoDuplicateParameters;
2760 2726
2761 // Note that the FunctionLiteral needs to be created in the main Zone again. 2727 // Note that the FunctionLiteral needs to be created in the main Zone again.
2762 FunctionLiteral* function_literal = factory()->NewFunctionLiteral( 2728 FunctionLiteral* function_literal = factory()->NewFunctionLiteral(
2763 function_name, scope, body, materialized_literal_count, 2729 function_name, scope, body, materialized_literal_count,
2764 expected_property_count, formals.num_parameters(), 2730 expected_property_count, num_parameters, function_length,
2765 formals.function_length, duplicate_parameters, function_type, 2731 duplicate_parameters, function_type, eager_compile_hint, pos);
2766 eager_compile_hint, pos);
2767 function_literal->set_function_token_position(function_token_pos); 2732 function_literal->set_function_token_position(function_token_pos);
2768 if (should_be_used_once_hint) 2733 if (should_be_used_once_hint)
2769 function_literal->set_should_be_used_once_hint(); 2734 function_literal->set_should_be_used_once_hint();
2770 2735
2771 if (should_infer_name) { 2736 if (should_infer_name) {
2772 DCHECK_NOT_NULL(fni_); 2737 DCHECK_NOT_NULL(fni_);
2773 fni_->AddFunction(function_literal); 2738 fni_->AddFunction(function_literal);
2774 } 2739 }
2775 return function_literal; 2740 return function_literal;
2776 } 2741 }
2777 2742
2778 Parser::LazyParsingResult Parser::SkipLazyFunctionBody( 2743 Parser::LazyParsingResult Parser::SkipLazyFunction(
2744 FunctionKind kind, DeclarationScope* function_scope, int* num_parameters,
2745 int* function_length, bool* has_duplicate_parameters,
2779 int* materialized_literal_count, int* expected_property_count, 2746 int* materialized_literal_count, int* expected_property_count,
2780 bool is_inner_function, bool may_abort, bool* ok) { 2747 bool is_inner_function, bool may_abort, bool* ok) {
2781 if (produce_cached_parse_data()) CHECK(log_); 2748 if (produce_cached_parse_data()) CHECK(log_);
2782 2749
2783 int function_block_pos = position(); 2750 // For normal functions, this is the position just before the left paren
2784 DeclarationScope* scope = function_state_->scope(); 2751 // (assuming the function is syntactically correct - however, it might not be,
2785 DCHECK(scope->is_function_scope()); 2752 // so we cannot DCHECK for Token::LPAREN here). For arrow functions, this is
2753 // the position of the arrow.
2754 int cache_key_position = peek_position();
2755 DCHECK_IMPLIES((kind & FunctionKind::kArrowFunction) != 0,
2756 scanner()->current_token() == Token::ARROW);
2757
2786 // Inner functions are not part of the cached data. 2758 // Inner functions are not part of the cached data.
2787 if (!is_inner_function && consume_cached_parse_data() && 2759 if (!is_inner_function && consume_cached_parse_data() &&
2788 !cached_parse_data_->rejected()) { 2760 !cached_parse_data_->rejected()) {
2789 // If we have cached data, we use it to skip parsing the function body. The 2761 // If we have cached data, we use it to skip parsing the function. The data
2790 // data contains the information we need to construct the lazy function. 2762 // contains the information we need to construct the lazy function.
2791 FunctionEntry entry = 2763 FunctionEntry entry =
2792 cached_parse_data_->GetFunctionEntry(function_block_pos); 2764 cached_parse_data_->GetFunctionEntry(cache_key_position);
2793 // Check that cached data is valid. If not, mark it as invalid (the embedder 2765 // Check that cached data is valid. If not, mark it as invalid (the embedder
2794 // handles it). Note that end position greater than end of stream is safe, 2766 // handles it). Note that end position greater than end of stream is safe,
2795 // and hard to check. 2767 // and hard to check.
2796 if (entry.is_valid() && entry.end_pos() > function_block_pos) { 2768 if (entry.is_valid() && entry.end_pos() > cache_key_position) {
2797 scanner()->SeekForward(entry.end_pos() - 1); 2769 scanner()->SeekForward(entry.end_pos() - 1);
2798 2770 // We need the start position separately from the cache key, since for
2799 scope->set_end_position(entry.end_pos()); 2771 // arrow functions, the scope start position is at the lparen of the
2772 // parameter list, and we've already read past it.
2773 function_scope->set_start_position(entry.start_pos());
2774 function_scope->set_end_position(entry.end_pos());
2800 Expect(Token::RBRACE, CHECK_OK_VALUE(kLazyParsingComplete)); 2775 Expect(Token::RBRACE, CHECK_OK_VALUE(kLazyParsingComplete));
2801 total_preparse_skipped_ += scope->end_position() - function_block_pos; 2776 total_preparse_skipped_ +=
2777 function_scope->end_position() - function_scope->start_position();
2778 *num_parameters = entry.num_parameters();
2779 *function_length = entry.function_length();
2780 *has_duplicate_parameters = entry.has_duplicate_parameters();
2802 *materialized_literal_count = entry.literal_count(); 2781 *materialized_literal_count = entry.literal_count();
2803 *expected_property_count = entry.property_count(); 2782 *expected_property_count = entry.property_count();
2804 SetLanguageMode(scope, entry.language_mode()); 2783 SetLanguageMode(function_scope, entry.language_mode());
2805 if (entry.uses_super_property()) scope->RecordSuperPropertyUsage(); 2784 if (entry.uses_super_property())
2806 if (entry.calls_eval()) scope->RecordEvalCall(); 2785 function_scope->RecordSuperPropertyUsage();
2786 if (entry.calls_eval()) function_scope->RecordEvalCall();
2807 return kLazyParsingComplete; 2787 return kLazyParsingComplete;
2808 } 2788 }
2809 cached_parse_data_->Reject(); 2789 cached_parse_data_->Reject();
2810 } 2790 }
2811 // With no cached data, we partially parse the function, without building an 2791 // With no cached data, we partially parse the function, without building an
2812 // AST. This gathers the data needed to build a lazy function. 2792 // AST. This gathers the data needed to build a lazy function.
2813 SingletonLogger logger; 2793 SingletonLogger logger;
2814 PreParser::PreParseResult result = 2794 PreParser::PreParseResult result = ParseFunctionWithPreParser(
2815 ParseFunctionBodyWithPreParser(&logger, is_inner_function, may_abort); 2795 kind, function_scope, &logger, is_inner_function, may_abort);
2816 2796
2817 // Return immediately if pre-parser decided to abort parsing. 2797 // Return immediately if pre-parser decided to abort parsing.
2818 if (result == PreParser::kPreParseAbort) return kLazyParsingAborted; 2798 if (result == PreParser::kPreParseAbort) return kLazyParsingAborted;
2819 if (result == PreParser::kPreParseStackOverflow) { 2799 if (result == PreParser::kPreParseStackOverflow) {
2820 // Propagate stack overflow. 2800 // Propagate stack overflow.
2821 set_stack_overflow(); 2801 set_stack_overflow();
2822 *ok = false; 2802 *ok = false;
2823 return kLazyParsingComplete; 2803 return kLazyParsingComplete;
2824 } 2804 }
2825 if (logger.has_error()) { 2805 if (logger.has_error()) {
2826 ReportMessageAt(Scanner::Location(logger.start(), logger.end()), 2806 ReportMessageAt(Scanner::Location(logger.start(), logger.end()),
2827 logger.message(), logger.argument_opt(), 2807 logger.message(), logger.argument_opt(),
2828 logger.error_type()); 2808 logger.error_type());
2829 *ok = false; 2809 *ok = false;
2830 return kLazyParsingComplete; 2810 return kLazyParsingComplete;
2831 } 2811 }
2832 scope->set_end_position(logger.end()); 2812 DCHECK_NE(kNoSourcePosition, function_scope->start_position());
2813 function_scope->set_end_position(logger.end());
2833 Expect(Token::RBRACE, CHECK_OK_VALUE(kLazyParsingComplete)); 2814 Expect(Token::RBRACE, CHECK_OK_VALUE(kLazyParsingComplete));
2834 total_preparse_skipped_ += scope->end_position() - function_block_pos; 2815 total_preparse_skipped_ +=
2816 function_scope->end_position() - function_scope->start_position();
2817 *num_parameters = logger.num_parameters();
2818 *function_length = logger.function_length();
2819 *has_duplicate_parameters = logger.has_duplicate_parameters();
2835 *materialized_literal_count = logger.literals(); 2820 *materialized_literal_count = logger.literals();
2836 *expected_property_count = logger.properties(); 2821 *expected_property_count = logger.properties();
2837 SetLanguageMode(scope, logger.language_mode()); 2822 SetLanguageMode(function_scope, logger.language_mode());
2838 if (logger.uses_super_property()) scope->RecordSuperPropertyUsage(); 2823 if (logger.uses_super_property()) function_scope->RecordSuperPropertyUsage();
2839 if (logger.calls_eval()) scope->RecordEvalCall(); 2824 if (logger.calls_eval()) function_scope->RecordEvalCall();
2840 if (!is_inner_function && produce_cached_parse_data()) { 2825 if (!is_inner_function && produce_cached_parse_data()) {
2841 DCHECK(log_); 2826 DCHECK(log_);
2842 // Position right after terminal '}'. 2827 log_->LogFunction(cache_key_position, function_scope->start_position(),
2843 int body_end = scanner()->location().end_pos; 2828 function_scope->end_position(), *num_parameters,
2844 log_->LogFunction(function_block_pos, body_end, *materialized_literal_count, 2829 *function_length, *has_duplicate_parameters,
2845 *expected_property_count, language_mode(), 2830 *materialized_literal_count, *expected_property_count,
2846 scope->uses_super_property(), scope->calls_eval()); 2831 language_mode(), function_scope->uses_super_property(),
2832 function_scope->calls_eval());
2847 } 2833 }
2848 return kLazyParsingComplete; 2834 return kLazyParsingComplete;
2849 } 2835 }
2850 2836
2851 2837
2852 Statement* Parser::BuildAssertIsCoercible(Variable* var) { 2838 Statement* Parser::BuildAssertIsCoercible(Variable* var) {
2853 // if (var === null || var === undefined) 2839 // if (var === null || var === undefined)
2854 // throw /* type error kNonCoercible) */; 2840 // throw /* type error kNonCoercible) */;
2855 2841
2856 Expression* condition = factory()->NewBinaryOperation( 2842 Expression* condition = factory()->NewBinaryOperation(
(...skipping 252 matching lines...) Expand 10 before | Expand all | Expand 10 after
3109 Token::INIT, init_proxy, allocation, kNoSourcePosition); 3095 Token::INIT, init_proxy, allocation, kNoSourcePosition);
3110 VariableProxy* get_proxy = 3096 VariableProxy* get_proxy =
3111 factory()->NewVariableProxy(function_state_->generator_object_variable()); 3097 factory()->NewVariableProxy(function_state_->generator_object_variable());
3112 // The position of the yield is important for reporting the exception 3098 // The position of the yield is important for reporting the exception
3113 // caused by calling the .throw method on a generator suspended at the 3099 // caused by calling the .throw method on a generator suspended at the
3114 // initial yield (i.e. right after generator instantiation). 3100 // initial yield (i.e. right after generator instantiation).
3115 return factory()->NewYield(get_proxy, assignment, scope()->start_position(), 3101 return factory()->NewYield(get_proxy, assignment, scope()->start_position(),
3116 Yield::kOnExceptionThrow); 3102 Yield::kOnExceptionThrow);
3117 } 3103 }
3118 3104
3105 ZoneList<Statement*>* Parser::ParseFunctionParametersAndBodyEagerly(
3106 const AstRawString* function_name, int pos, FunctionKind kind,
3107 FunctionLiteral::FunctionType function_type,
3108 DeclarationScope* function_scope, int* num_parameters, int* function_length,
3109 bool* has_duplicate_parameters, int* materialized_literal_count,
3110 int* expected_property_count, bool* ok) {
3111 FunctionState function_state(&function_state_, &scope_state_, function_scope);
3112
3113 DuplicateFinder duplicate_finder(scanner()->unicode_cache());
3114 ExpressionClassifier formals_classifier(this, &duplicate_finder);
3115
3116 if (IsGeneratorFunction(kind)) PrepareGeneratorVariables(&function_state);
3117
3118 Expect(Token::LPAREN, CHECK_OK);
3119 int start_position = scanner()->location().beg_pos;
3120 function_scope->set_start_position(start_position);
3121 ParserFormalParameters formals(function_scope);
3122 ParseFormalParameterList(&formals, CHECK_OK);
3123 Expect(Token::RPAREN, CHECK_OK);
3124 int formals_end_position = scanner()->location().end_pos;
3125 *num_parameters = formals.num_parameters();
3126 *function_length = formals.function_length;
3127
3128 CheckArityRestrictions(formals.arity, kind, formals.has_rest, start_position,
3129 formals_end_position, CHECK_OK);
3130 Expect(Token::LBRACE, CHECK_OK);
3131
3132 ZoneList<Statement*>* body = ParseEagerFunctionBody(
3133 function_name, pos, formals, kind, function_type, ok);
3134
3135 // Validate parameter names. We can do this only after parsing the function,
3136 // since the function can declare itself strict.
3137 const bool allow_duplicate_parameters =
3138 is_sloppy(function_scope->language_mode()) && formals.is_simple &&
3139 !IsConciseMethod(kind);
3140 ValidateFormalParameters(function_scope->language_mode(),
3141 allow_duplicate_parameters, CHECK_OK);
3142
3143 RewriteDestructuringAssignments();
3144
3145 *has_duplicate_parameters =
3146 !classifier()->is_valid_formal_parameter_list_without_duplicates();
3147
3148 *materialized_literal_count = function_state.materialized_literal_count();
3149 *expected_property_count = function_state.expected_property_count();
3150 return body;
3151 }
3152
3119 ZoneList<Statement*>* Parser::ParseEagerFunctionBody( 3153 ZoneList<Statement*>* Parser::ParseEagerFunctionBody(
3120 const AstRawString* function_name, int pos, 3154 const AstRawString* function_name, int pos,
3121 const ParserFormalParameters& parameters, FunctionKind kind, 3155 const ParserFormalParameters& parameters, FunctionKind kind,
3122 FunctionLiteral::FunctionType function_type, bool* ok) { 3156 FunctionLiteral::FunctionType function_type, bool* ok) {
3123 ParsingModeScope mode(this, allow_lazy() ? PARSE_LAZILY : PARSE_EAGERLY); 3157 ParsingModeScope mode(this, allow_lazy() ? PARSE_LAZILY : PARSE_EAGERLY);
3124 ZoneList<Statement*>* result = new(zone()) ZoneList<Statement*>(8, zone()); 3158 ZoneList<Statement*>* result = new(zone()) ZoneList<Statement*>(8, zone());
3125 3159
3126 static const int kFunctionNameAssignmentIndex = 0; 3160 static const int kFunctionNameAssignmentIndex = 0;
3127 if (function_type == FunctionLiteral::kNamedExpression) { 3161 if (function_type == FunctionLiteral::kNamedExpression) {
3128 DCHECK(function_name != NULL); 3162 DCHECK(function_name != NULL);
(...skipping 136 matching lines...) Expand 10 before | Expand all | Expand 10 after
3265 } else { 3299 } else {
3266 statement = factory()->NewEmptyStatement(kNoSourcePosition); 3300 statement = factory()->NewEmptyStatement(kNoSourcePosition);
3267 } 3301 }
3268 result->Set(kFunctionNameAssignmentIndex, statement); 3302 result->Set(kFunctionNameAssignmentIndex, statement);
3269 } 3303 }
3270 3304
3271 MarkCollectedTailCallExpressions(); 3305 MarkCollectedTailCallExpressions();
3272 return result; 3306 return result;
3273 } 3307 }
3274 3308
3275 PreParser::PreParseResult Parser::ParseFunctionBodyWithPreParser( 3309 PreParser::PreParseResult Parser::ParseFunctionWithPreParser(
3310 FunctionKind kind, DeclarationScope* function_scope,
3276 SingletonLogger* logger, bool is_inner_function, bool may_abort) { 3311 SingletonLogger* logger, bool is_inner_function, bool may_abort) {
3277 // This function may be called on a background thread too; record only the 3312 // This function may be called on a background thread too; record only the
3278 // main thread preparse times. 3313 // main thread preparse times.
3279 if (pre_parse_timer_ != NULL) { 3314 if (pre_parse_timer_ != NULL) {
3280 pre_parse_timer_->Start(); 3315 pre_parse_timer_->Start();
3281 } 3316 }
3282 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8.compile"), "V8.PreParse"); 3317 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8.compile"), "V8.PreParse");
3283 3318
3284 DCHECK_EQ(Token::LBRACE, scanner()->current_token());
3285
3286 if (reusable_preparser_ == NULL) { 3319 if (reusable_preparser_ == NULL) {
3287 reusable_preparser_ = new PreParser(zone(), &scanner_, ast_value_factory(), 3320 reusable_preparser_ = new PreParser(zone(), &scanner_, ast_value_factory(),
3288 NULL, stack_limit_); 3321 NULL, stack_limit_);
3289 reusable_preparser_->set_allow_lazy(true); 3322 reusable_preparser_->set_allow_lazy(true);
3290 #define SET_ALLOW(name) reusable_preparser_->set_allow_##name(allow_##name()); 3323 #define SET_ALLOW(name) reusable_preparser_->set_allow_##name(allow_##name());
3291 SET_ALLOW(natives); 3324 SET_ALLOW(natives);
3292 SET_ALLOW(harmony_do_expressions); 3325 SET_ALLOW(harmony_do_expressions);
3293 SET_ALLOW(harmony_function_sent); 3326 SET_ALLOW(harmony_function_sent);
3294 SET_ALLOW(harmony_restrictive_declarations); 3327 SET_ALLOW(harmony_restrictive_declarations);
3295 SET_ALLOW(harmony_async_await); 3328 SET_ALLOW(harmony_async_await);
3296 SET_ALLOW(harmony_trailing_commas); 3329 SET_ALLOW(harmony_trailing_commas);
3297 SET_ALLOW(harmony_class_fields); 3330 SET_ALLOW(harmony_class_fields);
3298 #undef SET_ALLOW 3331 #undef SET_ALLOW
3299 } 3332 }
3300 // Aborting inner function preparsing would leave scopes in an inconsistent 3333 // Aborting inner function preparsing would leave scopes in an inconsistent
3301 // state; we don't parse inner functions in the abortable mode anyway. 3334 // state; we don't parse inner functions in the abortable mode anyway.
3302 DCHECK(!is_inner_function || !may_abort); 3335 DCHECK(!is_inner_function || !may_abort);
3303 3336
3304 DeclarationScope* function_scope = function_state_->scope();
3305 PreParser::PreParseResult result = reusable_preparser_->PreParseFunction( 3337 PreParser::PreParseResult result = reusable_preparser_->PreParseFunction(
3306 function_scope, parsing_module_, logger, is_inner_function, may_abort, 3338 kind, function_scope, parsing_module_, logger, is_inner_function,
3307 use_counts_); 3339 may_abort, use_counts_);
3308 if (pre_parse_timer_ != NULL) { 3340 if (pre_parse_timer_ != NULL) {
3309 pre_parse_timer_->Stop(); 3341 pre_parse_timer_->Stop();
3310 } 3342 }
3311 return result; 3343 return result;
3312 } 3344 }
3313 3345
3314 Expression* Parser::InstallHomeObject(Expression* function_literal, 3346 Expression* Parser::InstallHomeObject(Expression* function_literal,
3315 Expression* home_object) { 3347 Expression* home_object) {
3316 Block* do_block = factory()->NewBlock(nullptr, 1, false, kNoSourcePosition); 3348 Block* do_block = factory()->NewBlock(nullptr, 1, false, kNoSourcePosition);
3317 Variable* result_var = 3349 Variable* result_var =
(...skipping 2103 matching lines...) Expand 10 before | Expand all | Expand 10 after
5421 5453
5422 return final_loop; 5454 return final_loop;
5423 } 5455 }
5424 5456
5425 #undef CHECK_OK 5457 #undef CHECK_OK
5426 #undef CHECK_OK_VOID 5458 #undef CHECK_OK_VOID
5427 #undef CHECK_FAILED 5459 #undef CHECK_FAILED
5428 5460
5429 } // namespace internal 5461 } // namespace internal
5430 } // namespace v8 5462 } // namespace v8
OLDNEW
« no previous file with comments | « src/parsing/parser.h ('k') | src/parsing/parser-base.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698