Chromium Code Reviews| 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 2501 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 |
| OLD | NEW |