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 // 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 |
| OLD | NEW |