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

Change-Id: Iae5ba2091c55a34dbd1005cf3d25fce2a8d5c1f9
diff --git a/src/compiler.cc b/src/compiler.cc
index 7369535..0a88cff 100644
--- a/src/compiler.cc
+++ b/src/compiler.cc
@@ -1215,7 +1215,7 @@
       CompiledClass* compiled_class = GetCompiledClass(ref);
       if (compiled_class == NULL) {
         compiled_class = new CompiledClass(status);
-        compiled_classes_[ref] = compiled_class;
+        compiled_classes_.Put(ref, compiled_class);
       } else {
         DCHECK_EQ(status, compiled_class->GetStatus());
       }
@@ -1301,6 +1301,14 @@
   ForAll(&context, 0, dex_file.NumClassDefs(), Compiler::CompileClass, thread_count_);
 }
 
+static std::string MakeInvokeStubKey(bool is_static, const char* shorty) {
+  std::string key(shorty);
+  if (is_static) {
+    key += "$";  // Must not be a shorty type character.
+  }
+  return key;
+}
+
 void Compiler::CompileMethod(const DexFile::CodeItem* code_item, uint32_t access_flags,
                              uint32_t method_idx, const ClassLoader* class_loader,
                              const DexFile& dex_file) {
@@ -1326,33 +1334,30 @@
     MethodReference ref(&dex_file, method_idx);
     CHECK(GetCompiledMethod(ref) == NULL) << PrettyMethod(method_idx, dex_file);
     MutexLock mu(compiled_methods_lock_);
-    compiled_methods_[ref] = compiled_method;
+    compiled_methods_.Put(ref, compiled_method);
     DCHECK(GetCompiledMethod(ref) != NULL) << PrettyMethod(method_idx, dex_file);
   }
 
   uint32_t shorty_len;
   const char* shorty = dex_file.GetMethodShorty(dex_file.GetMethodId(method_idx), &shorty_len);
   bool is_static = (access_flags & kAccStatic) != 0;
-  const CompiledInvokeStub* compiled_invoke_stub = FindInvokeStub(is_static, shorty);
+  std::string key(MakeInvokeStubKey(is_static, shorty));
+  const CompiledInvokeStub* compiled_invoke_stub = FindInvokeStub(key);
   if (compiled_invoke_stub == NULL) {
     compiled_invoke_stub = (*create_invoke_stub_)(*this, is_static, shorty, shorty_len);
     CHECK(compiled_invoke_stub != NULL);
-    InsertInvokeStub(is_static, shorty, compiled_invoke_stub);
+    InsertInvokeStub(key, compiled_invoke_stub);
   }
   CHECK(!Thread::Current()->IsExceptionPending()) << PrettyMethod(method_idx, dex_file);
 }
 
-static std::string MakeInvokeStubKey(bool is_static, const char* shorty) {
-  std::string key(shorty);
-  if (is_static) {
-    key += "$";  // Must not be a shorty type character.
-  }
-  return key;
+const CompiledInvokeStub* Compiler::FindInvokeStub(bool is_static, const char* shorty) const {
+  const std::string key(MakeInvokeStubKey(is_static, shorty));
+  return FindInvokeStub(key);
 }
 
-const CompiledInvokeStub* Compiler::FindInvokeStub(bool is_static, const char* shorty) const {
+const CompiledInvokeStub* Compiler::FindInvokeStub(const std::string& key) const {
   MutexLock mu(compiled_invoke_stubs_lock_);
-  const std::string key(MakeInvokeStubKey(is_static, shorty));
   InvokeStubTable::const_iterator it = compiled_invoke_stubs_.find(key);
   if (it == compiled_invoke_stubs_.end()) {
     return NULL;
@@ -1362,11 +1367,16 @@
   }
 }
 
-void Compiler::InsertInvokeStub(bool is_static, const char* shorty,
+void Compiler::InsertInvokeStub(const std::string& key,
                                 const CompiledInvokeStub* compiled_invoke_stub) {
   MutexLock mu(compiled_invoke_stubs_lock_);
-  std::string key(MakeInvokeStubKey(is_static, shorty));
-  compiled_invoke_stubs_[key] = compiled_invoke_stub;
+  InvokeStubTable::iterator it = compiled_invoke_stubs_.find(key);
+  if (it != compiled_invoke_stubs_.end()) {
+    // Someone else won the race.
+    delete compiled_invoke_stub;
+  } else {
+    compiled_invoke_stubs_.Put(key, compiled_invoke_stub);
+  }
 }
 
 CompiledClass* Compiler::GetCompiledClass(ClassReference ref) const {