[compiler] Split GenerateCode into AssembleCode and FinalizeCode.

AssembleCode will eventually be moved into ExecuteJob, i.e., off
the main thread.

Bug: v8:6048
Change-Id: If84ee2aaca6c8827cb769c7d69e5094fb4f32e4b
Reviewed-on: https://chromium-review.googlesource.com/506669
Commit-Queue: Georg Neis <neis@chromium.org>
Reviewed-by: Michael Starzinger <mstarzinger@chromium.org>
Cr-Commit-Position: refs/heads/master@{#45372}
This commit is contained in:
Georg Neis 2017-05-17 13:53:37 +02:00 committed by Commit Bot
parent 789b60458b
commit a28b940e89
3 changed files with 62 additions and 29 deletions

View File

@ -60,7 +60,8 @@ CodeGenerator::CodeGenerator(Frame* frame, Linkage* linkage,
osr_pc_offset_(-1), osr_pc_offset_(-1),
optimized_out_literal_id_(-1), optimized_out_literal_id_(-1),
source_position_table_builder_(code->zone(), source_position_table_builder_(code->zone(),
info->SourcePositionRecordingMode()) { info->SourcePositionRecordingMode()),
result_(kSuccess) {
for (int i = 0; i < code->InstructionBlockCount(); ++i) { for (int i = 0; i < code->InstructionBlockCount(); ++i) {
new (&labels_[i]) Label; new (&labels_[i]) Label;
} }
@ -74,8 +75,7 @@ void CodeGenerator::CreateFrameAccessState(Frame* frame) {
frame_access_state_ = new (code()->zone()) FrameAccessState(frame); frame_access_state_ = new (code()->zone()) FrameAccessState(frame);
} }
void CodeGenerator::AssembleCode() {
Handle<Code> CodeGenerator::GenerateCode() {
CompilationInfo* info = this->info(); CompilationInfo* info = this->info();
// Open a frame scope to indicate that there is a frame on the stack. The // Open a frame scope to indicate that there is a frame on the stack. The
@ -175,14 +175,13 @@ Handle<Code> CodeGenerator::GenerateCode() {
} }
} }
CodeGenResult result;
if (FLAG_enable_embedded_constant_pool && !block->needs_frame()) { if (FLAG_enable_embedded_constant_pool && !block->needs_frame()) {
ConstantPoolUnavailableScope constant_pool_unavailable(masm()); ConstantPoolUnavailableScope constant_pool_unavailable(masm());
result = AssembleBlock(block); result_ = AssembleBlock(block);
} else { } else {
result = AssembleBlock(block); result_ = AssembleBlock(block);
} }
if (result != kSuccess) return Handle<Code>(); if (result_ != kSuccess) return;
unwinding_info_writer_.EndInstructionBlock(block); unwinding_info_writer_.EndInstructionBlock(block);
} }
} }
@ -228,9 +227,15 @@ Handle<Code> CodeGenerator::GenerateCode() {
unwinding_info_writer_.Finish(masm()->pc_offset()); unwinding_info_writer_.Finish(masm()->pc_offset());
safepoints()->Emit(masm(), frame()->GetTotalFrameSlotCount()); safepoints()->Emit(masm(), frame()->GetTotalFrameSlotCount());
result_ = kSuccess;
}
Handle<Code> CodeGenerator::FinalizeCode() {
if (result_ != kSuccess) return Handle<Code>();
Handle<Code> result = v8::internal::CodeGenerator::MakeCodeEpilogue( Handle<Code> result = v8::internal::CodeGenerator::MakeCodeEpilogue(
masm(), unwinding_info_writer_.eh_frame_writer(), info, Handle<Object>()); masm(), unwinding_info_writer_.eh_frame_writer(), info(),
Handle<Object>());
result->set_is_turbofanned(true); result->set_is_turbofanned(true);
result->set_stack_slots(frame()->GetTotalFrameSlotCount()); result->set_stack_slots(frame()->GetTotalFrameSlotCount());
result->set_safepoint_table_offset(safepoints()->GetCodeOffset()); result->set_safepoint_table_offset(safepoints()->GetCodeOffset());
@ -255,7 +260,7 @@ Handle<Code> CodeGenerator::GenerateCode() {
PopulateDeoptimizationData(result); PopulateDeoptimizationData(result);
// Ensure there is space for lazy deoptimization in the relocation info. // Ensure there is space for lazy deoptimization in the relocation info.
if (info->ShouldEnsureSpaceForLazyDeopt()) { if (info()->ShouldEnsureSpaceForLazyDeopt()) {
Deoptimizer::EnsureRelocSpaceForLazyDeoptimization(result); Deoptimizer::EnsureRelocSpaceForLazyDeoptimization(result);
} }

View File

@ -80,8 +80,11 @@ class CodeGenerator final : public GapResolver::Assembler {
explicit CodeGenerator(Frame* frame, Linkage* linkage, explicit CodeGenerator(Frame* frame, Linkage* linkage,
InstructionSequence* code, CompilationInfo* info); InstructionSequence* code, CompilationInfo* info);
// Generate native code. // Generate native code. After calling AssembleCode, call FinalizeCode to
Handle<Code> GenerateCode(); // produce the actual code object. If an error occurs during either phase,
// FinalizeCode returns a null handle.
void AssembleCode();
Handle<Code> FinalizeCode();
InstructionSequence* code() const { return code_; } InstructionSequence* code() const { return code_; }
FrameAccessState* frame_access_state() const { return frame_access_state_; } FrameAccessState* frame_access_state() const { return frame_access_state_; }
@ -317,6 +320,7 @@ class CodeGenerator final : public GapResolver::Assembler {
int osr_pc_offset_; int osr_pc_offset_;
int optimized_out_literal_id_; int optimized_out_literal_id_;
SourcePositionTableBuilder source_position_table_builder_; SourcePositionTableBuilder source_position_table_builder_;
CodeGenResult result_;
}; };
} // namespace compiler } // namespace compiler

View File

@ -174,6 +174,8 @@ class PipelineData {
} }
~PipelineData() { ~PipelineData() {
delete code_generator_; // Must happen before zones are destroyed.
code_generator_ = nullptr;
DeleteRegisterAllocationZone(); DeleteRegisterAllocationZone();
DeleteInstructionZone(); DeleteInstructionZone();
DeleteGraphZone(); DeleteGraphZone();
@ -196,6 +198,8 @@ class PipelineData {
code_ = code; code_ = code;
} }
CodeGenerator* code_generator() const { return code_generator_; }
// RawMachineAssembler generally produces graphs which cannot be verified. // RawMachineAssembler generally produces graphs which cannot be verified.
bool MayHaveUnverifiableGraph() const { return outer_zone_ == nullptr; } bool MayHaveUnverifiableGraph() const { return outer_zone_ == nullptr; }
@ -314,6 +318,11 @@ class PipelineData {
sequence(), debug_name()); sequence(), debug_name());
} }
void InitializeCodeGenerator(Linkage* linkage) {
DCHECK_NULL(code_generator_);
code_generator_ = new CodeGenerator(frame(), linkage, sequence(), info());
}
void BeginPhaseKind(const char* phase_kind_name) { void BeginPhaseKind(const char* phase_kind_name) {
if (pipeline_statistics() != nullptr) { if (pipeline_statistics() != nullptr) {
pipeline_statistics()->BeginPhaseKind(phase_kind_name); pipeline_statistics()->BeginPhaseKind(phase_kind_name);
@ -339,6 +348,7 @@ class PipelineData {
bool verify_graph_ = false; bool verify_graph_ = false;
bool is_asm_ = false; bool is_asm_ = false;
Handle<Code> code_ = Handle<Code>::null(); Handle<Code> code_ = Handle<Code>::null();
CodeGenerator* code_generator_ = nullptr;
// All objects in the following group of fields are allocated in graph_zone_. // All objects in the following group of fields are allocated in graph_zone_.
// They are all set to nullptr when the graph_zone_ is destroyed. // They are all set to nullptr when the graph_zone_ is destroyed.
@ -356,8 +366,7 @@ class PipelineData {
// All objects in the following group of fields are allocated in // All objects in the following group of fields are allocated in
// instruction_zone_. They are all set to nullptr when the instruction_zone_ // instruction_zone_. They are all set to nullptr when the instruction_zone_
// is // is destroyed.
// destroyed.
ZoneStats::Scope instruction_zone_scope_; ZoneStats::Scope instruction_zone_scope_;
Zone* instruction_zone_; Zone* instruction_zone_;
InstructionSequence* sequence_ = nullptr; InstructionSequence* sequence_ = nullptr;
@ -400,8 +409,11 @@ class PipelineImpl final {
// Run the concurrent optimization passes. // Run the concurrent optimization passes.
bool OptimizeGraph(Linkage* linkage); bool OptimizeGraph(Linkage* linkage);
// Perform the actual code generation and return handle to a code object. // Run the code assembly pass.
Handle<Code> GenerateCode(Linkage* linkage); void AssembleCode(Linkage* linkage);
// Run the code finalization pass.
Handle<Code> FinalizeCode();
bool ScheduleAndSelectInstructions(Linkage* linkage, bool trim_graph); bool ScheduleAndSelectInstructions(Linkage* linkage, bool trim_graph);
void RunPrintAndVerify(const char* phase, bool untyped = false); void RunPrintAndVerify(const char* phase, bool untyped = false);
@ -624,7 +636,8 @@ PipelineCompilationJob::Status PipelineCompilationJob::ExecuteJobImpl() {
} }
PipelineCompilationJob::Status PipelineCompilationJob::FinalizeJobImpl() { PipelineCompilationJob::Status PipelineCompilationJob::FinalizeJobImpl() {
Handle<Code> code = pipeline_.GenerateCode(linkage_); pipeline_.AssembleCode(linkage_);
Handle<Code> code = pipeline_.FinalizeCode();
if (code.is_null()) { if (code.is_null()) {
if (info()->bailout_reason() == kNoReason) { if (info()->bailout_reason() == kNoReason) {
return AbortOptimization(kCodeGenerationFailed); return AbortOptimization(kCodeGenerationFailed);
@ -711,7 +724,8 @@ PipelineWasmCompilationJob::ExecuteJobImpl() {
PipelineWasmCompilationJob::Status PipelineWasmCompilationJob::Status
PipelineWasmCompilationJob::FinalizeJobImpl() { PipelineWasmCompilationJob::FinalizeJobImpl() {
pipeline_.GenerateCode(&linkage_); pipeline_.AssembleCode(&linkage_);
pipeline_.FinalizeCode();
return SUCCEEDED; return SUCCEEDED;
} }
@ -1448,14 +1462,19 @@ struct JumpThreadingPhase {
} }
}; };
struct AssembleCodePhase {
static const char* phase_name() { return "assemble code"; }
struct GenerateCodePhase { void Run(PipelineData* data, Zone* temp_zone) {
static const char* phase_name() { return "generate code"; } data->code_generator()->AssembleCode();
}
};
void Run(PipelineData* data, Zone* temp_zone, Linkage* linkage) { struct FinalizeCodePhase {
CodeGenerator generator(data->frame(), linkage, data->sequence(), static const char* phase_name() { return "finalize code"; }
data->info());
data->set_code(generator.GenerateCode()); void Run(PipelineData* data, Zone* temp_zone) {
data->set_code(data->code_generator()->FinalizeCode());
} }
}; };
@ -1724,7 +1743,8 @@ Handle<Code> Pipeline::GenerateCodeForTesting(CompilationInfo* info) {
if (!pipeline.CreateGraph()) return Handle<Code>::null(); if (!pipeline.CreateGraph()) return Handle<Code>::null();
if (!pipeline.OptimizeGraph(&linkage)) return Handle<Code>::null(); if (!pipeline.OptimizeGraph(&linkage)) return Handle<Code>::null();
return pipeline.GenerateCode(&linkage); pipeline.AssembleCode(&linkage);
return pipeline.FinalizeCode();
} }
// static // static
@ -1900,13 +1920,16 @@ bool PipelineImpl::ScheduleAndSelectInstructions(Linkage* linkage,
return true; return true;
} }
Handle<Code> PipelineImpl::GenerateCode(Linkage* linkage) { void PipelineImpl::AssembleCode(Linkage* linkage) {
PipelineData* data = this->data_; PipelineData* data = this->data_;
data->BeginPhaseKind("code generation"); data->BeginPhaseKind("code generation");
data->InitializeCodeGenerator(linkage);
Run<AssembleCodePhase>();
}
// Generate final machine code. Handle<Code> PipelineImpl::FinalizeCode() {
Run<GenerateCodePhase>(linkage); PipelineData* data = this->data_;
Run<FinalizeCodePhase>();
Handle<Code> code = data->code(); Handle<Code> code = data->code();
if (data->profiler_data()) { if (data->profiler_data()) {
@ -1954,7 +1977,8 @@ Handle<Code> PipelineImpl::ScheduleAndGenerateCode(
if (!ScheduleAndSelectInstructions(&linkage, false)) return Handle<Code>(); if (!ScheduleAndSelectInstructions(&linkage, false)) return Handle<Code>();
// Generate the final machine code. // Generate the final machine code.
return GenerateCode(&linkage); AssembleCode(&linkage);
return FinalizeCode();
} }
void PipelineImpl::AllocateRegisters(const RegisterConfiguration* config, void PipelineImpl::AllocateRegisters(const RegisterConfiguration* config,