Add a SafeMap equivalent to std::map but without the error-prone operator[].

Change-Id: Iae5ba2091c55a34dbd1005cf3d25fce2a8d5c1f9
diff --git a/src/oatdump.cc b/src/oatdump.cc
index 6680b57..93eb9a1 100644
--- a/src/oatdump.cc
+++ b/src/oatdump.cc
@@ -19,7 +19,6 @@
 
 #include <fstream>
 #include <iostream>
-#include <map>
 #include <string>
 #include <vector>
 
@@ -33,6 +32,7 @@
 #include "object_utils.h"
 #include "os.h"
 #include "runtime.h"
+#include "safe_map.h"
 #include "space.h"
 #include "stringpiece.h"
 
@@ -901,35 +901,35 @@
         size_t dex_instruction_bytes = code_item->insns_size_in_code_units_ * 2;
         state->stats_.dex_instruction_bytes += dex_instruction_bytes;
 
-        bool first_occurance;
-        size_t gc_map_bytes = state->ComputeOatSize(method->GetGcMapRaw(), &first_occurance);
-        if (first_occurance) {
+        bool first_occurrence;
+        size_t gc_map_bytes = state->ComputeOatSize(method->GetGcMapRaw(), &first_occurrence);
+        if (first_occurrence) {
           state->stats_.gc_map_bytes += gc_map_bytes;
         }
 
         size_t pc_mapping_table_bytes =
-            state->ComputeOatSize(method->GetMappingTableRaw(), &first_occurance);
-        if (first_occurance) {
+            state->ComputeOatSize(method->GetMappingTableRaw(), &first_occurrence);
+        if (first_occurrence) {
           state->stats_.pc_mapping_table_bytes += pc_mapping_table_bytes;
         }
 
         size_t vmap_table_bytes =
-            state->ComputeOatSize(method->GetVmapTableRaw(), &first_occurance);
-        if (first_occurance) {
+            state->ComputeOatSize(method->GetVmapTableRaw(), &first_occurrence);
+        if (first_occurrence) {
           state->stats_.vmap_table_bytes += vmap_table_bytes;
         }
 
         // TODO: compute invoke stub using length from oat file.
         size_t invoke_stub_size = state->ComputeOatSize(
-            reinterpret_cast<const void*>(method->GetInvokeStub()), &first_occurance);
-        if (first_occurance) {
+            reinterpret_cast<const void*>(method->GetInvokeStub()), &first_occurrence);
+        if (first_occurrence) {
           state->stats_.native_to_managed_code_bytes += invoke_stub_size;
         }
         const void* oat_code_begin = state->GetOatCodeBegin(method);
         const void* oat_code_end = state->GetOatCodeEnd(method);
         uint32_t oat_code_size = state->GetOatCodeSize(method);
-        state->ComputeOatSize(oat_code_begin, &first_occurance);
-        if (first_occurance) {
+        state->ComputeOatSize(oat_code_begin, &first_occurrence);
+        if (first_occurrence) {
           state->stats_.managed_code_bytes += oat_code_size;
           if (method->IsConstructor()) {
             if (method->IsStatic()) {
@@ -955,9 +955,7 @@
         state->stats_.ComputeOutliers(total_size, expansion, method);
       }
     }
-    std::string descriptor(ClassHelper(obj_class).GetDescriptor());
-    state->stats_.descriptor_to_bytes[descriptor] += object_bytes;
-    state->stats_.descriptor_to_count[descriptor] += 1;
+    state->stats_.Update(ClassHelper(obj_class).GetDescriptor(), object_bytes);
 
     state->os_ << summary << std::flush;
   }
@@ -965,12 +963,12 @@
   std::set<const void*> already_seen_;
   // Compute the size of the given data within the oat file and whether this is the first time
   // this data has been requested
-  size_t ComputeOatSize(const void* oat_data, bool* first_occurance) {
+  size_t ComputeOatSize(const void* oat_data, bool* first_occurrence) {
     if (already_seen_.count(oat_data) == 0) {
-      *first_occurance = true;
+      *first_occurrence = true;
       already_seen_.insert(oat_data);
     } else {
-      *first_occurance = false;
+      *first_occurrence = false;
     }
     return oat_dumper_->ComputeSize(oat_data);
   }
@@ -1020,11 +1018,23 @@
           vmap_table_bytes(0),
           dex_instruction_bytes(0) {}
 
-    typedef std::map<std::string, size_t> TableBytes;
-    TableBytes descriptor_to_bytes;
+    struct SizeAndCount {
+      SizeAndCount(size_t bytes, size_t count) : bytes(bytes), count(count) {}
+      size_t bytes;
+      size_t count;
+    };
+    typedef SafeMap<std::string, SizeAndCount> SizeAndCountTable;
+    SizeAndCountTable sizes_and_counts;
 
-    typedef std::map<std::string, size_t> TableCount;
-    TableCount descriptor_to_count;
+    void Update(const std::string& descriptor, size_t object_bytes) {
+      SizeAndCountTable::iterator it = sizes_and_counts.find(descriptor);
+      if (it != sizes_and_counts.end()) {
+        it->second.bytes += object_bytes;
+        it->second.count += 1;
+      } else {
+        sizes_and_counts.Put(descriptor, SizeAndCount(object_bytes, 1));
+      }
+    }
 
     double PercentOfOatBytes(size_t size) {
       return (static_cast<double>(size) / static_cast<double>(oat_file_bytes)) * 100;
@@ -1158,21 +1168,18 @@
 
       CHECK_EQ(file_bytes, header_bytes + object_bytes + alignment_bytes);
 
-      os << "\tobject_bytes = sum of descriptor_to_bytes values below:\n";
+      os << "\tobject_bytes breakdown:\n";
       size_t object_bytes_total = 0;
-      typedef TableBytes::const_iterator It;  // TODO: C++0x auto
-      for (It it = descriptor_to_bytes.begin(), end = descriptor_to_bytes.end(); it != end; ++it) {
+      typedef SizeAndCountTable::const_iterator It;  // TODO: C++0x auto
+      for (It it = sizes_and_counts.begin(), end = sizes_and_counts.end(); it != end; ++it) {
         const std::string& descriptor(it->first);
-        size_t bytes = it->second;
-        size_t count = descriptor_to_count[descriptor];
-        double average = static_cast<double>(bytes) / static_cast<double>(count);
-        double percent = PercentOfObjectBytes(bytes);
+        double average = static_cast<double>(it->second.bytes) / static_cast<double>(it->second.count);
+        double percent = PercentOfObjectBytes(it->second.bytes);
         os << StringPrintf("\t%32s %8zd bytes %6zd instances "
-                           "(%3.0f bytes/instance) %2.0f%% of object_bytes\n",
-                           descriptor.c_str(), bytes, count,
+                           "(%4.0f bytes/instance) %2.0f%% of object_bytes\n",
+                           descriptor.c_str(), it->second.bytes, it->second.count,
                            average, percent);
-
-        object_bytes_total += bytes;
+        object_bytes_total += it->second.bytes;
       }
       os << std::endl << std::flush;
       CHECK_EQ(object_bytes, object_bytes_total);