[Interpreter] Localize the CanonicalHandleScope to parsing and renumbering.

Ignition requires that objects which will be inserted into the
constant pool are canonicalized (to enable off-thread bytecode
generation). We created a CanonicalizeHandleScope across parse/compile
however this impacts performance (~5-8% on CodeLoad).

Now we localize the CanonicalHandleScope to only the parse /
internalization and renumbering phases where objects are created which
could end up in the constant array pool. This seems to address
the performance regression.

BUG=v8:5203,chromium:634953

Review-Url: https://codereview.chromium.org/2318653002
Cr-Commit-Position: refs/heads/master@{#39443}
This commit is contained in:
rmcilroy 2016-09-15 03:26:19 -07:00 committed by Commit bot
parent eeb4f28aed
commit b37daacd6b
3 changed files with 47 additions and 46 deletions

View File

@ -2223,15 +2223,18 @@ MaybeLocal<Script> ScriptCompiler::Compile(Local<Context> context,
source->info->set_script(script);
source->info->set_context(isolate->native_context());
// Create a canonical handle scope before internalizing parsed values if
// compiling bytecode. This is required for off-thread bytecode generation.
std::unique_ptr<i::CanonicalHandleScope> canonical;
if (i::FLAG_ignition) canonical.reset(new i::CanonicalHandleScope(isolate));
{
// Create a canonical handle scope if compiling ignition bytecode. This is
// required by the constant array builder to de-duplicate objects without
// dereferencing handles.
std::unique_ptr<i::CanonicalHandleScope> canonical;
if (i::FLAG_ignition) canonical.reset(new i::CanonicalHandleScope(isolate));
// Do the parsing tasks which need to be done on the main thread. This will
// also handle parse errors.
source->parser->Internalize(isolate, script,
source->info->literal() == nullptr);
// Do the parsing tasks which need to be done on the main thread. This will
// also handle parse errors.
source->parser->Internalize(isolate, script,
source->info->literal() == nullptr);
}
source->parser->HandleSourceURLComments(isolate, script);
i::Handle<i::SharedFunctionInfo> result;

View File

@ -138,11 +138,6 @@ bool CompilerDispatcherJob::FinalizeParsingOnMainThread() {
DeferredHandleScope scope(isolate_);
{
// Create a canonical handle scope before internalizing parsed values if
// compiling bytecode. This is required for off-thread bytecode generation.
std::unique_ptr<CanonicalHandleScope> canonical;
if (FLAG_ignition) canonical.reset(new CanonicalHandleScope(isolate_));
Handle<SharedFunctionInfo> shared(function_->shared(), isolate_);
Handle<Script> script(Script::cast(shared->script()), isolate_);
@ -150,9 +145,17 @@ bool CompilerDispatcherJob::FinalizeParsingOnMainThread() {
parse_info_->set_context(handle(function_->context(), isolate_));
parse_info_->set_shared_info(handle(function_->shared(), isolate_));
// Do the parsing tasks which need to be done on the main thread. This will
// also handle parse errors.
parser_->Internalize(isolate_, script, parse_info_->literal() == nullptr);
{
// Create a canonical handle scope if compiling ignition bytecode. This is
// required by the constant array builder to de-duplicate objects without
// dereferencing handles.
std::unique_ptr<CanonicalHandleScope> canonical;
if (FLAG_ignition) canonical.reset(new CanonicalHandleScope(isolate_));
// Do the parsing tasks which need to be done on the main thread. This
// will also handle parse errors.
parser_->Internalize(isolate_, script, parse_info_->literal() == nullptr);
}
parser_->HandleSourceURLComments(isolate_, script);
parse_info_->set_character_stream(nullptr);
@ -173,16 +176,9 @@ bool CompilerDispatcherJob::PrepareToCompileOnMainThread() {
compile_info_.reset(new CompilationInfo(parse_info_.get(), function_));
DeferredHandleScope scope(isolate_);
{
// Create a canonical handle scope before ast numbering if compiling
// bytecode. This is required for off-thread bytecode generation.
std::unique_ptr<CanonicalHandleScope> canonical;
if (FLAG_ignition) canonical.reset(new CanonicalHandleScope(isolate_));
if (Compiler::Analyze(parse_info_.get())) {
compile_job_.reset(
Compiler::PrepareUnoptimizedCompilationJob(compile_info_.get()));
}
if (Compiler::Analyze(parse_info_.get())) {
compile_job_.reset(
Compiler::PrepareUnoptimizedCompilationJob(compile_info_.get()));
}
compile_info_->set_deferred_handles(scope.Detach());

View File

@ -257,6 +257,16 @@ bool IsEvalToplevel(Handle<SharedFunctionInfo> shared) {
Script::COMPILATION_TYPE_EVAL;
}
bool Parse(ParseInfo* info) {
// Create a canonical handle scope if compiling ignition bytecode. This is
// required by the constant array builder to de-duplicate objects without
// dereferencing handles.
std::unique_ptr<CanonicalHandleScope> canonical;
if (FLAG_ignition) canonical.reset(new CanonicalHandleScope(info->isolate()));
return Parser::ParseStatic(info);
}
void RecordFunctionCompilation(CodeEventListener::LogEventsAndTags tag,
CompilationInfo* info) {
// Log the code generation. If source information is available include
@ -421,13 +431,8 @@ MUST_USE_RESULT MaybeHandle<Code> GetUnoptimizedCode(CompilationInfo* info) {
VMState<COMPILER> state(info->isolate());
PostponeInterruptsScope postpone(info->isolate());
// Create a canonical handle scope before internalizing parsed values if
// compiling bytecode. This is required for off-thread bytecode generation.
std::unique_ptr<CanonicalHandleScope> canonical;
if (FLAG_ignition) canonical.reset(new CanonicalHandleScope(info->isolate()));
// Parse and update CompilationInfo with the results.
if (!Parser::ParseStatic(info->parse_info())) return MaybeHandle<Code>();
if (!Parse(info->parse_info())) return MaybeHandle<Code>();
DCHECK_EQ(info->shared_info()->language_mode(),
info->literal()->language_mode());
@ -501,6 +506,14 @@ void InsertCodeIntoOptimizedCodeMap(CompilationInfo* info) {
}
bool Renumber(ParseInfo* parse_info) {
// Create a canonical handle scope if compiling ignition bytecode. This is
// required by the constant array builder to de-duplicate objects without
// dereferencing handles.
std::unique_ptr<CanonicalHandleScope> canonical;
if (FLAG_ignition) {
canonical.reset(new CanonicalHandleScope(parse_info->isolate()));
}
if (!AstNumbering::Renumber(parse_info->isolate(), parse_info->zone(),
parse_info->literal())) {
return false;
@ -924,7 +937,7 @@ MaybeHandle<Code> GetBaselineCode(Handle<JSFunction> function) {
}
// Parse and update CompilationInfo with the results.
if (!Parser::ParseStatic(info.parse_info())) return MaybeHandle<Code>();
if (!Parse(info.parse_info())) return MaybeHandle<Code>();
Handle<SharedFunctionInfo> shared = info.shared_info();
DCHECK_EQ(shared->language_mode(), info.literal()->language_mode());
@ -1027,11 +1040,6 @@ Handle<SharedFunctionInfo> CompileToplevel(CompilationInfo* info) {
ParseInfo* parse_info = info->parse_info();
Handle<Script> script = parse_info->script();
// Create a canonical handle scope before internalizing parsed values if
// compiling bytecode. This is required for off-thread bytecode generation.
std::unique_ptr<CanonicalHandleScope> canonical;
if (FLAG_ignition) canonical.reset(new CanonicalHandleScope(isolate));
// TODO(svenpanne) Obscure place for this, perhaps move to OnBeforeCompile?
FixedArray* array = isolate->native_context()->embedder_data();
script->set_context_data(array->get(v8::Context::kDebugIdIndex));
@ -1075,7 +1083,7 @@ Handle<SharedFunctionInfo> CompileToplevel(CompilationInfo* info) {
parse_info->set_compile_options(ScriptCompiler::kNoCompileOptions);
}
if (!Parser::ParseStatic(parse_info)) {
if (!Parse(parse_info)) {
return Handle<SharedFunctionInfo>::null();
}
}
@ -1152,7 +1160,7 @@ bool Compiler::Analyze(ParseInfo* info) {
}
bool Compiler::ParseAndAnalyze(ParseInfo* info) {
if (!Parser::ParseStatic(info)) return false;
if (!Parse(info)) return false;
if (!Compiler::Analyze(info)) return false;
DCHECK_NOT_NULL(info->literal());
DCHECK_NOT_NULL(info->scope());
@ -1774,12 +1782,6 @@ Handle<SharedFunctionInfo> Compiler::GetSharedFunctionInfo(
RuntimeCallTimerScope runtimeTimer(isolate, &RuntimeCallStats::CompileCode);
TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8.compile"), "V8.CompileCode");
// Create a canonical handle scope if compiling ignition bytecode. This is
// required by the constant array builder to de-duplicate common objects
// without dereferencing handles.
std::unique_ptr<CanonicalHandleScope> canonical;
if (FLAG_ignition) canonical.reset(new CanonicalHandleScope(info.isolate()));
if (lazy) {
info.SetCode(isolate->builtins()->CompileLazy());
} else if (Renumber(info.parse_info()) && GenerateUnoptimizedCode(&info)) {