Improvements and clustering for the .dot file generation.

Dot clusters are used to show SEA IR regions.
Passing around dex_file for improved instruction  text representation.
SeaGraph now stores the dex file.
Removed all .dot edges except ssa edges and inter-region control flow.
Changed color to gray for ssa edges and kept black for control flow.
Consistently labeled SSA edges with virtual register number.
Replaced stringstream with StringPrintf.

Change-Id: I67d9d92e594d3f2de94eec1c78a64f3972ae60b1
diff --git a/compiler/sea_ir/sea.cc b/compiler/sea_ir/sea.cc
index 3488afd..7a1894b 100644
--- a/compiler/sea_ir/sea.cc
+++ b/compiler/sea_ir/sea.cc
@@ -27,7 +27,6 @@
 
 namespace sea_ir {
 
-SeaGraph SeaGraph::graph_;
 int SeaNode::current_max_node_id_ = 0;
 
 void IRVisitor::Traverse(Region* region) {
@@ -51,16 +50,16 @@
   }
 }
 
-SeaGraph* SeaGraph::GetCurrentGraph() {
-  return &sea_ir::SeaGraph::graph_;
+SeaGraph* SeaGraph::GetCurrentGraph(const art::DexFile& dex_file) {
+  return new SeaGraph(dex_file);
 }
 
 void SeaGraph::DumpSea(std::string filename) const {
   LOG(INFO) << "Starting to write SEA string to file.";
   std::string result;
-  result += "digraph seaOfNodes {\n";
+  result += "digraph seaOfNodes {\ncompound=true\n";
   for (std::vector<Region*>::const_iterator cit = regions_.begin(); cit != regions_.end(); cit++) {
-    (*cit)->ToDot(result);
+    (*cit)->ToDot(result, dex_file_);
   }
   result += "}\n";
   art::File* file = art::OS::OpenFile(filename.c_str(), true, true);
@@ -490,33 +489,48 @@
   return NULL;
 }
 
-void Region::ToDot(std::string& result) const {
-  result += "\n// Region: \n" + StringId() + " [label=\"region " + StringId() + "(rpo=";
+void Region::ToDot(std::string& result, const art::DexFile& dex_file) const {
+  result += "\n// Region: \nsubgraph " + StringId() + " { label=\"region " + StringId() + "(rpo=";
   result += art::StringPrintf("%d", rpo_number_);
   if (NULL != GetIDominator()) {
     result += " dom=" + GetIDominator()->StringId();
   }
-  result += ")\"];\n";
+  result += ")\";\n";
+
+  for (std::vector<PhiInstructionNode*>::const_iterator cit = phi_instructions_.begin();
+        cit != phi_instructions_.end(); cit++) {
+    result += (*cit)->StringId() +";\n";
+  }
+
+  for (std::vector<InstructionNode*>::const_iterator cit = instructions_.begin();
+        cit != instructions_.end(); cit++) {
+      result += (*cit)->StringId() +";\n";
+      // result += StringId() + " -> " + (*cit)->StringId() + "; // region -> instruction \n";
+    }
+
+  result += "} // End Region.\n";
 
   // Save phi-nodes.
   for (std::vector<PhiInstructionNode*>::const_iterator cit = phi_instructions_.begin();
       cit != phi_instructions_.end(); cit++) {
-    (*cit)->ToDot(result);
-    result += StringId() + " -> " + (*cit)->StringId() + ";  // phi-function \n";
+    (*cit)->ToDot(result, dex_file);
+    // result += StringId() + " -> " + (*cit)->StringId() + "; // region -> phi-function \n";
   }
 
   // Save instruction nodes.
   for (std::vector<InstructionNode*>::const_iterator cit = instructions_.begin();
       cit != instructions_.end(); cit++) {
-    (*cit)->ToDot(result);
-    result += StringId() + " -> " + (*cit)->StringId() + ";  // region -> instruction \n";
+    (*cit)->ToDot(result, dex_file);
+    //result += StringId() + " -> " + (*cit)->StringId() + "; // region -> instruction \n";
   }
 
   for (std::vector<Region*>::const_iterator cit = successors_.begin(); cit != successors_.end();
       cit++) {
     DCHECK(NULL != *cit) << "Null successor found for SeaNode" << GetLastChild()->StringId() << ".";
-    result += GetLastChild()->StringId() + " -> " + (*cit)->StringId() + ";\n\n";
+    result += GetLastChild()->StringId() + " -> " + (*cit)->GetLastChild()->StringId() +
+         "[lhead=" + (*cit)->StringId() + ", " + "ltail=" + StringId() + "];\n\n";
   }
+  /*
   // Save reaching definitions.
   for (std::map<int, std::set<sea_ir::InstructionNode*>* >::const_iterator cit =
       reaching_defs_.begin();
@@ -536,7 +550,7 @@
         " -> " + (*cit)->StringId() +
         " [color=gray];  // Dominance frontier.\n";
   }
-  result += "// End Region.\n";
+  */
 }
 
 void Region::ComputeDownExposedDefs() {
@@ -698,9 +712,9 @@
   return sea_instructions;
 }
 
-void InstructionNode::ToDot(std::string& result) const {
+void InstructionNode::ToDot(std::string& result, const art::DexFile& dex_file) const {
   result += "// Instruction ("+StringId()+"): \n" + StringId() +
-      " [label=\"" + instruction_->DumpString(NULL) + "\"";
+      " [label=\"" + instruction_->DumpString(&dex_file) + "\"";
   if (de_def_) {
     result += "style=bold";
   }
@@ -709,9 +723,9 @@
   for (std::map<int, InstructionNode* >::const_iterator def_it = definition_edges_.begin();
       def_it != definition_edges_.end(); def_it++) {
     if (NULL != def_it->second) {
-      result += def_it->second->StringId() + " -> " + StringId() +"[color=red,label=\"";
-      result += art::StringPrintf("%d", def_it->first);
-      result += "\"] ;  // ssa edge\n";
+      result += def_it->second->StringId() + " -> " + StringId() +"[color=gray,label=\"";
+      result += art::StringPrintf("vR = %d", def_it->first);
+      result += "\"] ; // ssa edge\n";
     }
   }
 }
@@ -756,7 +770,7 @@
   return uses;
 }
 
-void PhiInstructionNode::ToDot(std::string& result) const {
+void PhiInstructionNode::ToDot(std::string& result, const art::DexFile& dex_file) const {
   result += "// PhiInstruction: \n" + StringId() +
       " [label=\"" + "PHI(";
   result += art::StringPrintf("%d", register_no_);
@@ -768,7 +782,7 @@
     std::vector<InstructionNode*>* defs_from_pred = *pred_it;
     for (std::vector<InstructionNode* >::const_iterator def_it = defs_from_pred->begin();
         def_it != defs_from_pred->end(); def_it++) {
-        result += (*def_it)->StringId() + " -> " + StringId() +"[color=red,label=\"vR = ";
+        result += (*def_it)->StringId() + " -> " + StringId() +"[color=gray,label=\"vR = ";
         result += art::StringPrintf("%d", GetRegisterNumber());
         result += "\"] ;  // phi-ssa edge\n";
     }