[turbofan] Output schedule, instructions and register allocator in C1 visualizer...
authorjarin@chromium.org <jarin@chromium.org>
Tue, 14 Oct 2014 08:43:33 +0000 (08:43 +0000)
committerjarin@chromium.org <jarin@chromium.org>
Tue, 14 Oct 2014 08:43:33 +0000 (08:43 +0000)
BUG=
R=bmeurer@chromium.org

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

git-svn-id: https://v8.googlecode.com/svn/branches/bleeding_edge@24583 ce2b1a6d-e550-0410-aec6-3dcde31c8c00

14 files changed:
src/compiler/graph-visualizer.cc
src/compiler/graph-visualizer.h
src/compiler/instruction.cc
src/compiler/node-aux-data-inl.h
src/compiler/node-aux-data.h
src/compiler/pipeline.cc
src/compiler/pipeline.h
src/compiler/schedule.h
src/compiler/source-position.cc
src/compiler/source-position.h
src/d8.cc
src/flag-definitions.h
src/isolate.cc
src/isolate.h

index 5bd8de7..4340c25 100644 (file)
@@ -17,6 +17,9 @@
 #include "src/compiler/node-properties-inl.h"
 #include "src/compiler/opcodes.h"
 #include "src/compiler/operator.h"
+#include "src/compiler/register-allocator.h"
+#include "src/compiler/schedule.h"
+#include "src/compiler/scheduler.h"
 #include "src/ostreams.h"
 
 namespace v8 {
@@ -389,6 +392,395 @@ std::ostream& operator<<(std::ostream& os, const AsDOT& ad) {
   GraphVisualizer(os, &tmp_zone, &ad.graph).Print();
   return os;
 }
+
+
+class GraphC1Visualizer {
+ public:
+  GraphC1Visualizer(std::ostream& os, Zone* zone);  // NOLINT
+
+  void PrintCompilation(const CompilationInfo* info);
+  void PrintSchedule(const char* phase, const Schedule* schedule,
+                     const SourcePositionTable* positions,
+                     const InstructionSequence* instructions);
+  void PrintAllocator(const char* phase, const RegisterAllocator* allocator);
+  Zone* zone() const { return zone_; }
+
+ private:
+  void PrintIndent();
+  void PrintStringProperty(const char* name, const char* value);
+  void PrintLongProperty(const char* name, int64_t value);
+  void PrintIntProperty(const char* name, int value);
+  void PrintBlockProperty(const char* name, BasicBlock::Id block_id);
+  void PrintNodeId(Node* n);
+  void PrintNode(Node* n);
+  void PrintInputs(Node* n);
+  void PrintInputs(InputIter* i, int count, const char* prefix);
+  void PrintType(Node* node);
+
+  void PrintLiveRange(LiveRange* range, const char* type);
+  class Tag FINAL BASE_EMBEDDED {
+   public:
+    Tag(GraphC1Visualizer* visualizer, const char* name) {
+      name_ = name;
+      visualizer_ = visualizer;
+      visualizer->PrintIndent();
+      visualizer_->os_ << "begin_" << name << "\n";
+      visualizer->indent_++;
+    }
+
+    ~Tag() {
+      visualizer_->indent_--;
+      visualizer_->PrintIndent();
+      visualizer_->os_ << "end_" << name_ << "\n";
+      DCHECK(visualizer_->indent_ >= 0);
+    }
+
+   private:
+    GraphC1Visualizer* visualizer_;
+    const char* name_;
+  };
+
+  std::ostream& os_;
+  int indent_;
+  Zone* zone_;
+
+  DISALLOW_COPY_AND_ASSIGN(GraphC1Visualizer);
+};
+
+
+void GraphC1Visualizer::PrintIndent() {
+  for (int i = 0; i < indent_; i++) {
+    os_ << "  ";
+  }
+}
+
+
+GraphC1Visualizer::GraphC1Visualizer(std::ostream& os, Zone* zone)
+    : os_(os), indent_(0), zone_(zone) {}
+
+
+void GraphC1Visualizer::PrintStringProperty(const char* name,
+                                            const char* value) {
+  PrintIndent();
+  os_ << name << " \"" << value << "\"\n";
+}
+
+
+void GraphC1Visualizer::PrintLongProperty(const char* name, int64_t value) {
+  PrintIndent();
+  os_ << name << " " << static_cast<int>(value / 1000) << "\n";
+}
+
+
+void GraphC1Visualizer::PrintBlockProperty(const char* name,
+                                           BasicBlock::Id block_id) {
+  PrintIndent();
+  os_ << name << " \"B" << block_id << "\"\n";
+}
+
+
+void GraphC1Visualizer::PrintIntProperty(const char* name, int value) {
+  PrintIndent();
+  os_ << name << " " << value << "\n";
+}
+
+
+void GraphC1Visualizer::PrintCompilation(const CompilationInfo* info) {
+  Tag tag(this, "compilation");
+  if (info->IsOptimizing()) {
+    Handle<String> name = info->function()->debug_name();
+    PrintStringProperty("name", name->ToCString().get());
+    PrintIndent();
+    os_ << "method \"" << name->ToCString().get() << ":"
+        << info->optimization_id() << "\"\n";
+  } else {
+    CodeStub::Major major_key = info->code_stub()->MajorKey();
+    PrintStringProperty("name", CodeStub::MajorName(major_key, false));
+    PrintStringProperty("method", "stub");
+  }
+  PrintLongProperty("date",
+                    static_cast<int64_t>(base::OS::TimeCurrentMillis()));
+}
+
+
+void GraphC1Visualizer::PrintNodeId(Node* n) { os_ << "n" << n->id(); }
+
+
+void GraphC1Visualizer::PrintNode(Node* n) {
+  PrintNodeId(n);
+  os_ << " " << *n->op() << " ";
+  PrintInputs(n);
+}
+
+
+void GraphC1Visualizer::PrintInputs(InputIter* i, int count,
+                                    const char* prefix) {
+  if (count > 0) {
+    os_ << prefix;
+  }
+  while (count > 0) {
+    os_ << " ";
+    PrintNodeId(**i);
+    ++(*i);
+    count--;
+  }
+}
+
+
+void GraphC1Visualizer::PrintInputs(Node* node) {
+  InputIter i = node->inputs().begin();
+  PrintInputs(&i, OperatorProperties::GetValueInputCount(node->op()), " ");
+  PrintInputs(&i, OperatorProperties::GetContextInputCount(node->op()),
+              " Ctx:");
+  PrintInputs(&i, OperatorProperties::GetFrameStateInputCount(node->op()),
+              " FS:");
+  PrintInputs(&i, OperatorProperties::GetEffectInputCount(node->op()), " Eff:");
+  PrintInputs(&i, OperatorProperties::GetControlInputCount(node->op()),
+              " Ctrl:");
+}
+
+
+void GraphC1Visualizer::PrintType(Node* node) {
+  Bounds bounds = NodeProperties::GetBounds(node);
+  os_ << " type:";
+  bounds.upper->PrintTo(os_);
+  os_ << "..";
+  bounds.lower->PrintTo(os_);
+}
+
+
+void GraphC1Visualizer::PrintSchedule(const char* phase,
+                                      const Schedule* schedule,
+                                      const SourcePositionTable* positions,
+                                      const InstructionSequence* instructions) {
+  Tag tag(this, "cfg");
+  PrintStringProperty("name", phase);
+  const BasicBlockVector* rpo = schedule->rpo_order();
+  for (size_t i = 0; i < rpo->size(); i++) {
+    BasicBlock* current = (*rpo)[i];
+    Tag block_tag(this, "block");
+    PrintBlockProperty("name", current->id());
+    PrintIntProperty("from_bci", -1);
+    PrintIntProperty("to_bci", -1);
+
+    PrintIndent();
+    os_ << "predecessors";
+    for (BasicBlock::Predecessors::iterator j = current->predecessors_begin();
+         j != current->predecessors_end(); ++j) {
+      os_ << " \"B" << (*j)->id() << "\"";
+    }
+    os_ << "\n";
+
+    PrintIndent();
+    os_ << "successors";
+    for (BasicBlock::Successors::iterator j = current->successors_begin();
+         j != current->successors_end(); ++j) {
+      os_ << " \"B" << (*j)->id() << "\"";
+    }
+    os_ << "\n";
+
+    PrintIndent();
+    os_ << "xhandlers\n";
+
+    PrintIndent();
+    os_ << "flags\n";
+
+    if (current->dominator() != NULL) {
+      PrintBlockProperty("dominator", current->dominator()->id());
+    }
+
+    PrintIntProperty("loop_depth", current->loop_depth());
+
+    if (current->code_start() >= 0) {
+      int first_index = current->first_instruction_index();
+      int last_index = current->last_instruction_index();
+      PrintIntProperty("first_lir_id", LifetimePosition::FromInstructionIndex(
+                                           first_index).Value());
+      PrintIntProperty("last_lir_id", LifetimePosition::FromInstructionIndex(
+                                          last_index).Value());
+    }
+
+    {
+      Tag states_tag(this, "states");
+      Tag locals_tag(this, "locals");
+      int total = 0;
+      for (BasicBlock::const_iterator i = current->begin(); i != current->end();
+           ++i) {
+        if ((*i)->opcode() == IrOpcode::kPhi) total++;
+      }
+      PrintIntProperty("size", total);
+      PrintStringProperty("method", "None");
+      int index = 0;
+      for (BasicBlock::const_iterator i = current->begin(); i != current->end();
+           ++i) {
+        if ((*i)->opcode() != IrOpcode::kPhi) continue;
+        PrintIndent();
+        os_ << index << " ";
+        PrintNodeId(*i);
+        os_ << " [";
+        PrintInputs(*i);
+        os_ << "]\n";
+        index++;
+      }
+    }
+
+    {
+      Tag HIR_tag(this, "HIR");
+      for (BasicBlock::const_iterator i = current->begin(); i != current->end();
+           ++i) {
+        Node* node = *i;
+        if (node->opcode() == IrOpcode::kPhi) continue;
+        int uses = node->UseCount();
+        PrintIndent();
+        os_ << "0 " << uses << " ";
+        PrintNode(node);
+        if (FLAG_trace_turbo_types) {
+          os_ << " ";
+          PrintType(node);
+        }
+        if (positions != NULL) {
+          SourcePosition position = positions->GetSourcePosition(node);
+          if (!position.IsUnknown()) {
+            DCHECK(!position.IsInvalid());
+            os_ << " pos:" << position.raw();
+          }
+        }
+        os_ << " <|@\n";
+      }
+
+      BasicBlock::Control control = current->control();
+      if (control != BasicBlock::kNone) {
+        PrintIndent();
+        os_ << "0 0 ";
+        if (current->control_input() != NULL) {
+          PrintNode(current->control_input());
+        } else {
+          os_ << -1 - current->id().ToInt() << " Goto";
+        }
+        os_ << " ->";
+        for (BasicBlock::Successors::iterator j = current->successors_begin();
+             j != current->successors_end(); ++j) {
+          os_ << " B" << (*j)->id();
+        }
+        if (FLAG_trace_turbo_types && current->control_input() != NULL) {
+          os_ << " ";
+          PrintType(current->control_input());
+        }
+        os_ << " <|@\n";
+      }
+    }
+
+    if (instructions != NULL) {
+      Tag LIR_tag(this, "LIR");
+      for (int j = current->first_instruction_index();
+           j <= current->last_instruction_index(); j++) {
+        PrintIndent();
+        os_ << j << " " << *instructions->InstructionAt(j) << " <|@\n";
+      }
+    }
+  }
+}
+
+
+void GraphC1Visualizer::PrintAllocator(const char* phase,
+                                       const RegisterAllocator* allocator) {
+  Tag tag(this, "intervals");
+  PrintStringProperty("name", phase);
+
+  const Vector<LiveRange*>* fixed_d = allocator->fixed_double_live_ranges();
+  for (int i = 0; i < fixed_d->length(); ++i) {
+    PrintLiveRange(fixed_d->at(i), "fixed");
+  }
+
+  const Vector<LiveRange*>* fixed = allocator->fixed_live_ranges();
+  for (int i = 0; i < fixed->length(); ++i) {
+    PrintLiveRange(fixed->at(i), "fixed");
+  }
+
+  const ZoneList<LiveRange*>* live_ranges = allocator->live_ranges();
+  for (int i = 0; i < live_ranges->length(); ++i) {
+    PrintLiveRange(live_ranges->at(i), "object");
+  }
+}
+
+
+void GraphC1Visualizer::PrintLiveRange(LiveRange* range, const char* type) {
+  if (range != NULL && !range->IsEmpty()) {
+    PrintIndent();
+    os_ << range->id() << " " << type;
+    if (range->HasRegisterAssigned()) {
+      InstructionOperand* op = range->CreateAssignedOperand(zone());
+      int assigned_reg = op->index();
+      if (op->IsDoubleRegister()) {
+        os_ << " \"" << DoubleRegister::AllocationIndexToString(assigned_reg)
+            << "\"";
+      } else {
+        DCHECK(op->IsRegister());
+        os_ << " \"" << Register::AllocationIndexToString(assigned_reg) << "\"";
+      }
+    } else if (range->IsSpilled()) {
+      InstructionOperand* op = range->TopLevel()->GetSpillOperand();
+      if (op->IsDoubleStackSlot()) {
+        os_ << " \"double_stack:" << op->index() << "\"";
+      } else if (op->IsStackSlot()) {
+        os_ << " \"stack:" << op->index() << "\"";
+      } else {
+        DCHECK(op->IsConstant());
+        os_ << " \"const(nostack):" << op->index() << "\"";
+      }
+    }
+    int parent_index = -1;
+    if (range->IsChild()) {
+      parent_index = range->parent()->id();
+    } else {
+      parent_index = range->id();
+    }
+    InstructionOperand* op = range->FirstHint();
+    int hint_index = -1;
+    if (op != NULL && op->IsUnallocated()) {
+      hint_index = UnallocatedOperand::cast(op)->virtual_register();
+    }
+    os_ << " " << parent_index << " " << hint_index;
+    UseInterval* cur_interval = range->first_interval();
+    while (cur_interval != NULL && range->Covers(cur_interval->start())) {
+      os_ << " [" << cur_interval->start().Value() << ", "
+          << cur_interval->end().Value() << "[";
+      cur_interval = cur_interval->next();
+    }
+
+    UsePosition* current_pos = range->first_pos();
+    while (current_pos != NULL) {
+      if (current_pos->RegisterIsBeneficial() || FLAG_trace_all_uses) {
+        os_ << " " << current_pos->pos().Value() << " M";
+      }
+      current_pos = current_pos->next();
+    }
+
+    os_ << " \"\"\n";
+  }
+}
+
+
+std::ostream& operator<<(std::ostream& os, const AsC1VCompilation& ac) {
+  Zone tmp_zone(ac.info_->isolate());
+  GraphC1Visualizer(os, &tmp_zone).PrintCompilation(ac.info_);
+  return os;
+}
+
+
+std::ostream& operator<<(std::ostream& os, const AsC1V& ac) {
+  Zone tmp_zone(ac.schedule_->zone()->isolate());
+  GraphC1Visualizer(os, &tmp_zone)
+      .PrintSchedule(ac.phase_, ac.schedule_, ac.positions_, ac.instructions_);
+  return os;
+}
+
+
+std::ostream& operator<<(std::ostream& os, const AsC1VAllocator& ac) {
+  Zone tmp_zone(ac.allocator_->code()->zone()->isolate());
+  GraphC1Visualizer(os, &tmp_zone).PrintAllocator(ac.phase_, ac.allocator_);
+  return os;
+}
 }
 }
 }  // namespace v8::internal::compiler
