summaryrefslogtreecommitdiff
path: root/deps/v8/src/compiler/pipeline.cc
diff options
context:
space:
mode:
Diffstat (limited to 'deps/v8/src/compiler/pipeline.cc')
-rw-r--r--deps/v8/src/compiler/pipeline.cc192
1 files changed, 151 insertions, 41 deletions
diff --git a/deps/v8/src/compiler/pipeline.cc b/deps/v8/src/compiler/pipeline.cc
index b0b3eb76ef..333382aaf3 100644
--- a/deps/v8/src/compiler/pipeline.cc
+++ b/deps/v8/src/compiler/pipeline.cc
@@ -6,6 +6,8 @@
#include "src/base/platform/elapsed-timer.h"
#include "src/compiler/ast-graph-builder.h"
+#include "src/compiler/basic-block-instrumentor.h"
+#include "src/compiler/change-lowering.h"
#include "src/compiler/code-generator.h"
#include "src/compiler/graph-replay.h"
#include "src/compiler/graph-visualizer.h"
@@ -13,13 +15,17 @@
#include "src/compiler/instruction-selector.h"
#include "src/compiler/js-context-specialization.h"
#include "src/compiler/js-generic-lowering.h"
+#include "src/compiler/js-inlining.h"
#include "src/compiler/js-typed-lowering.h"
+#include "src/compiler/machine-operator-reducer.h"
#include "src/compiler/phi-reducer.h"
#include "src/compiler/register-allocator.h"
#include "src/compiler/schedule.h"
#include "src/compiler/scheduler.h"
#include "src/compiler/simplified-lowering.h"
+#include "src/compiler/simplified-operator-reducer.h"
#include "src/compiler/typer.h"
+#include "src/compiler/value-numbering-reducer.h"
#include "src/compiler/verifier.h"
#include "src/hydrogen.h"
#include "src/ostreams.h"
@@ -73,23 +79,48 @@ class PhaseStats {
};
+static inline bool VerifyGraphs() {
+#ifdef DEBUG
+ return true;
+#else
+ return FLAG_turbo_verify;
+#endif
+}
+
+
void Pipeline::VerifyAndPrintGraph(Graph* graph, const char* phase) {
if (FLAG_trace_turbo) {
char buffer[256];
Vector<char> filename(buffer, sizeof(buffer));
- SmartArrayPointer<char> functionname =
- info_->shared_info()->DebugName()->ToCString();
- if (strlen(functionname.get()) > 0) {
- SNPrintF(filename, "turbo-%s-%s.dot", functionname.get(), phase);
+ if (!info_->shared_info().is_null()) {
+ SmartArrayPointer<char> 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);
+ }
} else {
- SNPrintF(filename, "turbo-%p-%s.dot", static_cast<void*>(info_), phase);
+ SNPrintF(filename, "turbo-none-%s", phase);
}
std::replace(filename.start(), filename.start() + filename.length(), ' ',
'_');
- FILE* file = base::OS::FOpen(filename.start(), "w+");
- OFStream of(file);
- of << AsDOT(*graph);
- fclose(file);
+
+ char dot_buffer[256];
+ Vector<char> dot_filename(dot_buffer, sizeof(dot_buffer));
+ SNPrintF(dot_filename, "%s.dot", filename.start());
+ FILE* dot_file = base::OS::FOpen(dot_filename.start(), "w+");
+ OFStream dot_of(dot_file);
+ dot_of << AsDOT(*graph);
+ fclose(dot_file);
+
+ char json_buffer[256];
+ Vector<char> json_filename(json_buffer, sizeof(json_buffer));
+ SNPrintF(json_filename, "%s.json", filename.start());
+ FILE* json_file = base::OS::FOpen(json_filename.start(), "w+");
+ OFStream json_of(json_file);
+ json_of << AsJSON(*graph);
+ fclose(json_file);
OFStream os(stdout);
os << "-- " << phase << " graph printed to file " << filename.start()
@@ -112,7 +143,7 @@ class AstGraphBuilderWithPositions : public AstGraphBuilder {
}
#define DEF_VISIT(type) \
- virtual void Visit##type(type* node) V8_OVERRIDE { \
+ virtual void Visit##type(type* node) OVERRIDE { \
SourcePositionTable::Scope pos(source_positions_, \
SourcePosition(node->position())); \
AstGraphBuilder::Visit##type(node); \
@@ -133,6 +164,17 @@ static void TraceSchedule(Schedule* schedule) {
Handle<Code> Pipeline::GenerateCode() {
+ if (info()->function()->dont_optimize_reason() == kTryCatchStatement ||
+ info()->function()->dont_optimize_reason() == kTryFinallyStatement ||
+ // TODO(turbofan): Make ES6 for-of work and remove this bailout.
+ info()->function()->dont_optimize_reason() == kForOfStatement ||
+ // TODO(turbofan): Make super work and remove this bailout.
+ info()->function()->dont_optimize_reason() == kSuperReference ||
+ // TODO(turbofan): Make OSR work and remove this bailout.
+ info()->is_osr()) {
+ return Handle<Code>::null();
+ }
+
if (FLAG_turbo_stats) isolate()->GetTStatistics()->Initialize(info_);
if (FLAG_trace_turbo) {
@@ -151,8 +193,10 @@ Handle<Code> Pipeline::GenerateCode() {
// construction. This is currently only needed for the node cache, which the
// typer could sweep over later.
Typer typer(zone());
+ MachineOperatorBuilder machine;
CommonOperatorBuilder common(zone());
- JSGraph jsgraph(&graph, &common, &typer);
+ JSOperatorBuilder javascript(zone());
+ JSGraph jsgraph(&graph, &common, &javascript, &typer, &machine);
Node* context_node;
{
PhaseStats graph_builder_stats(info(), PhaseStats::CREATE_GRAPH,
@@ -176,25 +220,37 @@ Handle<Code> Pipeline::GenerateCode() {
VerifyAndPrintGraph(&graph, "Initial untyped");
- if (FLAG_context_specialization) {
- SourcePositionTable::Scope pos_(&source_positions,
- SourcePosition::Unknown());
+ if (info()->is_context_specializing()) {
+ SourcePositionTable::Scope pos(&source_positions,
+ SourcePosition::Unknown());
// Specialize the code to the context as aggressively as possible.
JSContextSpecializer spec(info(), &jsgraph, context_node);
spec.SpecializeToContext();
VerifyAndPrintGraph(&graph, "Context specialized");
}
+ if (info()->is_inlining_enabled()) {
+ SourcePositionTable::Scope pos(&source_positions,
+ SourcePosition::Unknown());
+ JSInliner inliner(info(), &jsgraph);
+ inliner.Inline();
+ VerifyAndPrintGraph(&graph, "Inlined");
+ }
+
// Print a replay of the initial graph.
if (FLAG_print_turbo_replay) {
GraphReplayPrinter::PrintReplay(&graph);
}
- if (FLAG_turbo_types) {
+ // Bailout here in case target architecture is not supported.
+ if (!SupportedTarget()) return Handle<Code>::null();
+
+ if (info()->is_typing_enabled()) {
{
// Type the graph.
PhaseStats typer_stats(info(), PhaseStats::CREATE_GRAPH, "typer");
typer.Run(&graph, info()->context());
+ VerifyAndPrintGraph(&graph, "Typed");
}
// All new nodes must be typed.
typer.DecorateGraph(&graph);
@@ -202,42 +258,80 @@ Handle<Code> Pipeline::GenerateCode() {
// Lower JSOperators where we can determine types.
PhaseStats lowering_stats(info(), PhaseStats::CREATE_GRAPH,
"typed lowering");
- JSTypedLowering lowering(&jsgraph, &source_positions);
- lowering.LowerAllNodes();
+ SourcePositionTable::Scope pos(&source_positions,
+ SourcePosition::Unknown());
+ JSTypedLowering lowering(&jsgraph);
+ GraphReducer graph_reducer(&graph);
+ graph_reducer.AddReducer(&lowering);
+ graph_reducer.ReduceGraph();
VerifyAndPrintGraph(&graph, "Lowered typed");
}
- }
-
- Handle<Code> code = Handle<Code>::null();
- if (SupportedTarget()) {
{
- // Lower any remaining generic JSOperators.
+ // Lower simplified operators and insert changes.
PhaseStats lowering_stats(info(), PhaseStats::CREATE_GRAPH,
- "generic lowering");
- MachineOperatorBuilder machine(zone());
- JSGenericLowering lowering(info(), &jsgraph, &machine, &source_positions);
+ "simplified lowering");
+ SourcePositionTable::Scope pos(&source_positions,
+ SourcePosition::Unknown());
+ SimplifiedLowering lowering(&jsgraph);
lowering.LowerAllNodes();
- VerifyAndPrintGraph(&graph, "Lowered generic");
+ VerifyAndPrintGraph(&graph, "Lowered simplified");
}
-
- // Compute a schedule.
- Schedule* schedule = ComputeSchedule(&graph);
- TraceSchedule(schedule);
-
{
- // Generate optimized code.
- PhaseStats codegen_stats(info(), PhaseStats::CODEGEN, "codegen");
+ // Lower changes that have been inserted before.
+ PhaseStats lowering_stats(info(), PhaseStats::OPTIMIZATION,
+ "change lowering");
+ SourcePositionTable::Scope pos(&source_positions,
+ SourcePosition::Unknown());
Linkage linkage(info());
- code = GenerateCode(&linkage, &graph, schedule, &source_positions);
- info()->SetCode(code);
+ // TODO(turbofan): Value numbering disabled for now.
+ // ValueNumberingReducer vn_reducer(zone());
+ SimplifiedOperatorReducer simple_reducer(&jsgraph);
+ ChangeLowering lowering(&jsgraph, &linkage);
+ MachineOperatorReducer mach_reducer(&jsgraph);
+ GraphReducer graph_reducer(&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();
+
+ VerifyAndPrintGraph(&graph, "Lowered changes");
}
+ }
+
+ {
+ // Lower any remaining generic JSOperators.
+ PhaseStats lowering_stats(info(), PhaseStats::CREATE_GRAPH,
+ "generic lowering");
+ SourcePositionTable::Scope pos(&source_positions,
+ SourcePosition::Unknown());
+ JSGenericLowering lowering(info(), &jsgraph);
+ GraphReducer graph_reducer(&graph);
+ graph_reducer.AddReducer(&lowering);
+ graph_reducer.ReduceGraph();
- // Print optimized code.
- v8::internal::CodeGenerator::PrintCode(code, info());
+ VerifyAndPrintGraph(&graph, "Lowered generic");
}
+ source_positions.RemoveDecorator();
+
+ Handle<Code> code = Handle<Code>::null();
+ {
+ // Compute a schedule.
+ Schedule* schedule = ComputeSchedule(&graph);
+ // Generate optimized code.
+ PhaseStats codegen_stats(info(), PhaseStats::CODEGEN, "codegen");
+ Linkage linkage(info());
+ code = GenerateCode(&linkage, &graph, schedule, &source_positions);
+ info()->SetCode(code);
+ }
+
+ // Print optimized code.
+ v8::internal::CodeGenerator::PrintCode(code, info());
+
if (FLAG_trace_turbo) {
OFStream os(stdout);
os << "--------------------------------------------------\n"
@@ -252,7 +346,10 @@ Handle<Code> Pipeline::GenerateCode() {
Schedule* Pipeline::ComputeSchedule(Graph* graph) {
PhaseStats schedule_stats(info(), PhaseStats::CODEGEN, "scheduling");
- return Scheduler::ComputeSchedule(graph);
+ Schedule* schedule = Scheduler::ComputeSchedule(graph);
+ TraceSchedule(schedule);
+ if (VerifyGraphs()) ScheduleVerifier::Run(schedule);
+ return schedule;
}
@@ -287,6 +384,11 @@ Handle<Code> Pipeline::GenerateCode(Linkage* linkage, Graph* graph,
DCHECK_NOT_NULL(schedule);
CHECK(SupportedBackend());
+ BasicBlockProfiler::Data* profiler_data = NULL;
+ if (FLAG_turbo_profiling) {
+ profiler_data = BasicBlockInstrumentor::Instrument(info_, graph, schedule);
+ }
+
InstructionSequence sequence(linkage, graph, schedule);
// Select and schedule instructions covering the scheduled graph.
@@ -305,12 +407,12 @@ Handle<Code> Pipeline::GenerateCode(Linkage* linkage, Graph* graph,
{
int node_count = graph->NodeCount();
if (node_count > UnallocatedOperand::kMaxVirtualRegisters) {
- linkage->info()->set_bailout_reason(kNotEnoughVirtualRegistersForValues);
+ linkage->info()->AbortOptimization(kNotEnoughVirtualRegistersForValues);
return Handle<Code>::null();
}
RegisterAllocator allocator(&sequence);
if (!allocator.Allocate()) {
- linkage->info()->set_bailout_reason(kNotEnoughVirtualRegistersRegalloc);
+ linkage->info()->AbortOptimization(kNotEnoughVirtualRegistersRegalloc);
return Handle<Code>::null();
}
}
@@ -323,7 +425,15 @@ Handle<Code> Pipeline::GenerateCode(Linkage* linkage, Graph* graph,
// Generate native sequence.
CodeGenerator generator(&sequence);
- return generator.GenerateCode();
+ Handle<Code> code = generator.GenerateCode();
+ if (profiler_data != NULL) {
+#if ENABLE_DISASSEMBLER
+ OStringStream os;
+ code->Disassemble(NULL, os);
+ profiler_data->SetCode(&os);
+#endif
+ }
+ return code;
}