Commit c97a7acf authored by dcarney's avatar dcarney Committed by Commit bot

[turbofan] refactor pipeline to use hydrogen like Run calls

BUG=

Review URL: https://codereview.chromium.org/727733002

Cr-Commit-Position: refs/heads/master@{#25361}
parent f3d5b13e
......@@ -58,10 +58,6 @@ class AstGraphBuilder : public StructuredGraphBuilder, public AstVisitor {
typedef StructuredGraphBuilder::Environment BaseEnvironment;
virtual BaseEnvironment* CopyEnvironment(BaseEnvironment* env) OVERRIDE;
// TODO(mstarzinger): The pipeline only needs to be a friend to access the
// function context. Remove as soon as the context is a parameter.
friend class Pipeline;
// Getters for values in the activation record.
Node* GetFunctionClosure();
Node* GetFunctionContext();
......
......@@ -17,7 +17,7 @@ namespace compiler {
// registers for a compiled function. Frames are usually populated by the
// register allocator and are used by Linkage to generate code for the prologue
// and epilogue to compiled code.
class Frame {
class Frame : public ZoneObject {
public:
Frame()
: register_save_area_size_(0),
......@@ -69,6 +69,8 @@ class Frame {
int double_spill_slot_count_;
BitVector* allocated_registers_;
BitVector* allocated_double_registers_;
DISALLOW_COPY_AND_ASSIGN(Frame);
};
......
......@@ -889,7 +889,7 @@ struct PrintableInstructionSequence;
// Represents architecture-specific generated code before, during, and after
// register allocation.
// TODO(titzer): s/IsDouble/IsFloat64/
class InstructionSequence FINAL {
class InstructionSequence FINAL : public ZoneObject {
public:
static InstructionBlocks* InstructionBlocksFor(Zone* zone,
const Schedule* schedule);
......@@ -1015,6 +1015,8 @@ class InstructionSequence FINAL {
VirtualRegisterSet doubles_;
VirtualRegisterSet references_;
DeoptimizationVector deoptimization_entries_;
DISALLOW_COPY_AND_ASSIGN(InstructionSequence);
};
......
......@@ -43,12 +43,15 @@ namespace compiler {
class PipelineData {
public:
explicit PipelineData(CompilationInfo* info, ZonePool* zone_pool,
PipelineData(CompilationInfo* info, ZonePool* zone_pool,
PipelineStatistics* pipeline_statistics)
: isolate_(info->zone()->isolate()),
info_(info),
outer_zone_(info->zone()),
zone_pool_(zone_pool),
pipeline_statistics_(pipeline_statistics),
compilation_failed_(false),
code_(Handle<Code>::null()),
graph_zone_scope_(zone_pool_),
graph_zone_(graph_zone_scope_.zone()),
graph_(new (graph_zone()) Graph(graph_zone())),
......@@ -61,28 +64,38 @@ class PipelineData {
jsgraph_(new (graph_zone())
JSGraph(graph(), common(), javascript(), machine())),
typer_(new Typer(graph(), info->context())),
schedule_(NULL),
context_node_(nullptr),
schedule_(nullptr),
instruction_zone_scope_(zone_pool_),
instruction_zone_(instruction_zone_scope_.zone()) {}
instruction_zone_(instruction_zone_scope_.zone()),
sequence_(nullptr),
frame_(nullptr) {}
// For machine graph testing only.
PipelineData(Graph* graph, Schedule* schedule, ZonePool* zone_pool)
: isolate_(graph->zone()->isolate()),
outer_zone_(NULL),
info_(nullptr),
outer_zone_(nullptr),
zone_pool_(zone_pool),
pipeline_statistics_(NULL),
pipeline_statistics_(nullptr),
compilation_failed_(false),
code_(Handle<Code>::null()),
graph_zone_scope_(zone_pool_),
graph_zone_(NULL),
graph_zone_(nullptr),
graph_(graph),
source_positions_(new SourcePositionTable(graph)),
machine_(NULL),
common_(NULL),
javascript_(NULL),
jsgraph_(NULL),
typer_(NULL),
machine_(nullptr),
common_(nullptr),
javascript_(nullptr),
jsgraph_(nullptr),
typer_(nullptr),
context_node_(nullptr),
schedule_(schedule),
instruction_zone_scope_(zone_pool_),
instruction_zone_(instruction_zone_scope_.zone()) {}
instruction_zone_(instruction_zone_scope_.zone()),
sequence_(nullptr),
frame_(nullptr) {}
~PipelineData() {
DeleteInstructionZone();
......@@ -90,8 +103,19 @@ class PipelineData {
}
Isolate* isolate() const { return isolate_; }
CompilationInfo* info() const { return info_; }
ZonePool* zone_pool() const { return zone_pool_; }
PipelineStatistics* pipeline_statistics() { return pipeline_statistics_; }
bool compilation_failed() const { return compilation_failed_; }
void set_compilation_failed() { compilation_failed_ = true; }
Handle<Code> code() { return code_; }
void set_code(Handle<Code> code) {
DCHECK(code_.is_null());
code_ = code;
}
// RawMachineAssembler generally produces graphs which cannot be verified.
bool MayHaveUnverifiableGraph() const { return outer_zone_ == nullptr; }
Zone* graph_zone() const { return graph_zone_; }
Graph* graph() const { return graph_; }
......@@ -103,43 +127,64 @@ class PipelineData {
JSOperatorBuilder* javascript() const { return javascript_; }
JSGraph* jsgraph() const { return jsgraph_; }
Typer* typer() const { return typer_.get(); }
Node* context_node() const { return context_node_; }
void set_context_node(Node* context_node) {
DCHECK_EQ(nullptr, context_node_);
context_node_ = context_node;
}
Schedule* schedule() const { return schedule_; }
void set_schedule(Schedule* schedule) {
DCHECK_EQ(NULL, schedule_);
DCHECK_EQ(nullptr, schedule_);
schedule_ = schedule;
}
Zone* instruction_zone() const { return instruction_zone_; }
// RawMachineAssembler generally produces graphs which cannot be verified.
bool MayHaveUnverifiableGraph() const { return outer_zone_ == nullptr; }
InstructionSequence* sequence() const { return sequence_; }
void set_sequence(InstructionSequence* sequence) {
DCHECK_EQ(nullptr, sequence_);
sequence_ = sequence;
}
Frame* frame() const { return frame_; }
void set_frame(Frame* frame) {
DCHECK_EQ(nullptr, frame_);
frame_ = frame;
}
void DeleteGraphZone() {
// Destroy objects with destructors first.
source_positions_.Reset(NULL);
typer_.Reset(NULL);
if (graph_zone_ == NULL) return;
source_positions_.Reset(nullptr);
typer_.Reset(nullptr);
if (graph_zone_ == nullptr) return;
// Destroy zone and clear pointers.
graph_zone_scope_.Destroy();
graph_zone_ = NULL;
graph_ = NULL;
machine_ = NULL;
common_ = NULL;
javascript_ = NULL;
jsgraph_ = NULL;
schedule_ = NULL;
graph_zone_ = nullptr;
graph_ = nullptr;
machine_ = nullptr;
common_ = nullptr;
javascript_ = nullptr;
jsgraph_ = nullptr;
context_node_ = nullptr;
schedule_ = nullptr;
}
void DeleteInstructionZone() {
if (instruction_zone_ == NULL) return;
if (instruction_zone_ == nullptr) return;
instruction_zone_scope_.Destroy();
instruction_zone_ = NULL;
instruction_zone_ = nullptr;
sequence_ = nullptr;
frame_ = nullptr;
}
private:
Isolate* isolate_;
CompilationInfo* info_;
Zone* outer_zone_;
ZonePool* zone_pool_;
PipelineStatistics* pipeline_statistics_;
bool compilation_failed_;
Handle<Code> code_;
ZonePool::Scope graph_zone_scope_;
Zone* graph_zone_;
......@@ -154,6 +199,7 @@ class PipelineData {
JSGraph* jsgraph_;
// TODO(dcarney): make this into a ZoneObject.
SmartPointer<Typer> typer_;
Node* context_node_;
Schedule* schedule_;
// All objects in the following group of fields are allocated in
......@@ -161,6 +207,8 @@ class PipelineData {
// destroyed.
ZonePool::Scope instruction_zone_scope_;
Zone* instruction_zone_;
InstructionSequence* sequence_;
Frame* frame_;
DISALLOW_COPY_AND_ASSIGN(PipelineData);
};
......@@ -182,18 +230,335 @@ struct TurboCfgFile : public std::ofstream {
};
void Pipeline::VerifyAndPrintGraph(
Graph* graph, const char* phase, bool untyped) {
static void TraceSchedule(Schedule* schedule) {
if (!FLAG_trace_turbo) return;
OFStream os(stdout);
os << "-- Schedule --------------------------------------\n" << *schedule;
}
static SmartArrayPointer<char> GetDebugName(CompilationInfo* info) {
SmartArrayPointer<char> name;
if (info->IsStub()) {
if (info->code_stub() != NULL) {
CodeStub::Major major_key = info->code_stub()->MajorKey();
const char* major_name = CodeStub::MajorName(major_key, false);
size_t len = strlen(major_name);
name.Reset(new char[len]);
memcpy(name.get(), major_name, len);
}
} else {
AllowHandleDereference allow_deref;
name = info->function()->debug_name()->ToCString();
}
return name;
}
class AstGraphBuilderWithPositions : public AstGraphBuilder {
public:
explicit AstGraphBuilderWithPositions(Zone* local_zone, CompilationInfo* info,
JSGraph* jsgraph,
SourcePositionTable* source_positions)
: AstGraphBuilder(local_zone, info, jsgraph),
source_positions_(source_positions) {}
bool CreateGraph() {
SourcePositionTable::Scope pos(source_positions_,
SourcePosition::Unknown());
return AstGraphBuilder::CreateGraph();
}
#define DEF_VISIT(type) \
virtual void Visit##type(type* node) OVERRIDE { \
SourcePositionTable::Scope pos(source_positions_, \
SourcePosition(node->position())); \
AstGraphBuilder::Visit##type(node); \
}
AST_NODE_LIST(DEF_VISIT)
#undef DEF_VISIT
Node* GetFunctionContext() { return AstGraphBuilder::GetFunctionContext(); }
private:
SourcePositionTable* source_positions_;
};
class PipelineRunScope {
public:
PipelineRunScope(PipelineData* data, const char* phase_name)
: phase_scope_(
phase_name == nullptr ? nullptr : data->pipeline_statistics(),
phase_name),
zone_scope_(data->zone_pool()) {}
Zone* zone() { return zone_scope_.zone(); }
private:
PhaseScope phase_scope_;
ZonePool::Scope zone_scope_;
};
template <typename Phase>
void Pipeline::Run() {
PipelineRunScope scope(this->data_, Phase::phase_name());
Phase phase;
phase.Run(this->data_, scope.zone());
}
template <typename Phase, typename Arg0>
void Pipeline::Run(Arg0 arg_0) {
PipelineRunScope scope(this->data_, Phase::phase_name());
Phase phase;
phase.Run(this->data_, scope.zone(), arg_0);
}
// TODO(dcarney): this one should be unecessary.
template <typename Phase, typename Arg0, typename Arg1>
void Pipeline::Run(Arg0 arg_0, Arg1 arg_1) {
PipelineRunScope scope(this->data_, Phase::phase_name());
Phase phase;
phase.Run(this->data_, scope.zone(), arg_0, arg_1);
}
struct GraphBuilderPhase {
static const char* phase_name() { return "graph builder"; }
void Run(PipelineData* data, Zone* temp_zone) {
AstGraphBuilderWithPositions graph_builder(
temp_zone, data->info(), data->jsgraph(), data->source_positions());
if (graph_builder.CreateGraph()) {
data->set_context_node(graph_builder.GetFunctionContext());
} else {
data->set_compilation_failed();
}
}
};
struct ContextSpecializerPhase {
static const char* phase_name() { return nullptr; }
void Run(PipelineData* data, Zone* temp_zone) {
SourcePositionTable::Scope pos(data->source_positions(),
SourcePosition::Unknown());
JSContextSpecializer spec(data->info(), data->jsgraph(),
data->context_node());
spec.SpecializeToContext();
}
};
struct InliningPhase {
static const char* phase_name() { return "inlining"; }
void Run(PipelineData* data, Zone* temp_zone) {
SourcePositionTable::Scope pos(data->source_positions(),
SourcePosition::Unknown());
JSInliner inliner(temp_zone, data->info(), data->jsgraph());
inliner.Inline();
}
};
struct TyperPhase {
static const char* phase_name() { return "typer"; }
void Run(PipelineData* data, Zone* temp_zone) { data->typer()->Run(); }
};
struct TypedLoweringPhase {
static const char* phase_name() { return "typed lowering"; }
void Run(PipelineData* data, Zone* temp_zone) {
SourcePositionTable::Scope pos(data->source_positions(),
SourcePosition::Unknown());
ValueNumberingReducer vn_reducer(data->graph_zone());
JSTypedLowering lowering(data->jsgraph());
SimplifiedOperatorReducer simple_reducer(data->jsgraph());
GraphReducer graph_reducer(data->graph());
graph_reducer.AddReducer(&vn_reducer);
graph_reducer.AddReducer(&lowering);
graph_reducer.AddReducer(&simple_reducer);
graph_reducer.ReduceGraph();
}
};
struct SimplifiedLoweringPhase {
static const char* phase_name() { return "simplified lowering"; }
void Run(PipelineData* data, Zone* temp_zone) {
SourcePositionTable::Scope pos(data->source_positions(),
SourcePosition::Unknown());
SimplifiedLowering lowering(data->jsgraph());
lowering.LowerAllNodes();
ValueNumberingReducer vn_reducer(data->graph_zone());
SimplifiedOperatorReducer simple_reducer(data->jsgraph());
GraphReducer graph_reducer(data->graph());
graph_reducer.AddReducer(&vn_reducer);
graph_reducer.AddReducer(&simple_reducer);
graph_reducer.ReduceGraph();
}
};
struct ChangeLoweringPhase {
static const char* phase_name() { return "change lowering"; }
void Run(PipelineData* data, Zone* temp_zone) {
SourcePositionTable::Scope pos(data->source_positions(),
SourcePosition::Unknown());
Linkage linkage(data->graph_zone(), data->info());
ValueNumberingReducer vn_reducer(data->graph_zone());
SimplifiedOperatorReducer simple_reducer(data->jsgraph());
ChangeLowering lowering(data->jsgraph(), &linkage);
MachineOperatorReducer mach_reducer(data->jsgraph());
GraphReducer graph_reducer(data->graph());
// TODO(titzer): Figure out if we should run all reducers at once here.
graph_reducer.AddReducer(&vn_reducer);
graph_reducer.AddReducer(&simple_reducer);
graph_reducer.AddReducer(&lowering);
graph_reducer.AddReducer(&mach_reducer);
graph_reducer.ReduceGraph();
}
};
struct ControlReductionPhase {
void Run(PipelineData* data, Zone* temp_zone) {
SourcePositionTable::Scope pos(data->source_positions(),
SourcePosition::Unknown());
ControlReducer::ReduceGraph(temp_zone, data->jsgraph(), data->common());
}
};
struct EarlyControlReductionPhase : ControlReductionPhase {
static const char* phase_name() { return "early control reduction"; }
};
struct LateControlReductionPhase : ControlReductionPhase {
static const char* phase_name() { return "late control reduction"; }
};
struct GenericLoweringPhase {
static const char* phase_name() { return "generic lowering"; }
void Run(PipelineData* data, Zone* temp_zone) {
SourcePositionTable::Scope pos(data->source_positions(),
SourcePosition::Unknown());
JSGenericLowering generic(data->info(), data->jsgraph());
SelectLowering select(data->jsgraph()->graph(), data->jsgraph()->common());
GraphReducer graph_reducer(data->graph());
graph_reducer.AddReducer(&generic);
graph_reducer.AddReducer(&select);
graph_reducer.ReduceGraph();
}
};
struct ComputeSchedulePhase {
static const char* phase_name() { return "scheduling"; }
void Run(PipelineData* data, Zone* temp_zone) {
Schedule* schedule = Scheduler::ComputeSchedule(temp_zone, data->graph());
TraceSchedule(schedule);
if (VerifyGraphs()) ScheduleVerifier::Run(schedule);
data->set_schedule(schedule);
}
};
struct InstructionSelectionPhase {
static const char* phase_name() { return "select instructions"; }
void Run(PipelineData* data, Zone* temp_zone, Linkage* linkage) {
InstructionSelector selector(temp_zone, data->graph(), linkage,
data->sequence(), data->schedule(),
data->source_positions());
selector.SelectInstructions();
}
};
// TODO(dcarney): break this up.
struct RegisterAllocationPhase {
static const char* phase_name() { return nullptr; }
void Run(PipelineData* data, Zone* temp_zone) {
int node_count = data->sequence()->VirtualRegisterCount();
if (node_count > UnallocatedOperand::kMaxVirtualRegisters) {
data->set_compilation_failed();
return;
}
SmartArrayPointer<char> debug_name;
#ifdef DEBUG
if (data->info() != nullptr) {
debug_name = GetDebugName(data->info());
}
#endif
RegisterAllocator allocator(RegisterConfiguration::ArchDefault(), temp_zone,
data->frame(), data->sequence(),
debug_name.get());
if (!allocator.Allocate(data->pipeline_statistics())) {
data->set_compilation_failed();
return;
}
if (FLAG_trace_turbo) {
OFStream os(stdout);
PrintableInstructionSequence printable = {
RegisterConfiguration::ArchDefault(), data->sequence()};
os << "----- Instruction sequence after register allocation -----\n"
<< printable;
}
if (FLAG_trace_turbo && !data->MayHaveUnverifiableGraph()) {
TurboCfgFile tcf(data->isolate());
tcf << AsC1VAllocator("CodeGen", &allocator);
}
}
};
struct GenerateCodePhase {
static const char* phase_name() { return "generate code"; }
void Run(PipelineData* data, Zone* temp_zone, Linkage* linkage,
CompilationInfo* info) {
CodeGenerator generator(data->frame(), linkage, data->sequence(), info);
data->set_code(generator.GenerateCode());
}
};
struct PrintGraphPhase {
static const char* phase_name() { return nullptr; }
void Run(PipelineData* data, Zone* temp_zone, const char* phase) {
CompilationInfo* info = data->info();
Graph* graph = data->graph();
char buffer[256];
Vector<char> filename(buffer, sizeof(buffer));
SmartArrayPointer<char> functionname;
if (!info_->shared_info().is_null()) {
functionname = info_->shared_info()->DebugName()->ToCString();
if (!info->shared_info().is_null()) {
functionname = info->shared_info()->DebugName()->ToCString();
if (strlen(functionname.get()) > 0) {
SNPrintF(filename, "turbo-%s-%s", functionname.get(), phase);
} else {
SNPrintF(filename, "turbo-%p-%s", static_cast<void*>(info_), phase);
SNPrintF(filename, "turbo-%p-%s", static_cast<void*>(info), phase);
}
} else {
SNPrintF(filename, "turbo-none-%s", phase);
......@@ -221,63 +586,27 @@ void Pipeline::VerifyAndPrintGraph(
os << "-- " << phase << " graph printed to file " << filename.start()
<< "\n";
}
if (VerifyGraphs()) {
Verifier::Run(graph,
FLAG_turbo_types && !untyped ? Verifier::TYPED : Verifier::UNTYPED);
}
}
};
class AstGraphBuilderWithPositions : public AstGraphBuilder {
public:
explicit AstGraphBuilderWithPositions(Zone* local_zone, CompilationInfo* info,
JSGraph* jsgraph,
SourcePositionTable* source_positions)
: AstGraphBuilder(local_zone, info, jsgraph),
source_positions_(source_positions) {}
struct VerifyGraphPhase {
static const char* phase_name() { return nullptr; }
bool CreateGraph() {
SourcePositionTable::Scope pos(source_positions_,
SourcePosition::Unknown());
return AstGraphBuilder::CreateGraph();
void Run(PipelineData* data, Zone* temp_zone, const bool untyped) {
Verifier::Run(data->graph(), FLAG_turbo_types && !untyped
? Verifier::TYPED
: Verifier::UNTYPED);
}
#define DEF_VISIT(type) \
virtual void Visit##type(type* node) OVERRIDE { \
SourcePositionTable::Scope pos(source_positions_, \
SourcePosition(node->position())); \
AstGraphBuilder::Visit##type(node); \
}
AST_NODE_LIST(DEF_VISIT)
#undef DEF_VISIT
private:
SourcePositionTable* source_positions_;
};
static void TraceSchedule(Schedule* schedule) {
if (!FLAG_trace_turbo) return;
OFStream os(stdout);
os << "-- Schedule --------------------------------------\n" << *schedule;
}
static SmartArrayPointer<char> GetDebugName(CompilationInfo* info) {
SmartArrayPointer<char> name;
if (info->IsStub()) {
if (info->code_stub() != NULL) {
CodeStub::Major major_key = info->code_stub()->MajorKey();
const char* major_name = CodeStub::MajorName(major_key, false);
size_t len = strlen(major_name);
name.Reset(new char[len]);
memcpy(name.get(), major_name, len);
void Pipeline::RunPrintAndVerify(const char* phase, bool untyped) {
if (FLAG_trace_turbo) {
Run<PrintGraphPhase>(phase);
}
} else {
AllowHandleDereference allow_deref;
name = info->function()->debug_name()->ToCString();
if (VerifyGraphs()) {
Run<VerifyGraphPhase>(untyped);
}
return name;
}
......@@ -297,13 +626,16 @@ Handle<Code> Pipeline::GenerateCode() {
}
ZonePool zone_pool(isolate());
SmartPointer<PipelineStatistics> pipeline_statistics;
if (FLAG_turbo_stats) {
pipeline_statistics.Reset(new PipelineStatistics(info(), &zone_pool));
pipeline_statistics->BeginPhaseKind("graph creation");
}
PipelineData data(info(), &zone_pool, pipeline_statistics.get());
this->data_ = &data;
if (FLAG_trace_turbo) {
OFStream os(stdout);
os << "---------------------------------------------------\n"
......@@ -313,56 +645,28 @@ Handle<Code> Pipeline::GenerateCode() {
tcf << AsC1VCompilation(info());
}
// Initialize the graph and builders.
PipelineData data(info(), &zone_pool, pipeline_statistics.get());
data.source_positions()->AddDecorator();
Node* context_node;
{
PhaseScope phase_scope(pipeline_statistics.get(), "graph builder");
ZonePool::Scope zone_scope(data.zone_pool());
AstGraphBuilderWithPositions graph_builder(
zone_scope.zone(), info(), data.jsgraph(), data.source_positions());
if (!graph_builder.CreateGraph()) return Handle<Code>::null();
context_node = graph_builder.GetFunctionContext();
}
VerifyAndPrintGraph(data.graph(), "Initial untyped", true);
{
PhaseScope phase_scope(pipeline_statistics.get(),
"early control reduction");
SourcePositionTable::Scope pos(data.source_positions(),
SourcePosition::Unknown());
ZonePool::Scope zone_scope(data.zone_pool());
ControlReducer::ReduceGraph(zone_scope.zone(), data.jsgraph(),
data.common());
Run<GraphBuilderPhase>();
if (data.compilation_failed()) return Handle<Code>::null();
RunPrintAndVerify("Initial untyped", true);
VerifyAndPrintGraph(data.graph(), "Early Control reduced", true);
}
Run<EarlyControlReductionPhase>();
RunPrintAndVerify("Early Control reduced", true);
if (info()->is_context_specializing()) {
SourcePositionTable::Scope pos(data.source_positions(),
SourcePosition::Unknown());
// Specialize the code to the context as aggressively as possible.
JSContextSpecializer spec(info(), data.jsgraph(), context_node);
spec.SpecializeToContext();
VerifyAndPrintGraph(data.graph(), "Context specialized", true);
Run<ContextSpecializerPhase>();
RunPrintAndVerify("Context specialized", true);
}
if (info()->is_inlining_enabled()) {
PhaseScope phase_scope(pipeline_statistics.get(), "inlining");
SourcePositionTable::Scope pos(data.source_positions(),
SourcePosition::Unknown());
ZonePool::Scope zone_scope(data.zone_pool());
JSInliner inliner(zone_scope.zone(), info(), data.jsgraph());
inliner.Inline();
VerifyAndPrintGraph(data.graph(), "Inlined", true);
Run<InliningPhase>();
RunPrintAndVerify("Inlined", true);
}
// Print a replay of the initial graph.
if (FLAG_print_turbo_replay) {
// Print a replay of the initial graph.
GraphReplayPrinter::PrintReplay(data.graph());
}
......@@ -370,118 +674,54 @@ Handle<Code> Pipeline::GenerateCode() {
if (!SupportedTarget()) return Handle<Code>::null();
if (info()->is_typing_enabled()) {
{
// Type the graph.
PhaseScope phase_scope(pipeline_statistics.get(), "typer");
data.typer()->Run();
VerifyAndPrintGraph(data.graph(), "Typed");
}
Run<TyperPhase>();
RunPrintAndVerify("Typed");
}
if (!pipeline_statistics.is_empty()) {
pipeline_statistics->BeginPhaseKind("lowering");
data.pipeline_statistics()->BeginPhaseKind("lowering");
}
if (info()->is_typing_enabled()) {
{
// Lower JSOperators where we can determine types.
PhaseScope phase_scope(pipeline_statistics.get(), "typed lowering");
SourcePositionTable::Scope pos(data.source_positions(),
SourcePosition::Unknown());
ValueNumberingReducer vn_reducer(data.graph_zone());
JSTypedLowering lowering(data.jsgraph());
SimplifiedOperatorReducer simple_reducer(data.jsgraph());
GraphReducer graph_reducer(data.graph());
graph_reducer.AddReducer(&vn_reducer);
graph_reducer.AddReducer(&lowering);
graph_reducer.AddReducer(&simple_reducer);
graph_reducer.ReduceGraph();
Run<TypedLoweringPhase>();
RunPrintAndVerify("Lowered typed");
VerifyAndPrintGraph(data.graph(), "Lowered typed");
}
{
// Lower simplified operators and insert changes.
PhaseScope phase_scope(pipeline_statistics.get(), "simplified lowering");
SourcePositionTable::Scope pos(data.source_positions(),
SourcePosition::Unknown());
SimplifiedLowering lowering(data.jsgraph());
lowering.LowerAllNodes();
ValueNumberingReducer vn_reducer(data.graph_zone());
SimplifiedOperatorReducer simple_reducer(data.jsgraph());
GraphReducer graph_reducer(data.graph());
graph_reducer.AddReducer(&vn_reducer);
graph_reducer.AddReducer(&simple_reducer);
graph_reducer.ReduceGraph();
Run<SimplifiedLoweringPhase>();
RunPrintAndVerify("Lowered simplified");
VerifyAndPrintGraph(data.graph(), "Lowered simplified");
}
{
// Lower changes that have been inserted before.
PhaseScope phase_scope(pipeline_statistics.get(), "change lowering");
SourcePositionTable::Scope pos(data.source_positions(),
SourcePosition::Unknown());
Linkage linkage(data.graph_zone(), info());
ValueNumberingReducer vn_reducer(data.graph_zone());
SimplifiedOperatorReducer simple_reducer(data.jsgraph());
ChangeLowering lowering(data.jsgraph(), &linkage);
MachineOperatorReducer mach_reducer(data.jsgraph());
GraphReducer graph_reducer(data.graph());
// TODO(titzer): Figure out if we should run all reducers at once here.
graph_reducer.AddReducer(&vn_reducer);
graph_reducer.AddReducer(&simple_reducer);
graph_reducer.AddReducer(&lowering);
graph_reducer.AddReducer(&mach_reducer);
graph_reducer.ReduceGraph();
// TODO(jarin, rossberg): Remove UNTYPED once machine typing works.
VerifyAndPrintGraph(data.graph(), "Lowered changes", true);
}
{
PhaseScope phase_scope(pipeline_statistics.get(),
"late control reduction");
SourcePositionTable::Scope pos(data.source_positions(),
SourcePosition::Unknown());
ZonePool::Scope zone_scope(data.zone_pool());
ControlReducer::ReduceGraph(zone_scope.zone(), data.jsgraph(),
data.common());
Run<ChangeLoweringPhase>();
// // TODO(jarin, rossberg): Remove UNTYPED once machine typing works.
RunPrintAndVerify("Lowered changes", true);
VerifyAndPrintGraph(data.graph(), "Late Control reduced");
}
Run<LateControlReductionPhase>();
RunPrintAndVerify("Late Control reduced");
}
{
// Lower any remaining generic JSOperators.
PhaseScope phase_scope(pipeline_statistics.get(), "generic lowering");
SourcePositionTable::Scope pos(data.source_positions(),
SourcePosition::Unknown());
JSGenericLowering generic(info(), data.jsgraph());
SelectLowering select(data.jsgraph()->graph(), data.jsgraph()->common());
GraphReducer graph_reducer(data.graph());
graph_reducer.AddReducer(&generic);
graph_reducer.AddReducer(&select);
graph_reducer.ReduceGraph();
Run<GenericLoweringPhase>();
// TODO(jarin, rossberg): Remove UNTYPED once machine typing works.
VerifyAndPrintGraph(data.graph(), "Lowered generic", true);
}
RunPrintAndVerify("Lowered generic", true);
if (!pipeline_statistics.is_empty()) {
pipeline_statistics->BeginPhaseKind("block building");
data.pipeline_statistics()->BeginPhaseKind("block building");
}
data.source_positions()->RemoveDecorator();
// Compute a schedule.
ComputeSchedule(&data);
Run<ComputeSchedulePhase>();
Handle<Code> code = Handle<Code>::null();
{
// Generate optimized code.
Linkage linkage(data.instruction_zone(), info());
code = GenerateCode(&linkage, &data);
info()->SetCode(code);
GenerateCode(&linkage);
}
Handle<Code> code = data.code();
info()->SetCode(code);
// Print optimized code.
v8::internal::CodeGenerator::PrintCode(code, info());
......@@ -497,32 +737,24 @@ Handle<Code> Pipeline::GenerateCode() {
}
void Pipeline::ComputeSchedule(PipelineData* data) {
PhaseScope phase_scope(data->pipeline_statistics(), "scheduling");
ZonePool::Scope zone_scope(data->zone_pool());
Schedule* schedule =
Scheduler::ComputeSchedule(zone_scope.zone(), data->graph());
TraceSchedule(schedule);
if (VerifyGraphs()) ScheduleVerifier::Run(schedule);
data->set_schedule(schedule);
}
Handle<Code> Pipeline::GenerateCodeForMachineGraph(Linkage* linkage,
Graph* graph,
Schedule* schedule) {
ZonePool zone_pool(isolate());
CHECK(SupportedBackend());
PipelineData data(graph, schedule, &zone_pool);
this->data_ = &data;
if (schedule == NULL) {
// TODO(rossberg): Should this really be untyped?
VerifyAndPrintGraph(graph, "Machine", true);
ComputeSchedule(&data);
RunPrintAndVerify("Machine", true);
Run<ComputeSchedulePhase>();
} else {
TraceSchedule(schedule);
}
Handle<Code> code = GenerateCode(linkage, &data);
GenerateCode(linkage);
Handle<Code> code = data.code();
#if ENABLE_DISASSEMBLER
if (!code.is_null() && FLAG_print_opt_code) {
CodeTracer::Scope tracing_scope(isolate()->GetCodeTracer());
......@@ -534,7 +766,9 @@ Handle<Code> Pipeline::GenerateCodeForMachineGraph(Linkage* linkage,
}
Handle<Code> Pipeline::GenerateCode(Linkage* linkage, PipelineData* data) {
void Pipeline::GenerateCode(Linkage* linkage) {
PipelineData* data = this->data_;
DCHECK_NOT_NULL(linkage);
DCHECK_NOT_NULL(data->graph());
DCHECK_NOT_NULL(data->schedule());
......@@ -549,22 +783,16 @@ Handle<Code> Pipeline::GenerateCode(Linkage* linkage, PipelineData* data) {
InstructionBlocks* instruction_blocks =
InstructionSequence::InstructionBlocksFor(data->instruction_zone(),
data->schedule());
InstructionSequence sequence(data->instruction_zone(), instruction_blocks);
data->set_sequence(new (data->instruction_zone()) InstructionSequence(
data->instruction_zone(), instruction_blocks));
// Select and schedule instructions covering the scheduled graph.
{
PhaseScope phase_scope(data->pipeline_statistics(), "select instructions");
ZonePool::Scope zone_scope(data->zone_pool());
InstructionSelector selector(zone_scope.zone(), data->graph(), linkage,
&sequence, data->schedule(),
data->source_positions());
selector.SelectInstructions();
}
Run<InstructionSelectionPhase>(linkage);
if (FLAG_trace_turbo && !data->MayHaveUnverifiableGraph()) {
TurboCfgFile tcf(isolate());
tcf << AsC1V("CodeGen", data->schedule(), data->source_positions(),
&sequence);
data->sequence());
}
data->DeleteGraphZone();
......@@ -577,43 +805,15 @@ Handle<Code> Pipeline::GenerateCode(Linkage* linkage, PipelineData* data) {
// Don't track usage for this zone in compiler stats.
Zone verifier_zone(info()->isolate());
RegisterAllocatorVerifier verifier(
&verifier_zone, RegisterConfiguration::ArchDefault(), &sequence);
&verifier_zone, RegisterConfiguration::ArchDefault(), data->sequence());
#endif
// Allocate registers.
Frame frame;
{
int node_count = sequence.VirtualRegisterCount();
if (node_count > UnallocatedOperand::kMaxVirtualRegisters) {
info()->AbortOptimization(kNotEnoughVirtualRegistersForValues);
return Handle<Code>::null();
}
ZonePool::Scope zone_scope(data->zone_pool());
SmartArrayPointer<char> debug_name;
#ifdef DEBUG
debug_name = GetDebugName(info());
#endif
RegisterAllocator allocator(RegisterConfiguration::ArchDefault(),
zone_scope.zone(), &frame, &sequence,
debug_name.get());
if (!allocator.Allocate(data->pipeline_statistics())) {
data->set_frame(new (data->instruction_zone()) Frame);
Run<RegisterAllocationPhase>();
if (data->compilation_failed()) {
info()->AbortOptimization(kNotEnoughVirtualRegistersRegalloc);
return Handle<Code>::null();
}
if (FLAG_trace_turbo && !data->MayHaveUnverifiableGraph()) {
TurboCfgFile tcf(isolate());
tcf << AsC1VAllocator("CodeGen", &allocator);
}
}
if (FLAG_trace_turbo) {
OFStream os(stdout);
PrintableInstructionSequence printable = {
RegisterConfiguration::ArchDefault(), &sequence};
os << "----- Instruction sequence after register allocation -----\n"
<< printable;
return;
}
#ifdef DEBUG
......@@ -626,20 +826,15 @@ Handle<Code> Pipeline::GenerateCode(Linkage* linkage, PipelineData* data) {
}
// Generate native sequence.
Handle<Code> code;
{
PhaseScope phase_scope(data->pipeline_statistics(), "generate code");
CodeGenerator generator(&frame, linkage, &sequence, info());
code = generator.GenerateCode();
}
Run<GenerateCodePhase>(linkage, info());
if (profiler_data != NULL) {
#if ENABLE_DISASSEMBLER
std::ostringstream os;
code->Disassemble(NULL, os);
data->code()->Disassemble(NULL, os);
profiler_data->SetCode(&os);
#endif
}
return code;
}
......
......@@ -42,17 +42,25 @@ class Pipeline {
private:
CompilationInfo* info_;
PipelineData* data_;
// Helpers for executing pipeline phases.
template <typename Phase>
void Run();
template <typename Phase, typename Arg0>
void Run(Arg0 arg_0);
template <typename Phase, typename Arg0, typename Arg1>
void Run(Arg0 arg_0, Arg1 arg_1);
CompilationInfo* info() const { return info_; }
Isolate* isolate() { return info_->isolate(); }
void ComputeSchedule(PipelineData* data);
void VerifyAndPrintGraph(Graph* graph, const char* phase,
bool untyped = false);
Handle<Code> GenerateCode(Linkage* linkage, PipelineData* data);
void RunPrintAndVerify(const char* phase, bool untyped = false);
void GenerateCode(Linkage* linkage);
};
}
}
} // namespace v8::internal::compiler
} // namespace compiler
} // namespace internal
} // namespace v8
#endif // V8_COMPILER_PIPELINE_H_
......@@ -56,7 +56,7 @@ class DeoptCodegenTester {
graph = new (scope_->main_zone()) Graph(scope_->main_zone());
}
virtual ~DeoptCodegenTester() { delete code; }
virtual ~DeoptCodegenTester() {}
void GenerateCodeFromSchedule(Schedule* schedule) {
OFStream os(stdout);
......@@ -68,7 +68,8 @@ class DeoptCodegenTester {
Linkage* linkage = new (scope_->main_zone()) Linkage(info.zone(), &info);
InstructionBlocks* instruction_blocks =
TestInstrSeq::InstructionBlocksFor(scope_->main_zone(), schedule);
code = new TestInstrSeq(scope_->main_zone(), instruction_blocks);
code = new (scope_->main_zone())
TestInstrSeq(scope_->main_zone(), instruction_blocks);
SourcePositionTable source_positions(graph);
InstructionSelector selector(scope_->main_zone(), graph, linkage, code,
schedule, &source_positions);
......
......@@ -36,8 +36,6 @@ class InstructionTester : public HandleAndZoneScope {
machine(zone()),
code(NULL) {}
~InstructionTester() { delete code; }
Isolate* isolate;
Graph graph;
Schedule schedule;
......@@ -57,7 +55,7 @@ class InstructionTester : public HandleAndZoneScope {
}
InstructionBlocks* instruction_blocks =
TestInstrSeq::InstructionBlocksFor(main_zone(), &schedule);
code = new TestInstrSeq(main_zone(), instruction_blocks);
code = new (main_zone()) TestInstrSeq(main_zone(), instruction_blocks);
}
Node* Int32Constant(int32_t val) {
......
......@@ -124,7 +124,9 @@ class RegisterAllocatorTest : public TestWithZone {
}
RegisterAllocatorTest()
: num_general_registers_(kDefaultNRegs),
: frame_(nullptr),
sequence_(nullptr),
num_general_registers_(kDefaultNRegs),
num_double_registers_(kDefaultNRegs),
instruction_blocks_(zone()),
current_instruction_index_(-1),
......@@ -151,17 +153,18 @@ class RegisterAllocatorTest : public TestWithZone {
}
Frame* frame() {
if (frame_.is_empty()) {
frame_.Reset(new Frame());
if (frame_ == nullptr) {
frame_ = new (zone()) Frame();
}
return frame_.get();
return frame_;
}
InstructionSequence* sequence() {
if (sequence_.is_empty()) {
sequence_.Reset(new InstructionSequence(zone(), &instruction_blocks_));
if (sequence_ == nullptr) {
sequence_ =
new (zone()) InstructionSequence(zone(), &instruction_blocks_);
}
return sequence_.get();
return sequence_;
}
RegisterAllocator* allocator() {
......@@ -516,9 +519,9 @@ class RegisterAllocatorTest : public TestWithZone {
typedef std::vector<BlockCompletion> Completions;
SmartPointer<RegisterConfiguration> config_;
SmartPointer<Frame> frame_;
Frame* frame_;
SmartPointer<RegisterAllocator> allocator_;
SmartPointer<InstructionSequence> sequence_;
InstructionSequence* sequence_;
int num_general_registers_;
int num_double_registers_;
......
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