From 173b07faa90d819584dfc22a54a89028c2e71530 Mon Sep 17 00:00:00 2001 From: "jarin@chromium.org" Date: Tue, 14 Oct 2014 08:43:33 +0000 Subject: [PATCH] [turbofan] Output schedule, instructions and register allocator in C1 visualizer format when --turbo-trace is specified. 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 --- src/compiler/graph-visualizer.cc | 392 +++++++++++++++++++++++++++++++++++++++ src/compiler/graph-visualizer.h | 41 ++++ src/compiler/instruction.cc | 4 +- src/compiler/node-aux-data-inl.h | 2 +- src/compiler/node-aux-data.h | 2 +- src/compiler/pipeline.cc | 43 ++++- src/compiler/pipeline.h | 12 +- src/compiler/schedule.h | 3 +- src/compiler/source-position.cc | 2 +- src/compiler/source-position.h | 2 +- src/d8.cc | 1 + src/flag-definitions.h | 2 + src/isolate.cc | 22 +++ src/isolate.h | 2 + 14 files changed, 520 insertions(+), 10 deletions(-) diff --git a/src/compiler/graph-visualizer.cc b/src/compiler/graph-visualizer.cc index 5bd8de7..4340c25 100644 --- a/src/compiler/graph-visualizer.cc +++ b/src/compiler/graph-visualizer.cc @@ -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(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 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(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* fixed_d = allocator->fixed_double_live_ranges(); + for (int i = 0; i < fixed_d->length(); ++i) { + PrintLiveRange(fixed_d->at(i), "fixed"); + } + + const Vector* fixed = allocator->fixed_live_ranges(); + for (int i = 0; i < fixed->length(); ++i) { + PrintLiveRange(fixed->at(i), "fixed"); + } + + const ZoneList* 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 diff --git a/src/compiler/graph-visualizer.h b/src/compiler/graph-visualizer.h index ccb2289..7212a4f 100644 --- a/src/compiler/graph-visualizer.h +++ b/src/compiler/graph-visualizer.h @@ -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 diff --git a/src/compiler/instruction.cc b/src/compiler/instruction.cc index 4a1cd1a..1a82765 100644 --- a/src/compiler/instruction.cc +++ b/src/compiler/instruction.cc @@ -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(); diff --git a/src/compiler/node-aux-data-inl.h b/src/compiler/node-aux-data-inl.h index 79f1abf..d8db4b9 100644 --- a/src/compiler/node-aux-data-inl.h +++ b/src/compiler/node-aux-data-inl.h @@ -29,7 +29,7 @@ void NodeAuxData::Set(Node* node, const T& data) { template -T NodeAuxData::Get(Node* node) { +T NodeAuxData::Get(Node* node) const { int id = node->id(); if (id >= static_cast(aux_data_.size())) { return T(); diff --git a/src/compiler/node-aux-data.h b/src/compiler/node-aux-data.h index 7acce33..a08dc58 100644 --- a/src/compiler/node-aux-data.h +++ b/src/compiler/node-aux-data.h @@ -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 aux_data_; diff --git a/src/compiler/pipeline.cc b/src/compiler/pipeline.cc index 7da2fb5..81a0ec5 100644 --- a/src/compiler/pipeline.cc +++ b/src/compiler/pipeline.cc @@ -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 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 filename(buffer, sizeof(buffer)); + SmartArrayPointer functionname; if (!info_->shared_info().is_null()) { - SmartArrayPointer 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 Pipeline::GenerateCode() { << "Begin compiling method " << info()->function()->debug_name()->ToCString().get() << " using Turbofan" << std::endl; + PrintCompilationStart(); } // Build the graph. @@ -405,6 +439,8 @@ Handle 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 Pipeline::GenerateCode(Linkage* linkage, Graph* graph, linkage->info()->AbortOptimization(kNotEnoughVirtualRegistersRegalloc); return Handle::null(); } + if (FLAG_trace_turbo) { + PrintAllocator("CodeGen", &allocator); + } } if (FLAG_trace_turbo) { diff --git a/src/compiler/pipeline.h b/src/compiler/pipeline.h index 9f8241a..f47c3c1 100644 --- a/src/compiler/pipeline.h +++ b/src/compiler/pipeline.h @@ -5,6 +5,8 @@ #ifndef V8_COMPILER_PIPELINE_H_ #define V8_COMPILER_PIPELINE_H_ +#include // 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 GenerateCode(Linkage* linkage, Graph* graph, Schedule* schedule, SourcePositionTable* source_positions); diff --git a/src/compiler/schedule.h b/src/compiler/schedule.h index 7def37f..68686b5 100644 --- a/src/compiler/schedule.h +++ b/src/compiler/schedule.h @@ -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; diff --git a/src/compiler/source-position.cc b/src/compiler/source-position.cc index 1178390..9503010 100644 --- a/src/compiler/source-position.cc +++ b/src/compiler/source-position.cc @@ -46,7 +46,7 @@ void SourcePositionTable::RemoveDecorator() { } -SourcePosition SourcePositionTable::GetSourcePosition(Node* node) { +SourcePosition SourcePositionTable::GetSourcePosition(Node* node) const { return table_.Get(node); } diff --git a/src/compiler/source-position.h b/src/compiler/source-position.h index 778f067..390a17d 100644 --- a/src/compiler/source-position.h +++ b/src/compiler/source-position.h @@ -79,7 +79,7 @@ class SourcePositionTable FINAL { void AddDecorator(); void RemoveDecorator(); - SourcePosition GetSourcePosition(Node* node); + SourcePosition GetSourcePosition(Node* node) const; private: class Decorator; diff --git a/src/d8.cc b/src/d8.cc index d1929b0..a36ec5e 100644 --- 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; diff --git a/src/flag-definitions.h b/src/flag-definitions.h index ded5bcf..83b0abf 100644 --- a/src/flag-definitions.h +++ b/src/flag-definitions.h @@ -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") diff --git a/src/isolate.cc b/src/isolate.cc index e8e1d66..2874c16 100644 --- a/src/isolate.cc +++ b/src/isolate.cc @@ -4,6 +4,8 @@ #include +#include // 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 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 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 diff --git a/src/isolate.h b/src/isolate.h index f1e6a3e..7fd4a82 100644 --- a/src/isolate.h +++ b/src/isolate.h @@ -1107,6 +1107,8 @@ class Isolate { static Isolate* NewForTesting() { return new Isolate(false); } + void GetTurboCfgFileName(Vector buffer); + private: explicit Isolate(bool enable_serializer); -- 2.7.4