index ccb2289..7212a4f 100644 (file)
@@ -9,9 +9,17 @@
 
 namespace v8 {
 namespace internal {
+
+class CompilationInfo;
+
 namespace compiler {
 
 class Graph;
+class InstructionSequence;
+class RegisterAllocator;
+class Schedule;
+class SourcePositionTable;
+
 
 struct AsDOT {
   explicit AsDOT(const Graph& g) : graph(g) {}
@@ -28,6 +36,39 @@ struct AsJSON {
 
 std::ostream& operator<<(std::ostream& os, const AsJSON& ad);
 
+struct AsC1VCompilation {
+  explicit AsC1VCompilation(const CompilationInfo* info) : info_(info) {}
+  const CompilationInfo* info_;
+};
+
+
+struct AsC1V {
+  AsC1V(const char* phase, const Schedule* schedule,
+        const SourcePositionTable* positions = NULL,
+        const InstructionSequence* instructions = NULL)
+      : schedule_(schedule),
+        instructions_(instructions),
+        positions_(positions),
+        phase_(phase) {}
+  const Schedule* schedule_;
+  const InstructionSequence* instructions_;
+  const SourcePositionTable* positions_;
+  const char* phase_;
+};
+
+struct AsC1VAllocator {
+  explicit AsC1VAllocator(const char* phase,
+                          const RegisterAllocator* allocator = NULL)
+      : phase_(phase), allocator_(allocator) {}
+  const char* phase_;
+  const RegisterAllocator* allocator_;
+};
+
+std::ostream& operator<<(std::ostream& os, const AsDOT& ad);
+std::ostream& operator<<(std::ostream& os, const AsC1VCompilation& ac);
+std::ostream& operator<<(std::ostream& os, const AsC1V& ac);
+std::ostream& operator<<(std::ostream& os, const AsC1VAllocator& ac);
+
 }  // namespace compiler
 }  // namespace internal
 }  // namespace v8
index 4a1cd1a..1a82765 100644 (file)
@@ -291,7 +291,7 @@ std::ostream& operator<<(std::ostream& os, const Instruction& instr) {
       os << " " << *instr.InputAt(i);
     }
   }
-  return os << "\n";
+  return os;
 }
 
 
