Revision: 23600
Author: [email protected]
Date: Tue Sep 2 11:36:21 2014 UTC
Log: Refactor Parser to make it usable on a background thread.
- Background Parsers cannot get the following data from Isolate (pass it to
the
ctor instead): stack limit (background Parsers need a different stack
limit),
UnicodeCache (background parsers need a separate UnicodeCache), hash seed
(Parser cannot access the Heap to get it). The Parser::Parse API won't
change.
- Make the internalization phase (where Parser interacts with the heap) more
explicit. Previously, Parser was interacting with the heap here and there.
- Move HandleSourceURLComments out of DoParseProgram, so that background
parsing
can use DoParseProgram too.
BUG=
[email protected]
Review URL: https://codereview.chromium.org/527763002
https://code.google.com/p/v8/source/detail?r=23600
Modified:
/branches/bleeding_edge/src/parser.cc
/branches/bleeding_edge/src/parser.h
/branches/bleeding_edge/src/preparser.h
/branches/bleeding_edge/test/cctest/test-parsing.cc
=======================================
--- /branches/bleeding_edge/src/parser.cc Tue Sep 2 07:07:52 2014 UTC
+++ /branches/bleeding_edge/src/parser.cc Tue Sep 2 11:36:21 2014 UTC
@@ -739,23 +739,25 @@
}
-Parser::Parser(CompilationInfo* info)
- : ParserBase<ParserTraits>(
- &scanner_, info->isolate()->stack_guard()->real_climit(),
- info->extension(), NULL, info->zone(), info->ast_node_id_gen(),
this),
+Parser::Parser(CompilationInfo* info, ParseInfo* parse_info)
+ : ParserBase<ParserTraits>(&scanner_, parse_info->stack_limit,
+ info->extension(), NULL, info->zone(),
+ info->ast_node_id_gen(), this),
isolate_(info->isolate()),
script_(info->script()),
- scanner_(isolate_->unicode_cache()),
+ scanner_(parse_info->unicode_cache),
reusable_preparser_(NULL),
original_scope_(NULL),
target_stack_(NULL),
cached_parse_data_(NULL),
- ast_value_factory_(NULL),
+ ast_value_factory_(info->ast_value_factory()),
info_(info),
has_pending_error_(false),
pending_error_message_(NULL),
pending_error_arg_(NULL),
- pending_error_char_arg_(NULL) {
+ pending_error_char_arg_(NULL),
+ total_preparse_skipped_(0),
+ pre_parse_timer_(NULL) {
DCHECK(!script_.is_null());
set_allow_harmony_scoping(!info->is_native() && FLAG_harmony_scoping);
set_allow_modules(!info->is_native() && FLAG_harmony_modules);
@@ -769,12 +771,18 @@
++feature) {
use_counts_[feature] = 0;
}
+ if (ast_value_factory_ == NULL) {
+ ast_value_factory_ = new AstValueFactory(zone(),
parse_info->hash_seed);
+ }
}
FunctionLiteral* Parser::ParseProgram() {
// TODO(bmeurer): We temporarily need to pass allow_nesting = true here,
// see comment for HistogramTimerScope class.
+
+ // It's OK to use the counters here, since this function is only called
in
+ // the main thread.
HistogramTimerScope timer_scope(isolate()->counters()->parse(), true);
Handle<String> source(String::cast(script_->source()));
isolate()->counters()->total_parse_size()->Increment(source->length());
@@ -808,6 +816,7 @@
scanner_.Initialize(&stream);
result = DoParseProgram(info(), source);
}
+ HandleSourceURLComments();
if (FLAG_trace_parse && result != NULL) {
double ms = timer.Elapsed().InMillisecondsF();
@@ -876,8 +885,6 @@
int beg_pos = scanner()->location().beg_pos;
ParseSourceElements(body, Token::EOS, info->is_eval(), true, &ok);
- HandleSourceURLComments();
-
if (ok && strict_mode() == STRICT) {
CheckOctalLiteral(beg_pos, scanner()->location().end_pos, &ok);
}
@@ -896,7 +903,6 @@
}
}
- ast_value_factory_->Internalize(isolate());
if (ok) {
result = factory()->NewFunctionLiteral(
ast_value_factory_->empty_string(), ast_value_factory_, scope_,
body,
@@ -910,10 +916,6 @@
result->set_ast_properties(factory()->visitor()->ast_properties());
result->set_dont_optimize_reason(
factory()->visitor()->dont_optimize_reason());
- } else if (stack_overflow()) {
- isolate()->StackOverflow();
- } else {
- ThrowPendingError();
}
}
@@ -925,6 +927,8 @@
FunctionLiteral* Parser::ParseLazy() {
+ // It's OK to use the counters here, since this function is only called
in
+ // the main thread.
HistogramTimerScope timer_scope(isolate()->counters()->parse_lazy());
Handle<String> source(String::cast(script_->source()));
isolate()->counters()->total_parse_size()->Increment(source->length());
@@ -1017,14 +1021,7 @@
// Make sure the target stack is empty.
DCHECK(target_stack_ == NULL);
- ast_value_factory_->Internalize(isolate());
- if (result == NULL) {
- if (stack_overflow()) {
- isolate()->StackOverflow();
- } else {
- ThrowPendingError();
- }
- } else {
+ if (result != NULL) {
Handle<String> inferred_name(shared_info->inferred_name());
result->set_inferred_name(inferred_name);
}
@@ -3654,8 +3651,7 @@
if (!*ok) {
return;
}
- isolate()->counters()->total_preparse_skipped()->Increment(
- scope_->end_position() - function_block_pos);
+ total_preparse_skipped_ += scope_->end_position() - function_block_pos;
*materialized_literal_count = entry.literal_count();
*expected_property_count = entry.property_count();
scope_->SetStrictMode(entry.strict_mode());
@@ -3683,8 +3679,7 @@
if (!*ok) {
return;
}
- isolate()->counters()->total_preparse_skipped()->Increment(
- scope_->end_position() - function_block_pos);
+ total_preparse_skipped_ += scope_->end_position() - function_block_pos;
*materialized_literal_count = logger.literals();
*expected_property_count = logger.properties();
scope_->SetStrictMode(logger.strict_mode());
@@ -3762,12 +3757,15 @@
PreParser::PreParseResult Parser::ParseLazyFunctionBodyWithPreParser(
SingletonLogger* logger) {
- HistogramTimerScope preparse_scope(isolate()->counters()->pre_parse());
+ // This function may be called on a background thread too; record only
the
+ // main thread preparse times.
+ if (pre_parse_timer_ != NULL) {
+ pre_parse_timer_->Start();
+ }
DCHECK_EQ(Token::LBRACE, scanner()->current_token());
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_);
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());
@@ -3782,6 +3780,9 @@
reusable_preparser_->PreParseLazyFunction(strict_mode(),
is_generator(),
logger);
+ if (pre_parse_timer_ != NULL) {
+ pre_parse_timer_->Stop();
+ }
return result;
}
@@ -3964,14 +3965,29 @@
}
}
+
+void Parser::Internalize() {
+ // Internalize strings.
+ ast_value_factory_->Internalize(isolate());
-void Parser::InternalizeUseCounts() {
+ // Error processing.
+ if (info()->function() == NULL) {
+ if (stack_overflow()) {
+ isolate()->StackOverflow();
+ } else {
+ ThrowPendingError();
+ }
+ }
+
+ // Move statistics to Isolate.
for (int feature = 0; feature < v8::Isolate::kUseCounterFeatureCount;
++feature) {
for (int i = 0; i < use_counts_[feature]; ++i) {
isolate()->CountUsage(v8::Isolate::UseCounterFeature(feature));
}
}
+ isolate()->counters()->total_preparse_skipped()->Increment(
+ total_preparse_skipped_);
}
@@ -4809,14 +4825,10 @@
bool Parser::Parse() {
DCHECK(info()->function() == NULL);
FunctionLiteral* result = NULL;
- ast_value_factory_ = info()->ast_value_factory();
- if (ast_value_factory_ == NULL) {
- ast_value_factory_ =
- new AstValueFactory(zone(), isolate()->heap()->HashSeed());
- }
+ pre_parse_timer_ = isolate()->counters()->pre_parse();
if (allow_natives_syntax() || extension_ != NULL) {
// If intrinsics are allowed, the Parser cannot operate independent of
the
- // V8 heap because of Rumtime. Tell the string table to internalize
strings
+ // V8 heap because of Runtime. Tell the string table to internalize
strings
// and values right after they're created.
ast_value_factory_->Internalize(isolate());
}
@@ -4833,15 +4845,14 @@
result = ParseProgram();
}
info()->SetFunction(result);
+
+ Internalize();
DCHECK(ast_value_factory_->IsInternalized());
// info takes ownership of ast_value_factory_.
if (info()->ast_value_factory() == NULL) {
info()->SetAstValueFactory(ast_value_factory_);
}
ast_value_factory_ = NULL;
-
- InternalizeUseCounts();
-
return (result != NULL);
}
=======================================
--- /branches/bleeding_edge/src/parser.h Fri Aug 22 14:40:38 2014 UTC
+++ /branches/bleeding_edge/src/parser.h Tue Sep 2 11:36:21 2014 UTC
@@ -597,7 +597,16 @@
class Parser : public ParserBase<ParserTraits> {
public:
- explicit Parser(CompilationInfo* info);
+ // Note that the hash seed in ParseInfo must be the hash seed from the
+ // Isolate's heap, otherwise the heap will be in an inconsistent state
once
+ // the strings created by the Parser are internalized.
+ struct ParseInfo {
+ uintptr_t stack_limit;
+ uint32_t hash_seed;
+ UnicodeCache* unicode_cache;
+ };
+
+ Parser(CompilationInfo* info, ParseInfo* parse_info);
~Parser() {
delete reusable_preparser_;
reusable_preparser_ = NULL;
@@ -610,7 +619,10 @@
// nodes) if parsing failed.
static bool Parse(CompilationInfo* info,
bool allow_lazy = false) {
- Parser parser(info);
+ ParseInfo parse_info = {info->isolate()->stack_guard()->real_climit(),
+ info->isolate()->heap()->HashSeed(),
+ info->isolate()->unicode_cache()};
+ Parser parser(info, &parse_info);
parser.set_allow_lazy(allow_lazy);
return parser.Parse();
}
@@ -797,7 +809,9 @@
void ThrowPendingError();
- void InternalizeUseCounts();
+ // Handle errors detected during parsing, move statistics to Isolate,
+ // internalize strings (move them to the heap).
+ void Internalize();
Isolate* isolate_;
@@ -819,7 +833,11 @@
const char* pending_error_char_arg_;
bool pending_error_is_reference_error_;
+ // Other information which will be stored in Parser and moved to Isolate
after
+ // parsing.
int use_counts_[v8::Isolate::kUseCounterFeatureCount];
+ int total_preparse_skipped_;
+ HistogramTimer* pre_parse_timer_;
};
=======================================
--- /branches/bleeding_edge/src/preparser.h Tue Sep 2 07:07:52 2014 UTC
+++ /branches/bleeding_edge/src/preparser.h Tue Sep 2 11:36:21 2014 UTC
@@ -78,8 +78,8 @@
fni_(NULL),
log_(log),
mode_(PARSE_EAGERLY), // Lazy mode must be set explicitly.
+ stack_limit_(stack_limit),
scanner_(scanner),
- stack_limit_(stack_limit),
stack_overflow_(false),
allow_lazy_(false),
allow_natives_syntax_(false),
@@ -569,10 +569,10 @@
FuncNameInferrer* fni_;
ParserRecorder* log_;
Mode mode_;
+ uintptr_t stack_limit_;
private:
Scanner* scanner_;
- uintptr_t stack_limit_;
bool stack_overflow_;
bool allow_lazy_;
=======================================
--- /branches/bleeding_edge/test/cctest/test-parsing.cc Tue Aug 26 09:19:24
2014 UTC
+++ /branches/bleeding_edge/test/cctest/test-parsing.cc Tue Sep 2 11:36:21
2014 UTC
@@ -1128,7 +1128,10 @@
CHECK_EQ(source->length(), kProgramSize);
i::Handle<i::Script> script = factory->NewScript(source);
i::CompilationInfoWithZone info(script);
- i::Parser parser(&info);
+ i::Parser::ParseInfo parse_info =
{isolate->stack_guard()->real_climit(),
+ isolate->heap()->HashSeed(),
+ isolate->unicode_cache()};
+ i::Parser parser(&info, &parse_info);
parser.set_allow_lazy(true);
parser.set_allow_harmony_scoping(true);
parser.set_allow_arrow_functions(true);
@@ -1263,7 +1266,10 @@
{
i::Handle<i::Script> script = factory->NewScript(source);
i::CompilationInfoWithZone info(script);
- i::Parser parser(&info);
+ i::Parser::ParseInfo parse_info =
{isolate->stack_guard()->real_climit(),
+ isolate->heap()->HashSeed(),
+ isolate->unicode_cache()};
+ i::Parser parser(&info, &parse_info);
SetParserFlags(&parser, flags);
info.MarkAsGlobal();
parser.Parse();
@@ -3125,7 +3131,10 @@
i::Handle<i::Script> script = factory->NewScript(source);
i::CompilationInfoWithZone info(script);
- i::Parser parser(&info);
+ i::Parser::ParseInfo parse_info = {
+ isolate->stack_guard()->real_climit(),
+ isolate->heap()->HashSeed(), isolate->unicode_cache()};
+ i::Parser parser(&info, &parse_info);
parser.set_allow_harmony_scoping(true);
CHECK(parser.Parse());
CHECK(i::Rewriter::Rewrite(&info));
--
--
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev
---
You received this message because you are subscribed to the Google Groups "v8-dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
For more options, visit https://groups.google.com/d/optout.