Break Crankshaft into phases.

Crankshaft now runs by calling CreateGraph on the HGraphBuilder, then
calling Optimize and Codegen on the HGraph.

BUG=
TEST=

Review URL: https://chromiumcodereview.appspot.com/10700115

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@12064 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
sanjoy@chromium.org 2012-07-12 15:10:34 +00:00
parent 1132b27e25
commit c1ee1b457f
11 changed files with 124 additions and 95 deletions

View File

@ -43,9 +43,9 @@ class SafepointGenerator;
class LCodeGen BASE_EMBEDDED { class LCodeGen BASE_EMBEDDED {
public: public:
LCodeGen(LChunk* chunk, MacroAssembler* assembler, CompilationInfo* info) LCodeGen(LChunkBase* chunk, MacroAssembler* assembler, CompilationInfo* info)
: zone_(info->zone()), : zone_(info->zone()),
chunk_(chunk), chunk_(static_cast<LChunk*>(chunk)),
masm_(assembler), masm_(assembler),
info_(info), info_(info),
current_block_(-1), current_block_(-1),

View File

@ -308,11 +308,19 @@ static bool MakeCrankshaftCode(CompilationInfo* info) {
} }
if (graph != NULL) { if (graph != NULL) {
Handle<Code> optimized_code = graph->Compile(); SmartArrayPointer<char> bailout_reason;
if (!optimized_code.is_null()) { if (!graph->Optimize(&bailout_reason)) {
info->SetCode(optimized_code); if (!bailout_reason.is_empty()) builder.Bailout(*bailout_reason);
FinishOptimization(info->closure(), start); } else {
return true; LChunkBase* chunk = LChunkBase::NewChunk(graph);
if (chunk != NULL) {
Handle<Code> optimized_code = chunk->Codegen();
if (!optimized_code.is_null()) {
info->SetCode(optimized_code);
FinishOptimization(info->closure(), start);
return true;
}
}
} }
} }

View File

@ -703,47 +703,6 @@ HGraph::HGraph(CompilationInfo* info)
} }
Handle<Code> HGraph::Compile() {
int values = GetMaximumValueID();
if (values > LUnallocated::kMaxVirtualRegisters) {
if (FLAG_trace_bailout) {
PrintF("Not enough virtual registers for (values).\n");
}
return Handle<Code>::null();
}
LAllocator allocator(values, this);
LChunkBuilder builder(info(), this, &allocator);
LChunk* chunk = builder.Build();
if (chunk == NULL) return Handle<Code>::null();
if (!allocator.Allocate(chunk)) {
if (FLAG_trace_bailout) {
PrintF("Not enough virtual registers (regalloc).\n");
}
return Handle<Code>::null();
}
MacroAssembler assembler(isolate(), NULL, 0);
LCodeGen generator(chunk, &assembler, info());
chunk->MarkEmptyBlocks();
if (generator.GenerateCode()) {
if (FLAG_trace_codegen) {
PrintF("Crankshaft Compiler - ");
}
CodeGenerator::MakeCodePrologue(info());
Code::Flags flags = Code::ComputeFlags(Code::OPTIMIZED_FUNCTION);
Handle<Code> code =
CodeGenerator::MakeCodeEpilogue(&assembler, flags, info());
generator.FinishCode(code);
CodeGenerator::PrintCode(code, info());
return code;
}
return Handle<Code>::null();
}
HBasicBlock* HGraph::CreateBasicBlock() { HBasicBlock* HGraph::CreateBasicBlock() {
HBasicBlock* result = new(zone()) HBasicBlock(this); HBasicBlock* result = new(zone()) HBasicBlock(this);
blocks_.Add(result, zone()); blocks_.Add(result, zone());
@ -3122,48 +3081,55 @@ HGraph* HGraphBuilder::CreateGraph() {
} }
} }
graph()->OrderBlocks(); return graph();
graph()->AssignDominators(); }
bool HGraph::Optimize(SmartArrayPointer<char>* bailout_reason) {
*bailout_reason = SmartArrayPointer<char>();
OrderBlocks();
AssignDominators();
#ifdef DEBUG #ifdef DEBUG
// Do a full verify after building the graph and computing dominators. // Do a full verify after building the graph and computing dominators.
graph()->Verify(true); Verify(true);
#endif #endif
graph()->PropagateDeoptimizingMark(); PropagateDeoptimizingMark();
if (!graph()->CheckConstPhiUses()) { if (!CheckConstPhiUses()) {
Bailout("Unsupported phi use of const variable"); *bailout_reason = SmartArrayPointer<char>(StrDup(
return NULL; "Unsupported phi use of const variable"));
return false;
} }
graph()->EliminateRedundantPhis(); EliminateRedundantPhis();
if (!graph()->CheckArgumentsPhiUses()) { if (!CheckArgumentsPhiUses()) {
Bailout("Unsupported phi use of arguments"); *bailout_reason = SmartArrayPointer<char>(StrDup(
return NULL; "Unsupported phi use of arguments"));
return false;
} }
if (FLAG_eliminate_dead_phis) graph()->EliminateUnreachablePhis(); if (FLAG_eliminate_dead_phis) EliminateUnreachablePhis();
graph()->CollectPhis(); CollectPhis();
if (graph()->has_osr_loop_entry()) { if (has_osr_loop_entry()) {
const ZoneList<HPhi*>* phis = graph()->osr_loop_entry()->phis(); const ZoneList<HPhi*>* phis = osr_loop_entry()->phis();
for (int j = 0; j < phis->length(); j++) { for (int j = 0; j < phis->length(); j++) {
HPhi* phi = phis->at(j); HPhi* phi = phis->at(j);
graph()->osr_values()->at(phi->merged_index())->set_incoming_value(phi); osr_values()->at(phi->merged_index())->set_incoming_value(phi);
} }
} }
HInferRepresentation rep(graph()); HInferRepresentation rep(this);
rep.Analyze(); rep.Analyze();
graph()->MarkDeoptimizeOnUndefined(); MarkDeoptimizeOnUndefined();
graph()->InsertRepresentationChanges(); InsertRepresentationChanges();
graph()->InitializeInferredTypes(); InitializeInferredTypes();
graph()->Canonicalize(); Canonicalize();
// Perform common subexpression elimination and loop-invariant code motion. // Perform common subexpression elimination and loop-invariant code motion.
if (FLAG_use_gvn) { if (FLAG_use_gvn) {
HPhase phase("H_Global value numbering", graph()); HPhase phase("H_Global value numbering", this);
HGlobalValueNumberer gvn(graph(), info()); HGlobalValueNumberer gvn(this, info());
bool removed_side_effects = gvn.Analyze(); bool removed_side_effects = gvn.Analyze();
// Trigger a second analysis pass to further eliminate duplicate values that // Trigger a second analysis pass to further eliminate duplicate values that
// could only be discovered by removing side-effect-generating instructions // could only be discovered by removing side-effect-generating instructions
@ -3175,19 +3141,19 @@ HGraph* HGraphBuilder::CreateGraph() {
} }
if (FLAG_use_range) { if (FLAG_use_range) {
HRangeAnalysis rangeAnalysis(graph()); HRangeAnalysis rangeAnalysis(this);
rangeAnalysis.Analyze(); rangeAnalysis.Analyze();
} }
graph()->ComputeMinusZeroChecks(); ComputeMinusZeroChecks();
// Eliminate redundant stack checks on backwards branches. // Eliminate redundant stack checks on backwards branches.
HStackCheckEliminator sce(graph()); HStackCheckEliminator sce(this);
sce.Process(); sce.Process();
graph()->EliminateRedundantBoundsChecks(); EliminateRedundantBoundsChecks();
graph()->DehoistSimpleArrayIndexComputations(); DehoistSimpleArrayIndexComputations();
return graph(); return true;
} }

