| 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 94 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 105 | 105 |
| 106 // Helper for putting parts of the parse results into a temporary zone when | 106 // Helper for putting parts of the parse results into a temporary zone when |
| 107 // parsing inner function bodies. | 107 // parsing inner function bodies. |
| 108 class DiscardableZoneScope { | 108 class DiscardableZoneScope { |
| 109 public: | 109 public: |
| 110 DiscardableZoneScope(Parser* parser, Zone* temp_zone, bool use_temp_zone) | 110 DiscardableZoneScope(Parser* parser, Zone* temp_zone, bool use_temp_zone) |
| 111 : ast_node_factory_scope_(parser->factory(), temp_zone, use_temp_zone), | 111 : ast_node_factory_scope_(parser->factory(), temp_zone, use_temp_zone), |
| 112 fni_(parser->ast_value_factory_, temp_zone), | 112 fni_(parser->ast_value_factory_, temp_zone), |
| 113 parser_(parser), | 113 parser_(parser), |
| 114 prev_fni_(parser->fni_), | 114 prev_fni_(parser->fni_), |
| 115 prev_zone_(parser->zone_) { | 115 prev_zone_(parser->zone_), |
| 116 prev_allow_lazy_(parser->allow_lazy_), |
| 117 prev_temp_zoned_(parser->temp_zoned_) { |
| 116 if (use_temp_zone) { | 118 if (use_temp_zone) { |
| 119 DCHECK(!parser_->temp_zoned_); |
| 120 parser_->allow_lazy_ = false; |
| 121 parser_->temp_zoned_ = true; |
| 117 parser_->fni_ = &fni_; | 122 parser_->fni_ = &fni_; |
| 118 parser_->zone_ = temp_zone; | 123 parser_->zone_ = temp_zone; |
| 119 if (parser_->reusable_preparser_ != nullptr) { | 124 if (parser_->reusable_preparser_ != nullptr) { |
| 120 parser_->reusable_preparser_->zone_ = temp_zone; | 125 parser_->reusable_preparser_->zone_ = temp_zone; |
| 121 parser_->reusable_preparser_->factory()->set_zone(temp_zone); | 126 parser_->reusable_preparser_->factory()->set_zone(temp_zone); |
| 122 } | 127 } |
| 123 } | 128 } |
| 124 } | 129 } |
| 125 void Reset() { | 130 void Reset() { |
| 126 parser_->fni_ = prev_fni_; | 131 parser_->fni_ = prev_fni_; |
| 127 parser_->zone_ = prev_zone_; | 132 parser_->zone_ = prev_zone_; |
| 133 parser_->allow_lazy_ = prev_allow_lazy_; |
| 134 parser_->temp_zoned_ = prev_temp_zoned_; |
| 128 if (parser_->reusable_preparser_ != nullptr) { | 135 if (parser_->reusable_preparser_ != nullptr) { |
| 129 parser_->reusable_preparser_->zone_ = prev_zone_; | 136 parser_->reusable_preparser_->zone_ = prev_zone_; |
| 130 parser_->reusable_preparser_->factory()->set_zone(prev_zone_); | 137 parser_->reusable_preparser_->factory()->set_zone(prev_zone_); |
| 131 } | 138 } |
| 132 ast_node_factory_scope_.Reset(); | 139 ast_node_factory_scope_.Reset(); |
| 133 } | 140 } |
| 134 ~DiscardableZoneScope() { Reset(); } | 141 ~DiscardableZoneScope() { Reset(); } |
| 135 | 142 |
| 136 private: | 143 private: |
| 137 AstNodeFactory::BodyScope ast_node_factory_scope_; | 144 AstNodeFactory::BodyScope ast_node_factory_scope_; |
| 138 FuncNameInferrer fni_; | 145 FuncNameInferrer fni_; |
| 139 Parser* parser_; | 146 Parser* parser_; |
| 140 FuncNameInferrer* prev_fni_; | 147 FuncNameInferrer* prev_fni_; |
| 141 Zone* prev_zone_; | 148 Zone* prev_zone_; |
| 149 bool prev_allow_lazy_; |
| 150 bool prev_temp_zoned_; |
| 142 | 151 |
| 143 DISALLOW_COPY_AND_ASSIGN(DiscardableZoneScope); | 152 DISALLOW_COPY_AND_ASSIGN(DiscardableZoneScope); |
| 144 }; | 153 }; |
| 145 | 154 |
| 146 void Parser::SetCachedData(ParseInfo* info) { | 155 void Parser::SetCachedData(ParseInfo* info) { |
| 147 DCHECK_NULL(cached_parse_data_); | 156 DCHECK_NULL(cached_parse_data_); |
| 148 if (consume_cached_parse_data()) { | 157 if (consume_cached_parse_data()) { |
| 149 cached_parse_data_ = ParseData::FromCachedData(*info->cached_data()); | 158 if (allow_lazy_) { |
| 150 if (cached_parse_data_ == nullptr) { | 159 cached_parse_data_ = ParseData::FromCachedData(*info->cached_data()); |
| 151 compile_options_ = ScriptCompiler::kNoCompileOptions; | 160 if (cached_parse_data_ != nullptr) return; |
| 152 } | 161 } |
| 162 compile_options_ = ScriptCompiler::kNoCompileOptions; |
| 153 } | 163 } |
| 154 } | 164 } |
| 155 | 165 |
| 156 Expression* Parser::CallClassFieldInitializer(Scope* scope, | 166 Expression* Parser::CallClassFieldInitializer(Scope* scope, |
| 157 Expression* this_expr) { | 167 Expression* this_expr) { |
| 158 // This produces the expression | 168 // This produces the expression |
| 159 // `.class_field_intializer(this_expr)`, where '.class_field_intializer' is | 169 // `.class_field_intializer(this_expr)`, where '.class_field_intializer' is |
| 160 // the name | 170 // the name |
| 161 // of a synthetic variable. | 171 // of a synthetic variable. |
| 162 // 'this_expr' will be 'this' in a base constructor and the result of calling | 172 // 'this_expr' will be 'this' in a base constructor and the result of calling |
| (...skipping 422 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 585 info->isolate()->counters()->runtime_call_stats(), | 595 info->isolate()->counters()->runtime_call_stats(), |
| 586 true), | 596 true), |
| 587 scanner_(info->unicode_cache()), | 597 scanner_(info->unicode_cache()), |
| 588 reusable_preparser_(nullptr), | 598 reusable_preparser_(nullptr), |
| 589 original_scope_(nullptr), | 599 original_scope_(nullptr), |
| 590 mode_(PARSE_EAGERLY), // Lazy mode must be set explicitly. | 600 mode_(PARSE_EAGERLY), // Lazy mode must be set explicitly. |
| 591 target_stack_(nullptr), | 601 target_stack_(nullptr), |
| 592 compile_options_(info->compile_options()), | 602 compile_options_(info->compile_options()), |
| 593 cached_parse_data_(nullptr), | 603 cached_parse_data_(nullptr), |
| 594 total_preparse_skipped_(0), | 604 total_preparse_skipped_(0), |
| 605 temp_zoned_(false), |
| 595 log_(nullptr) { | 606 log_(nullptr) { |
| 596 // Even though we were passed ParseInfo, we should not store it in | 607 // Even though we were passed ParseInfo, we should not store it in |
| 597 // Parser - this makes sure that Isolate is not accidentally accessed via | 608 // Parser - this makes sure that Isolate is not accidentally accessed via |
| 598 // ParseInfo during background parsing. | 609 // ParseInfo during background parsing. |
| 599 DCHECK(!info->script().is_null() || info->source_stream() != nullptr || | 610 DCHECK(!info->script().is_null() || info->source_stream() != nullptr || |
| 600 info->character_stream() != nullptr); | 611 info->character_stream() != nullptr); |
| 601 // Determine if functions can be lazily compiled. This is necessary to | 612 // Determine if functions can be lazily compiled. This is necessary to |
| 602 // allow some of our builtin JS files to be lazily compiled. These | 613 // allow some of our builtin JS files to be lazily compiled. These |
| 603 // builtins cannot be handled lazily by the parser, since we have to know | 614 // builtins cannot be handled lazily by the parser, since we have to know |
| 604 // if a function uses the special natives syntax, which is something the | 615 // if a function uses the special natives syntax, which is something the |
| (...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 673 base::ElapsedTimer timer; | 684 base::ElapsedTimer timer; |
| 674 if (FLAG_trace_parse) { | 685 if (FLAG_trace_parse) { |
| 675 timer.Start(); | 686 timer.Start(); |
| 676 } | 687 } |
| 677 fni_ = new (zone()) FuncNameInferrer(ast_value_factory(), zone()); | 688 fni_ = new (zone()) FuncNameInferrer(ast_value_factory(), zone()); |
| 678 | 689 |
| 679 // Initialize parser state. | 690 // Initialize parser state. |
| 680 ParserLogger logger; | 691 ParserLogger logger; |
| 681 | 692 |
| 682 if (produce_cached_parse_data()) { | 693 if (produce_cached_parse_data()) { |
| 683 log_ = &logger; | 694 if (allow_lazy_) { |
| 695 log_ = &logger; |
| 696 } else { |
| 697 compile_options_ = ScriptCompiler::kNoCompileOptions; |
| 698 } |
| 684 } else if (consume_cached_parse_data()) { | 699 } else if (consume_cached_parse_data()) { |
| 685 cached_parse_data_->Initialize(); | 700 cached_parse_data_->Initialize(); |
| 686 } | 701 } |
| 687 | 702 |
| 688 DeserializeScopeChain(info, info->maybe_outer_scope_info()); | 703 DeserializeScopeChain(info, info->maybe_outer_scope_info()); |
| 689 | 704 |
| 690 source = String::Flatten(source); | 705 source = String::Flatten(source); |
| 691 FunctionLiteral* result; | 706 FunctionLiteral* result; |
| 692 | 707 |
| 693 { | 708 { |
| (...skipping 1991 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2685 } | 2700 } |
| 2686 | 2701 |
| 2687 DCHECK(use_temp_zone || !is_lazy_top_level_function); | 2702 DCHECK(use_temp_zone || !is_lazy_top_level_function); |
| 2688 if (use_temp_zone) { | 2703 if (use_temp_zone) { |
| 2689 // If the preconditions are correct the function body should never be | 2704 // If the preconditions are correct the function body should never be |
| 2690 // accessed, but do this anyway for better behaviour if they're wrong. | 2705 // accessed, but do this anyway for better behaviour if they're wrong. |
| 2691 body = nullptr; | 2706 body = nullptr; |
| 2692 scope->AnalyzePartially(&previous_zone_ast_node_factory); | 2707 scope->AnalyzePartially(&previous_zone_ast_node_factory); |
| 2693 } | 2708 } |
| 2694 | 2709 |
| 2710 DCHECK_IMPLIES(use_temp_zone, temp_zoned_); |
| 2695 if (FLAG_trace_preparse) { | 2711 if (FLAG_trace_preparse) { |
| 2696 PrintF(" [%s]: %i-%i %.*s\n", | 2712 PrintF(" [%s]: %i-%i %.*s\n", |
| 2697 is_lazy_top_level_function | 2713 is_lazy_top_level_function |
| 2698 ? "Preparse no-resolution" | 2714 ? "Preparse no-resolution" |
| 2699 : (use_temp_zone ? "Preparse resolution" : "Full parse"), | 2715 : (temp_zoned_ ? "Preparse resolution" : "Full parse"), |
| 2700 scope->start_position(), scope->end_position(), | 2716 scope->start_position(), scope->end_position(), |
| 2701 function_name->byte_length(), function_name->raw_data()); | 2717 function_name->byte_length(), function_name->raw_data()); |
| 2702 } | 2718 } |
| 2703 if (is_lazy_top_level_function) { | 2719 if (is_lazy_top_level_function) { |
| 2704 CHANGE_CURRENT_RUNTIME_COUNTER(runtime_call_stats_, | 2720 CHANGE_CURRENT_RUNTIME_COUNTER(runtime_call_stats_, |
| 2705 PreParseNoVariableResolution); | 2721 PreParseNoVariableResolution); |
| 2706 } else if (use_temp_zone) { | 2722 } else if (temp_zoned_) { |
| 2707 CHANGE_CURRENT_RUNTIME_COUNTER(runtime_call_stats_, | 2723 CHANGE_CURRENT_RUNTIME_COUNTER(runtime_call_stats_, |
| 2708 PreParseWithVariableResolution); | 2724 PreParseWithVariableResolution); |
| 2709 } | 2725 } |
| 2710 | 2726 |
| 2711 // Validate function name. We can do this only after parsing the function, | 2727 // Validate function name. We can do this only after parsing the function, |
| 2712 // since the function can declare itself strict. | 2728 // since the function can declare itself strict. |
| 2713 language_mode = scope->language_mode(); | 2729 language_mode = scope->language_mode(); |
| 2714 CheckFunctionName(language_mode, function_name, function_name_validity, | 2730 CheckFunctionName(language_mode, function_name, function_name_validity, |
| 2715 function_name_location, CHECK_OK); | 2731 function_name_location, CHECK_OK); |
| 2716 | 2732 |
| (...skipping 392 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3109 return factory()->NewYield(get_proxy, assignment, scope()->start_position(), | 3125 return factory()->NewYield(get_proxy, assignment, scope()->start_position(), |
| 3110 Yield::kOnExceptionThrow); | 3126 Yield::kOnExceptionThrow); |
| 3111 } | 3127 } |
| 3112 | 3128 |
| 3113 ZoneList<Statement*>* Parser::ParseFunction( | 3129 ZoneList<Statement*>* Parser::ParseFunction( |
| 3114 const AstRawString* function_name, int pos, FunctionKind kind, | 3130 const AstRawString* function_name, int pos, FunctionKind kind, |
| 3115 FunctionLiteral::FunctionType function_type, | 3131 FunctionLiteral::FunctionType function_type, |
| 3116 DeclarationScope* function_scope, int* num_parameters, int* function_length, | 3132 DeclarationScope* function_scope, int* num_parameters, int* function_length, |
| 3117 bool* has_duplicate_parameters, int* materialized_literal_count, | 3133 bool* has_duplicate_parameters, int* materialized_literal_count, |
| 3118 int* expected_property_count, bool* ok) { | 3134 int* expected_property_count, bool* ok) { |
| 3135 ParsingModeScope mode(this, allow_lazy_ ? PARSE_LAZILY : PARSE_EAGERLY); |
| 3136 |
| 3119 FunctionState function_state(&function_state_, &scope_state_, function_scope); | 3137 FunctionState function_state(&function_state_, &scope_state_, function_scope); |
| 3120 | 3138 |
| 3121 DuplicateFinder duplicate_finder(scanner()->unicode_cache()); | 3139 DuplicateFinder duplicate_finder(scanner()->unicode_cache()); |
| 3122 ExpressionClassifier formals_classifier(this, &duplicate_finder); | 3140 ExpressionClassifier formals_classifier(this, &duplicate_finder); |
| 3123 | 3141 |
| 3124 if (IsGeneratorFunction(kind)) PrepareGeneratorVariables(&function_state); | 3142 if (IsGeneratorFunction(kind)) PrepareGeneratorVariables(&function_state); |
| 3125 | 3143 |
| 3126 ParserFormalParameters formals(function_scope); | 3144 ParserFormalParameters formals(function_scope); |
| 3127 ParseFormalParameterList(&formals, CHECK_OK); | 3145 ParseFormalParameterList(&formals, CHECK_OK); |
| 3128 Expect(Token::RPAREN, CHECK_OK); | 3146 Expect(Token::RPAREN, CHECK_OK); |
| (...skipping 24 matching lines...) Expand all Loading... |
| 3153 | 3171 |
| 3154 *materialized_literal_count = function_state.materialized_literal_count(); | 3172 *materialized_literal_count = function_state.materialized_literal_count(); |
| 3155 *expected_property_count = function_state.expected_property_count(); | 3173 *expected_property_count = function_state.expected_property_count(); |
| 3156 return body; | 3174 return body; |
| 3157 } | 3175 } |
| 3158 | 3176 |
| 3159 ZoneList<Statement*>* Parser::ParseEagerFunctionBody( | 3177 ZoneList<Statement*>* Parser::ParseEagerFunctionBody( |
| 3160 const AstRawString* function_name, int pos, | 3178 const AstRawString* function_name, int pos, |
| 3161 const ParserFormalParameters& parameters, FunctionKind kind, | 3179 const ParserFormalParameters& parameters, FunctionKind kind, |
| 3162 FunctionLiteral::FunctionType function_type, bool* ok) { | 3180 FunctionLiteral::FunctionType function_type, bool* ok) { |
| 3163 ParsingModeScope mode(this, allow_lazy_ ? PARSE_LAZILY : PARSE_EAGERLY); | |
| 3164 ZoneList<Statement*>* result = new(zone()) ZoneList<Statement*>(8, zone()); | 3181 ZoneList<Statement*>* result = new(zone()) ZoneList<Statement*>(8, zone()); |
| 3165 | 3182 |
| 3166 static const int kFunctionNameAssignmentIndex = 0; | 3183 static const int kFunctionNameAssignmentIndex = 0; |
| 3167 if (function_type == FunctionLiteral::kNamedExpression) { | 3184 if (function_type == FunctionLiteral::kNamedExpression) { |
| 3168 DCHECK(function_name != NULL); | 3185 DCHECK(function_name != NULL); |
| 3169 // If we have a named function expression, we add a local variable | 3186 // If we have a named function expression, we add a local variable |
| 3170 // declaration to the body of the function with the name of the | 3187 // declaration to the body of the function with the name of the |
| 3171 // function and let it refer to the function itself (closure). | 3188 // function and let it refer to the function itself (closure). |
| 3172 // Not having parsed the function body, the language mode may still change, | 3189 // Not having parsed the function body, the language mode may still change, |
| 3173 // so we reserve a spot and create the actual const assignment later. | 3190 // so we reserve a spot and create the actual const assignment later. |
| (...skipping 638 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3812 } | 3829 } |
| 3813 | 3830 |
| 3814 | 3831 |
| 3815 void Parser::ParseOnBackground(ParseInfo* info) { | 3832 void Parser::ParseOnBackground(ParseInfo* info) { |
| 3816 parsing_on_main_thread_ = false; | 3833 parsing_on_main_thread_ = false; |
| 3817 | 3834 |
| 3818 DCHECK(info->literal() == NULL); | 3835 DCHECK(info->literal() == NULL); |
| 3819 FunctionLiteral* result = NULL; | 3836 FunctionLiteral* result = NULL; |
| 3820 | 3837 |
| 3821 ParserLogger logger; | 3838 ParserLogger logger; |
| 3822 if (produce_cached_parse_data()) log_ = &logger; | 3839 if (produce_cached_parse_data()) { |
| 3840 if (allow_lazy_) { |
| 3841 log_ = &logger; |
| 3842 } else { |
| 3843 compile_options_ = ScriptCompiler::kNoCompileOptions; |
| 3844 } |
| 3845 } |
| 3823 if (FLAG_runtime_stats) { | 3846 if (FLAG_runtime_stats) { |
| 3824 // Create separate runtime stats for background parsing. | 3847 // Create separate runtime stats for background parsing. |
| 3825 runtime_call_stats_ = new (zone()) RuntimeCallStats(); | 3848 runtime_call_stats_ = new (zone()) RuntimeCallStats(); |
| 3826 } | 3849 } |
| 3827 | 3850 |
| 3828 std::unique_ptr<Utf16CharacterStream> stream; | 3851 std::unique_ptr<Utf16CharacterStream> stream; |
| 3829 Utf16CharacterStream* stream_ptr; | 3852 Utf16CharacterStream* stream_ptr; |
| 3830 if (info->character_stream()) { | 3853 if (info->character_stream()) { |
| 3831 DCHECK(info->source_stream() == nullptr); | 3854 DCHECK(info->source_stream() == nullptr); |
| 3832 stream_ptr = info->character_stream(); | 3855 stream_ptr = info->character_stream(); |
| (...skipping 1604 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5437 | 5460 |
| 5438 return final_loop; | 5461 return final_loop; |
| 5439 } | 5462 } |
| 5440 | 5463 |
| 5441 #undef CHECK_OK | 5464 #undef CHECK_OK |
| 5442 #undef CHECK_OK_VOID | 5465 #undef CHECK_OK_VOID |
| 5443 #undef CHECK_FAILED | 5466 #undef CHECK_FAILED |
| 5444 | 5467 |
| 5445 } // namespace internal | 5468 } // namespace internal |
| 5446 } // namespace v8 | 5469 } // namespace v8 |
| OLD | NEW |