Commit 9a4b334f authored by Ross McIlroy's avatar Ross McIlroy Committed by Commit Bot

[compiler] Add background compilation mode.

Adds support for compiling top-level code on a background thread behind a flag.
When the flag is enabled, any background-parsing-task will perform compilation
as well as parsing.

BUG=v8:5203
TBR=marja@chromium.org,mstarzinger@chromium.org

Cq-Include-Trybots: master.tryserver.chromium.linux:linux_chromium_rel_ng
Change-Id: Icf90ac7211298d3555515dafc7c3245618ec1304
Reviewed-on: https://chromium-review.googlesource.com/764048
Commit-Queue: Ross McIlroy <rmcilroy@chromium.org>
Reviewed-by: 's avatarRoss McIlroy <rmcilroy@chromium.org>
Cr-Commit-Position: refs/heads/master@{#49364}
parent adc52af5
......@@ -2613,20 +2613,26 @@ MaybeLocal<Script> ScriptCompiler::Compile(Local<Context> context,
}
source->info->set_script(script);
if (source->info->literal() == nullptr) {
source->info->pending_error_handler()->ReportErrors(
isolate, script, source->info->ast_value_factory());
}
source->parser->UpdateStatistics(isolate, script);
source->info->UpdateStatisticsAfterBackgroundParse(isolate);
source->parser->HandleSourceURLComments(isolate, script);
i::Handle<i::SharedFunctionInfo> result;
if (source->info->literal() != nullptr) {
// Parsing has succeeded.
if (source->info->literal() == nullptr) {
// Parsing has failed - report error messages.
source->info->pending_error_handler()->ReportErrors(
isolate, script, source->info->ast_value_factory());
} else {
// Parsing has succeeded - finalize compile.
if (i::FLAG_background_compile) {
result = i::Compiler::GetSharedFunctionInfoForBackgroundCompile(
script, source->info.get(), str->length(),
source->outer_function_job.get(), &source->inner_function_jobs);
} else {
result = i::Compiler::GetSharedFunctionInfoForStreamedScript(
script, source->info.get(), str->length());
}
}
has_pending_exception = result.is_null();
if (has_pending_exception) isolate->ReportPendingMessages();
......
......@@ -188,7 +188,7 @@ class AsmJsCompilationJob final : public CompilationJob {
explicit AsmJsCompilationJob(ParseInfo* parse_info, FunctionLiteral* literal,
Isolate* isolate)
: CompilationJob(parse_info->stack_limit(), parse_info,
&compilation_info_, "AsmJs"),
&compilation_info_, "AsmJs", State::kReadyToExecute),
zone_(isolate->allocator(), ZONE_NAME),
compilation_info_(&zone_, isolate, parse_info, literal),
module_(nullptr),
......@@ -215,6 +215,7 @@ class AsmJsCompilationJob final : public CompilationJob {
};
CompilationJob::Status AsmJsCompilationJob::PrepareJobImpl() {
UNREACHABLE(); // Prepare should always be skipped.
return SUCCEEDED;
}
......
......@@ -11,6 +11,7 @@
#include "src/compiler.h"
#include "src/flags.h"
#include "src/global-handles.h"
#include "src/interpreter/interpreter.h"
#include "src/isolate.h"
#include "src/objects-inl.h"
#include "src/parsing/parse-info.h"
......@@ -360,8 +361,9 @@ void UnoptimizedCompileJob::PrepareToCompileOnMainThread(Isolate* isolate) {
DCHECK_EQ(status(), Status::kAnalyzed);
COMPILER_DISPATCHER_TRACE_SCOPE(tracer_, kPrepareToCompile);
compilation_job_.reset(
Compiler::PrepareUnoptimizedCompilationJob(parse_info_.get(), isolate));
compilation_job_.reset(interpreter::Interpreter::NewCompilationJob(
parse_info_.get(), parse_info_->literal(), isolate));
if (!compilation_job_.get()) {
if (!isolate->has_pending_exception()) isolate->StackOverflow();
status_ = Status::kFailed;
......
This diff is collapsed.
......@@ -5,6 +5,7 @@
#ifndef V8_COMPILER_H_
#define V8_COMPILER_H_
#include <forward_list>
#include <memory>
#include "src/allocation.h"
......@@ -28,6 +29,8 @@ class ThreadedList;
template <typename T>
class ThreadedListZoneEntry;
typedef std::forward_list<std::unique_ptr<CompilationJob>> CompilationJobList;
// The V8 compiler API.
//
// This is the central hub for dispatching to the various compilers within V8.
......@@ -54,9 +57,11 @@ class V8_EXPORT_PRIVATE Compiler : public AllStatic {
static bool CompileOptimized(Handle<JSFunction> function, ConcurrencyMode);
static MaybeHandle<JSArray> CompileForLiveEdit(Handle<Script> script);
// Prepare a compilation job for unoptimized code. Requires ParseAndAnalyse.
static CompilationJob* PrepareUnoptimizedCompilationJob(ParseInfo* parse_info,
Isolate* isolate);
// Compile top level code on a background thread. Should be finalized by
// GetSharedFunctionInfoForBackgroundCompile.
static std::unique_ptr<CompilationJob> CompileTopLevelOnBackgroundThread(
ParseInfo* parse_info, Isolate* isolate,
CompilationJobList* inner_function_jobs);
// Generate and install code from previously queued compilation job.
static bool FinalizeCompilationJob(CompilationJob* job);
......@@ -128,6 +133,13 @@ class V8_EXPORT_PRIVATE Compiler : public AllStatic {
Handle<Script> script,
Isolate* isolate);
// Create a shared function info object for a Script that has already been
// compiled on a background thread.
static Handle<SharedFunctionInfo> GetSharedFunctionInfoForBackgroundCompile(
Handle<Script> script, ParseInfo* parse_info, int source_length,
CompilationJob* outer_function_job,
CompilationJobList* inner_function_jobs);
// Create a shared function info object for a native function literal.
static Handle<SharedFunctionInfo> GetSharedFunctionInfoForNative(
v8::Extension* extension, Handle<String> name);
......
......@@ -785,10 +785,13 @@ class RuntimeCallTimer final {
V(ArrayLengthSetter) \
V(BoundFunctionNameGetter) \
V(BoundFunctionLengthGetter) \
V(CompileBackgroundAnalyse) \
V(CompileBackgroundEval) \
V(CompileBackgroundIgnition) \
V(CompileBackgroundScript) \
V(CompileDeserialize) \
V(CompileEval) \
V(CompileAnalyse) \
V(CompileBackgroundIgnition) \
V(CompileFunction) \
V(CompileGetFromOptimizedCodeMap) \
V(CompileIgnition) \
......
......@@ -889,6 +889,9 @@ DEFINE_BOOL(preparser_scope_analysis, true,
"perform scope analysis for preparsed inner functions")
DEFINE_IMPLICATION(preparser_scope_analysis, aggressive_lazy_inner_functions)
// compiler.cc
DEFINE_BOOL(background_compile, false, "enable background compilation")
// simulator-arm.cc, simulator-arm64.cc and simulator-mips.cc
DEFINE_BOOL(trace_sim, false, "Trace simulator execution")
DEFINE_BOOL(debug_sim, false, "Enable debugging the simulator")
......
......@@ -37,41 +37,11 @@ class InterpreterCompilationJob final : public CompilationJob {
Status FinalizeJobImpl() final;
private:
class TimerScope final {
public:
explicit TimerScope(RuntimeCallCounter* counter)
: runtime_stats_enabled_(FLAG_runtime_stats) {
if (V8_UNLIKELY(runtime_stats_enabled_ && counter != nullptr)) {
timer_.Start(counter, nullptr);
}
}
~TimerScope() {
if (V8_UNLIKELY(runtime_stats_enabled_)) {
timer_.Stop();
}
}
private:
RuntimeCallTimer timer_;
bool runtime_stats_enabled_;
DISALLOW_COPY_AND_ASSIGN(TimerScope);
};
bool executed_on_background_thread() {
// TODO(rmcilroy): Fix once we create InterpreterCompilationJob on
// background thread.
return false;
}
BytecodeGenerator* generator() { return &generator_; }
Zone zone_;
CompilationInfo compilation_info_;
BytecodeGenerator generator_;
RuntimeCallStats* runtime_call_stats_;
RuntimeCallCounter background_execute_counter_;
DISALLOW_COPY_AND_ASSIGN(InterpreterCompilationJob);
};
......@@ -195,24 +165,26 @@ InterpreterCompilationJob::InterpreterCompilationJob(ParseInfo* parse_info,
FunctionLiteral* literal,
Isolate* isolate)
: CompilationJob(parse_info->stack_limit(), parse_info, &compilation_info_,
"Ignition"),
"Ignition", State::kReadyToExecute),
zone_(isolate->allocator(), ZONE_NAME),
compilation_info_(&zone_, isolate, parse_info, literal),
generator_(&compilation_info_),
runtime_call_stats_(isolate->counters()->runtime_call_stats()),
background_execute_counter_("CompileBackgroundIgnition") {}
generator_(&compilation_info_) {}
InterpreterCompilationJob::Status InterpreterCompilationJob::PrepareJobImpl() {
MaybePrintAst(parse_info(), compilation_info());
UNREACHABLE(); // Prepare should always be skipped.
return SUCCEEDED;
}
InterpreterCompilationJob::Status InterpreterCompilationJob::ExecuteJobImpl() {
TimerScope runtimeTimer(
executed_on_background_thread() ? &background_execute_counter_ : nullptr);
RuntimeCallTimerScope runtimeTimerScope(
!executed_on_background_thread() ? runtime_call_stats_ : nullptr,
&RuntimeCallStats::CompileIgnition);
parse_info()->runtime_call_stats(),
parse_info()->on_background_thread()
? &RuntimeCallStats::CompileBackgroundIgnition
: &RuntimeCallStats::CompileIgnition);
// Print AST if flag is enabled. Note, if compiling on a background thread
// then ASTs from different functions may be intersperse when printed.
MaybePrintAst(parse_info(), compilation_info());
// TODO(lpy): add support for background compilation RCS trace.
TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8.compile"), "V8.CompileIgnition");
......@@ -226,14 +198,8 @@ InterpreterCompilationJob::Status InterpreterCompilationJob::ExecuteJobImpl() {
}
InterpreterCompilationJob::Status InterpreterCompilationJob::FinalizeJobImpl() {
// Add background runtime call stats.
if (V8_UNLIKELY(FLAG_runtime_stats && executed_on_background_thread())) {
runtime_call_stats_->CompileBackgroundIgnition.Add(
&background_execute_counter_);
}
RuntimeCallTimerScope runtimeTimerScope(
!executed_on_background_thread() ? runtime_call_stats_ : nullptr,
parse_info()->runtime_call_stats(),
&RuntimeCallStats::CompileIgnitionFinalization);
Handle<BytecodeArray> bytecodes = generator()->FinalizeBytecode(
......
......@@ -347,6 +347,7 @@ class Logger : public CodeEventListener {
V(CompileFullCode, true) \
V(OptimizeCode, true) \
V(CompileCode, true) \
V(CompileCodeBackground, true) \
V(DeoptimizeCode, true) \
V(Execute, true) \
V(External, true)
......
......@@ -52,8 +52,12 @@ BackgroundParsingTask::BackgroundParsingTask(
info->AllocateSourceRangeMap();
}
info->set_cached_data(&script_data_);
LanguageMode language_mode = construct_language_mode(FLAG_use_strict);
info->set_language_mode(
stricter_language_mode(info->language_mode(), language_mode));
source->info.reset(info);
isolate_ = isolate;
// Parser needs to stay alive for finalizing the parsing on the main
// thread.
......@@ -67,12 +71,21 @@ void BackgroundParsingTask::Run() {
DisallowHandleAllocation no_handles;
DisallowHandleDereference no_deref;
source_->info->set_on_background_thread(true);
// Reset the stack limit of the parser to reflect correctly that we're on a
// background thread.
uintptr_t old_stack_limit = source_->info->stack_limit();
uintptr_t stack_limit = GetCurrentStackPosition() - stack_size_ * KB;
source_->info->set_stack_limit(stack_limit);
source_->parser->set_stack_limit(stack_limit);
source_->parser->ParseOnBackground(source_->info.get());
if (FLAG_background_compile && source_->info->literal() != nullptr) {
// Parsing has succeeded, compile.
source_->outer_function_job = Compiler::CompileTopLevelOnBackgroundThread(
source_->info.get(), isolate_, &source_->inner_function_jobs);
}
if (script_data_ != nullptr) {
source_->cached_data.reset(new ScriptCompiler::CachedData(
......@@ -82,6 +95,9 @@ void BackgroundParsingTask::Run() {
delete script_data_;
script_data_ = nullptr;
}
source_->info->set_on_background_thread(false);
source_->info->set_stack_limit(old_stack_limit);
}
} // namespace internal
......
......@@ -10,6 +10,7 @@
#include "include/v8.h"
#include "src/base/platform/platform.h"
#include "src/base/platform/semaphore.h"
#include "src/compiler.h"
#include "src/parsing/parse-info.h"
#include "src/unicode-cache.h"
......@@ -41,6 +42,10 @@ struct StreamedSource {
std::unique_ptr<ParseInfo> info;
std::unique_ptr<Parser> parser;
// Data needed for finalizing compilation after background compilation.
std::unique_ptr<CompilationJob> outer_function_job;
CompilationJobList inner_function_jobs;
// Prevent copying.
StreamedSource(const StreamedSource&) = delete;
StreamedSource& operator=(const StreamedSource&) = delete;
......@@ -58,7 +63,9 @@ class BackgroundParsingTask : public ScriptCompiler::ScriptStreamingTask {
StreamedSource* source_; // Not owned.
int stack_size_;
ScriptData* script_data_;
Isolate* isolate_;
};
} // namespace internal
} // namespace v8
......
......@@ -81,6 +81,8 @@ class V8_EXPORT_PRIVATE ParseInfo {
FLAG_ACCESSOR(kIsAsmWasmBroken, is_asm_wasm_broken, set_asm_wasm_broken)
FLAG_ACCESSOR(kBlockCoverageEnabled, block_coverage_enabled,
set_block_coverage_enabled)
FLAG_ACCESSOR(kOnBackgroundThread, on_background_thread,
set_on_background_thread)
#undef FLAG_ACCESSOR
void set_parse_restriction(ParseRestriction restriction) {
......@@ -255,6 +257,7 @@ class V8_EXPORT_PRIVATE ParseInfo {
kCollectTypeProfile = 1 << 10,
kBlockCoverageEnabled = 1 << 11,
kIsAsmWasmBroken = 1 << 12,
kOnBackgroundThread = 1 << 14,
};
//------------- Inputs to parsing and scope analysis -----------------------
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment