Chromium Code Reviews| Index: src/parser.cc |
| diff --git a/src/parser.cc b/src/parser.cc |
| index 9d37c88bf4aad9fbb03830440c58453c77f6402f..a93d3218eee384e745e7cf9890e0fadaa808b2e9 100644 |
| --- a/src/parser.cc |
| +++ b/src/parser.cc |
| @@ -35,6 +35,7 @@ |
| #include "compiler.h" |
| #include "messages.h" |
| #include "parser.h" |
| +#include "parser-thread.h" |
| #include "platform.h" |
| #include "preparser.h" |
| #include "runtime.h" |
| @@ -839,6 +840,7 @@ Parser::Parser(CompilationInfo* info) |
| info->isolate()->stack_guard()->real_climit(), |
| info->extension(), |
| NULL, |
| + NULL, |
| info->zone(), |
| this), |
| isolate_(info->isolate()), |
| @@ -875,22 +877,54 @@ FunctionLiteral* Parser::ParseProgram() { |
| } |
| fni_ = new(zone()) FuncNameInferrer(isolate(), zone()); |
| - // Initialize parser state. |
| + source = String::Flatten(source); |
| + |
| CompleteParserRecorder recorder; |
| if (cached_data_mode_ == PRODUCE_CACHED_DATA) { |
| + ASSERT(allow_lazy()); |
| log_ = &recorder; |
| + if (source->length() >= FLAG_min_parallel_parse_length) { |
| + // Start a thread for doing a fast pass over the script to find lazy |
| + // functions with PreParser. Restrictions: 1) PreParser cannot yet parse |
| + // everything that Parser can (e.g., harmony modules). So here we are on |
| + // the safe side, and only use the FastParserThread when we're sure that |
| + // the script is good (i.e., for scripts for which we produce cached |
| + // data). TODO(marja): Use FastParserThread for other kinds of |
| + // compilations too. 2) The thread cannot use the Isolate, or Handles, so |
| + // this will only work if the actual data is kept outside the V8 heap as |
| + // an external string. |
| + if (source->IsExternalAsciiString()) { |
| + thread_ = new FastParserThread( |
| + 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
|
| + Handle<ExternalAsciiString>::cast(source)->GetChars(), 0, |
| + source->length()), |
| + allow_harmony_scoping(), allow_modules(), allow_natives_syntax(), |
| + allow_generators(), allow_for_of(), |
| + allow_harmony_numeric_literals()); |
| + thread_->Start(); |
| + } else if (source->IsExternalTwoByteString()) { |
| + thread_ = new FastParserThread( |
| + new ExternalTwoByteStringUtf16CharacterStream( |
| + Handle<ExternalTwoByteString>::cast(source)->GetTwoByteData(0), |
| + 0, source->length()), |
| + allow_harmony_scoping(), allow_modules(), allow_natives_syntax(), |
| + allow_generators(), allow_for_of(), |
| + allow_harmony_numeric_literals()); |
| + thread_->Start(); |
| + } |
| + } |
| } else if (cached_data_mode_ == CONSUME_CACHED_DATA) { |
| (*cached_data_)->Initialize(); |
| } |
| - source = String::Flatten(source); |
| FunctionLiteral* result; |
| if (source->IsExternalTwoByteString()) { |
| // Notice that the stream is destroyed at the end of the branch block. |
| // The last line of the blocks can't be moved outside, even though they're |
| // identical calls. |
| ExternalTwoByteStringUtf16CharacterStream stream( |
| - Handle<ExternalTwoByteString>::cast(source), 0, source->length()); |
| + Handle<ExternalTwoByteString>::cast(source)->GetTwoByteData(0), 0, |
| + source->length()); |
| scanner_.Initialize(&stream); |
| result = DoParseProgram(info(), source); |
| } else { |
| @@ -916,6 +950,11 @@ FunctionLiteral* Parser::ParseProgram() { |
| Vector<unsigned> store = recorder.ExtractData(); |
| *cached_data_ = new ScriptData(store); |
| log_ = NULL; |
| + 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
|
| + thread_->Join(); |
| + delete thread_; |
| + thread_ = NULL; |
| + } |
| } |
| return result; |
| } |
| @@ -1026,7 +1065,7 @@ FunctionLiteral* Parser::ParseLazy() { |
| FunctionLiteral* result; |
| if (source->IsExternalTwoByteString()) { |
| ExternalTwoByteStringUtf16CharacterStream stream( |
| - Handle<ExternalTwoByteString>::cast(source), |
| + Handle<ExternalTwoByteString>::cast(source)->GetTwoByteData(0), |
| shared_info->start_position(), |
| shared_info->end_position()); |
| result = ParseLazy(&stream); |
| @@ -3500,6 +3539,49 @@ void Parser::SkipLazyFunctionBody(Handle<String> function_name, |
| ReportInvalidCachedData(function_name, ok); |
| return; |
| } |
| + } 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.
|
| + int start, end; |
| + StrictMode strict_mode; |
| + // This will wait until the background thread has found the lazy function. |
| + thread_->Consume(&start, &end, materialized_literal_count, |
| + expected_property_count, &strict_mode); |
| + ASSERT(log_); |
| + log_->LogFunction(start, end, *materialized_literal_count, |
| + *expected_property_count, strict_mode); |
| + if (start == function_block_pos) { |
| + scanner()->SeekForward(end - 1); |
| + scope_->set_end_position(end); |
| + Expect(Token::RBRACE, ok); |
| + if (!ok) { |
| + return; |
| + } |
| + isolate()->counters()->total_preparse_skipped()->Increment(end - start); |
| + scope_->SetStrictMode(strict_mode); |
| + } else { |
| + // The thread might have found an error. Handle it. |
| + const SingletonLogger* logger = thread_->recorder(); |
| + if (thread_->GetResult() == PreParser::kPreParseStackOverflow) { |
| + set_stack_overflow(); |
| + } else if (logger->has_error()) { |
| + const char* arg = logger->argument_opt(); |
| + Vector<const char*> args; |
| + if (arg != NULL) { |
| + args = Vector<const char*>(&arg, 1); |
| + } |
| + ParserTraits::ReportMessageAt( |
| + Scanner::Location(logger->start(), logger->end()), |
| + logger->message(), args, logger->is_reference_error()); |
| + } else { |
| + // The thread produced data for a lazy function which was not the |
| + // function we expected. This should never happen. |
| + ASSERT(false); |
| + } |
| + thread_->Join(); |
| + delete thread_; |
| + thread_ = NULL; |
| + *ok = false; |
| + return; |
| + } |
| } else { |
| // With no cached data, we partially parse the function, without building an |
| // AST. This gathers the data needed to build a lazy function. |
| @@ -3613,7 +3695,7 @@ PreParser::PreParseResult Parser::ParseLazyFunctionBodyWithPreParser( |
| if (reusable_preparser_ == NULL) { |
| intptr_t stack_limit = isolate()->stack_guard()->real_climit(); |
| - reusable_preparser_ = new PreParser(&scanner_, NULL, stack_limit); |
| + reusable_preparser_ = new PreParser(&scanner_, NULL, stack_limit, NULL); |
| reusable_preparser_->set_allow_harmony_scoping(allow_harmony_scoping()); |
| reusable_preparser_->set_allow_modules(allow_modules()); |
| reusable_preparser_->set_allow_natives_syntax(allow_natives_syntax()); |