[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
This commit is contained in:
parent
d75f736c11
commit
173b07faa9
@ -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
|
||||
|
@ -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
|
||||
|
@ -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();
|
||||
|
@ -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();
|
||||
|
@ -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_;
|
||||
|
@ -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) {
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
@ -46,7 +46,7 @@ void SourcePositionTable::RemoveDecorator() {
|
||||
}
|
||||
|
||||
|
||||
SourcePosition SourcePositionTable::GetSourcePosition(Node* node) {
|
||||
SourcePosition SourcePositionTable::GetSourcePosition(Node* node) const {
|
||||
return table_.Get(node);
|
||||
}
|
||||
|
||||
|
@ -79,7 +79,7 @@ class SourcePositionTable FINAL {
|
||||
void AddDecorator();
|
||||
void RemoveDecorator();
|
||||
|
||||
SourcePosition GetSourcePosition(Node* node);
|
||||
SourcePosition GetSourcePosition(Node* node) const;
|
||||
|
||||
private:
|
||||
class Decorator;
|
||||
|
@ -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;
|
||||
|
@ -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")
|
||||
|
@ -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
|
||||
|
@ -1107,6 +1107,8 @@ class Isolate {
|
||||
|
||||
static Isolate* NewForTesting() { return new Isolate(false); }
|
||||
|
||||
void GetTurboCfgFileName(Vector<char> buffer);
|
||||
|
||||
private:
|
||||
explicit Isolate(bool enable_serializer);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user