| 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 568 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 579 ReportMessage(MessageTemplate::kNotDefined, name); | 579 ReportMessage(MessageTemplate::kNotDefined, name); |
| 580 *ok = false; | 580 *ok = false; |
| 581 return nullptr; | 581 return nullptr; |
| 582 } | 582 } |
| 583 | 583 |
| 584 return factory()->NewCallRuntime(context_index, args, pos); | 584 return factory()->NewCallRuntime(context_index, args, pos); |
| 585 } | 585 } |
| 586 | 586 |
| 587 Parser::Parser(ParseInfo* info) | 587 Parser::Parser(ParseInfo* info) |
| 588 : ParserBase<Parser>(info->zone(), &scanner_, info->stack_limit(), | 588 : ParserBase<Parser>(info->zone(), &scanner_, info->stack_limit(), |
| 589 info->extension(), info->ast_value_factory(), NULL), | 589 info->extension(), info->ast_value_factory()), |
| 590 scanner_(info->unicode_cache()), | 590 scanner_(info->unicode_cache()), |
| 591 reusable_preparser_(NULL), | 591 reusable_preparser_(nullptr), |
| 592 original_scope_(NULL), | 592 original_scope_(nullptr), |
| 593 target_stack_(NULL), | 593 target_stack_(nullptr), |
| 594 compile_options_(info->compile_options()), | 594 compile_options_(info->compile_options()), |
| 595 cached_parse_data_(nullptr), | 595 cached_parse_data_(nullptr), |
| 596 total_preparse_skipped_(0), | 596 total_preparse_skipped_(0), |
| 597 parsing_on_main_thread_(true) { | 597 parsing_on_main_thread_(true), |
| 598 log_(nullptr) { |
| 598 // Even though we were passed ParseInfo, we should not store it in | 599 // Even though we were passed ParseInfo, we should not store it in |
| 599 // Parser - this makes sure that Isolate is not accidentally accessed via | 600 // Parser - this makes sure that Isolate is not accidentally accessed via |
| 600 // ParseInfo during background parsing. | 601 // ParseInfo during background parsing. |
| 601 DCHECK(!info->script().is_null() || info->source_stream() != nullptr || | 602 DCHECK(!info->script().is_null() || info->source_stream() != nullptr || |
| 602 info->character_stream() != nullptr); | 603 info->character_stream() != nullptr); |
| 603 // Determine if functions can be lazily compiled. This is necessary to | 604 // Determine if functions can be lazily compiled. This is necessary to |
| 604 // allow some of our builtin JS files to be lazily compiled. These | 605 // allow some of our builtin JS files to be lazily compiled. These |
| 605 // builtins cannot be handled lazily by the parser, since we have to know | 606 // builtins cannot be handled lazily by the parser, since we have to know |
| 606 // if a function uses the special natives syntax, which is something the | 607 // if a function uses the special natives syntax, which is something the |
| 607 // parser records. | 608 // parser records. |
| (...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 674 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8.compile"), "V8.ParseProgram"); | 675 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8.compile"), "V8.ParseProgram"); |
| 675 Handle<String> source(String::cast(info->script()->source())); | 676 Handle<String> source(String::cast(info->script()->source())); |
| 676 isolate->counters()->total_parse_size()->Increment(source->length()); | 677 isolate->counters()->total_parse_size()->Increment(source->length()); |
| 677 base::ElapsedTimer timer; | 678 base::ElapsedTimer timer; |
| 678 if (FLAG_trace_parse) { | 679 if (FLAG_trace_parse) { |
| 679 timer.Start(); | 680 timer.Start(); |
| 680 } | 681 } |
| 681 fni_ = new (zone()) FuncNameInferrer(ast_value_factory(), zone()); | 682 fni_ = new (zone()) FuncNameInferrer(ast_value_factory(), zone()); |
| 682 | 683 |
| 683 // Initialize parser state. | 684 // Initialize parser state. |
| 684 CompleteParserRecorder recorder; | 685 ParserLogger logger; |
| 685 | 686 |
| 686 if (produce_cached_parse_data()) { | 687 if (produce_cached_parse_data()) { |
| 687 log_ = &recorder; | 688 log_ = &logger; |
| 688 } else if (consume_cached_parse_data()) { | 689 } else if (consume_cached_parse_data()) { |
| 689 cached_parse_data_->Initialize(); | 690 cached_parse_data_->Initialize(); |
| 690 } | 691 } |
| 691 | 692 |
| 692 DeserializeScopeChain(info, info->maybe_outer_scope_info()); | 693 DeserializeScopeChain(info, info->maybe_outer_scope_info()); |
| 693 | 694 |
| 694 source = String::Flatten(source); | 695 source = String::Flatten(source); |
| 695 FunctionLiteral* result; | 696 FunctionLiteral* result; |
| 696 | 697 |
| 697 { | 698 { |
| 698 std::unique_ptr<Utf16CharacterStream> stream(ScannerStream::For(source)); | 699 std::unique_ptr<Utf16CharacterStream> stream(ScannerStream::For(source)); |
| 699 scanner_.Initialize(stream.get()); | 700 scanner_.Initialize(stream.get()); |
| 700 result = DoParseProgram(info); | 701 result = DoParseProgram(info); |
| 701 } | 702 } |
| 702 if (result != NULL) { | 703 if (result != NULL) { |
| 703 DCHECK_EQ(scanner_.peek_location().beg_pos, source->length()); | 704 DCHECK_EQ(scanner_.peek_location().beg_pos, source->length()); |
| 704 } | 705 } |
| 705 HandleSourceURLComments(isolate, info->script()); | 706 HandleSourceURLComments(isolate, info->script()); |
| 706 | 707 |
| 707 if (FLAG_trace_parse && result != NULL) { | 708 if (FLAG_trace_parse && result != nullptr) { |
| 708 double ms = timer.Elapsed().InMillisecondsF(); | 709 double ms = timer.Elapsed().InMillisecondsF(); |
| 709 if (info->is_eval()) { | 710 if (info->is_eval()) { |
| 710 PrintF("[parsing eval"); | 711 PrintF("[parsing eval"); |
| 711 } else if (info->script()->name()->IsString()) { | 712 } else if (info->script()->name()->IsString()) { |
| 712 String* name = String::cast(info->script()->name()); | 713 String* name = String::cast(info->script()->name()); |
| 713 std::unique_ptr<char[]> name_chars = name->ToCString(); | 714 std::unique_ptr<char[]> name_chars = name->ToCString(); |
| 714 PrintF("[parsing script: %s", name_chars.get()); | 715 PrintF("[parsing script: %s", name_chars.get()); |
| 715 } else { | 716 } else { |
| 716 PrintF("[parsing script"); | 717 PrintF("[parsing script"); |
| 717 } | 718 } |
| 718 PrintF(" - took %0.3f ms]\n", ms); | 719 PrintF(" - took %0.3f ms]\n", ms); |
| 719 } | 720 } |
| 720 if (produce_cached_parse_data()) { | 721 if (produce_cached_parse_data() && result != nullptr) { |
| 721 if (result != NULL) *info->cached_data() = recorder.GetScriptData(); | 722 *info->cached_data() = logger.GetScriptData(); |
| 722 log_ = NULL; | |
| 723 } | 723 } |
| 724 log_ = nullptr; |
| 724 return result; | 725 return result; |
| 725 } | 726 } |
| 726 | 727 |
| 727 | 728 |
| 728 FunctionLiteral* Parser::DoParseProgram(ParseInfo* info) { | 729 FunctionLiteral* Parser::DoParseProgram(ParseInfo* info) { |
| 729 // Note that this function can be called from the main thread or from a | 730 // Note that this function can be called from the main thread or from a |
| 730 // background thread. We should not access anything Isolate / heap dependent | 731 // background thread. We should not access anything Isolate / heap dependent |
| 731 // via ParseInfo, and also not pass it forward. | 732 // via ParseInfo, and also not pass it forward. |
| 732 DCHECK_NULL(scope_state_); | 733 DCHECK_NULL(scope_state_); |
| 733 DCHECK_NULL(target_stack_); | 734 DCHECK_NULL(target_stack_); |
| (...skipping 2035 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2769 SetLanguageMode(function_scope, entry.language_mode()); | 2770 SetLanguageMode(function_scope, entry.language_mode()); |
| 2770 if (entry.uses_super_property()) | 2771 if (entry.uses_super_property()) |
| 2771 function_scope->RecordSuperPropertyUsage(); | 2772 function_scope->RecordSuperPropertyUsage(); |
| 2772 if (entry.calls_eval()) function_scope->RecordEvalCall(); | 2773 if (entry.calls_eval()) function_scope->RecordEvalCall(); |
| 2773 return kLazyParsingComplete; | 2774 return kLazyParsingComplete; |
| 2774 } | 2775 } |
| 2775 cached_parse_data_->Reject(); | 2776 cached_parse_data_->Reject(); |
| 2776 } | 2777 } |
| 2777 // 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 |
| 2778 // AST. This gathers the data needed to build a lazy function. | 2779 // AST. This gathers the data needed to build a lazy function. |
| 2779 SingletonLogger logger; | |
| 2780 PreParser::PreParseResult result = ParseFunctionWithPreParser( | 2780 PreParser::PreParseResult result = ParseFunctionWithPreParser( |
| 2781 kind, function_scope, &logger, is_inner_function, may_abort); | 2781 kind, function_scope, is_inner_function, may_abort); |
| 2782 | 2782 |
| 2783 // Return immediately if pre-parser decided to abort parsing. | 2783 // Return immediately if pre-parser decided to abort parsing. |
| 2784 if (result == PreParser::kPreParseAbort) return kLazyParsingAborted; | 2784 if (result == PreParser::kPreParseAbort) return kLazyParsingAborted; |
| 2785 if (result == PreParser::kPreParseStackOverflow) { | 2785 if (result == PreParser::kPreParseStackOverflow) { |
| 2786 // Propagate stack overflow. | 2786 // Propagate stack overflow. |
| 2787 set_stack_overflow(); | 2787 set_stack_overflow(); |
| 2788 *ok = false; | 2788 *ok = false; |
| 2789 return kLazyParsingComplete; | 2789 return kLazyParsingComplete; |
| 2790 } | 2790 } |
| 2791 if (logger.has_error()) { | 2791 PreParserLogger* logger = reusable_preparser_->logger(); |
| 2792 ReportMessageAt(Scanner::Location(logger.start(), logger.end()), | 2792 if (logger->has_error()) { |
| 2793 logger.message(), logger.argument_opt(), | 2793 ReportMessageAt(Scanner::Location(logger->start(), logger->end()), |
| 2794 logger.error_type()); | 2794 logger->message(), logger->argument_opt(), |
| 2795 logger->error_type()); |
| 2795 *ok = false; | 2796 *ok = false; |
| 2796 return kLazyParsingComplete; | 2797 return kLazyParsingComplete; |
| 2797 } | 2798 } |
| 2798 function_scope->set_end_position(logger.end()); | 2799 function_scope->set_end_position(logger->end()); |
| 2799 Expect(Token::RBRACE, CHECK_OK_VALUE(kLazyParsingComplete)); | 2800 Expect(Token::RBRACE, CHECK_OK_VALUE(kLazyParsingComplete)); |
| 2800 total_preparse_skipped_ += | 2801 total_preparse_skipped_ += |
| 2801 function_scope->end_position() - function_scope->start_position(); | 2802 function_scope->end_position() - function_scope->start_position(); |
| 2802 *num_parameters = logger.num_parameters(); | 2803 *num_parameters = logger->num_parameters(); |
| 2803 *function_length = logger.function_length(); | 2804 *function_length = logger->function_length(); |
| 2804 *has_duplicate_parameters = logger.has_duplicate_parameters(); | 2805 *has_duplicate_parameters = logger->has_duplicate_parameters(); |
| 2805 *materialized_literal_count = logger.literals(); | 2806 *materialized_literal_count = logger->literals(); |
| 2806 *expected_property_count = logger.properties(); | 2807 *expected_property_count = logger->properties(); |
| 2807 SetLanguageMode(function_scope, logger.language_mode()); | |
| 2808 if (logger.uses_super_property()) function_scope->RecordSuperPropertyUsage(); | |
| 2809 if (logger.calls_eval()) function_scope->RecordEvalCall(); | |
| 2810 if (!is_inner_function && produce_cached_parse_data()) { | 2808 if (!is_inner_function && produce_cached_parse_data()) { |
| 2811 DCHECK(log_); | 2809 DCHECK(log_); |
| 2812 log_->LogFunction( | 2810 log_->LogFunction( |
| 2813 function_scope->start_position(), function_scope->end_position(), | 2811 function_scope->start_position(), function_scope->end_position(), |
| 2814 *num_parameters, *function_length, *has_duplicate_parameters, | 2812 *num_parameters, *function_length, *has_duplicate_parameters, |
| 2815 *materialized_literal_count, *expected_property_count, language_mode(), | 2813 *materialized_literal_count, *expected_property_count, language_mode(), |
| 2816 function_scope->uses_super_property(), function_scope->calls_eval()); | 2814 function_scope->uses_super_property(), function_scope->calls_eval()); |
| 2817 } | 2815 } |
| 2818 return kLazyParsingComplete; | 2816 return kLazyParsingComplete; |
| 2819 } | 2817 } |
| (...skipping 462 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3282 statement = factory()->NewEmptyStatement(kNoSourcePosition); | 3280 statement = factory()->NewEmptyStatement(kNoSourcePosition); |
| 3283 } | 3281 } |
| 3284 result->Set(kFunctionNameAssignmentIndex, statement); | 3282 result->Set(kFunctionNameAssignmentIndex, statement); |
| 3285 } | 3283 } |
| 3286 | 3284 |
| 3287 MarkCollectedTailCallExpressions(); | 3285 MarkCollectedTailCallExpressions(); |
| 3288 return result; | 3286 return result; |
| 3289 } | 3287 } |
| 3290 | 3288 |
| 3291 PreParser::PreParseResult Parser::ParseFunctionWithPreParser( | 3289 PreParser::PreParseResult Parser::ParseFunctionWithPreParser( |
| 3292 FunctionKind kind, DeclarationScope* function_scope, | 3290 FunctionKind kind, DeclarationScope* function_scope, bool is_inner_function, |
| 3293 SingletonLogger* logger, bool is_inner_function, bool may_abort) { | 3291 bool may_abort) { |
| 3294 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8.compile"), "V8.PreParse"); | 3292 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8.compile"), "V8.PreParse"); |
| 3295 | 3293 |
| 3296 if (reusable_preparser_ == NULL) { | 3294 if (reusable_preparser_ == NULL) { |
| 3297 reusable_preparser_ = new PreParser(zone(), &scanner_, ast_value_factory(), | 3295 reusable_preparser_ = |
| 3298 NULL, stack_limit_); | 3296 new PreParser(zone(), &scanner_, ast_value_factory(), stack_limit_); |
| 3299 reusable_preparser_->set_allow_lazy(true); | 3297 reusable_preparser_->set_allow_lazy(true); |
| 3300 #define SET_ALLOW(name) reusable_preparser_->set_allow_##name(allow_##name()); | 3298 #define SET_ALLOW(name) reusable_preparser_->set_allow_##name(allow_##name()); |
| 3301 SET_ALLOW(natives); | 3299 SET_ALLOW(natives); |
| 3302 SET_ALLOW(harmony_do_expressions); | 3300 SET_ALLOW(harmony_do_expressions); |
| 3303 SET_ALLOW(harmony_function_sent); | 3301 SET_ALLOW(harmony_function_sent); |
| 3304 SET_ALLOW(harmony_restrictive_declarations); | 3302 SET_ALLOW(harmony_restrictive_declarations); |
| 3305 SET_ALLOW(harmony_async_await); | 3303 SET_ALLOW(harmony_async_await); |
| 3306 SET_ALLOW(harmony_trailing_commas); | 3304 SET_ALLOW(harmony_trailing_commas); |
| 3307 SET_ALLOW(harmony_class_fields); | 3305 SET_ALLOW(harmony_class_fields); |
| 3308 #undef SET_ALLOW | 3306 #undef SET_ALLOW |
| 3309 } | 3307 } |
| 3310 // Aborting inner function preparsing would leave scopes in an inconsistent | 3308 // Aborting inner function preparsing would leave scopes in an inconsistent |
| 3311 // state; we don't parse inner functions in the abortable mode anyway. | 3309 // state; we don't parse inner functions in the abortable mode anyway. |
| 3312 DCHECK(!is_inner_function || !may_abort); | 3310 DCHECK(!is_inner_function || !may_abort); |
| 3313 | 3311 |
| 3314 PreParser::PreParseResult result = reusable_preparser_->PreParseFunction( | 3312 PreParser::PreParseResult result = reusable_preparser_->PreParseFunction( |
| 3315 kind, function_scope, parsing_module_, logger, is_inner_function, | 3313 kind, function_scope, parsing_module_, is_inner_function, may_abort, |
| 3316 may_abort, use_counts_); | 3314 use_counts_); |
| 3317 return result; | 3315 return result; |
| 3318 } | 3316 } |
| 3319 | 3317 |
| 3320 Expression* Parser::InstallHomeObject(Expression* function_literal, | 3318 Expression* Parser::InstallHomeObject(Expression* function_literal, |
| 3321 Expression* home_object) { | 3319 Expression* home_object) { |
| 3322 Block* do_block = factory()->NewBlock(nullptr, 1, false, kNoSourcePosition); | 3320 Block* do_block = factory()->NewBlock(nullptr, 1, false, kNoSourcePosition); |
| 3323 Variable* result_var = | 3321 Variable* result_var = |
| 3324 scope()->NewTemporary(ast_value_factory()->empty_string()); | 3322 scope()->NewTemporary(ast_value_factory()->empty_string()); |
| 3325 DoExpression* do_expr = | 3323 DoExpression* do_expr = |
| 3326 factory()->NewDoExpression(do_block, result_var, kNoSourcePosition); | 3324 factory()->NewDoExpression(do_block, result_var, kNoSourcePosition); |
| (...skipping 478 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3805 return (result != NULL); | 3803 return (result != NULL); |
| 3806 } | 3804 } |
| 3807 | 3805 |
| 3808 | 3806 |
| 3809 void Parser::ParseOnBackground(ParseInfo* info) { | 3807 void Parser::ParseOnBackground(ParseInfo* info) { |
| 3810 parsing_on_main_thread_ = false; | 3808 parsing_on_main_thread_ = false; |
| 3811 | 3809 |
| 3812 DCHECK(info->literal() == NULL); | 3810 DCHECK(info->literal() == NULL); |
| 3813 FunctionLiteral* result = NULL; | 3811 FunctionLiteral* result = NULL; |
| 3814 | 3812 |
| 3815 CompleteParserRecorder recorder; | 3813 ParserLogger logger; |
| 3816 if (produce_cached_parse_data()) log_ = &recorder; | 3814 if (produce_cached_parse_data()) log_ = &logger; |
| 3817 | 3815 |
| 3818 std::unique_ptr<Utf16CharacterStream> stream; | 3816 std::unique_ptr<Utf16CharacterStream> stream; |
| 3819 Utf16CharacterStream* stream_ptr; | 3817 Utf16CharacterStream* stream_ptr; |
| 3820 if (info->character_stream()) { | 3818 if (info->character_stream()) { |
| 3821 DCHECK(info->source_stream() == nullptr); | 3819 DCHECK(info->source_stream() == nullptr); |
| 3822 stream_ptr = info->character_stream(); | 3820 stream_ptr = info->character_stream(); |
| 3823 } else { | 3821 } else { |
| 3824 DCHECK(info->character_stream() == nullptr); | 3822 DCHECK(info->character_stream() == nullptr); |
| 3825 stream.reset(ScannerStream::For(info->source_stream(), | 3823 stream.reset(ScannerStream::For(info->source_stream(), |
| 3826 info->source_stream_encoding())); | 3824 info->source_stream_encoding())); |
| (...skipping 16 matching lines...) Expand all Loading... |
| 3843 } else { | 3841 } else { |
| 3844 result = DoParseFunction(info, info->function_name(), stream_ptr); | 3842 result = DoParseFunction(info, info->function_name(), stream_ptr); |
| 3845 } | 3843 } |
| 3846 | 3844 |
| 3847 info->set_literal(result); | 3845 info->set_literal(result); |
| 3848 | 3846 |
| 3849 // We cannot internalize on a background thread; a foreground task will take | 3847 // We cannot internalize on a background thread; a foreground task will take |
| 3850 // care of calling Parser::Internalize just before compilation. | 3848 // care of calling Parser::Internalize just before compilation. |
| 3851 | 3849 |
| 3852 if (produce_cached_parse_data()) { | 3850 if (produce_cached_parse_data()) { |
| 3853 if (result != NULL) *info->cached_data() = recorder.GetScriptData(); | 3851 if (result != NULL) *info->cached_data() = logger.GetScriptData(); |
| 3854 log_ = NULL; | 3852 log_ = NULL; |
| 3855 } | 3853 } |
| 3856 } | 3854 } |
| 3857 | 3855 |
| 3858 Parser::TemplateLiteralState Parser::OpenTemplateLiteral(int pos) { | 3856 Parser::TemplateLiteralState Parser::OpenTemplateLiteral(int pos) { |
| 3859 return new (zone()) TemplateLiteral(zone(), pos); | 3857 return new (zone()) TemplateLiteral(zone(), pos); |
| 3860 } | 3858 } |
| 3861 | 3859 |
| 3862 | 3860 |
| 3863 void Parser::AddTemplateSpan(TemplateLiteralState* state, bool tail) { | 3861 void Parser::AddTemplateSpan(TemplateLiteralState* state, bool tail) { |
| (...skipping 1559 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5423 | 5421 |
| 5424 return final_loop; | 5422 return final_loop; |
| 5425 } | 5423 } |
| 5426 | 5424 |
| 5427 #undef CHECK_OK | 5425 #undef CHECK_OK |
| 5428 #undef CHECK_OK_VOID | 5426 #undef CHECK_OK_VOID |
| 5429 #undef CHECK_FAILED | 5427 #undef CHECK_FAILED |
| 5430 | 5428 |
| 5431 } // namespace internal | 5429 } // namespace internal |
| 5432 } // namespace v8 | 5430 } // namespace v8 |
| OLD | NEW |