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

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

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

Powered by Google App Engine
This is Rietveld 408576698