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

Unified Diff: src/parser.cc

Issue 214883002: Two-threaded parser (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: rebased Created 6 years, 7 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « src/parser.h ('k') | src/parser-thread.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/parser.cc
diff --git a/src/parser.cc b/src/parser.cc
index 94d657504e8392ce3e456217fd02c9260bc72477..76b45450e81a1220443896da119654a8019b0e2c 100644
--- a/src/parser.cc
+++ b/src/parser.cc
@@ -12,6 +12,7 @@
#include "compiler.h"
#include "messages.h"
#include "parser.h"
+#include "parser-thread.h"
#include "platform.h"
#include "preparser.h"
#include "runtime.h"
@@ -22,6 +23,27 @@
namespace v8 {
namespace internal {
+namespace {
+
+// Returns NULL if the string is not external. Caller takes ownership of the
+// returned stream.
+Utf16CharacterStream* ExternalCharacterStreamFromString(Handle<String> string) {
+ if (string->IsExternalAsciiString()) {
+ return new ExternalOneByteStringUtf16CharacterStream(
+ Handle<ExternalAsciiString>::cast(string)->GetChars(), 0,
+ string->length());
+ }
+ if (string->IsExternalTwoByteString()) {
+ return new ExternalTwoByteStringUtf16CharacterStream(
+ Handle<ExternalTwoByteString>::cast(string)->GetTwoByteData(0), 0,
+ string->length());
+ }
+ return NULL;
+}
+
+} // namespace
+
+
RegExpBuilder::RegExpBuilder(Zone* zone)
: zone_(zone),
pending_empty_(false),
@@ -780,6 +802,7 @@ Parser::Parser(CompilationInfo* info)
info->isolate()->stack_guard()->real_climit(),
info->extension(),
NULL,
+ NULL,
info->zone(),
this),
isolate_(info->isolate()),
@@ -815,22 +838,25 @@ FunctionLiteral* Parser::ParseProgram() {
}
fni_ = new(zone()) FuncNameInferrer(isolate(), zone());
- // Initialize parser state.
CompleteParserRecorder recorder;
+
if (cached_data_mode_ == PRODUCE_CACHED_DATA) {
+ ASSERT(allow_lazy());
log_ = &recorder;
} else if (cached_data_mode_ == CONSUME_CACHED_DATA) {
(*cached_data_)->Initialize();
}
-
source = String::Flatten(source);
+ StartFastParserTaskIfPossible(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 {
@@ -859,6 +885,7 @@ FunctionLiteral* Parser::ParseProgram() {
}
log_ = NULL;
}
+ FinishFastParserTask();
return result;
}
@@ -967,7 +994,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);
@@ -3307,8 +3334,24 @@ FunctionLiteral* Parser::ParseFunctionLiteral(
parenthesized_function_ = false; // The bit was set for this function only.
if (is_lazily_parsed) {
- SkipLazyFunctionBody(function_name, &materialized_literal_count,
- &expected_property_count, CHECK_OK);
+ int function_block_pos = position();
+ StrictMode strict_mode;
+ SkipLazyFunctionBody(
+ function_name, function_block_pos, &materialized_literal_count,
+ &expected_property_count, &strict_mode, CHECK_OK);
+ scope_->SetStrictMode(strict_mode);
+ Expect(Token::RBRACE, CHECK_OK);
+ // Position right after terminal '}'.
+ int body_end = scanner()->location().end_pos;
+ scope_->set_end_position(body_end);
+ isolate()->counters()->total_preparse_skipped()->Increment(
+ body_end - function_block_pos);
+ if (cached_data_mode_ == PRODUCE_CACHED_DATA) {
+ ASSERT(log_);
+ log_->LogFunction(function_block_pos, body_end,
+ materialized_literal_count, expected_property_count,
+ strict_mode);
+ }
} else {
body = ParseEagerFunctionBody(function_name, pos, fvar, fvar_init_op,
is_generator, CHECK_OK);
@@ -3384,10 +3427,11 @@ FunctionLiteral* Parser::ParseFunctionLiteral(
void Parser::SkipLazyFunctionBody(Handle<String> function_name,
+ int function_block_pos,
int* materialized_literal_count,
int* expected_property_count,
+ StrictMode* strict_mode,
bool* ok) {
- int function_block_pos = position();
if (cached_data_mode_ == CONSUME_CACHED_DATA) {
// If we have cached data, we use it to skip parsing the function body. The
// data contains the information we need to construct the lazy function.
@@ -3397,70 +3441,65 @@ void Parser::SkipLazyFunctionBody(Handle<String> function_name,
if (entry.end_pos() <= function_block_pos) {
// End position greater than end of stream is safe, and hard to check.
ReportInvalidCachedData(function_name, ok);
- if (!*ok) {
- return;
- }
- }
- scanner()->SeekForward(entry.end_pos() - 1);
-
- scope_->set_end_position(entry.end_pos());
- Expect(Token::RBRACE, ok);
- if (!*ok) {
return;
}
- isolate()->counters()->total_preparse_skipped()->Increment(
- scope_->end_position() - function_block_pos);
+ scanner()->SeekForward(entry.end_pos() - 1);
*materialized_literal_count = entry.literal_count();
*expected_property_count = entry.property_count();
- scope_->SetStrictMode(entry.strict_mode());
+ *strict_mode = entry.strict_mode();
} else {
// This case happens when we have preparse data but it doesn't contain an
// entry for the function. Fail the compilation.
ReportInvalidCachedData(function_name, ok);
return;
}
+ } else if (thread_) {
+ int start, end;
+ // This will wait until the background thread has found the lazy function.
+ thread_->Consume(&start, &end, materialized_literal_count,
+ expected_property_count, strict_mode);
+ if (start == function_block_pos) {
+ scanner()->SeekForward(end - 1);
+ } else {
+ ProcessErrorFromRecorder(thread_->result(), thread_->recorder(), ok);
+ // If there is no error, the thread produced data for a lazy function
+ // which was not the function we expected. That should never happen.
+ ASSERT(!*ok);
+ *ok = false;
+ FinishFastParserTask();
+ }
} else {
// With no cached data, we partially parse the function, without building an
- // AST. This gathers the data needed to build a lazy function.
+ // AST. This gathers the data needed to build a lazy function. The PreParser
+ // uses the same scanner, so it will be automatically positioned in the
+ // right position without additional seeking.
SingletonLogger logger;
PreParser::PreParseResult result =
ParseLazyFunctionBodyWithPreParser(&logger);
- if (result == PreParser::kPreParseStackOverflow) {
- // Propagate stack overflow.
- set_stack_overflow();
- *ok = false;
- return;
- }
- if (logger.has_error()) {
- ParserTraits::ReportMessageAt(
- Scanner::Location(logger.start(), logger.end()),
- logger.message(), logger.argument_opt(), logger.is_reference_error());
- *ok = false;
- return;
- }
- scope_->set_end_position(logger.end());
- Expect(Token::RBRACE, ok);
+ ProcessErrorFromRecorder(result, &logger, ok);
if (!*ok) {
return;
}
- isolate()->counters()->total_preparse_skipped()->Increment(
- scope_->end_position() - function_block_pos);
*materialized_literal_count = logger.literals();
*expected_property_count = logger.properties();
- scope_->SetStrictMode(logger.strict_mode());
- if (cached_data_mode_ == PRODUCE_CACHED_DATA) {
- ASSERT(log_);
- // Position right after terminal '}'.
- int body_end = scanner()->location().end_pos;
- log_->LogFunction(function_block_pos, body_end,
- *materialized_literal_count,
- *expected_property_count,
- scope_->strict_mode());
- }
+ *strict_mode = logger.strict_mode();
}
}
+void Parser::ProcessErrorFromRecorder(PreParser::PreParseResult result,
+ const SingletonLogger* logger, bool* ok) {
+ if (result == PreParser::kPreParseStackOverflow) {
+ set_stack_overflow();
+ *ok = false;
+ } else if (logger->has_error()) {
+ ParserTraits::ReportMessageAt(
+ Scanner::Location(logger->start(), logger->end()), logger->message(),
+ logger->argument_opt(), logger->is_reference_error());
+ *ok = false;
+ }
+}
+
ZoneList<Statement*>* Parser::ParseEagerFunctionBody(
Handle<String> function_name, int pos, Variable* fvar,
Token::Value fvar_init_op, bool is_generator, bool* ok) {
@@ -3527,7 +3566,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());
@@ -3537,14 +3576,36 @@ PreParser::PreParseResult Parser::ParseLazyFunctionBodyWithPreParser(
reusable_preparser_->set_allow_harmony_numeric_literals(
allow_harmony_numeric_literals());
}
- PreParser::PreParseResult result =
- reusable_preparser_->PreParseLazyFunction(strict_mode(),
- is_generator(),
- logger);
+ PreParser::PreParseResult result = reusable_preparser_->PreParseLazyFunction(
+ strict_mode(), is_generator(), logger);
return result;
}
+void Parser::StartFastParserTaskIfPossible(Handle<String> source) {
+ if (cached_data_mode_ == PRODUCE_CACHED_DATA && FLAG_parallel_parse &&
+ source->length() >= FLAG_min_parallel_parse_length) {
+ Utf16CharacterStream* stream = ExternalCharacterStreamFromString(source);
+ if (stream) {
+ ASSERT(isolate()->fast_parser_thread());
+ thread_ = isolate()->fast_parser_thread();
+ thread_->StartBackgroundParsing(stream, allow_harmony_scoping(),
+ allow_modules(), allow_natives_syntax(),
+ allow_generators(), allow_for_of(),
+ allow_harmony_numeric_literals());
+ }
+ }
+}
+
+
+void Parser::FinishFastParserTask() {
+ if (thread_) {
+ thread_->FinishBackgroundParsing();
+ thread_ = NULL;
+ }
+}
+
+
Expression* Parser::ParseV8Intrinsic(bool* ok) {
// CallRuntime ::
// '%' Identifier Arguments
« no previous file with comments | « src/parser.h ('k') | src/parser-thread.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698