Use std::string rather than String* in hprof to avoid managed-heap allocations.

Change-Id: Ia4491aa50f48ab435ca32c1d2b1825bf6553430b
diff --git a/src/hprof/hprof.h b/src/hprof/hprof.h
index 092f00d..897a996 100644
--- a/src/hprof/hprof.h
+++ b/src/hprof/hprof.h
@@ -149,11 +149,6 @@
     int fd;
 };
 
-
-/*
- * hprof_string.cc functions
- */
-
 hprof_string_id hprofLookupStringId(String* string);
 hprof_string_id hprofLookupStringId(const char* string);
 hprof_string_id hprofLookupStringId(std::string string);
@@ -163,11 +158,6 @@
 int hprofStartup_String(void);
 int hprofShutdown_String(void);
 
-
-/*
- * hprof_class.cc functions
- */
-
 hprof_class_object_id hprofLookupClassId(Class* clazz);
 
 int hprofDumpClasses(hprof_context_t *ctx);
@@ -175,11 +165,6 @@
 int hprofStartup_Class(void);
 int hprofShutdown_Class(void);
 
-
-/*
- * hprof_heap.cc functions
- */
-
 int hprofStartHeapDump(hprof_context_t *ctx);
 int hprofFinishHeapDump(hprof_context_t *ctx);
 
@@ -190,10 +175,6 @@
 
 int hprofDumpHeapObject(hprof_context_t *ctx, const Object *obj);
 
-/*
- * hprof_output.cc functions
- */
-
 void hprofContextInit(hprof_context_t *ctx, char *fileName, int fd,
                       bool writeHeader, bool directToDdms);
 
@@ -223,10 +204,6 @@
 #define hprofAddIdListToRecord(rec, values, numValues) \
             hprofAddU4ListToRecord((rec), (const uint32_t *)(values), (numValues))
 
-/*
- * hprof.cc functions
- */
-
 hprof_context_t* hprofStartup(const char *outputFileName, int fd,
     bool directToDdms);
 bool hprofShutdown(hprof_context_t *ctx);
diff --git a/src/hprof/hprof_class.cc b/src/hprof/hprof_class.cc
index d64e553..2e40ad4 100644
--- a/src/hprof/hprof_class.cc
+++ b/src/hprof/hprof_class.cc
@@ -40,8 +40,7 @@
 }
 
 static int getPrettyClassNameId(Class* clazz) {
-    std::string name(PrettyClass(clazz));
-    return hprofLookupStringId(name); // TODO: leaks
+    return hprofLookupStringId(PrettyClass(clazz));
 }
 
 hprof_class_object_id hprofLookupClassId(Class* clazz) {
diff --git a/src/hprof/hprof_string.cc b/src/hprof/hprof_string.cc
index 7fb4027..f498b6d 100644
--- a/src/hprof/hprof_string.cc
+++ b/src/hprof/hprof_string.cc
@@ -18,17 +18,18 @@
  */
 #include "hprof.h"
 #include "object.h"
-#include "unordered_set.h"
+#include "unordered_map.h"
 #include "logging.h"
 
 namespace art {
 
 namespace hprof {
 
-typedef std::tr1::unordered_set<String*, StringHashCode> StringSet;
-typedef std::tr1::unordered_set<String*, StringHashCode>::iterator StringSetIterator; // TODO: equals by VALUE not REFERENCE
+size_t next_string_id_ = 200001;
+typedef std::tr1::unordered_map<std::string, size_t> StringMap;
+typedef std::tr1::unordered_map<std::string, size_t>::iterator StringMapIterator;
 static Mutex strings_lock_("hprof strings");
-static StringSet strings_;
+static StringMap strings_;
 
 int hprofStartup_String() {
     return 0;
@@ -39,18 +40,19 @@
 }
 
 hprof_string_id hprofLookupStringId(String* string) {
-    MutexLock mu(strings_lock_);
-    std::pair<StringSetIterator, bool> result = strings_.insert(string);
-    String* present = *result.first;
-    return (hprof_string_id) present;
+    return hprofLookupStringId(string->ToModifiedUtf8());
 }
 
 hprof_string_id hprofLookupStringId(const char* string) {
-    return hprofLookupStringId(String::AllocFromModifiedUtf8(string)); // TODO: leaks? causes GC?
+    return hprofLookupStringId(std::string(string));
 }
 
 hprof_string_id hprofLookupStringId(std::string string) {
-    return hprofLookupStringId(string.c_str()); // TODO: leaks? causes GC?
+    MutexLock mu(strings_lock_);
+    if (strings_.find(string) == strings_.end()) {
+        strings_[string] = next_string_id_++;
+    }
+    return strings_[string];
 }
 
 int hprofDumpStrings(hprof_context_t *ctx) {
@@ -58,9 +60,9 @@
 
     hprof_record_t *rec = &ctx->curRec;
 
-    for (StringSetIterator it = strings_.begin(); it != strings_.end(); ++it) {
-        String* string = *it;
-        CHECK(string != NULL);
+    for (StringMapIterator   it = strings_.begin(); it != strings_.end(); ++it) {
+        std::string string = (*it).first;
+        size_t id = (*it).second;
 
         int err = hprofStartNewRecord(ctx, HPROF_TAG_STRING, HPROF_TIME);
         if (err != 0) {
@@ -75,11 +77,11 @@
          *
          * We use the address of the string data as its ID.
          */
-        err = hprofAddU4ToRecord(rec, (uint32_t) string);
+        err = hprofAddU4ToRecord(rec, id);
         if (err != 0) {
             return err;
         }
-        err = hprofAddUtf8StringToRecord(rec, string->ToModifiedUtf8().c_str()); // TODO: leak?
+        err = hprofAddUtf8StringToRecord(rec, string.c_str());
         if (err != 0) {
             return err;
         }