| Index: vm/il_printer.cc
|
| ===================================================================
|
| --- vm/il_printer.cc (revision 8145)
|
| +++ vm/il_printer.cc (working copy)
|
| @@ -11,16 +11,21 @@
|
|
|
|
|
| void BufferFormatter::Print(const char* format, ...) {
|
| + va_list args;
|
| + va_start(args, format);
|
| + VPrint(format, args);
|
| + va_end(args);
|
| +}
|
| +
|
| +
|
| +void BufferFormatter::VPrint(const char* format, va_list args) {
|
| intptr_t available = size_ - position_;
|
| if (available <= 0) return;
|
| - va_list args;
|
| - va_start(args, format);
|
| intptr_t written =
|
| OS::VSNPrint(buffer_ + position_, available, format, args);
|
| if (written >= 0) {
|
| position_ += (available <= written) ? available : written;
|
| }
|
| - va_end(args);
|
| }
|
|
|
|
|
| @@ -65,7 +70,6 @@
|
| }
|
|
|
|
|
| -
|
| void Computation::PrintTo(BufferFormatter* f) const {
|
| f->Print("%s(", DebugName());
|
| PrintOperandsTo(f);
|
| @@ -351,4 +355,187 @@
|
| }
|
|
|
|
|
| +void FlowGraphVisualizer::Print(const char* format, ...) {
|
| + char str[120];
|
| + BufferFormatter f(str, sizeof(str));
|
| + f.Print("%*s", 2 * indent_, "");
|
| + va_list args;
|
| + va_start(args, format);
|
| + f.VPrint(format, args);
|
| + va_end(args);
|
| + (*Dart::flow_graph_writer())(str, strlen(str));
|
| +}
|
| +
|
| +
|
| +void FlowGraphVisualizer::PrintInstruction(Instruction* instr) {
|
| + char str[120];
|
| + BufferFormatter f(str, sizeof(str));
|
| + instr->PrintToVisualizer(&f);
|
| + f.Print("%s <|@\n", str);
|
| + (*Dart::flow_graph_writer())(str, strlen(str));
|
| +}
|
| +
|
| +
|
| +void FlowGraphVisualizer::PrintFunction() {
|
| +#define BEGIN(name) \
|
| + Print("begin_%s\n", name); \
|
| + indent_++;
|
| +#define END(name) \
|
| + Print("end_%s\n", name); \
|
| + indent_--;
|
| +
|
| + {
|
| + BEGIN("compilation");
|
| + const char* name = function_.ToFullyQualifiedCString();
|
| + Print("%s \"%s\"\n", "name", name);
|
| + Print("%s \"%s\"\n", "method", name);
|
| + Print("%s %d\n", "date", 0); // Required field. Unused.
|
| + END("compilation");
|
| + }
|
| +
|
| + {
|
| + BEGIN("cfg");
|
| + Print("%s \"%s\"\n", "name", "Flow graph builder");
|
| +
|
| + for (intptr_t i = 0; i < block_order_.length(); ++i) {
|
| + BEGIN("block");
|
| + BlockEntryInstr* entry = block_order_[i];
|
| + Print("%s \"B%d\"\n", "name", entry->block_id());
|
| + Print("%s %d\n", "from_bci", -1); // Required field. Unused.
|
| + Print("%s %d\n", "to_bci", -1); // Required field. Unused.
|
| +
|
| + Print("predecessors");
|
| + for (intptr_t j = 0; j < entry->PredecessorCount(); ++j) {
|
| + BlockEntryInstr* pred = entry->PredecessorAt(j);
|
| + Print(" \"B%d\"", pred->block_id());
|
| + }
|
| + Print("\n");
|
| +
|
| + Print("successors");
|
| + Instruction* last = entry->last_instruction();
|
| + for (intptr_t j = 0; j < last->SuccessorCount(); ++j) {
|
| + intptr_t next_id = last->SuccessorAt(j)->block_id();
|
| + Print(" \"B%d\"", next_id);
|
| + }
|
| + Print("\n");
|
| +
|
| + // TODO(fschneider): Use this for exception handlers.
|
| + Print("xhandlers\n");
|
| +
|
| + // Can be freely used to mark blocks
|
| + Print("flags\n");
|
| +
|
| + if (entry->dominator() != NULL) {
|
| + Print("%s \"B%d\"\n", "dominator", entry->dominator()->block_id());
|
| + }
|
| +
|
| + // TODO(fschneider): Mark blocks with loop nesting level.
|
| + Print("%s %d\n", "loop_depth", 0);
|
| +
|
| + {
|
| + BEGIN("states"); // Required section.
|
| + {
|
| + BEGIN("locals"); // Required section.
|
| + // TODO(fschneider): Insert phi-instructions here.
|
| + intptr_t num_phis = 0;
|
| + Print("%s %d\n", "size", num_phis);
|
| + END("locals");
|
| + }
|
| + END("states");
|
| + }
|
| +
|
| + {
|
| + BEGIN("HIR");
|
| + // Print the block entry.
|
| + Print("0 0 "); // Required fields "bci" and "use". Unused.
|
| + Instruction* current = block_order_[i];
|
| + PrintInstruction(current);
|
| + current = current->StraightLineSuccessor();
|
| + // And all the successors until an exit, branch, or a block entry.
|
| + while ((current != NULL) && !current->IsBlockEntry()) {
|
| + Print("0 0 ");
|
| + PrintInstruction(current);
|
| + current = current->StraightLineSuccessor();
|
| + }
|
| + BlockEntryInstr* successor =
|
| + (current == NULL) ? NULL : current->AsBlockEntry();
|
| + if (successor != NULL) {
|
| + Print("0 0 _ Goto B%d <|@\n", successor->block_id());
|
| + }
|
| + END("HIR");
|
| + }
|
| + END("block");
|
| + }
|
| + END("cfg");
|
| + }
|
| +#undef BEGIN
|
| +#undef END
|
| +}
|
| +
|
| +
|
| +// === Printing instructions in a visualizer-understandable format:
|
| +// "result instruction(op1, op2)" where result is a temporary name
|
| +// or _ for instruction without result.
|
| +void GraphEntryInstr::PrintToVisualizer(BufferFormatter* f) const {
|
| + f->Print("_ [graph]");
|
| +}
|
| +
|
| +
|
| +void JoinEntryInstr::PrintToVisualizer(BufferFormatter* f) const {
|
| + f->Print("_ [join]");
|
| +}
|
| +
|
| +
|
| +void TargetEntryInstr::PrintToVisualizer(BufferFormatter* f) const {
|
| + f->Print("_ [target");
|
| + if (HasTryIndex()) {
|
| + f->Print(" catch %d]", try_index());
|
| + } else {
|
| + f->Print("]");
|
| + }
|
| +}
|
| +
|
| +
|
| +void DoInstr::PrintToVisualizer(BufferFormatter* f) const {
|
| + f->Print("_ ");
|
| + computation()->PrintTo(f);
|
| +}
|
| +
|
| +
|
| +void BindInstr::PrintToVisualizer(BufferFormatter* f) const {
|
| + f->Print("t%d ", temp_index());
|
| + computation()->PrintTo(f);
|
| +}
|
| +
|
| +
|
| +void ReturnInstr::PrintToVisualizer(BufferFormatter* f) const {
|
| + f->Print("_ %s ", DebugName());
|
| + value()->PrintTo(f);
|
| +}
|
| +
|
| +
|
| +void ThrowInstr::PrintToVisualizer(BufferFormatter* f) const {
|
| + f->Print("_ %s ", DebugName());
|
| + exception()->PrintTo(f);
|
| +}
|
| +
|
| +
|
| +void ReThrowInstr::PrintToVisualizer(BufferFormatter* f) const {
|
| + f->Print("_ %s ", DebugName());
|
| + exception()->PrintTo(f);
|
| + f->Print(", ");
|
| + stack_trace()->PrintTo(f);
|
| +}
|
| +
|
| +
|
| +void BranchInstr::PrintToVisualizer(BufferFormatter* f) const {
|
| + f->Print("_ %s ", DebugName());
|
| + f->Print("if ");
|
| + value()->PrintTo(f);
|
| + f->Print(" goto (B%d, B%d)",
|
| + true_successor()->block_id(),
|
| + false_successor()->block_id());
|
| +}
|
| +
|
| +
|
| } // namespace dart
|
|
|