Improve art::CodeInfo dumping.

- Refactor existing dumping code into a set of new routines.
- Use art::Indenter to properly indent in the output.
- Add an additional argument to art::CodeInfo::Dump to
  enable or disable the dumping of stack maps and Dex
  register maps.

Change-Id: I52814095ff465522302d5d69d416726369ca5258
diff --git a/oatdump/oatdump.cc b/oatdump/oatdump.cc
index a67ef8f..04f5a6a 100644
--- a/oatdump/oatdump.cc
+++ b/oatdump/oatdump.cc
@@ -1035,7 +1035,7 @@
   void DumpCodeInfo(std::ostream& os,
                     const CodeInfo& code_info,
                     const DexFile::CodeItem& code_item) {
-    code_info.Dump(os, code_item.registers_size_);
+    code_info.Dump(os, code_item.registers_size_, true);
   }
 
   // Display a vmap table.
diff --git a/runtime/stack_map.cc b/runtime/stack_map.cc
index 6a0c07d..c36ee05 100644
--- a/runtime/stack_map.cc
+++ b/runtime/stack_map.cc
@@ -18,6 +18,8 @@
 
 #include <stdint.h>
 
+#include "indenter.h"
+
 namespace art {
 
 constexpr size_t DexRegisterLocationCatalog::kNoLocationEntryIndex;
@@ -203,72 +205,95 @@
                                 DexRegisterLocation location,
                                 const std::string& prefix = "v",
                                 const std::string& suffix = "") {
-  os << "      " << prefix << dex_register_num << ": "
-     << DexRegisterLocation::PrettyDescriptor(location.GetInternalKind())
-     << " (" << location.GetValue() << ")" << suffix << '\n';
+  Indenter indent_filter(os.rdbuf(), kIndentChar, kIndentBy1Count);
+  std::ostream indented_os(&indent_filter);
+  indented_os << prefix << dex_register_num << ": "
+              << DexRegisterLocation::PrettyDescriptor(location.GetInternalKind())
+              << " (" << location.GetValue() << ")" << suffix << '\n';
+}
+
+void CodeInfo::DumpStackMap(std::ostream& os,
+                            size_t stack_map_num,
+                            uint16_t number_of_dex_registers) const {
+  StackMap stack_map = GetStackMapAt(stack_map_num);
+  DumpStackMapHeader(os, stack_map_num);
+  if (stack_map.HasDexRegisterMap(*this)) {
+    DexRegisterMap dex_register_map = GetDexRegisterMapOf(stack_map, number_of_dex_registers);
+    dex_register_map.Dump(os, *this, number_of_dex_registers);
+  }
 }
 
 void CodeInfo::DumpStackMapHeader(std::ostream& os, size_t stack_map_num) const {
   StackMap stack_map = GetStackMapAt(stack_map_num);
-  os << "    StackMap " << stack_map_num
-     << std::hex
-     << " (dex_pc=0x" << stack_map.GetDexPc(*this)
-     << ", native_pc_offset=0x" << stack_map.GetNativePcOffset(*this)
-     << ", dex_register_map_offset=0x" << stack_map.GetDexRegisterMapOffset(*this)
-     << ", inline_info_offset=0x" << stack_map.GetInlineDescriptorOffset(*this)
-     << ", register_mask=0x" << stack_map.GetRegisterMask(*this)
-     << std::dec
-     << ", stack_mask=0b";
+  Indenter indent_filter(os.rdbuf(), kIndentChar, kIndentBy1Count);
+  std::ostream indented_os(&indent_filter);
+  indented_os << "StackMap " << stack_map_num
+              << std::hex
+              << " (dex_pc=0x" << stack_map.GetDexPc(*this)
+              << ", native_pc_offset=0x" << stack_map.GetNativePcOffset(*this)
+              << ", dex_register_map_offset=0x" << stack_map.GetDexRegisterMapOffset(*this)
+              << ", inline_info_offset=0x" << stack_map.GetInlineDescriptorOffset(*this)
+              << ", register_mask=0x" << stack_map.GetRegisterMask(*this)
+              << std::dec
+              << ", stack_mask=0b";
   MemoryRegion stack_mask = stack_map.GetStackMask(*this);
   for (size_t i = 0, e = stack_mask.size_in_bits(); i < e; ++i) {
-    os << stack_mask.LoadBit(e - i - 1);
+    indented_os << stack_mask.LoadBit(e - i - 1);
   }
-  os << ")\n";
+  indented_os << ")\n";
 };
 