@@ -564,7 +564,7 @@ std::ostream& operator<<(std::ostream& os, const InstructionSequence& code) {
          j <= block->last_instruction_index(); j++) {
       // TODO(svenpanne) Add some basic formatting to our streams.
       SNPrintF(buf, "%5d", j);
-      os << "   " << buf.start() << ": " << *code.InstructionAt(j);
+      os << "   " << buf.start() << ": " << *code.InstructionAt(j) << "\n";
     }
 
     os << "  " << block->control();
index 79f1abf..d8db4b9 100644 (file)
@@ -29,7 +29,7 @@ void NodeAuxData<T>::Set(Node* node, const T& data) {
 
 
 template <class T>
-T NodeAuxData<T>::Get(Node* node) {
+T NodeAuxData<T>::Get(Node* node) const {
   int id = node->id();
   if (id >= static_cast<int>(aux_data_.size())) {
     return T();
index 7acce33..a08dc58 100644 (file)
@@ -21,7 +21,7 @@ class NodeAuxData {
   inline explicit NodeAuxData(Zone* zone);
 
   inline void Set(Node* node, const T& data);
-  inline T Get(Node* node);
+  inline T Get(Node* node) const;
 
  private:
   ZoneVector<T> aux_data_;
index 7da2fb5..81a0ec5 100644 (file)
@@ -90,13 +90,28 @@ static inline bool VerifyGraphs() {
 }
 
 
+void Pipeline::PrintCompilationStart() {
+  std::ofstream turbo_cfg_stream;
+  OpenTurboCfgFile(&turbo_cfg_stream);
+  turbo_cfg_stream << AsC1VCompilation(info());
+}
+
+
+void Pipeline::OpenTurboCfgFile(std::ofstream* stream) {
+  char buffer[512];
+  Vector<char> filename(buffer, sizeof(buffer));
+  isolate()->GetTurboCfgFileName(filename);
+  stream->open(filename.start(), std::fstream::out | std::fstream::app);
+}
+
+
 void Pipeline::VerifyAndPrintGraph(Graph* graph, const char* phase) {
   if (FLAG_trace_turbo) {
     char buffer[256];
     Vector<char> filename(buffer, sizeof(buffer));
+    SmartArrayPointer<char> functionname;
     if (!info_->shared_info().is_null()) {
-      SmartArrayPointer<char> functionname =
-          info_->shared_info()->DebugName()->ToCString();
+      functionname = info_->shared_info()->DebugName()->ToCString();
       if (strlen(functionname.get()) > 0) {
         SNPrintF(filename, "turbo-%s-%s", functionname.get(), phase);
       } else {
@@ -132,6 +147,24 @@ void Pipeline::VerifyAndPrintGraph(Graph* graph, const char* phase) {
 }
 
 
+void Pipeline::PrintScheduleAndInstructions(
+    const char* phase, const Schedule* schedule,
+    const SourcePositionTable* positions,
+    const InstructionSequence* instructions) {
+  std::ofstream turbo_cfg_stream;
+  OpenTurboCfgFile(&turbo_cfg_stream);
+  turbo_cfg_stream << AsC1V(phase, schedule, positions, instructions);
+}
+
+
+void Pipeline::PrintAllocator(const char* phase,
+                              const RegisterAllocator* allocator) {
+  std::ofstream turbo_cfg_stream;
+  OpenTurboCfgFile(&turbo_cfg_stream);
+  turbo_cfg_stream << AsC1VAllocator(phase, allocator);
+}
+
+
 class AstGraphBuilderWithPositions : public AstGraphBuilder {
  public:
   explicit AstGraphBuilderWithPositions(CompilationInfo* info, JSGraph* jsgraph,
@@ -188,6 +221,7 @@ Handle<Code> Pipeline::GenerateCode() {
        << "Begin compiling method "
        << info()->function()->debug_name()->ToCString().get()
        << " using Turbofan" << std::endl;
+    PrintCompilationStart();
   }
 
   // Build the graph.
@@ -405,6 +439,8 @@ Handle<Code> Pipeline::GenerateCode(Linkage* linkage, Graph* graph,
     OFStream os(stdout);
     os << "----- Instruction sequence before register allocation -----\n"
        << sequence;
+    PrintScheduleAndInstructions("CodeGen", schedule, source_positions,
+                                 &sequence);
   }
 
   // Allocate registers.
@@ -419,6 +455,9 @@ Handle<Code> Pipeline::GenerateCode(Linkage* linkage, Graph* graph,
       linkage->info()->AbortOptimization(kNotEnoughVirtualRegistersRegalloc);
       return Handle<Code>::null();
     }
+    if (FLAG_trace_turbo) {
+      PrintAllocator("CodeGen", &allocator);
+    }
   }
 
   if (FLAG_trace_turbo) {
index 9f8241a..f47c3c1 100644 (file)
@@ -5,6 +5,8 @@
 #ifndef V8_COMPILER_PIPELINE_H_
 #define V8_COMPILER_PIPELINE_H_
 
+#include <fstream>  // NOLINT(readability/streams)
+
 #include "src/v8.h"
 
 #include "src/compiler.h"
@@ -18,9 +20,11 @@ namespace compiler {
 
 // Clients of this interface shouldn't depend on lots of compiler internals.
 class Graph;
+class InstructionSequence;
+class Linkage;
+class RegisterAllocator;
 class Schedule;
 class SourcePositionTable;
-class Linkage;
 
 class Pipeline {
  public:
@@ -48,6 +52,12 @@ class Pipeline {
   Zone* zone() { return info_->zone(); }
 
   Schedule* ComputeSchedule(Graph* graph);
+  void OpenTurboCfgFile(std::ofstream* stream);
+  void PrintCompilationStart();
+  void PrintScheduleAndInstructions(const char* phase, const Schedule* schedule,
+                                    const SourcePositionTable* positions,
+                                    const InstructionSequence* instructions);
+  void PrintAllocator(const char* phase, const RegisterAllocator* allocator);
   void VerifyAndPrintGraph(Graph* graph, const char* phase);
   Handle<Code> GenerateCode(Linkage* linkage, Graph* graph, Schedule* schedule,
                             SourcePositionTable* source_positions);
index 7def37f..68686b5 100644 (file)
@@ -218,11 +218,12 @@ class Schedule FINAL : public ZoneObject {
   void AddSuccessor(BasicBlock* block, BasicBlock* succ);
 
   BasicBlockVector* rpo_order() { return &rpo_order_; }
+  const BasicBlockVector* rpo_order() const { return &rpo_order_; }
 
   BasicBlock* start() { return start_; }
   BasicBlock* end() { return end_; }
 
-  Zone* zone() { return zone_; }
+  Zone* zone() const { return zone_; }
 
  private:
   friend class Scheduler;
index 1178390..9503010 100644 (file)
@@ -46,7 +46,7 @@ void SourcePositionTable::RemoveDecorator() {
 }
 
 
-SourcePosition SourcePositionTable::GetSourcePosition(Node* node) {
+SourcePosition SourcePositionTable::GetSourcePosition(Node* node) const {
   return table_.Get(node);
 }
 
index 778f067..390a17d 100644 (file)
@@ -79,7 +79,7 @@ class SourcePositionTable FINAL {
   void AddDecorator();
   void RemoveDecorator();
 
-  SourcePosition GetSourcePosition(Node* node);
+  SourcePosition GetSourcePosition(Node* node) const;
 
  private:
   class Decorator;
index d1929b0..a36ec5e 100644 (file)
--- a/src/d8.cc
+++ b/src/d8.cc
@@ -1625,6 +1625,7 @@ int Shell::Main(int argc, char* argv[]) {
   StartupDataHandler startup_data(options.natives_blob, options.snapshot_blob);
 #endif
   SetFlagsFromString("--trace-hydrogen-file=hydrogen.cfg");
+  SetFlagsFromString("--trace-turbo-cfg-file=turbo.cfg");
   SetFlagsFromString("--redirect-code-traces-to=code.asm");
   ShellArrayBufferAllocator array_buffer_allocator;
   MockArrayBufferAllocator mock_arraybuffer_allocator;
index ded5bcf..83b0abf 100644 (file)
@@ -333,6 +333,8 @@ DEFINE_BOOL(omit_map_checks_for_leaf_maps, true,
 // Flags for TurboFan.
 DEFINE_STRING(turbo_filter, "~", "optimization filter for TurboFan compiler")
 DEFINE_BOOL(trace_turbo, false, "trace generated TurboFan IR")
+DEFINE_STRING(trace_turbo_cfg_file, NULL,
+              "trace turbo cfg graph (for C1 visualizer) to a given file name")
 DEFINE_BOOL(trace_turbo_types, true, "trace generated TurboFan types")
 DEFINE_BOOL(trace_turbo_scheduler, false, "trace generated TurboFan scheduler")
 DEFINE_BOOL(turbo_asm, false, "enable TurboFan for asm.js code")
index e8e1d66..2874c16 100644 (file)
@@ -4,6 +4,8 @@
 
 #include <stdlib.h>
 
+#include <fstream>  // NOLINT(readability/streams)
+
 #include "src/v8.h"
 
 #include "src/ast.h"
@@ -1951,6 +1953,16 @@ bool Isolate::Init(Deserializer* des) {
 
   runtime_profiler_ = new RuntimeProfiler(this);
 
+  if (FLAG_trace_turbo) {
+    // Erase the file.
+    char buffer[512];
+    Vector<char> filename(buffer, sizeof(buffer));
+    GetTurboCfgFileName(filename);
+    std::ofstream turbo_cfg_stream(filename.start(),
+                                   std::fstream::out | std::fstream::trunc);
+  }
+
+
   // If we are deserializing, log non-function code objects and compiled
   // functions found in the snapshot.
   if (!create_heap_objects &&
@@ -2364,6 +2376,16 @@ BasicBlockProfiler* Isolate::GetOrCreateBasicBlockProfiler() {
 }
 
 
+void Isolate::GetTurboCfgFileName(Vector<char> filename) {
+  if (FLAG_trace_turbo_cfg_file == NULL) {
+    SNPrintF(filename, "turbo-%d-%d.cfg", base::OS::GetCurrentProcessId(),
+             id());
+  } else {
+    StrNCpy(filename, FLAG_trace_turbo_cfg_file, filename.length());
+  }
+}
+
+
 bool StackLimitCheck::JsHasOverflowed() const {
   StackGuard* stack_guard = isolate_->stack_guard();
 #ifdef USE_SIMULATOR
index f1e6a3e..7fd4a82 100644 (file)
@@ -1107,6 +1107,8 @@ class Isolate {
 
   static Isolate* NewForTesting() { return new Isolate(false); }
 
+  void GetTurboCfgFileName(Vector<char> buffer);
+
  private:
   explicit Isolate(bool enable_serializer);