View File

@ -281,8 +281,6 @@ class HGraph: public ZoneObject {
void CollectPhis(); void CollectPhis();
Handle<Code> Compile();
void set_undefined_constant(HConstant* constant) { void set_undefined_constant(HConstant* constant) {
undefined_constant_.set(constant); undefined_constant_.set(constant);
} }
@ -313,6 +311,8 @@ class HGraph: public ZoneObject {
return NULL; return NULL;
} }
bool Optimize(SmartArrayPointer<char>* bailout_reason);
#ifdef DEBUG #ifdef DEBUG
void Verify(bool do_full_verify) const; void Verify(bool do_full_verify) const;
#endif #endif

View File

@ -46,9 +46,9 @@ class SafepointGenerator;
class LCodeGen BASE_EMBEDDED { class LCodeGen BASE_EMBEDDED {
public: public:
LCodeGen(LChunk* chunk, MacroAssembler* assembler, CompilationInfo* info) LCodeGen(LChunkBase* chunk, MacroAssembler* assembler, CompilationInfo* info)
: zone_(info->zone()), : zone_(info->zone()),
chunk_(chunk), chunk_(static_cast<LChunk*>(chunk)),
masm_(assembler), masm_(assembler),
info_(info), info_(info),
current_block_(-1), current_block_(-1),

View File

@ -1062,9 +1062,9 @@ void LAllocator::ResolvePhis(HBasicBlock* block) {
} }
bool LAllocator::Allocate(LChunk* chunk) { bool LAllocator::Allocate(LChunkBase* chunk) {
ASSERT(chunk_ == NULL); ASSERT(chunk_ == NULL);
chunk_ = chunk; chunk_ = static_cast<LChunk*>(chunk);
MeetRegisterConstraints(); MeetRegisterConstraints();
if (!AllocationOk()) return false; if (!AllocationOk()) return false;
ResolvePhis(); ResolvePhis();

View File

@ -445,7 +445,7 @@ class LAllocator BASE_EMBEDDED {
// Returns the register kind required by the given virtual register. // Returns the register kind required by the given virtual register.
RegisterKind RequiredRegisterKind(int virtual_register) const; RegisterKind RequiredRegisterKind(int virtual_register) const;
bool Allocate(LChunk* chunk); bool Allocate(LChunkBase* chunk);
const ZoneList<LiveRange*>* live_ranges() const { return &live_ranges_; } const ZoneList<LiveRange*>* live_ranges() const { return &live_ranges_; }
const Vector<LiveRange*>* fixed_live_ranges() const { const Vector<LiveRange*>* fixed_live_ranges() const {

View File

@ -31,12 +31,16 @@
#if V8_TARGET_ARCH_IA32 #if V8_TARGET_ARCH_IA32
#include "ia32/lithium-ia32.h" #include "ia32/lithium-ia32.h"
#include "ia32/lithium-codegen-ia32.h"
#elif V8_TARGET_ARCH_X64 #elif V8_TARGET_ARCH_X64
#include "x64/lithium-x64.h" #include "x64/lithium-x64.h"
#include "x64/lithium-codegen-x64.h"
#elif V8_TARGET_ARCH_ARM #elif V8_TARGET_ARCH_ARM
#include "arm/lithium-arm.h" #include "arm/lithium-arm.h"
#include "arm/lithium-codegen-arm.h"
#elif V8_TARGET_ARCH_MIPS #elif V8_TARGET_ARCH_MIPS
#include "mips/lithium-mips.h" #include "mips/lithium-mips.h"
#include "mips/lithium-codegen-mips.h"
#else #else
#error "Unknown architecture." #error "Unknown architecture."
#endif #endif
@ -386,4 +390,50 @@ Representation LChunkBase::LookupLiteralRepresentation(
} }
LChunkBase* LChunkBase::NewChunk(HGraph* graph) {
int values = graph->GetMaximumValueID();
if (values > LUnallocated::kMaxVirtualRegisters) {
if (FLAG_trace_bailout) {
PrintF("Not enough virtual registers for (values).\n");
}
return NULL;
}
LAllocator allocator(values, graph);
LChunkBuilder builder(graph->info(), graph, &allocator);
LChunkBase* chunk = builder.Build();
if (chunk == NULL) return NULL;
if (!allocator.Allocate(chunk)) {
if (FLAG_trace_bailout) {
PrintF("Not enough virtual registers (regalloc).\n");
}
return NULL;
}
return chunk;
}
Handle<Code> LChunkBase::Codegen() {
MacroAssembler assembler(info()->isolate(), NULL, 0);
LCodeGen generator(this, &assembler, info());
MarkEmptyBlocks();
if (generator.GenerateCode()) {
if (FLAG_trace_codegen) {
PrintF("Crankshaft Compiler - ");
}
CodeGenerator::MakeCodePrologue(info());
Code::Flags flags = Code::ComputeFlags(Code::OPTIMIZED_FUNCTION);
Handle<Code> code =
CodeGenerator::MakeCodeEpilogue(&assembler, flags, info());
generator.FinishCode(code);
CodeGenerator::PrintCode(code, info());
return code;
}
return Handle<Code>::null();
}
} } // namespace v8::internal } } // namespace v8::internal

View File

@ -622,6 +622,7 @@ class DeepIterator BASE_EMBEDDED {
}; };
class LChunk;
class LGap; class LGap;
class LLabel; class LLabel;
@ -629,13 +630,7 @@ class LLabel;
// arch-specific LChunk classes. // arch-specific LChunk classes.
class LChunkBase: public ZoneObject { class LChunkBase: public ZoneObject {
public: public:
LChunkBase(CompilationInfo* info, HGraph* graph) static LChunkBase* NewChunk(HGraph* graph);
: spill_slot_count_(0),
info_(info),
graph_(graph),
instructions_(32, graph->zone()),
pointer_maps_(8, graph->zone()),
inlined_closures_(1, graph->zone()) { }
void AddInstruction(LInstruction* instruction, HBasicBlock* block); void AddInstruction(LInstruction* instruction, HBasicBlock* block);
LConstantOperand* DefineConstantOperand(HConstant* constant); LConstantOperand* DefineConstantOperand(HConstant* constant);
@ -668,7 +663,17 @@ class LChunkBase: public ZoneObject {
Zone* zone() const { return info_->zone(); } Zone* zone() const { return info_->zone(); }
Handle<Code> Codegen();
protected: protected:
LChunkBase(CompilationInfo* info, HGraph* graph)
: spill_slot_count_(0),
info_(info),
graph_(graph),
instructions_(32, graph->zone()),
pointer_maps_(8, graph->zone()),
inlined_closures_(1, graph->zone()) { }
int spill_slot_count_; int spill_slot_count_;
private: private:

View File

@ -43,9 +43,9 @@ class SafepointGenerator;
class LCodeGen BASE_EMBEDDED { class LCodeGen BASE_EMBEDDED {
public: public:
LCodeGen(LChunk* chunk, MacroAssembler* assembler, CompilationInfo* info) LCodeGen(LChunkBase* chunk, MacroAssembler* assembler, CompilationInfo* info)
: zone_(info->zone()), : zone_(info->zone()),
chunk_(chunk), chunk_(static_cast<LChunk*>(chunk)),
masm_(assembler), masm_(assembler),
info_(info), info_(info),
current_block_(-1), current_block_(-1),

View File

@ -45,9 +45,9 @@ class SafepointGenerator;
class LCodeGen BASE_EMBEDDED { class LCodeGen BASE_EMBEDDED {
public: public:
LCodeGen(LChunk* chunk, MacroAssembler* assembler, CompilationInfo* info) LCodeGen(LChunkBase* chunk, MacroAssembler* assembler, CompilationInfo* info)
: zone_(info->zone()), : zone_(info->zone()),
chunk_(chunk), chunk_(static_cast<LChunk*>(chunk)),
masm_(assembler), masm_(assembler),
info_(info), info_(info),
current_block_(-1), current_block_(-1),