-void CodeInfo::Dump(std::ostream& os, uint16_t number_of_dex_registers) const {
+void CodeInfo::Dump(std::ostream& os,
+                    uint16_t number_of_dex_registers,
+                    bool dump_stack_maps) const {
   uint32_t code_info_size = GetOverallSize();
   size_t number_of_stack_maps = GetNumberOfStackMaps();
-  os << "  Optimized CodeInfo (size=" << code_info_size
-     << ", number_of_dex_registers=" << number_of_dex_registers
-     << ", number_of_stack_maps=" << number_of_stack_maps
-     << ", has_inline_info=" << HasInlineInfo()
-     << ", number_of_bytes_for_inline_info=" << NumberOfBytesForInlineInfo()
-     << ", number_of_bytes_for_dex_register_map=" << NumberOfBytesForDexRegisterMap()
-     << ", number_of_bytes_for_dex_pc=" << NumberOfBytesForDexPc()
-     << ", number_of_bytes_for_native_pc=" << NumberOfBytesForNativePc()
-     << ", number_of_bytes_for_register_mask=" << NumberOfBytesForRegisterMask()
-     << ")\n";
-
+  Indenter indent_filter(os.rdbuf(), kIndentChar, kIndentBy1Count);
+  std::ostream indented_os(&indent_filter);
+  indented_os << "Optimized CodeInfo (size=" << code_info_size
+              << ", number_of_dex_registers=" << number_of_dex_registers
+              << ", number_of_stack_maps=" << number_of_stack_maps
+              << ", has_inline_info=" << HasInlineInfo()
+              << ", number_of_bytes_for_inline_info=" << NumberOfBytesForInlineInfo()
+              << ", number_of_bytes_for_dex_register_map=" << NumberOfBytesForDexRegisterMap()
+              << ", number_of_bytes_for_dex_pc=" << NumberOfBytesForDexPc()
+              << ", number_of_bytes_for_native_pc=" << NumberOfBytesForNativePc()
+              << ", number_of_bytes_for_register_mask=" << NumberOfBytesForRegisterMask()
+              << ")\n";
   // Display the Dex register location catalog.
-  size_t number_of_location_catalog_entries = GetNumberOfDexRegisterLocationCatalogEntries();
-  size_t location_catalog_size_in_bytes = GetDexRegisterLocationCatalogSize();
-  os << "  DexRegisterLocationCatalog (number_of_entries=" << number_of_location_catalog_entries
-     << ", size_in_bytes=" << location_catalog_size_in_bytes << ")\n";
-  DexRegisterLocationCatalog dex_register_location_catalog = GetDexRegisterLocationCatalog();
-  for (size_t i = 0; i < number_of_location_catalog_entries; ++i) {
-    DexRegisterLocation location = dex_register_location_catalog.GetDexRegisterLocation(i);
-    DumpRegisterMapping(os, i, location, "entry ");
-  }
-
+  GetDexRegisterLocationCatalog().Dump(indented_os, *this);
   // Display stack maps along with (live) Dex register maps.
-  for (size_t i = 0; i < number_of_stack_maps; ++i) {
-    StackMap stack_map = GetStackMapAt(i);
-    DumpStackMapHeader(os, i);
-    if (stack_map.HasDexRegisterMap(*this)) {
-      DexRegisterMap dex_register_map = GetDexRegisterMapOf(stack_map, number_of_dex_registers);
-      dex_register_map.Dump(os, *this, number_of_dex_registers);
+  if (dump_stack_maps) {
+    for (size_t i = 0; i < number_of_stack_maps; ++i) {
+      DumpStackMap(indented_os, i, number_of_dex_registers);
     }
   }
   // TODO: Dump the stack map's inline information? We need to know more from the caller:
   //       we need to know the number of dex registers for each inlined method.
 }
 
+void DexRegisterLocationCatalog::Dump(std::ostream& os, const CodeInfo& code_info) {
+  size_t number_of_location_catalog_entries =
+      code_info.GetNumberOfDexRegisterLocationCatalogEntries();
+  size_t location_catalog_size_in_bytes = code_info.GetDexRegisterLocationCatalogSize();
+  Indenter indent_filter(os.rdbuf(), kIndentChar, kIndentBy1Count);
+  std::ostream indented_os(&indent_filter);
+  indented_os
+      << "DexRegisterLocationCatalog (number_of_entries=" << number_of_location_catalog_entries
+      << ", size_in_bytes=" << location_catalog_size_in_bytes << ")\n";
+  for (size_t i = 0; i < number_of_location_catalog_entries; ++i) {
+    DexRegisterLocation location = GetDexRegisterLocation(i);
+    DumpRegisterMapping(indented_os, i, location, "entry ");
+  }
+}
+
 void DexRegisterMap::Dump(std::ostream& os,
                           const CodeInfo& code_info,
                           uint16_t number_of_dex_registers) const {
   size_t number_of_location_catalog_entries =
       code_info.GetNumberOfDexRegisterLocationCatalogEntries();
+  Indenter indent_filter(os.rdbuf(), kIndentChar, kIndentBy1Count);
+  std::ostream indented_os(&indent_filter);
   // TODO: Display the bit mask of live Dex registers.
   for (size_t j = 0; j < number_of_dex_registers; ++j) {
     if (IsDexRegisterLive(j)) {
@@ -276,7 +301,7 @@
           j, number_of_dex_registers, number_of_location_catalog_entries);
       DexRegisterLocation location = GetDexRegisterLocation(j, number_of_dex_registers, code_info);
       DumpRegisterMapping(
-          os, j, location, "v",
+          indented_os, j, location, "v",
           "\t[entry " + std::to_string(static_cast<int>(location_catalog_entry_index)) + "]");
     }
   }
@@ -285,18 +310,20 @@
 void InlineInfo::Dump(std::ostream& os,
                       const CodeInfo& code_info,
                       uint16_t number_of_dex_registers[]) const {
-  os << "InlineInfo with depth " << static_cast<uint32_t>(GetDepth()) << "\n";
+  Indenter indent_filter(os.rdbuf(), kIndentChar, kIndentBy1Count);
+  std::ostream indented_os(&indent_filter);
+  indented_os << "InlineInfo with depth " << static_cast<uint32_t>(GetDepth()) << "\n";
 
   for (size_t i = 0; i < GetDepth(); ++i) {
-    os << " At depth " << i
-       << std::hex
-       << " (dex_pc=0x" << GetDexPcAtDepth(i)
-       << ", method_index=0x" << GetMethodIndexAtDepth(i)
-       << ")\n";
+    indented_os << " At depth " << i
+                << std::hex
+                << " (dex_pc=0x" << GetDexPcAtDepth(i)
+                << ", method_index=0x" << GetMethodIndexAtDepth(i)
+                << ")\n";
     if (HasDexRegisterMapAtDepth(i)) {
       DexRegisterMap dex_register_map =
           code_info.GetDexRegisterMapAtDepth(i, *this, number_of_dex_registers[i]);
-      dex_register_map.Dump(os, code_info, number_of_dex_registers[i]);
+      dex_register_map.Dump(indented_os, code_info, number_of_dex_registers[i]);
     }
   }
 }
diff --git a/runtime/stack_map.h b/runtime/stack_map.h
index 69e57ff..eefdaa7 100644
--- a/runtime/stack_map.h
+++ b/runtime/stack_map.h
@@ -356,6 +356,8 @@
     return region_.size();
   }
 
+  void Dump(std::ostream& os, const CodeInfo& code_info);
+
   // Special (invalid) Dex register location catalog entry index meaning
   // that there is no location for a given Dex register (i.e., it is
   // mapped to a DexRegisterLocation::Kind::kNone location).
@@ -1046,7 +1048,15 @@
     return StackMap();
   }
 
-  void Dump(std::ostream& os, uint16_t number_of_dex_registers) const;
+  // Dump this CodeInfo object on `os`.  If `dump_stack_maps` is true,
+  // also dump the stack maps and the associated Dex register maps.
+  void Dump(std::ostream& os, uint16_t number_of_dex_registers, bool dump_stack_maps) const;
+
+  // Dump stack map number `stack_map_num` as well as associated data on `os`,
+  // such as Dex register locations.
+  void DumpStackMap(std::ostream& os, size_t stack_map_num, uint16_t number_of_dex_registers) const;
+  // Dump the header of stack map number `stack_map_num` on `os`, without
+  // associated data.
   void DumpStackMapHeader(std::ostream& os, size_t stack_map_num) const;
 
  private: