Commit 9c6fab07 authored by Michael Starzinger's avatar Michael Starzinger Committed by Commit Bot

[wasm] Move code generation fully to background task.

This moves the entire code generation phase (including code emission
into the native module) into the background task. The code manager is
fully thread safe by now and there are no Isolate-bound steps anymore.

The only step remaining on the foreground task is publishing the fully
finished code to other threads via {NativeModule::PublishCode}.

R=clemensh@chromium.org
BUG=v8:7921

Change-Id: Ia64c6ce945aabd071b26e61ef8d397fb7727a038
Reviewed-on: https://chromium-review.googlesource.com/1135004
Commit-Queue: Michael Starzinger <mstarzinger@chromium.org>
Reviewed-by: 's avatarClemens Hammacher <clemensh@chromium.org>
Cr-Commit-Position: refs/heads/master@{#54425}
parent 3255d8dd
......@@ -1056,18 +1056,10 @@ PipelineWasmCompilationJob::ExecuteJobImpl() {
pipeline_.ComputeScheduledGraph();
if (!pipeline_.SelectInstructions(&linkage_)) return FAILED;
pipeline_.AssembleCode(&linkage_);
return SUCCEEDED;
}
size_t PipelineWasmCompilationJob::AllocatedMemory() const {
return pipeline_.data_->zone_stats()->GetCurrentAllocatedBytes();
}
PipelineWasmCompilationJob::Status PipelineWasmCompilationJob::FinalizeJobImpl(
Isolate* isolate) {
CodeGenerator* code_generator = pipeline_.data_->code_generator();
CodeDesc code_desc;
code_generator->tasm()->GetCode(isolate, &code_desc);
code_generator->tasm()->GetCode(nullptr, &code_desc);
wasm::WasmCode* code = native_module_->AddCode(
data_.wasm_function_index(), code_desc,
......@@ -1077,15 +1069,13 @@ PipelineWasmCompilationJob::Status PipelineWasmCompilationJob::FinalizeJobImpl(
data_.wasm_compilation_data()->GetProtectedInstructions(),
code_generator->GetSourcePositionTable(), wasm::WasmCode::kTurbofan);
if (!code) return FAILED;
if (data_.info()->trace_turbo_json_enabled()) {
TurboJsonFile json_of(data_.info(), std::ios_base::app);
json_of << "{\"name\":\"disassembly\",\"type\":\"disassembly\",\"data\":\"";
#ifdef ENABLE_DISASSEMBLER
std::stringstream disassembler_stream;
Disassembler::Decode(
isolate, &disassembler_stream, code->instructions().start(),
nullptr, &disassembler_stream, code->instructions().start(),
code->instructions().start() + code->safepoint_table_offset(),
CodeReference(code));
for (auto const c : disassembler_stream.str()) {
......@@ -1101,6 +1091,16 @@ PipelineWasmCompilationJob::Status PipelineWasmCompilationJob::FinalizeJobImpl(
return SUCCEEDED;
}
size_t PipelineWasmCompilationJob::AllocatedMemory() const {
return pipeline_.data_->zone_stats()->GetCurrentAllocatedBytes();
}
PipelineWasmCompilationJob::Status PipelineWasmCompilationJob::FinalizeJobImpl(
Isolate* isolate) {
UNREACHABLE(); // Finalize should always be skipped for WasmCompilationJob.
return SUCCEEDED;
}
template <typename Phase>
void PipelineImpl::Run() {
PipelineRunScope scope(this->data_, Phase::phase_name());
......
......@@ -5255,24 +5255,10 @@ wasm::WasmCode* TurbofanWasmCompilationUnit::FinishCompilation(
return nullptr;
}
base::ElapsedTimer codegen_timer;
if (FLAG_trace_wasm_decode_time) {
codegen_timer.Start();
}
if (job_->FinalizeJob(wasm_unit_->isolate_) != CompilationJob::SUCCEEDED) {
return nullptr;
}
if (FLAG_trace_wasm_decode_time) {
double codegen_ms = codegen_timer.Elapsed().InMillisecondsF();
PrintF("wasm-code-generation ok: %u bytes, %0.3f ms code generation\n",
static_cast<unsigned>(wasm_unit_->func_body_.end -
wasm_unit_->func_body_.start),
codegen_ms);
}
return job_->compilation_info()->wasm_code();
wasm::WasmCode* code = job_->compilation_info()->wasm_code();
wasm_unit_->native_module()->PublishCode(code);
return code;
}
namespace {
......
......@@ -1879,6 +1879,7 @@ bool LiftoffCompilationUnit::ExecuteCompilation() {
wasm_unit_->func_index_, desc, frame_slot_count, safepoint_table_offset,
0, std::move(protected_instructions), std::move(source_positions),
wasm::WasmCode::kLiftoff);
wasm_unit_->native_module_->PublishCode(code_);
// Record the memory cost this unit places on the system until
// it is finalized.
......
......@@ -168,9 +168,6 @@ void WasmCode::LogCode(Isolate* isolate) const {
void WasmCode::Validate() const {
#ifdef DEBUG
// We run NativeModule::Lookup, which accesses owned_code_, thuse we need to
// hold the mutex to avoid race conditions.
base::LockGuard<base::Mutex> lock(&native_module_->allocation_mutex_);
// We expect certain relocation info modes to never appear in {WasmCode}
// objects or to be restricted to a small set of valid values. Hence the
// iteration below does not use a mask, but visits all relocation data.
......@@ -537,17 +534,6 @@ WasmCode* NativeModule::AddCode(
}
}
{
// TODO(clemensh): Remove the need for locking here. Probably requires
// word-aligning the jump table slots.
base::LockGuard<base::Mutex> lock(&allocation_mutex_);
if (!ret->protected_instructions_.is_empty()) {
ret->RegisterTrapHandlerData();
}
set_code(index, ret);
PatchJumpTable(index, ret->instruction_start(), WasmCode::kFlushICache);
}
// Flush the i-cache here instead of in AddOwnedCode, to include the changes
// made while iterating over the RelocInfo above.
Assembler::FlushICache(ret->instructions().start(),
......@@ -580,6 +566,19 @@ WasmCode* NativeModule::AddDeserializedCode(
return code;
}
void NativeModule::PublishCode(WasmCode* code) {
// TODO(clemensh): Remove the need for locking here. Probably requires
// word-aligning the jump table slots.
base::LockGuard<base::Mutex> lock(&allocation_mutex_);
if (!code->protected_instructions_.is_empty()) {
code->RegisterTrapHandlerData();
}
DCHECK(!code->IsAnonymous());
set_code(code->index(), code);
PatchJumpTable(code->index(), code->instruction_start(),
WasmCode::kFlushICache);
}
WasmCode* NativeModule::CreateEmptyJumpTable(uint32_t num_wasm_functions) {
// Only call this if we really need a jump table.
DCHECK_LT(0, num_wasm_functions);
......@@ -675,6 +674,7 @@ Address NativeModule::AllocateForCode(size_t size) {
}
WasmCode* NativeModule::Lookup(Address pc) const {
base::LockGuard<base::Mutex> lock(&allocation_mutex_);
if (owned_code_.empty()) return nullptr;
auto iter = std::upper_bound(owned_code_.begin(), owned_code_.end(), pc,
WasmCodeUniquePtrComparator());
......
......@@ -264,6 +264,11 @@ class V8_EXPORT_PRIVATE NativeModule final {
// resolved during relocation.
void SetRuntimeStubs(Isolate* isolate);
// Makes the code available to the system (by entering it into the code table
// and patching the jump table). Callers have to take care not to race with
// threads executing the old code.
void PublishCode(WasmCode* code);
WasmCode* code(uint32_t index) const {
DCHECK_LT(index, num_functions());
DCHECK_LE(module_->num_imported_functions, index);
......
......@@ -3438,8 +3438,10 @@ TEST(Liftoff_tier_up) {
memcpy(buffer.get(), sub_code->instructions().start(), sub_size);
desc.buffer = buffer.get();
desc.instr_size = static_cast<int>(sub_size);
native_module->AddCode(add.function_index(), desc, 0, 0, 0, {},
OwnedVector<byte>(), WasmCode::kOther);
WasmCode* code =
native_module->AddCode(add.function_index(), desc, 0, 0, 0, {},
OwnedVector<byte>(), WasmCode::kOther);
native_module->PublishCode(code);
// Second run should now execute {sub}.
CHECK_EQ(4, r.Call(11, 7));
......
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