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() { ...@@ -1056,18 +1056,10 @@ PipelineWasmCompilationJob::ExecuteJobImpl() {
pipeline_.ComputeScheduledGraph(); pipeline_.ComputeScheduledGraph();
if (!pipeline_.SelectInstructions(&linkage_)) return FAILED; if (!pipeline_.SelectInstructions(&linkage_)) return FAILED;
pipeline_.AssembleCode(&linkage_); 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(); CodeGenerator* code_generator = pipeline_.data_->code_generator();
CodeDesc code_desc; CodeDesc code_desc;
code_generator->tasm()->GetCode(isolate, &code_desc); code_generator->tasm()->GetCode(nullptr, &code_desc);
wasm::WasmCode* code = native_module_->AddCode( wasm::WasmCode* code = native_module_->AddCode(
data_.wasm_function_index(), code_desc, data_.wasm_function_index(), code_desc,
...@@ -1077,15 +1069,13 @@ PipelineWasmCompilationJob::Status PipelineWasmCompilationJob::FinalizeJobImpl( ...@@ -1077,15 +1069,13 @@ PipelineWasmCompilationJob::Status PipelineWasmCompilationJob::FinalizeJobImpl(
data_.wasm_compilation_data()->GetProtectedInstructions(), data_.wasm_compilation_data()->GetProtectedInstructions(),
code_generator->GetSourcePositionTable(), wasm::WasmCode::kTurbofan); code_generator->GetSourcePositionTable(), wasm::WasmCode::kTurbofan);
if (!code) return FAILED;
if (data_.info()->trace_turbo_json_enabled()) { if (data_.info()->trace_turbo_json_enabled()) {
TurboJsonFile json_of(data_.info(), std::ios_base::app); TurboJsonFile json_of(data_.info(), std::ios_base::app);
json_of << "{\"name\":\"disassembly\",\"type\":\"disassembly\",\"data\":\""; json_of << "{\"name\":\"disassembly\",\"type\":\"disassembly\",\"data\":\"";
#ifdef ENABLE_DISASSEMBLER #ifdef ENABLE_DISASSEMBLER
std::stringstream disassembler_stream; std::stringstream disassembler_stream;
Disassembler::Decode( Disassembler::Decode(
isolate, &disassembler_stream, code->instructions().start(), nullptr, &disassembler_stream, code->instructions().start(),
code->instructions().start() + code->safepoint_table_offset(), code->instructions().start() + code->safepoint_table_offset(),
CodeReference(code)); CodeReference(code));
for (auto const c : disassembler_stream.str()) { for (auto const c : disassembler_stream.str()) {
...@@ -1101,6 +1091,16 @@ PipelineWasmCompilationJob::Status PipelineWasmCompilationJob::FinalizeJobImpl( ...@@ -1101,6 +1091,16 @@ PipelineWasmCompilationJob::Status PipelineWasmCompilationJob::FinalizeJobImpl(
return SUCCEEDED; 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> template <typename Phase>
void PipelineImpl::Run() { void PipelineImpl::Run() {
PipelineRunScope scope(this->data_, Phase::phase_name()); PipelineRunScope scope(this->data_, Phase::phase_name());
......
...@@ -5255,24 +5255,10 @@ wasm::WasmCode* TurbofanWasmCompilationUnit::FinishCompilation( ...@@ -5255,24 +5255,10 @@ wasm::WasmCode* TurbofanWasmCompilationUnit::FinishCompilation(
return nullptr; 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) { wasm::WasmCode* code = job_->compilation_info()->wasm_code();
double codegen_ms = codegen_timer.Elapsed().InMillisecondsF(); wasm_unit_->native_module()->PublishCode(code);
PrintF("wasm-code-generation ok: %u bytes, %0.3f ms code generation\n", return code;
static_cast<unsigned>(wasm_unit_->func_body_.end -
wasm_unit_->func_body_.start),
codegen_ms);
}
return job_->compilation_info()->wasm_code();
} }
namespace { namespace {
......
...@@ -1879,6 +1879,7 @@ bool LiftoffCompilationUnit::ExecuteCompilation() { ...@@ -1879,6 +1879,7 @@ bool LiftoffCompilationUnit::ExecuteCompilation() {
wasm_unit_->func_index_, desc, frame_slot_count, safepoint_table_offset, wasm_unit_->func_index_, desc, frame_slot_count, safepoint_table_offset,
0, std::move(protected_instructions), std::move(source_positions), 0, std::move(protected_instructions), std::move(source_positions),
wasm::WasmCode::kLiftoff); wasm::WasmCode::kLiftoff);
wasm_unit_->native_module_->PublishCode(code_);
// Record the memory cost this unit places on the system until // Record the memory cost this unit places on the system until
// it is finalized. // it is finalized.
......
...@@ -168,9 +168,6 @@ void WasmCode::LogCode(Isolate* isolate) const { ...@@ -168,9 +168,6 @@ void WasmCode::LogCode(Isolate* isolate) const {
void WasmCode::Validate() const { void WasmCode::Validate() const {
#ifdef DEBUG #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} // 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 // 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. // iteration below does not use a mask, but visits all relocation data.
...@@ -537,17 +534,6 @@ WasmCode* NativeModule::AddCode( ...@@ -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 // Flush the i-cache here instead of in AddOwnedCode, to include the changes
// made while iterating over the RelocInfo above. // made while iterating over the RelocInfo above.
Assembler::FlushICache(ret->instructions().start(), Assembler::FlushICache(ret->instructions().start(),
...@@ -580,6 +566,19 @@ WasmCode* NativeModule::AddDeserializedCode( ...@@ -580,6 +566,19 @@ WasmCode* NativeModule::AddDeserializedCode(
return code; 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) { WasmCode* NativeModule::CreateEmptyJumpTable(uint32_t num_wasm_functions) {
// Only call this if we really need a jump table. // Only call this if we really need a jump table.
DCHECK_LT(0, num_wasm_functions); DCHECK_LT(0, num_wasm_functions);
...@@ -675,6 +674,7 @@ Address NativeModule::AllocateForCode(size_t size) { ...@@ -675,6 +674,7 @@ Address NativeModule::AllocateForCode(size_t size) {
} }
WasmCode* NativeModule::Lookup(Address pc) const { WasmCode* NativeModule::Lookup(Address pc) const {
base::LockGuard<base::Mutex> lock(&allocation_mutex_);
if (owned_code_.empty()) return nullptr; if (owned_code_.empty()) return nullptr;
auto iter = std::upper_bound(owned_code_.begin(), owned_code_.end(), pc, auto iter = std::upper_bound(owned_code_.begin(), owned_code_.end(), pc,
WasmCodeUniquePtrComparator()); WasmCodeUniquePtrComparator());
......
...@@ -264,6 +264,11 @@ class V8_EXPORT_PRIVATE NativeModule final { ...@@ -264,6 +264,11 @@ class V8_EXPORT_PRIVATE NativeModule final {
// resolved during relocation. // resolved during relocation.
void SetRuntimeStubs(Isolate* isolate); 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 { WasmCode* code(uint32_t index) const {
DCHECK_LT(index, num_functions()); DCHECK_LT(index, num_functions());
DCHECK_LE(module_->num_imported_functions, index); DCHECK_LE(module_->num_imported_functions, index);
......
...@@ -3438,8 +3438,10 @@ TEST(Liftoff_tier_up) { ...@@ -3438,8 +3438,10 @@ TEST(Liftoff_tier_up) {
memcpy(buffer.get(), sub_code->instructions().start(), sub_size); memcpy(buffer.get(), sub_code->instructions().start(), sub_size);
desc.buffer = buffer.get(); desc.buffer = buffer.get();
desc.instr_size = static_cast<int>(sub_size); desc.instr_size = static_cast<int>(sub_size);
native_module->AddCode(add.function_index(), desc, 0, 0, 0, {}, WasmCode* code =
OwnedVector<byte>(), WasmCode::kOther); native_module->AddCode(add.function_index(), desc, 0, 0, 0, {},
OwnedVector<byte>(), WasmCode::kOther);
native_module->PublishCode(code);
// Second run should now execute {sub}. // Second run should now execute {sub}.
CHECK_EQ(4, r.Call(11, 7)); 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