Parsing: Make Parser not know about Isolate during background parsing.
Parser must be able to operate independent of Isolate and the V8 heap during parsing. After the heap-independent phase, there is a heap dependent phase, during which we internalize strings, handle errors, etc. This makes Isolate (also via CompilationInfo) unaccessible during parsing, and thus decreases the probability of accidental code changes which would add heap-dependent operations into the heap-independent phase. Since Isolate is also accessible via CompilationInfo, now CompilationInfo is only passed to the entry points of parsing, and not stored in Parser. R=rossberg@chromium.org BUG= Review URL: https://codereview.chromium.org/908173003 Cr-Commit-Position: refs/heads/master@{#26612}
This commit is contained in:
parent
3336d2e11e
commit
df0cb9999f
@ -1727,8 +1727,8 @@ Local<Script> ScriptCompiler::Compile(Isolate* v8_isolate,
|
||||
|
||||
// Do the parsing tasks which need to be done on the main thread. This will
|
||||
// also handle parse errors.
|
||||
source->parser->Internalize();
|
||||
source->parser->HandleSourceURLComments();
|
||||
source->parser->Internalize(source->info.get());
|
||||
source->parser->HandleSourceURLComments(source->info.get());
|
||||
|
||||
i::Handle<i::SharedFunctionInfo> result =
|
||||
i::Handle<i::SharedFunctionInfo>::null();
|
||||
|
@ -54,7 +54,7 @@ void BackgroundParsingTask::Run() {
|
||||
source_->hash_seed,
|
||||
&source_->unicode_cache));
|
||||
source_->parser->set_allow_lazy(source_->allow_lazy);
|
||||
source_->parser->ParseOnBackground();
|
||||
source_->parser->ParseOnBackground(source_->info.get());
|
||||
|
||||
if (script_data != NULL) {
|
||||
source_->cached_data.Reset(new ScriptCompiler::CachedData(
|
||||
|
@ -645,7 +645,7 @@ MUST_USE_RESULT static MaybeHandle<Code> GetUnoptimizedCodeCommon(
|
||||
PostponeInterruptsScope postpone(info->isolate());
|
||||
|
||||
// Parse and update CompilationInfo with the results.
|
||||
if (!Parser::Parse(info)) return MaybeHandle<Code>();
|
||||
if (!Parser::ParseStatic(info)) return MaybeHandle<Code>();
|
||||
Handle<SharedFunctionInfo> shared = info->shared_info();
|
||||
FunctionLiteral* lit = info->function();
|
||||
shared->set_language_mode(lit->language_mode());
|
||||
@ -817,7 +817,7 @@ bool Compiler::Analyze(CompilationInfo* info) {
|
||||
|
||||
|
||||
bool Compiler::ParseAndAnalyze(CompilationInfo* info) {
|
||||
if (!Parser::Parse(info)) return false;
|
||||
if (!Parser::ParseStatic(info)) return false;
|
||||
return Compiler::Analyze(info);
|
||||
}
|
||||
|
||||
@ -1058,7 +1058,7 @@ void Compiler::CompileForLiveEdit(Handle<Script> script) {
|
||||
VMState<COMPILER> state(info.isolate());
|
||||
|
||||
info.MarkAsGlobal();
|
||||
if (!Parser::Parse(&info)) return;
|
||||
if (!Parser::ParseStatic(&info)) return;
|
||||
|
||||
LiveEditFunctionTracker tracker(info.isolate(), info.function());
|
||||
if (!CompileUnoptimizedCode(&info)) return;
|
||||
@ -1108,7 +1108,7 @@ static Handle<SharedFunctionInfo> CompileToplevel(CompilationInfo* info) {
|
||||
// data while parsing eagerly is not implemented.
|
||||
info->SetCachedData(NULL, ScriptCompiler::kNoCompileOptions);
|
||||
}
|
||||
if (!Parser::Parse(info, parse_allow_lazy)) {
|
||||
if (!Parser::ParseStatic(info, parse_allow_lazy)) {
|
||||
return Handle<SharedFunctionInfo>::null();
|
||||
}
|
||||
}
|
||||
|
205
src/parser.cc
205
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;
|
||||
}
|
||||
}
|
||||
|
35
src/parser.h
35
src/parser.h
@ -647,14 +647,14 @@ class Parser : public ParserBase<ParserTraits> {
|
||||
// Parses the source code represented by the compilation info and sets its
|
||||
// function literal. Returns false (and deallocates any allocated AST
|
||||
// nodes) if parsing failed.
|
||||
static bool Parse(CompilationInfo* info, bool allow_lazy = false);
|
||||
bool Parse();
|
||||
void ParseOnBackground();
|
||||
static bool ParseStatic(CompilationInfo* info, bool allow_lazy = false);
|
||||
bool Parse(CompilationInfo* info);
|
||||
void ParseOnBackground(CompilationInfo* info);
|
||||
|
||||
// Handle errors detected during parsing, move statistics to Isolate,
|
||||
// internalize strings (move them to the heap).
|
||||
void Internalize();
|
||||
void HandleSourceURLComments();
|
||||
void Internalize(CompilationInfo* info);
|
||||
void HandleSourceURLComments(CompilationInfo* info);
|
||||
|
||||
private:
|
||||
friend class ParserTraits;
|
||||
@ -681,31 +681,28 @@ class Parser : public ParserBase<ParserTraits> {
|
||||
};
|
||||
|
||||
// Returns NULL if parsing failed.
|
||||
FunctionLiteral* ParseProgram();
|
||||
FunctionLiteral* ParseProgram(CompilationInfo* info);
|
||||
|
||||
FunctionLiteral* ParseLazy();
|
||||
FunctionLiteral* ParseLazy(Utf16CharacterStream* source);
|
||||
|
||||
Isolate* isolate() { return info_->isolate(); }
|
||||
CompilationInfo* info() const { return info_; }
|
||||
Handle<Script> script() const { return info_->script(); }
|
||||
FunctionLiteral* ParseLazy(CompilationInfo* info);
|
||||
FunctionLiteral* ParseLazy(CompilationInfo* info,
|
||||
Utf16CharacterStream* source);
|
||||
|
||||
// Called by ParseProgram after setting up the scanner.
|
||||
FunctionLiteral* DoParseProgram(CompilationInfo* info, Scope** scope,
|
||||
Scope** ad_hoc_eval_scope);
|
||||
|
||||
void SetCachedData();
|
||||
void SetCachedData(CompilationInfo* info);
|
||||
|
||||
bool inside_with() const { return scope_->inside_with(); }
|
||||
ScriptCompiler::CompileOptions compile_options() const {
|
||||
return info_->compile_options();
|
||||
return compile_options_;
|
||||
}
|
||||
bool consume_cached_parse_data() const {
|
||||
return compile_options() == ScriptCompiler::kConsumeParserCache &&
|
||||
return compile_options_ == ScriptCompiler::kConsumeParserCache &&
|
||||
cached_parse_data_ != NULL;
|
||||
}
|
||||
bool produce_cached_parse_data() const {
|
||||
return compile_options() == ScriptCompiler::kProduceParserCache;
|
||||
return compile_options_ == ScriptCompiler::kProduceParserCache;
|
||||
}
|
||||
Scope* DeclarationScope(VariableMode mode) {
|
||||
return IsLexicalVariableMode(mode)
|
||||
@ -841,7 +838,7 @@ class Parser : public ParserBase<ParserTraits> {
|
||||
const AstRawString* function_name, int pos, Variable* fvar,
|
||||
Token::Value fvar_init_op, FunctionKind kind, bool* ok);
|
||||
|
||||
void ThrowPendingError();
|
||||
void ThrowPendingError(Isolate* isolate, Handle<Script> script);
|
||||
|
||||
TemplateLiteralState OpenTemplateLiteral(int pos);
|
||||
void AddTemplateSpan(TemplateLiteralState* state, bool tail);
|
||||
@ -855,9 +852,9 @@ class Parser : public ParserBase<ParserTraits> {
|
||||
PreParser* reusable_preparser_;
|
||||
Scope* original_scope_; // for ES5 function declarations in sloppy eval
|
||||
Target* target_stack_; // for break, continue statements
|
||||
ScriptCompiler::CompileOptions compile_options_;
|
||||
ParseData* cached_parse_data_;
|
||||
|
||||
CompilationInfo* info_;
|
||||
bool parsing_lazy_arrow_parameters_; // for lazily parsed arrow functions.
|
||||
|
||||
// Pending errors.
|
||||
@ -873,6 +870,8 @@ class Parser : public ParserBase<ParserTraits> {
|
||||
int use_counts_[v8::Isolate::kUseCounterFeatureCount];
|
||||
int total_preparse_skipped_;
|
||||
HistogramTimer* pre_parse_timer_;
|
||||
|
||||
bool parsing_on_main_thread_;
|
||||
};
|
||||
|
||||
|
||||
|
@ -67,10 +67,9 @@ class ParserBase : public Traits {
|
||||
typedef typename Traits::Type::Literal LiteralT;
|
||||
typedef typename Traits::Type::ObjectLiteralProperty ObjectLiteralPropertyT;
|
||||
|
||||
ParserBase(Isolate* isolate, Zone* zone, Scanner* scanner,
|
||||
uintptr_t stack_limit, v8::Extension* extension,
|
||||
AstValueFactory* ast_value_factory, ParserRecorder* log,
|
||||
typename Traits::Type::Parser this_object)
|
||||
ParserBase(Zone* zone, Scanner* scanner, uintptr_t stack_limit,
|
||||
v8::Extension* extension, AstValueFactory* ast_value_factory,
|
||||
ParserRecorder* log, typename Traits::Type::Parser this_object)
|
||||
: Traits(this_object),
|
||||
parenthesized_function_(false),
|
||||
scope_(NULL),
|
||||
@ -81,7 +80,6 @@ class ParserBase : public Traits {
|
||||
log_(log),
|
||||
mode_(PARSE_EAGERLY), // Lazy mode must be set explicitly.
|
||||
stack_limit_(stack_limit),
|
||||
isolate_(isolate),
|
||||
zone_(zone),
|
||||
scanner_(scanner),
|
||||
stack_overflow_(false),
|
||||
@ -318,7 +316,6 @@ class ParserBase : public Traits {
|
||||
return result;
|
||||
}
|
||||
|
||||
Isolate* isolate() const { return isolate_; }
|
||||
Scanner* scanner() const { return scanner_; }
|
||||
AstValueFactory* ast_value_factory() const { return ast_value_factory_; }
|
||||
int position() { return scanner_->location().beg_pos; }
|
||||
@ -653,7 +650,6 @@ class ParserBase : public Traits {
|
||||
uintptr_t stack_limit_;
|
||||
|
||||
private:
|
||||
Isolate* isolate_;
|
||||
Zone* zone_;
|
||||
|
||||
Scanner* scanner_;
|
||||
@ -1507,10 +1503,9 @@ class PreParser : public ParserBase<PreParserTraits> {
|
||||
kPreParseSuccess
|
||||
};
|
||||
|
||||
PreParser(Isolate* isolate, Zone* zone, Scanner* scanner,
|
||||
AstValueFactory* ast_value_factory, ParserRecorder* log,
|
||||
uintptr_t stack_limit)
|
||||
: ParserBase<PreParserTraits>(isolate, zone, scanner, stack_limit, NULL,
|
||||
PreParser(Zone* zone, Scanner* scanner, AstValueFactory* ast_value_factory,
|
||||
ParserRecorder* log, uintptr_t stack_limit)
|
||||
: ParserBase<PreParserTraits>(zone, scanner, stack_limit, NULL,
|
||||
ast_value_factory, log, this) {}
|
||||
|
||||
// Pre-parse the program from the character stream; returns true on
|
||||
|
@ -1208,14 +1208,14 @@ class ScopeIterator {
|
||||
info.MarkAsEval();
|
||||
info.SetContext(Handle<Context>(function_->context()));
|
||||
}
|
||||
if (Parser::Parse(&info) && Scope::Analyze(&info)) {
|
||||
if (Parser::ParseStatic(&info) && Scope::Analyze(&info)) {
|
||||
scope = info.function()->scope();
|
||||
}
|
||||
RetrieveScopeChain(scope, shared_info);
|
||||
} else {
|
||||
// Function code
|
||||
CompilationInfoWithZone info(shared_info);
|
||||
if (Parser::Parse(&info) && Scope::Analyze(&info)) {
|
||||
if (Parser::ParseStatic(&info) && Scope::Analyze(&info)) {
|
||||
scope = info.function()->scope();
|
||||
}
|
||||
RetrieveScopeChain(scope, shared_info);
|
||||
|
@ -166,7 +166,7 @@ RUNTIME_FUNCTION(Runtime_RenderCallSite) {
|
||||
Zone zone;
|
||||
if (location.function()->shared()->is_function()) {
|
||||
CompilationInfo info(location.function(), &zone);
|
||||
if (!Parser::Parse(&info)) {
|
||||
if (!Parser::ParseStatic(&info)) {
|
||||
isolate->clear_pending_exception();
|
||||
return isolate->heap()->empty_string();
|
||||
}
|
||||
@ -176,7 +176,7 @@ RUNTIME_FUNCTION(Runtime_RenderCallSite) {
|
||||
}
|
||||
|
||||
CompilationInfo info(location.script(), &zone);
|
||||
if (!Parser::Parse(&info)) {
|
||||
if (!Parser::ParseStatic(&info)) {
|
||||
isolate->clear_pending_exception();
|
||||
return isolate->heap()->empty_string();
|
||||
}
|
||||
|
@ -154,7 +154,7 @@ class FunctionTester : public InitializedHandleScope {
|
||||
#if V8_TURBOFAN_TARGET
|
||||
CompilationInfoWithZone info(function);
|
||||
|
||||
CHECK(Parser::Parse(&info));
|
||||
CHECK(Parser::ParseStatic(&info));
|
||||
info.SetOptimizing(BailoutId::None(), Handle<Code>(function->code()));
|
||||
if (flags_ & CompilationInfo::kContextSpecializing) {
|
||||
info.MarkAsContextSpecializing();
|
||||
@ -210,7 +210,7 @@ class FunctionTester : public InitializedHandleScope {
|
||||
CHECK(Pipeline::SupportedTarget());
|
||||
CompilationInfoWithZone info(function);
|
||||
|
||||
CHECK(Parser::Parse(&info));
|
||||
CHECK(Parser::ParseStatic(&info));
|
||||
info.SetOptimizing(BailoutId::None(),
|
||||
Handle<Code>(function->shared()->code()));
|
||||
CHECK(Compiler::Analyze(&info));
|
||||
|
@ -46,7 +46,7 @@ class DeoptCodegenTester {
|
||||
function(NewFunction(src)),
|
||||
info(function, scope->main_zone()),
|
||||
bailout_id(-1) {
|
||||
CHECK(Parser::Parse(&info));
|
||||
CHECK(Parser::ParseStatic(&info));
|
||||
info.SetOptimizing(BailoutId::None(), Handle<Code>(function->code()));
|
||||
CHECK(Compiler::Analyze(&info));
|
||||
CHECK(Compiler::EnsureDeoptimizationSupport(&info));
|
||||
|
@ -31,7 +31,7 @@ struct TestHelper : public HandleAndZoneScope {
|
||||
// TODO(titzer): don't scope analyze every single time.
|
||||
CompilationInfo info(function, main_zone());
|
||||
|
||||
CHECK(Parser::Parse(&info));
|
||||
CHECK(Parser::ParseStatic(&info));
|
||||
CHECK(Rewriter::Rewrite(&info));
|
||||
CHECK(Scope::Analyze(&info));
|
||||
|
||||
|
@ -160,8 +160,8 @@ TEST(ScanHTMLEndComments) {
|
||||
i::Zone zone;
|
||||
i::AstValueFactory ast_value_factory(
|
||||
&zone, CcTest::i_isolate()->heap()->HashSeed());
|
||||
i::PreParser preparser(CcTest::i_isolate(), &zone, &scanner,
|
||||
&ast_value_factory, &log, stack_limit);
|
||||
i::PreParser preparser(&zone, &scanner, &ast_value_factory, &log,
|
||||
stack_limit);
|
||||
preparser.set_allow_lazy(true);
|
||||
i::PreParser::PreParseResult result = preparser.PreParseProgram();
|
||||
CHECK_EQ(i::PreParser::kPreParseSuccess, result);
|
||||
@ -178,8 +178,8 @@ TEST(ScanHTMLEndComments) {
|
||||
i::Zone zone;
|
||||
i::AstValueFactory ast_value_factory(
|
||||
&zone, CcTest::i_isolate()->heap()->HashSeed());
|
||||
i::PreParser preparser(CcTest::i_isolate(), &zone, &scanner,
|
||||
&ast_value_factory, &log, stack_limit);
|
||||
i::PreParser preparser(&zone, &scanner, &ast_value_factory, &log,
|
||||
stack_limit);
|
||||
preparser.set_allow_lazy(true);
|
||||
i::PreParser::PreParseResult result = preparser.PreParseProgram();
|
||||
// Even in the case of a syntax error, kPreParseSuccess is returned.
|
||||
@ -328,8 +328,8 @@ TEST(StandAlonePreParser) {
|
||||
i::Zone zone;
|
||||
i::AstValueFactory ast_value_factory(
|
||||
&zone, CcTest::i_isolate()->heap()->HashSeed());
|
||||
i::PreParser preparser(CcTest::i_isolate(), &zone, &scanner,
|
||||
&ast_value_factory, &log, stack_limit);
|
||||
i::PreParser preparser(&zone, &scanner, &ast_value_factory, &log,
|
||||
stack_limit);
|
||||
preparser.set_allow_lazy(true);
|
||||
preparser.set_allow_natives(true);
|
||||
preparser.set_allow_harmony_arrow_functions(true);
|
||||
@ -366,8 +366,8 @@ TEST(StandAlonePreParserNoNatives) {
|
||||
i::Zone zone;
|
||||
i::AstValueFactory ast_value_factory(
|
||||
&zone, CcTest::i_isolate()->heap()->HashSeed());
|
||||
i::PreParser preparser(CcTest::i_isolate(), &zone, &scanner,
|
||||
&ast_value_factory, &log, stack_limit);
|
||||
i::PreParser preparser(&zone, &scanner, &ast_value_factory, &log,
|
||||
stack_limit);
|
||||
preparser.set_allow_lazy(true);
|
||||
i::PreParser::PreParseResult result = preparser.PreParseProgram();
|
||||
CHECK_EQ(i::PreParser::kPreParseSuccess, result);
|
||||
@ -435,8 +435,7 @@ TEST(RegressChromium62639) {
|
||||
i::Zone zone;
|
||||
i::AstValueFactory ast_value_factory(&zone,
|
||||
CcTest::i_isolate()->heap()->HashSeed());
|
||||
i::PreParser preparser(CcTest::i_isolate(), &zone, &scanner,
|
||||
&ast_value_factory, &log,
|
||||
i::PreParser preparser(&zone, &scanner, &ast_value_factory, &log,
|
||||
CcTest::i_isolate()->stack_guard()->real_climit());
|
||||
preparser.set_allow_lazy(true);
|
||||
i::PreParser::PreParseResult result = preparser.PreParseProgram();
|
||||
@ -471,8 +470,7 @@ TEST(Regress928) {
|
||||
i::Zone zone;
|
||||
i::AstValueFactory ast_value_factory(&zone,
|
||||
CcTest::i_isolate()->heap()->HashSeed());
|
||||
i::PreParser preparser(CcTest::i_isolate(), &zone, &scanner,
|
||||
&ast_value_factory, &log,
|
||||
i::PreParser preparser(&zone, &scanner, &ast_value_factory, &log,
|
||||
CcTest::i_isolate()->stack_guard()->real_climit());
|
||||
preparser.set_allow_lazy(true);
|
||||
i::PreParser::PreParseResult result = preparser.PreParseProgram();
|
||||
@ -524,8 +522,8 @@ TEST(PreParseOverflow) {
|
||||
i::Zone zone;
|
||||
i::AstValueFactory ast_value_factory(&zone,
|
||||
CcTest::i_isolate()->heap()->HashSeed());
|
||||
i::PreParser preparser(CcTest::i_isolate(), &zone, &scanner,
|
||||
&ast_value_factory, &log, stack_limit);
|
||||
i::PreParser preparser(&zone, &scanner, &ast_value_factory, &log,
|
||||
stack_limit);
|
||||
preparser.set_allow_lazy(true);
|
||||
preparser.set_allow_harmony_arrow_functions(true);
|
||||
i::PreParser::PreParseResult result = preparser.PreParseProgram();
|
||||
@ -1062,7 +1060,7 @@ TEST(ScopeUsesArgumentsSuperThis) {
|
||||
parser.set_allow_harmony_scoping(true);
|
||||
parser.set_allow_harmony_sloppy(true);
|
||||
info.MarkAsGlobal();
|
||||
CHECK(parser.Parse());
|
||||
CHECK(parser.Parse(&info));
|
||||
CHECK(i::Rewriter::Rewrite(&info));
|
||||
CHECK(i::Scope::Analyze(&info));
|
||||
CHECK(info.function() != NULL);
|
||||
@ -1317,7 +1315,7 @@ TEST(ScopePositions) {
|
||||
parser.set_allow_harmony_arrow_functions(true);
|
||||
info.MarkAsGlobal();
|
||||
info.SetLanguageMode(source_data[i].language_mode);
|
||||
parser.Parse();
|
||||
parser.Parse(&info);
|
||||
CHECK(info.function() != NULL);
|
||||
|
||||
// Check scope types and positions.
|
||||
@ -1453,8 +1451,8 @@ void TestParserSyncWithFlags(i::Handle<i::String> source,
|
||||
i::Zone zone;
|
||||
i::AstValueFactory ast_value_factory(
|
||||
&zone, CcTest::i_isolate()->heap()->HashSeed());
|
||||
i::PreParser preparser(CcTest::i_isolate(), &zone, &scanner,
|
||||
&ast_value_factory, &log, stack_limit);
|
||||
i::PreParser preparser(&zone, &scanner, &ast_value_factory, &log,
|
||||
stack_limit);
|
||||
SetParserFlags(&preparser, flags);
|
||||
scanner.Initialize(&stream);
|
||||
i::PreParser::PreParseResult result = preparser.PreParseProgram(
|
||||
@ -1473,7 +1471,7 @@ void TestParserSyncWithFlags(i::Handle<i::String> source,
|
||||
isolate->heap()->HashSeed(), isolate->unicode_cache());
|
||||
SetParserFlags(&parser, flags);
|
||||
info.MarkAsGlobal();
|
||||
parser.Parse();
|
||||
parser.Parse(&info);
|
||||
function = info.function();
|
||||
if (function) {
|
||||
parser_materialized_literals = function->materialized_literal_count();
|
||||
@ -2558,7 +2556,7 @@ TEST(DontRegressPreParserDataSizes) {
|
||||
i::CompilationInfoWithZone info(script);
|
||||
i::ScriptData* sd = NULL;
|
||||
info.SetCachedData(&sd, v8::ScriptCompiler::kProduceParserCache);
|
||||
i::Parser::Parse(&info, true);
|
||||
i::Parser::ParseStatic(&info, true);
|
||||
i::ParseData* pd = i::ParseData::FromCachedData(sd);
|
||||
|
||||
if (pd->FunctionCount() != test_cases[i].functions) {
|
||||
@ -3437,7 +3435,7 @@ TEST(InnerAssignment) {
|
||||
isolate->heap()->HashSeed(),
|
||||
isolate->unicode_cache());
|
||||
parser.set_allow_harmony_scoping(true);
|
||||
CHECK(parser.Parse());
|
||||
CHECK(parser.Parse(&info));
|
||||
CHECK(i::Compiler::Analyze(&info));
|
||||
CHECK(info.function() != NULL);
|
||||
|
||||
@ -5051,7 +5049,7 @@ TEST(BasicImportExportParsing) {
|
||||
parser.set_allow_harmony_modules(true);
|
||||
parser.set_allow_harmony_scoping(true);
|
||||
info.MarkAsModule();
|
||||
if (!parser.Parse()) {
|
||||
if (!parser.Parse(&info)) {
|
||||
i::Handle<i::JSObject> exception_handle(
|
||||
i::JSObject::cast(isolate->pending_exception()));
|
||||
i::Handle<i::String> message_string =
|
||||
@ -5079,7 +5077,7 @@ TEST(BasicImportExportParsing) {
|
||||
parser.set_allow_harmony_modules(true);
|
||||
parser.set_allow_harmony_scoping(true);
|
||||
info.MarkAsGlobal();
|
||||
CHECK(!parser.Parse());
|
||||
CHECK(!parser.Parse(&info));
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -5169,7 +5167,7 @@ TEST(ImportExportParsingErrors) {
|
||||
parser.set_allow_harmony_modules(true);
|
||||
parser.set_allow_harmony_scoping(true);
|
||||
info.MarkAsModule();
|
||||
CHECK(!parser.Parse());
|
||||
CHECK(!parser.Parse(&info));
|
||||
}
|
||||
}
|
||||
|
||||
@ -5261,7 +5259,7 @@ void TestLanguageMode(const char* source,
|
||||
isolate->heap()->HashSeed(), isolate->unicode_cache());
|
||||
parser.set_allow_strong_mode(true);
|
||||
info.MarkAsGlobal();
|
||||
parser.Parse();
|
||||
parser.Parse(&info);
|
||||
CHECK(info.function() != NULL);
|
||||
CHECK_EQ(expected_language_mode, info.function()->language_mode());
|
||||
}
|
||||
|
@ -95,7 +95,7 @@ std::pair<v8::base::TimeDelta, v8::base::TimeDelta> RunBaselineParser(
|
||||
v8::base::ElapsedTimer timer;
|
||||
timer.Start();
|
||||
// Allow lazy parsing; otherwise we won't produce cached data.
|
||||
bool success = Parser::Parse(&info, true);
|
||||
bool success = Parser::ParseStatic(&info, true);
|
||||
parse_time1 = timer.Elapsed();
|
||||
if (!success) {
|
||||
fprintf(stderr, "Parsing failed\n");
|
||||
@ -111,7 +111,7 @@ std::pair<v8::base::TimeDelta, v8::base::TimeDelta> RunBaselineParser(
|
||||
v8::base::ElapsedTimer timer;
|
||||
timer.Start();
|
||||
// Allow lazy parsing; otherwise cached data won't help.
|
||||
bool success = Parser::Parse(&info, true);
|
||||
bool success = Parser::ParseStatic(&info, true);
|
||||
parse_time2 = timer.Elapsed();
|
||||
if (!success) {
|
||||
fprintf(stderr, "Parsing failed\n");
|
||||
|
Loading…
Reference in New Issue
Block a user