Cleanup proxy stub compiler code.

Change-Id: I2a5815cc2a38f5cea9e9c36e5e6db92c1a861eaa
diff --git a/src/compiler.cc b/src/compiler.cc
index dadfc40..5389127 100644
--- a/src/compiler.cc
+++ b/src/compiler.cc
@@ -307,6 +307,9 @@
       compiled_classes_lock_("compiled classes lock"),
       compiled_methods_lock_("compiled method lock"),
       compiled_invoke_stubs_lock_("compiled invoke stubs lock"),
+#if defined(ART_USE_LLVM_COMPILER)
+      compiled_proxy_stubs_lock_("compiled proxy stubs lock"),
+#endif
       image_(image),
       thread_count_(thread_count),
       support_debugging_(support_debugging),
@@ -350,6 +353,8 @@
   create_invoke_stub_ = FindFunction<CreateInvokeStubFn>(compiler_so_name, compiler_library_, "ArtCreateInvokeStub");
 
 #if defined(ART_USE_LLVM_COMPILER)
+  create_proxy_stub_ = FindFunction<CreateProxyStubFn>(
+      compiler_so_name, compiler_library_, "ArtCreateProxyStub");
   compiler_enable_auto_elf_loading_ = FindFunction<CompilerEnableAutoElfLoadingFn>(
       compiler_so_name, compiler_library_, "compilerLLVMEnableAutoElfLoading");
   compiler_get_method_code_addr_ = FindFunction<CompilerGetMethodCodeAddrFn>(
@@ -378,6 +383,10 @@
     STLDeleteValues(&compiled_invoke_stubs_);
   }
   {
+    MutexLock mu(compiled_proxy_stubs_lock_);
+    STLDeleteValues(&compiled_proxy_stubs_);
+  }
+  {
     MutexLock mu(compiled_methods_lock_);
     STLDeleteElements(&code_to_patch_);
   }
@@ -1505,6 +1514,18 @@
     CHECK(compiled_invoke_stub != NULL);
     InsertInvokeStub(key, compiled_invoke_stub);
   }
+
+#if defined(ART_USE_LLVM_COMPILER)
+  if (!is_static) {
+    const CompiledInvokeStub* compiled_proxy_stub = FindProxyStub(shorty);
+    if (compiled_proxy_stub == NULL) {
+      compiled_proxy_stub = (*create_proxy_stub_)(*this, shorty, shorty_len);
+      CHECK(compiled_proxy_stub != NULL);
+      InsertProxyStub(shorty, compiled_proxy_stub);
+    }
+  }
+#endif
+
   CHECK(!Thread::Current()->IsExceptionPending()) << PrettyMethod(method_idx, dex_file);
 }
 
@@ -1536,6 +1557,31 @@
   }
 }
 
+#if defined(ART_USE_LLVM_COMPILER)
+const CompiledInvokeStub* Compiler::FindProxyStub(const char* shorty) const {
+  MutexLock mu(compiled_proxy_stubs_lock_);
+  ProxyStubTable::const_iterator it = compiled_proxy_stubs_.find(shorty);
+  if (it == compiled_proxy_stubs_.end()) {
+    return NULL;
+  } else {
+    DCHECK(it->second != NULL);
+    return it->second;
+  }
+}
+
+void Compiler::InsertProxyStub(const char* shorty,
+                               const CompiledInvokeStub* compiled_proxy_stub) {
+  MutexLock mu(compiled_proxy_stubs_lock_);
+  InvokeStubTable::iterator it = compiled_proxy_stubs_.find(shorty);
+  if (it != compiled_proxy_stubs_.end()) {
+    // Someone else won the race.
+    delete compiled_proxy_stub;
+  } else {
+    compiled_proxy_stubs_.Put(shorty, compiled_proxy_stub);
+  }
+}
+#endif
+
 CompiledClass* Compiler::GetCompiledClass(ClassReference ref) const {
   MutexLock mu(compiled_classes_lock_);
   ClassTable::const_iterator it = compiled_classes_.find(ref);