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

Side by Side Diff: src/parser.cc

Issue 214883002: Two-threaded parser (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: code review (svenpanne) Created 6 years, 8 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 | Annotate | Revision Log
OLDNEW
1 // Copyright 2012 the V8 project authors. All rights reserved. 1 // Copyright 2012 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without 2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are 3 // modification, are permitted provided that the following conditions are
4 // met: 4 // met:
5 // 5 //
6 // * Redistributions of source code must retain the above copyright 6 // * Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer. 7 // notice, this list of conditions and the following disclaimer.
8 // * Redistributions in binary form must reproduce the above 8 // * Redistributions in binary form must reproduce the above
9 // copyright notice, this list of conditions and the following 9 // copyright notice, this list of conditions and the following
10 // disclaimer in the documentation and/or other materials provided 10 // disclaimer in the documentation and/or other materials provided
(...skipping 17 matching lines...) Expand all
28 #include "v8.h" 28 #include "v8.h"
29 29
30 #include "api.h" 30 #include "api.h"
31 #include "ast.h" 31 #include "ast.h"
32 #include "bootstrapper.h" 32 #include "bootstrapper.h"
33 #include "char-predicates-inl.h" 33 #include "char-predicates-inl.h"
34 #include "codegen.h" 34 #include "codegen.h"
35 #include "compiler.h" 35 #include "compiler.h"
36 #include "messages.h" 36 #include "messages.h"
37 #include "parser.h" 37 #include "parser.h"
38 #include "parser-thread.h"
38 #include "platform.h" 39 #include "platform.h"
39 #include "preparser.h" 40 #include "preparser.h"
40 #include "runtime.h" 41 #include "runtime.h"
41 #include "scanner-character-streams.h" 42 #include "scanner-character-streams.h"
42 #include "scopeinfo.h" 43 #include "scopeinfo.h"
43 #include "string-stream.h" 44 #include "string-stream.h"
44 45
45 namespace v8 { 46 namespace v8 {
46 namespace internal { 47 namespace internal {
47 48
(...skipping 784 matching lines...) Expand 10 before | Expand all | Expand 10 after
832 name_is_strict_reserved, is_generator, 833 name_is_strict_reserved, is_generator,
833 function_token_position, type, ok); 834 function_token_position, type, ok);
834 } 835 }
835 836
836 837
837 Parser::Parser(CompilationInfo* info) 838 Parser::Parser(CompilationInfo* info)
838 : ParserBase<ParserTraits>(&scanner_, 839 : ParserBase<ParserTraits>(&scanner_,
839 info->isolate()->stack_guard()->real_climit(), 840 info->isolate()->stack_guard()->real_climit(),
840 info->extension(), 841 info->extension(),
841 NULL, 842 NULL,
843 NULL,
842 info->zone(), 844 info->zone(),
843 this), 845 this),
844 isolate_(info->isolate()), 846 isolate_(info->isolate()),
845 symbol_cache_(0, info->zone()), 847 symbol_cache_(0, info->zone()),
846 script_(info->script()), 848 script_(info->script()),
847 scanner_(isolate_->unicode_cache()), 849 scanner_(isolate_->unicode_cache()),
848 reusable_preparser_(NULL), 850 reusable_preparser_(NULL),
849 original_scope_(NULL), 851 original_scope_(NULL),
850 target_stack_(NULL), 852 target_stack_(NULL),
851 cached_data_(NULL), 853 cached_data_(NULL),
(...skipping 16 matching lines...) Expand all
868 // see comment for HistogramTimerScope class. 870 // see comment for HistogramTimerScope class.
869 HistogramTimerScope timer_scope(isolate()->counters()->parse(), true); 871 HistogramTimerScope timer_scope(isolate()->counters()->parse(), true);
870 Handle<String> source(String::cast(script_->source())); 872 Handle<String> source(String::cast(script_->source()));
871 isolate()->counters()->total_parse_size()->Increment(source->length()); 873 isolate()->counters()->total_parse_size()->Increment(source->length());
872 ElapsedTimer timer; 874 ElapsedTimer timer;
873 if (FLAG_trace_parse) { 875 if (FLAG_trace_parse) {
874 timer.Start(); 876 timer.Start();
875 } 877 }
876 fni_ = new(zone()) FuncNameInferrer(isolate(), zone()); 878 fni_ = new(zone()) FuncNameInferrer(isolate(), zone());
877 879
878 // Initialize parser state. 880 source = String::Flatten(source);
881
879 CompleteParserRecorder recorder; 882 CompleteParserRecorder recorder;
880 if (cached_data_mode_ == PRODUCE_CACHED_DATA) { 883 if (cached_data_mode_ == PRODUCE_CACHED_DATA) {
884 ASSERT(allow_lazy());
881 log_ = &recorder; 885 log_ = &recorder;
886 if (source->length() >= FLAG_min_parallel_parse_length) {
887 // Start a thread for doing a fast pass over the script to find lazy
888 // functions with PreParser. Restrictions: 1) PreParser cannot yet parse
889 // everything that Parser can (e.g., harmony modules). So here we are on
890 // the safe side, and only use the FastParserThread when we're sure that
891 // the script is good (i.e., for scripts for which we produce cached
892 // data). TODO(marja): Use FastParserThread for other kinds of
893 // compilations too. 2) The thread cannot use the Isolate, or Handles, so
894 // this will only work if the actual data is kept outside the V8 heap as
895 // an external string.
896 if (source->IsExternalAsciiString()) {
897 thread_ = new FastParserThread(
898 new ExternalOneByteStringUtf16CharacterStream(
Sven Panne 2014/04/16 11:55:35 Extract the creation of the Utf16CharacterStream*
marja 2014/04/16 14:33:10 Extracted the Stream creation. But I don't get wha
899 Handle<ExternalAsciiString>::cast(source)->GetChars(), 0,
900 source->length()),
901 allow_harmony_scoping(), allow_modules(), allow_natives_syntax(),
902 allow_generators(), allow_for_of(),
903 allow_harmony_numeric_literals());
904 thread_->Start();
905 } else if (source->IsExternalTwoByteString()) {
906 thread_ = new FastParserThread(
907 new ExternalTwoByteStringUtf16CharacterStream(
908 Handle<ExternalTwoByteString>::cast(source)->GetTwoByteData(0),
909 0, source->length()),
910 allow_harmony_scoping(), allow_modules(), allow_natives_syntax(),
911 allow_generators(), allow_for_of(),
912 allow_harmony_numeric_literals());
913 thread_->Start();
914 }
915 }
882 } else if (cached_data_mode_ == CONSUME_CACHED_DATA) { 916 } else if (cached_data_mode_ == CONSUME_CACHED_DATA) {
883 (*cached_data_)->Initialize(); 917 (*cached_data_)->Initialize();
884 } 918 }
885 919
886 source = String::Flatten(source);
887 FunctionLiteral* result; 920 FunctionLiteral* result;
888 if (source->IsExternalTwoByteString()) { 921 if (source->IsExternalTwoByteString()) {
889 // Notice that the stream is destroyed at the end of the branch block. 922 // Notice that the stream is destroyed at the end of the branch block.
890 // The last line of the blocks can't be moved outside, even though they're 923 // The last line of the blocks can't be moved outside, even though they're
891 // identical calls. 924 // identical calls.
892 ExternalTwoByteStringUtf16CharacterStream stream( 925 ExternalTwoByteStringUtf16CharacterStream stream(
893 Handle<ExternalTwoByteString>::cast(source), 0, source->length()); 926 Handle<ExternalTwoByteString>::cast(source)->GetTwoByteData(0), 0,
927 source->length());
894 scanner_.Initialize(&stream); 928 scanner_.Initialize(&stream);
895 result = DoParseProgram(info(), source); 929 result = DoParseProgram(info(), source);
896 } else { 930 } else {
897 GenericStringUtf16CharacterStream stream(source, 0, source->length()); 931 GenericStringUtf16CharacterStream stream(source, 0, source->length());
898 scanner_.Initialize(&stream); 932 scanner_.Initialize(&stream);
899 result = DoParseProgram(info(), source); 933 result = DoParseProgram(info(), source);
900 } 934 }
901 935
902 if (FLAG_trace_parse && result != NULL) { 936 if (FLAG_trace_parse && result != NULL) {
903 double ms = timer.Elapsed().InMillisecondsF(); 937 double ms = timer.Elapsed().InMillisecondsF();
904 if (info()->is_eval()) { 938 if (info()->is_eval()) {
905 PrintF("[parsing eval"); 939 PrintF("[parsing eval");
906 } else if (info()->script()->name()->IsString()) { 940 } else if (info()->script()->name()->IsString()) {
907 String* name = String::cast(info()->script()->name()); 941 String* name = String::cast(info()->script()->name());
908 SmartArrayPointer<char> name_chars = name->ToCString(); 942 SmartArrayPointer<char> name_chars = name->ToCString();
909 PrintF("[parsing script: %s", name_chars.get()); 943 PrintF("[parsing script: %s", name_chars.get());
910 } else { 944 } else {
911 PrintF("[parsing script"); 945 PrintF("[parsing script");
912 } 946 }
913 PrintF(" - took %0.3f ms]\n", ms); 947 PrintF(" - took %0.3f ms]\n", ms);
914 } 948 }
915 if (cached_data_mode_ == PRODUCE_CACHED_DATA) { 949 if (cached_data_mode_ == PRODUCE_CACHED_DATA) {
916 Vector<unsigned> store = recorder.ExtractData(); 950 Vector<unsigned> store = recorder.ExtractData();
917 *cached_data_ = new ScriptData(store); 951 *cached_data_ = new ScriptData(store);
918 log_ = NULL; 952 log_ = NULL;
953 if (thread_) {
Sven Panne 2014/04/16 11:55:35 Lift this block out into a separate method, it's u
marja 2014/04/16 14:33:10 Done, and I also added a function for (possibly) s
954 thread_->Join();
955 delete thread_;
956 thread_ = NULL;
957 }
919 } 958 }
920 return result; 959 return result;
921 } 960 }
922 961
923 962
924 FunctionLiteral* Parser::DoParseProgram(CompilationInfo* info, 963 FunctionLiteral* Parser::DoParseProgram(CompilationInfo* info,
925 Handle<String> source) { 964 Handle<String> source) {
926 ASSERT(scope_ == NULL); 965 ASSERT(scope_ == NULL);
927 ASSERT(target_stack_ == NULL); 966 ASSERT(target_stack_ == NULL);
928 967
(...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after
1019 if (FLAG_trace_parse) { 1058 if (FLAG_trace_parse) {
1020 timer.Start(); 1059 timer.Start();
1021 } 1060 }
1022 Handle<SharedFunctionInfo> shared_info = info()->shared_info(); 1061 Handle<SharedFunctionInfo> shared_info = info()->shared_info();
1023 1062
1024 // Initialize parser state. 1063 // Initialize parser state.
1025 source = String::Flatten(source); 1064 source = String::Flatten(source);
1026 FunctionLiteral* result; 1065 FunctionLiteral* result;
1027 if (source->IsExternalTwoByteString()) { 1066 if (source->IsExternalTwoByteString()) {
1028 ExternalTwoByteStringUtf16CharacterStream stream( 1067 ExternalTwoByteStringUtf16CharacterStream stream(
1029 Handle<ExternalTwoByteString>::cast(source), 1068 Handle<ExternalTwoByteString>::cast(source)->GetTwoByteData(0),
1030 shared_info->start_position(), 1069 shared_info->start_position(),
1031 shared_info->end_position()); 1070 shared_info->end_position());
1032 result = ParseLazy(&stream); 1071 result = ParseLazy(&stream);
1033 } else { 1072 } else {
1034 GenericStringUtf16CharacterStream stream(source, 1073 GenericStringUtf16CharacterStream stream(source,
1035 shared_info->start_position(), 1074 shared_info->start_position(),
1036 shared_info->end_position()); 1075 shared_info->end_position());
1037 result = ParseLazy(&stream); 1076 result = ParseLazy(&stream);
1038 } 1077 }
1039 1078
(...skipping 2453 matching lines...) Expand 10 before | Expand all | Expand 10 after
3493 scope_->end_position() - function_block_pos); 3532 scope_->end_position() - function_block_pos);
3494 *materialized_literal_count = entry.literal_count(); 3533 *materialized_literal_count = entry.literal_count();
3495 *expected_property_count = entry.property_count(); 3534 *expected_property_count = entry.property_count();
3496 scope_->SetStrictMode(entry.strict_mode()); 3535 scope_->SetStrictMode(entry.strict_mode());
3497 } else { 3536 } else {
3498 // This case happens when we have preparse data but it doesn't contain an 3537 // This case happens when we have preparse data but it doesn't contain an
3499 // entry for the function. Fail the compilation. 3538 // entry for the function. Fail the compilation.
3500 ReportInvalidCachedData(function_name, ok); 3539 ReportInvalidCachedData(function_name, ok);
3501 return; 3540 return;
3502 } 3541 }
3542 } else if (thread_) {
Sven Panne 2014/04/16 11:55:35 Hmmm, the block below contains some heavy copy-n-p
marja 2014/04/16 14:33:10 Done.
3543 int start, end;
3544 StrictMode strict_mode;
3545 // This will wait until the background thread has found the lazy function.
3546 thread_->Consume(&start, &end, materialized_literal_count,
3547 expected_property_count, &strict_mode);
3548 ASSERT(log_);
3549 log_->LogFunction(start, end, *materialized_literal_count,
3550 *expected_property_count, strict_mode);
3551 if (start == function_block_pos) {
3552 scanner()->SeekForward(end - 1);
3553 scope_->set_end_position(end);
3554 Expect(Token::RBRACE, ok);
3555 if (!ok) {
3556 return;
3557 }
3558 isolate()->counters()->total_preparse_skipped()->Increment(end - start);
3559 scope_->SetStrictMode(strict_mode);
3560 } else {
3561 // The thread might have found an error. Handle it.
3562 const SingletonLogger* logger = thread_->recorder();
3563 if (thread_->GetResult() == PreParser::kPreParseStackOverflow) {
3564 set_stack_overflow();
3565 } else if (logger->has_error()) {
3566 const char* arg = logger->argument_opt();
3567 Vector<const char*> args;
3568 if (arg != NULL) {
3569 args = Vector<const char*>(&arg, 1);
3570 }
3571 ParserTraits::ReportMessageAt(
3572 Scanner::Location(logger->start(), logger->end()),
3573 logger->message(), args, logger->is_reference_error());
3574 } else {
3575 // The thread produced data for a lazy function which was not the
3576 // function we expected. This should never happen.
3577 ASSERT(false);
3578 }
3579 thread_->Join();
3580 delete thread_;
3581 thread_ = NULL;
3582 *ok = false;
3583 return;
3584 }
3503 } else { 3585 } else {
3504 // With no cached data, we partially parse the function, without building an 3586 // With no cached data, we partially parse the function, without building an
3505 // AST. This gathers the data needed to build a lazy function. 3587 // AST. This gathers the data needed to build a lazy function.
3506 SingletonLogger logger; 3588 SingletonLogger logger;
3507 PreParser::PreParseResult result = 3589 PreParser::PreParseResult result =
3508 ParseLazyFunctionBodyWithPreParser(&logger); 3590 ParseLazyFunctionBodyWithPreParser(&logger);
3509 if (result == PreParser::kPreParseStackOverflow) { 3591 if (result == PreParser::kPreParseStackOverflow) {
3510 // Propagate stack overflow. 3592 // Propagate stack overflow.
3511 set_stack_overflow(); 3593 set_stack_overflow();
3512 *ok = false; 3594 *ok = false;
(...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after
3606 } 3688 }
3607 3689
3608 3690
3609 PreParser::PreParseResult Parser::ParseLazyFunctionBodyWithPreParser( 3691 PreParser::PreParseResult Parser::ParseLazyFunctionBodyWithPreParser(
3610 SingletonLogger* logger) { 3692 SingletonLogger* logger) {
3611 HistogramTimerScope preparse_scope(isolate()->counters()->pre_parse()); 3693 HistogramTimerScope preparse_scope(isolate()->counters()->pre_parse());
3612 ASSERT_EQ(Token::LBRACE, scanner()->current_token()); 3694 ASSERT_EQ(Token::LBRACE, scanner()->current_token());
3613 3695
3614 if (reusable_preparser_ == NULL) { 3696 if (reusable_preparser_ == NULL) {
3615 intptr_t stack_limit = isolate()->stack_guard()->real_climit(); 3697 intptr_t stack_limit = isolate()->stack_guard()->real_climit();
3616 reusable_preparser_ = new PreParser(&scanner_, NULL, stack_limit); 3698 reusable_preparser_ = new PreParser(&scanner_, NULL, stack_limit, NULL);
3617 reusable_preparser_->set_allow_harmony_scoping(allow_harmony_scoping()); 3699 reusable_preparser_->set_allow_harmony_scoping(allow_harmony_scoping());
3618 reusable_preparser_->set_allow_modules(allow_modules()); 3700 reusable_preparser_->set_allow_modules(allow_modules());
3619 reusable_preparser_->set_allow_natives_syntax(allow_natives_syntax()); 3701 reusable_preparser_->set_allow_natives_syntax(allow_natives_syntax());
3620 reusable_preparser_->set_allow_lazy(true); 3702 reusable_preparser_->set_allow_lazy(true);
3621 reusable_preparser_->set_allow_generators(allow_generators()); 3703 reusable_preparser_->set_allow_generators(allow_generators());
3622 reusable_preparser_->set_allow_for_of(allow_for_of()); 3704 reusable_preparser_->set_allow_for_of(allow_for_of());
3623 reusable_preparser_->set_allow_harmony_numeric_literals( 3705 reusable_preparser_->set_allow_harmony_numeric_literals(
3624 allow_harmony_numeric_literals()); 3706 allow_harmony_numeric_literals());
3625 } 3707 }
3626 PreParser::PreParseResult result = 3708 PreParser::PreParseResult result =
(...skipping 1066 matching lines...) Expand 10 before | Expand all | Expand 10 after
4693 ASSERT(info()->isolate()->has_pending_exception()); 4775 ASSERT(info()->isolate()->has_pending_exception());
4694 } else { 4776 } else {
4695 result = ParseProgram(); 4777 result = ParseProgram();
4696 } 4778 }
4697 } 4779 }
4698 info()->SetFunction(result); 4780 info()->SetFunction(result);
4699 return (result != NULL); 4781 return (result != NULL);
4700 } 4782 }
4701 4783
4702 } } // namespace v8::internal 4784 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/flag-definitions.h ('k') | src/parser-thread.h » ('j') | src/parser-thread.cc » ('J')

Powered by Google App Engine
This is Rietveld 408576698