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

Unified Diff: src/parser.cc

Issue 908173003: Parsing: Make Parser not know about Isolate during background parsing. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: main thread check Created 5 years, 10 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/preparser.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 c1e6815b002af688d7be6266384c1e561f3df94f..6db2b0d71c43a376f082819fd6d0dfa9b8907ae2 100644
--- a/src/parser.cc
+++ b/src/parser.cc
@@ -251,13 +251,13 @@ int ParseData::FunctionsSize() {
}
-void Parser::SetCachedData() {
- if (compile_options() == ScriptCompiler::kNoCompileOptions) {
+void Parser::SetCachedData(CompilationInfo* info) {
+ if (compile_options_ == ScriptCompiler::kNoCompileOptions) {
cached_parse_data_ = NULL;
} else {
- DCHECK(info_->cached_data() != NULL);
- if (compile_options() == ScriptCompiler::kConsumeParserCache) {
- cached_parse_data_ = ParseData::FromCachedData(*info_->cached_data());
+ DCHECK(info->cached_data() != NULL);
+ if (compile_options_ == ScriptCompiler::kConsumeParserCache) {
+ cached_parse_data_ = ParseData::FromCachedData(*info->cached_data());
}
}
}
@@ -790,23 +790,27 @@ ClassLiteral* ParserTraits::ParseClassLiteral(
Parser::Parser(CompilationInfo* info, uintptr_t stack_limit, uint32_t hash_seed,
UnicodeCache* unicode_cache)
- : ParserBase<ParserTraits>(info->isolate(), info->zone(), &scanner_,
- stack_limit, info->extension(),
- info->ast_value_factory(), NULL, this),
+ : ParserBase<ParserTraits>(info->zone(), &scanner_, stack_limit,
+ info->extension(), info->ast_value_factory(),
+ NULL, this),
scanner_(unicode_cache),
reusable_preparser_(NULL),
original_scope_(NULL),
target_stack_(NULL),
+ compile_options_(info->compile_options()),
cached_parse_data_(NULL),
- info_(info),
parsing_lazy_arrow_parameters_(false),
has_pending_error_(false),
pending_error_message_(NULL),
pending_error_arg_(NULL),
pending_error_char_arg_(NULL),
total_preparse_skipped_(0),
- pre_parse_timer_(NULL) {
- DCHECK(!script().is_null() || info->source_stream() != NULL);
+ pre_parse_timer_(NULL),
+ parsing_on_main_thread_(true) {
+ // Even though we were passed CompilationInfo, we should not store it in
+ // Parser - this makes sure that Isolate is not accidentally accessed via
+ // CompilationInfo during background parsing.
+ DCHECK(!info->script().is_null() || info->source_stream() != NULL);
set_allow_lazy(false); // Must be explicitly enabled.
set_allow_natives(FLAG_allow_natives_syntax || info->is_native());
set_allow_harmony_scoping(!info->is_native() && FLAG_harmony_scoping);
@@ -834,15 +838,18 @@ Parser::Parser(CompilationInfo* info, uintptr_t stack_limit, uint32_t hash_seed,
}
-FunctionLiteral* Parser::ParseProgram() {
+FunctionLiteral* Parser::ParseProgram(CompilationInfo* info) {
// 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());
+ // It's OK to use the Isolate & counters here, since this function is only
+ // called in the main thread.
+ DCHECK(parsing_on_main_thread_);
+
+ Isolate* isolate = info->isolate();
+ HistogramTimerScope timer_scope(isolate->counters()->parse(), true);
+ Handle<String> source(String::cast(info->script()->source()));
+ isolate->counters()->total_parse_size()->Increment(source->length());
base::ElapsedTimer timer;
if (FLAG_trace_parse) {
timer.Start();
@@ -870,24 +877,24 @@ FunctionLiteral* Parser::ParseProgram() {
ExternalTwoByteStringUtf16CharacterStream stream(
Handle<ExternalTwoByteString>::cast(source), 0, source->length());
scanner_.Initialize(&stream);
- result = DoParseProgram(info(), &top_scope, &eval_scope);
+ result = DoParseProgram(info, &top_scope, &eval_scope);
} else {
GenericStringUtf16CharacterStream stream(source, 0, source->length());
scanner_.Initialize(&stream);
- result = DoParseProgram(info(), &top_scope, &eval_scope);
+ result = DoParseProgram(info, &top_scope, &eval_scope);
}
top_scope->set_end_position(source->length());
if (eval_scope != NULL) {
eval_scope->set_end_position(source->length());
}
- HandleSourceURLComments();
+ HandleSourceURLComments(info);
if (FLAG_trace_parse && result != NULL) {
double ms = timer.Elapsed().InMillisecondsF();
- if (info()->is_eval()) {
+ if (info->is_eval()) {
PrintF("[parsing eval");
- } else if (info()->script()->name()->IsString()) {
- String* name = String::cast(info()->script()->name());
+ } else if (info->script()->name()->IsString()) {
+ String* name = String::cast(info->script()->name());
SmartArrayPointer<char> name_chars = name->ToCString();
PrintF("[parsing script: %s", name_chars.get());
} else {
@@ -896,7 +903,7 @@ FunctionLiteral* Parser::ParseProgram() {
PrintF(" - took %0.3f ms]\n", ms);
}
if (produce_cached_parse_data()) {
- if (result != NULL) *info_->cached_data() = recorder.GetScriptData();
+ if (result != NULL) *info->cached_data() = recorder.GetScriptData();
log_ = NULL;
}
return result;
@@ -905,6 +912,9 @@ FunctionLiteral* Parser::ParseProgram() {
FunctionLiteral* Parser::DoParseProgram(CompilationInfo* info, Scope** scope,
Scope** eval_scope) {
+ // Note that this function can be called from the main thread or from a
+ // background thread. We should not access anything Isolate / heap dependent
+ // via CompilationInfo, and also not pass it forward.
DCHECK(scope_ == NULL);
DCHECK(target_stack_ == NULL);
@@ -918,8 +928,9 @@ FunctionLiteral* Parser::DoParseProgram(CompilationInfo* info, Scope** scope,
// The Scope is backed up by ScopeInfo (which is in the V8 heap); this
// means the Parser cannot operate independent of the V8 heap. Tell the
// string table to internalize strings and values right after they're
- // created.
- ast_value_factory()->Internalize(isolate());
+ // created. This kind of parsing can only be done in the main thread.
+ DCHECK(parsing_on_main_thread_);
+ ast_value_factory()->Internalize(info->isolate());
}
original_scope_ = *scope;
if (info->is_eval()) {
@@ -996,17 +1007,18 @@ FunctionLiteral* Parser::DoParseProgram(CompilationInfo* info, Scope** scope,
}
-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());
+FunctionLiteral* Parser::ParseLazy(CompilationInfo* info) {
+ // It's OK to use the Isolate & counters here, since this function is only
+ // called in the main thread.
+ DCHECK(parsing_on_main_thread_);
+ HistogramTimerScope timer_scope(info->isolate()->counters()->parse_lazy());
+ Handle<String> source(String::cast(info->script()->source()));
+ info->isolate()->counters()->total_parse_size()->Increment(source->length());
base::ElapsedTimer timer;
if (FLAG_trace_parse) {
timer.Start();
}
- Handle<SharedFunctionInfo> shared_info = info()->shared_info();
+ Handle<SharedFunctionInfo> shared_info = info->shared_info();
// Initialize parser state.
source = String::Flatten(source);
@@ -1016,12 +1028,12 @@ FunctionLiteral* Parser::ParseLazy() {
Handle<ExternalTwoByteString>::cast(source),
shared_info->start_position(),
shared_info->end_position());
- result = ParseLazy(&stream);
+ result = ParseLazy(info, &stream);
} else {
GenericStringUtf16CharacterStream stream(source,
shared_info->start_position(),
shared_info->end_position());
- result = ParseLazy(&stream);
+ result = ParseLazy(info, &stream);
}
if (FLAG_trace_parse && result != NULL) {
@@ -1033,8 +1045,9 @@ FunctionLiteral* Parser::ParseLazy() {
}
-FunctionLiteral* Parser::ParseLazy(Utf16CharacterStream* source) {
- Handle<SharedFunctionInfo> shared_info = info()->shared_info();
+FunctionLiteral* Parser::ParseLazy(CompilationInfo* info,
+ Utf16CharacterStream* source) {
+ Handle<SharedFunctionInfo> shared_info = info->shared_info();
scanner_.Initialize(source);
DCHECK(scope_ == NULL);
DCHECK(target_stack_ == NULL);
@@ -1053,18 +1066,21 @@ FunctionLiteral* Parser::ParseLazy(Utf16CharacterStream* source) {
{
// Parse the function literal.
Scope* scope = NewScope(scope_, SCRIPT_SCOPE);
- info()->SetScriptScope(scope);
- if (!info()->closure().is_null()) {
- scope = Scope::DeserializeScopeChain(isolate(), zone(),
- info()->closure()->context(), scope);
+ info->SetScriptScope(scope);
+ if (!info->closure().is_null()) {
+ // Ok to use Isolate here, since lazy function parsing is only done in the
+ // main thread.
+ DCHECK(parsing_on_main_thread_);
+ scope = Scope::DeserializeScopeChain(info->isolate(), zone(),
+ info->closure()->context(), scope);
}
original_scope_ = scope;
AstNodeFactory function_factory(ast_value_factory());
FunctionState function_state(&function_state_, &scope_, scope,
shared_info->kind(), &function_factory);
DCHECK(is_sloppy(scope->language_mode()) ||
- is_strict(info()->language_mode()));
- DCHECK(info()->language_mode() == shared_info->language_mode());
+ is_strict(info->language_mode()));
+ DCHECK(info->language_mode() == shared_info->language_mode());
scope->SetLanguageMode(shared_info->language_mode());
FunctionLiteral::FunctionType function_type = shared_info->is_expression()
? (shared_info->is_anonymous()
@@ -4009,8 +4025,8 @@ PreParser::PreParseResult Parser::ParseLazyFunctionBodyWithPreParser(
DCHECK_EQ(Token::LBRACE, scanner()->current_token());
if (reusable_preparser_ == NULL) {
- reusable_preparser_ = new PreParser(
- isolate(), zone(), &scanner_, ast_value_factory(), NULL, stack_limit_);
+ reusable_preparser_ = new PreParser(zone(), &scanner_, ast_value_factory(),
+ NULL, stack_limit_);
reusable_preparser_->set_allow_lazy(true);
reusable_preparser_->set_allow_natives(allow_natives());
reusable_preparser_->set_allow_harmony_scoping(allow_harmony_scoping());
@@ -4250,25 +4266,26 @@ IterationStatement* Parser::LookupContinueTarget(const AstRawString* label,
}
-void Parser::HandleSourceURLComments() {
+void Parser::HandleSourceURLComments(CompilationInfo* info) {
if (scanner_.source_url()->length() > 0) {
- Handle<String> source_url = scanner_.source_url()->Internalize(isolate());
- info_->script()->set_source_url(*source_url);
+ Handle<String> source_url =
+ scanner_.source_url()->Internalize(info->isolate());
+ info->script()->set_source_url(*source_url);
}
if (scanner_.source_mapping_url()->length() > 0) {
Handle<String> source_mapping_url =
- scanner_.source_mapping_url()->Internalize(isolate());
- info_->script()->set_source_mapping_url(*source_mapping_url);
+ scanner_.source_mapping_url()->Internalize(info->isolate());
+ info->script()->set_source_mapping_url(*source_mapping_url);
}
}
-void Parser::ThrowPendingError() {
+void Parser::ThrowPendingError(Isolate* isolate, Handle<Script> script) {
DCHECK(ast_value_factory()->IsInternalized());
if (has_pending_error_) {
- MessageLocation location(script(), pending_error_location_.beg_pos,
+ MessageLocation location(script, pending_error_location_.beg_pos,
pending_error_location_.end_pos);
- Factory* factory = isolate()->factory();
+ Factory* factory = isolate->factory();
bool has_arg =
pending_error_arg_ != NULL || pending_error_char_arg_ != NULL;
Handle<FixedArray> elements = factory->NewFixedArray(has_arg ? 1 : 0);
@@ -4281,7 +4298,7 @@ void Parser::ThrowPendingError() {
.ToHandleChecked();
elements->set(0, *arg_string);
}
- isolate()->debug()->OnCompileError(script());
+ isolate->debug()->OnCompileError(script);
Handle<JSArray> array = factory->NewJSArrayWithElements(elements);
Handle<Object> error;
@@ -4294,35 +4311,34 @@ void Parser::ThrowPendingError() {
Handle<JSObject> jserror = Handle<JSObject>::cast(error);
Handle<Name> key_start_pos = factory->error_start_pos_symbol();
- JSObject::SetProperty(
- jserror, key_start_pos,
- handle(Smi::FromInt(location.start_pos()), isolate()),
- SLOPPY).Check();
+ JSObject::SetProperty(jserror, key_start_pos,
+ handle(Smi::FromInt(location.start_pos()), isolate),
+ SLOPPY).Check();
Handle<Name> key_end_pos = factory->error_end_pos_symbol();
JSObject::SetProperty(jserror, key_end_pos,
- handle(Smi::FromInt(location.end_pos()), isolate()),
+ handle(Smi::FromInt(location.end_pos()), isolate),
SLOPPY).Check();
Handle<Name> key_script = factory->error_script_symbol();
- JSObject::SetProperty(jserror, key_script, script(), SLOPPY).Check();
+ JSObject::SetProperty(jserror, key_script, script, SLOPPY).Check();
- isolate()->Throw(*error, &location);
+ isolate->Throw(*error, &location);
}
}
}
-void Parser::Internalize() {
+void Parser::Internalize(CompilationInfo* info) {
// Internalize strings.
- ast_value_factory()->Internalize(isolate());
+ ast_value_factory()->Internalize(info->isolate());
// Error processing.
- if (info()->function() == NULL) {
+ if (info->function() == NULL) {
if (stack_overflow()) {
- isolate()->StackOverflow();
+ info->isolate()->StackOverflow();
} else {
- ThrowPendingError();
+ ThrowPendingError(info->isolate(), info->script());
}
}
@@ -4330,10 +4346,10 @@ void Parser::Internalize() {
for (int feature = 0; feature < v8::Isolate::kUseCounterFeatureCount;
++feature) {
for (int i = 0; i < use_counts_[feature]; ++i) {
- isolate()->CountUsage(v8::Isolate::UseCounterFeature(feature));
+ info->isolate()->CountUsage(v8::Isolate::UseCounterFeature(feature));
}
}
- isolate()->counters()->total_preparse_skipped()->Increment(
+ info->isolate()->counters()->total_preparse_skipped()->Increment(
total_preparse_skipped_);
}
@@ -5251,12 +5267,12 @@ bool RegExpParser::ParseRegExp(Isolate* isolate, Zone* zone,
}
-bool Parser::Parse(CompilationInfo* info, bool allow_lazy) {
+bool Parser::ParseStatic(CompilationInfo* info, bool allow_lazy) {
Parser parser(info, info->isolate()->stack_guard()->real_climit(),
info->isolate()->heap()->HashSeed(),
info->isolate()->unicode_cache());
parser.set_allow_lazy(allow_lazy);
- if (parser.Parse()) {
+ if (parser.Parse(info)) {
info->SetLanguageMode(info->function()->language_mode());
return true;
}
@@ -5264,49 +5280,54 @@ bool Parser::Parse(CompilationInfo* info, bool allow_lazy) {
}
-bool Parser::Parse() {
- DCHECK(info()->function() == NULL);
+bool Parser::Parse(CompilationInfo* info) {
+ DCHECK(info->function() == NULL);
FunctionLiteral* result = NULL;
- pre_parse_timer_ = isolate()->counters()->pre_parse();
+ // Ok to use Isolate here; this function is only called in the main thread.
+ DCHECK(parsing_on_main_thread_);
+ Isolate* isolate = info->isolate();
+ pre_parse_timer_ = isolate->counters()->pre_parse();
if (FLAG_trace_parse || allow_natives() || extension_ != NULL) {
// If intrinsics are allowed, the Parser cannot operate independent of the
// V8 heap because of Runtime. Tell the string table to internalize strings
// and values right after they're created.
- ast_value_factory()->Internalize(isolate());
+ ast_value_factory()->Internalize(isolate);
}
- if (info()->is_lazy()) {
- DCHECK(!info()->is_eval());
- if (info()->shared_info()->is_function()) {
- result = ParseLazy();
+ if (info->is_lazy()) {
+ DCHECK(!info->is_eval());
+ if (info->shared_info()->is_function()) {
+ result = ParseLazy(info);
} else {
- result = ParseProgram();
+ result = ParseProgram(info);
}
} else {
- SetCachedData();
- result = ParseProgram();
+ SetCachedData(info);
+ result = ParseProgram(info);
}
- info()->SetFunction(result);
+ info->SetFunction(result);
- Internalize();
+ Internalize(info);
DCHECK(ast_value_factory()->IsInternalized());
return (result != NULL);
}
-void Parser::ParseOnBackground() {
- DCHECK(info()->function() == NULL);
+void Parser::ParseOnBackground(CompilationInfo* info) {
+ parsing_on_main_thread_ = false;
+
+ DCHECK(info->function() == NULL);
FunctionLiteral* result = NULL;
fni_ = new (zone()) FuncNameInferrer(ast_value_factory(), zone());
CompleteParserRecorder recorder;
if (produce_cached_parse_data()) log_ = &recorder;
- DCHECK(info()->source_stream() != NULL);
- ExternalStreamingStream stream(info()->source_stream(),
- info()->source_stream_encoding());
+ DCHECK(info->source_stream() != NULL);
+ ExternalStreamingStream stream(info->source_stream(),
+ info->source_stream_encoding());
scanner_.Initialize(&stream);
- DCHECK(info()->context().is_null() || info()->context()->IsNativeContext());
+ DCHECK(info->context().is_null() || info->context()->IsNativeContext());
// When streaming, we don't know the length of the source until we have parsed
// it. The raw data can be UTF-8, so we wouldn't know the source length until
@@ -5316,20 +5337,20 @@ void Parser::ParseOnBackground() {
// scopes) and set their end position after we know the script length.
Scope* top_scope = NULL;
Scope* eval_scope = NULL;
- result = DoParseProgram(info(), &top_scope, &eval_scope);
+ result = DoParseProgram(info, &top_scope, &eval_scope);
top_scope->set_end_position(scanner()->location().end_pos);
if (eval_scope != NULL) {
eval_scope->set_end_position(scanner()->location().end_pos);
}
- info()->SetFunction(result);
+ info->SetFunction(result);
// We cannot internalize on a background thread; a foreground task will take
// care of calling Parser::Internalize just before compilation.
if (produce_cached_parse_data()) {
- if (result != NULL) *info_->cached_data() = recorder.GetScriptData();
+ if (result != NULL) *info->cached_data() = recorder.GetScriptData();
log_ = NULL;
}
}
« no previous file with comments | « src/parser.h ('k') | src/preparser.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698