Use ELF function index to distinguish generated functions.

We replaced LLVMLongName and LLVMStubName with ElfFuncName,
and we are using the simple name: Art0, Art1, ..., ArtN,
as the function name of every generated functions.  This
gives us 3 benefits:

1. We can avoid the ambiguous function name returned by
   LLVMLongName() in some special situation.

2. We don't need to have the art::Method object during
   the executable linking procedure.  Besides, this will
   make bootstrapping easier.

3. Reduce the size of the ELF executable, since we don't
   have to save a long function name, which usually contains
   more than 30 characters.

Change-Id: Ib698062b272458e847ad5545d7acf33a4dc9eb85
diff --git a/src/compiler_llvm/compilation_unit.cc b/src/compiler_llvm/compilation_unit.cc
index c5952f0..b3a9c71 100644
--- a/src/compiler_llvm/compilation_unit.cc
+++ b/src/compiler_llvm/compilation_unit.cc
@@ -62,7 +62,7 @@
 
 CompilationUnit::CompilationUnit(InstructionSet insn_set, size_t elf_idx)
 : insn_set_(insn_set), elf_idx_(elf_idx), context_(new llvm::LLVMContext()),
-  mem_usage_(0) {
+  mem_usage_(0), num_elf_funcs_(0) {
 
   // Create the module and include the runtime function declaration
   module_ = new llvm::Module("art", *context_);
diff --git a/src/compiler_llvm/compilation_unit.h b/src/compiler_llvm/compilation_unit.h
index eb92ce4..1db54fc 100644
--- a/src/compiler_llvm/compilation_unit.h
+++ b/src/compiler_llvm/compilation_unit.h
@@ -73,6 +73,11 @@
     return ElfImage(elf_image_);
   }
 
+  uint16_t AcquireUniqueElfFuncIndex() {
+    CHECK(num_elf_funcs_ < UINT16_MAX);
+    return num_elf_funcs_++;
+  }
+
   bool WriteBitcodeToFile();
 
   bool Materialize();
@@ -101,6 +106,7 @@
   std::string bitcode_filename_;
 
   size_t mem_usage_;
+  uint16_t num_elf_funcs_;
 };
 
 } // namespace compiler_llvm
diff --git a/src/compiler_llvm/compiler_llvm.cc b/src/compiler_llvm/compiler_llvm.cc
index 2b18903..f9af139 100644
--- a/src/compiler_llvm/compiler_llvm.cc
+++ b/src/compiler_llvm/compiler_llvm.cc
@@ -213,15 +213,16 @@
 }
 
 
-const void* CompilerLLVM::GetMethodCodeAddr(const CompiledMethod* cm,
-                                            const Method* method) const {
-  return elf_loader_->GetMethodCodeAddr(cm->GetElfIndex(), method);
+const void* CompilerLLVM::GetMethodCodeAddr(const CompiledMethod* cm) const {
+  return elf_loader_->GetMethodCodeAddr(cm->GetElfIndex(),
+                                        cm->GetElfFuncIndex());
 }
 
 
 const Method::InvokeStub* CompilerLLVM::
-GetMethodInvokeStubAddr(const CompiledInvokeStub* cm, const Method* method) const {
-  return elf_loader_->GetMethodInvokeStubAddr(cm->GetElfIndex(), method);
+GetMethodInvokeStubAddr(const CompiledInvokeStub* cm) const {
+  return elf_loader_->GetMethodInvokeStubAddr(cm->GetElfIndex(),
+                                              cm->GetElfFuncIndex());
 }
 
 
@@ -353,18 +354,18 @@
 
 extern "C" const void* compilerLLVMGetMethodCodeAddr(const art::Compiler& compiler,
                                                      const art::CompiledMethod* cm,
-                                                     const art::Method* method) {
+                                                     const art::Method*) {
   const art::compiler_llvm::CompilerLLVM* compiler_llvm =
       reinterpret_cast<const art::compiler_llvm::CompilerLLVM*>(compiler.GetCompilerContext());
-  return compiler_llvm->GetMethodCodeAddr(cm, method);
+  return compiler_llvm->GetMethodCodeAddr(cm);
 }
 
 extern "C" const art::Method::InvokeStub* compilerLLVMGetMethodInvokeStubAddr(const art::Compiler& compiler,
                                                                               const art::CompiledInvokeStub* cm,
-                                                                              const art::Method* method) {
+                                                                              const art::Method*) {
   const art::compiler_llvm::CompilerLLVM* compiler_llvm =
       reinterpret_cast<const art::compiler_llvm::CompilerLLVM*>(compiler.GetCompilerContext());
-  return compiler_llvm->GetMethodInvokeStubAddr(cm, method);
+  return compiler_llvm->GetMethodInvokeStubAddr(cm);
 }
 
 extern "C" std::vector<art::ElfImage> compilerLLVMGetElfImages(const art::Compiler& compiler) {
diff --git a/src/compiler_llvm/compiler_llvm.h b/src/compiler_llvm/compiler_llvm.h
index b9f8d00..8bb053e 100644
--- a/src/compiler_llvm/compiler_llvm.h
+++ b/src/compiler_llvm/compiler_llvm.h
@@ -93,12 +93,10 @@
     return (elf_loader_.get() != NULL);
   }
 
-  const void* GetMethodCodeAddr(const CompiledMethod* cm,
-                                const Method* method) const;
+  const void* GetMethodCodeAddr(const CompiledMethod* cm) const;
 
   const Method::InvokeStub* GetMethodInvokeStubAddr(
-                                const CompiledInvokeStub* cm,
-                                const Method* method) const;
+                                const CompiledInvokeStub* cm) const;
 
   std::vector<ElfImage> GetElfImages() const;
 
diff --git a/src/compiler_llvm/elf_loader.cc b/src/compiler_llvm/elf_loader.cc
index adea85d..8f8eff9 100644
--- a/src/compiler_llvm/elf_loader.cc
+++ b/src/compiler_llvm/elf_loader.cc
@@ -84,20 +84,18 @@
 }
 
 
-const void* ElfLoader::GetMethodCodeAddr(size_t elf_idx,
-                                         const Method* method) const {
+const void* ElfLoader::GetMethodCodeAddr(uint16_t elf_idx,
+                                         uint16_t elf_func_idx) const {
   CHECK_LT(elf_idx, executables_.size());
-  CHECK(method != NULL);
-  return GetAddr(elf_idx, LLVMLongName(method).c_str());
+  return GetAddr(elf_idx, ElfFuncName(elf_func_idx).c_str());
 }
 
 
 const Method::InvokeStub* ElfLoader::
-GetMethodInvokeStubAddr(size_t elf_idx, const Method* method) const {
+GetMethodInvokeStubAddr(uint16_t elf_idx, uint16_t elf_func_idx) const {
   CHECK_LT(elf_idx, executables_.size());
-  CHECK(method != NULL);
   return reinterpret_cast<const Method::InvokeStub*>(
-      GetAddr(elf_idx, LLVMStubName(method).c_str()));
+      GetAddr(elf_idx, ElfFuncName(elf_func_idx).c_str()));
 }
 
 
diff --git a/src/compiler_llvm/elf_loader.h b/src/compiler_llvm/elf_loader.h
index 9e8137f..ea98f61 100644
--- a/src/compiler_llvm/elf_loader.h
+++ b/src/compiler_llvm/elf_loader.h
@@ -26,10 +26,6 @@
 #include <vector>
 
 namespace art {
-  class Method;
-}
-
-namespace art {
 namespace compiler_llvm {
 
 class ElfLoader {
@@ -41,10 +37,11 @@
 
   void RelocateExecutable();
 
-  const void* GetMethodCodeAddr(size_t elf_idx, const Method* method) const;
+  const void* GetMethodCodeAddr(uint16_t elf_idx,
+                                uint16_t elf_func_idx) const;
 
-  const Method::InvokeStub* GetMethodInvokeStubAddr(size_t elf_idx,
-                                                    const Method* method) const;
+  const Method::InvokeStub* GetMethodInvokeStubAddr(uint16_t elf_idx,
+                                                    uint16_t elf_func_idx) const;
 
  private:
   const void* GetAddr(size_t elf_idx, const char* sym_name) const;
diff --git a/src/compiler_llvm/jni_compiler.cc b/src/compiler_llvm/jni_compiler.cc
index 097c4f1..285caab 100644
--- a/src/compiler_llvm/jni_compiler.cc
+++ b/src/compiler_llvm/jni_compiler.cc
@@ -52,7 +52,8 @@
   class_loader_(oat_compilation_unit->class_loader_),
   dex_cache_(oat_compilation_unit->dex_cache_),
   dex_file_(oat_compilation_unit->dex_file_),
-  method_(dex_cache_->GetResolvedMethod(method_idx_)) {
+  method_(dex_cache_->GetResolvedMethod(method_idx_)),
+  elf_func_idx_(cunit_->AcquireUniqueElfFuncIndex()) {
 
   // Check: Ensure that the method is resolved
   CHECK_NE(method_, static_cast<art::Method*>(NULL));
@@ -289,13 +290,14 @@
   llvm::verifyFunction(*func_, llvm::PrintMessageAction);
 
   return new CompiledMethod(cunit_->GetInstructionSet(),
-                            cunit_->GetElfIndex());
+                            cunit_->GetElfIndex(),
+                            elf_func_idx_);
 }
 
 
 void JniCompiler::CreateFunction() {
   // LLVM function name
-  std::string func_name(LLVMLongName(method_));
+  std::string func_name(ElfFuncName(elf_func_idx_));
 
   // Get function type
   llvm::FunctionType* func_type =
diff --git a/src/compiler_llvm/jni_compiler.h b/src/compiler_llvm/jni_compiler.h
index c15dae5..d91293d 100644
--- a/src/compiler_llvm/jni_compiler.h
+++ b/src/compiler_llvm/jni_compiler.h
@@ -84,6 +84,7 @@
   Method* method_;
 
   llvm::Function* func_;
+  uint16_t elf_func_idx_;
 };
 
 
diff --git a/src/compiler_llvm/method_compiler.cc b/src/compiler_llvm/method_compiler.cc
index 8b1cef6..57dbf15 100644
--- a/src/compiler_llvm/method_compiler.cc
+++ b/src/compiler_llvm/method_compiler.cc
@@ -67,7 +67,7 @@
     basic_blocks_(code_item_->insns_size_in_code_units_),
     basic_block_landing_pads_(code_item_->tries_size_, NULL),
     basic_block_unwind_(NULL), basic_block_unreachable_(NULL),
-    shadow_frame_(NULL) {
+    shadow_frame_(NULL), elf_func_idx_(cunit_->AcquireUniqueElfFuncIndex()) {
 }
 
 
@@ -78,7 +78,7 @@
 
 void MethodCompiler::CreateFunction() {
   // LLVM function name
-  std::string func_name(LLVMLongName(method_));
+  std::string func_name(ElfFuncName(elf_func_idx_));
 
   // Get function type
   llvm::FunctionType* func_type =
@@ -3773,7 +3773,8 @@
   // Thus, we got our magic number 9.
 
   return new CompiledMethod(cunit_->GetInstructionSet(),
-                            cunit_->GetElfIndex());
+                            cunit_->GetElfIndex(),
+                            elf_func_idx_);
 }
 
 
diff --git a/src/compiler_llvm/method_compiler.h b/src/compiler_llvm/method_compiler.h
index 006f763..1ff3a9f 100644
--- a/src/compiler_llvm/method_compiler.h
+++ b/src/compiler_llvm/method_compiler.h
@@ -460,6 +460,8 @@
   llvm::BasicBlock* basic_block_unreachable_;
 
   llvm::AllocaInst* shadow_frame_;
+
+  uint16_t elf_func_idx_;
 };
 
 
diff --git a/src/compiler_llvm/upcall_compiler.cc b/src/compiler_llvm/upcall_compiler.cc
index 20bd94b..85bfe24 100644
--- a/src/compiler_llvm/upcall_compiler.cc
+++ b/src/compiler_llvm/upcall_compiler.cc
@@ -24,6 +24,7 @@
 #include "logging.h"
 #include "object.h"
 #include "runtime_support_func.h"
+#include "utils_llvm.h"
 
 #include <llvm/Analysis/Verifier.h>
 #include <llvm/BasicBlock.h>
@@ -42,7 +43,8 @@
 
 UpcallCompiler::UpcallCompiler(CompilationUnit* cunit, Compiler& compiler)
 : cunit_(cunit), compiler_(&compiler), module_(cunit_->GetModule()),
-  context_(cunit_->GetLLVMContext()), irb_(*cunit_->GetIRBuilder()) {
+  context_(cunit_->GetLLVMContext()), irb_(*cunit_->GetIRBuilder()),
+  elf_func_idx_(cunit_->AcquireUniqueElfFuncIndex()) {
 }
 
 
@@ -53,13 +55,7 @@
   size_t shorty_size = strlen(shorty);
 
   // Function name
-  std::string func_name;
-
-  if (is_static) {
-    StringAppendF(&func_name, "ArtSUpcall_%s", shorty);
-  } else {
-    StringAppendF(&func_name, "ArtUpcall_%s", shorty);
-  }
+  std::string func_name(ElfFuncName(elf_func_idx_));
 
   // Get argument types
   llvm::Type* arg_types[] = {
@@ -179,7 +175,7 @@
   // store ret_addr, and ret_void.  Beside, we guess that we have to use
   // 50 bytes to represent one LLVM instruction.
 
-  return new CompiledInvokeStub(cunit_->GetElfIndex());
+  return new CompiledInvokeStub(cunit_->GetElfIndex(), elf_func_idx_);
 }
 
 
diff --git a/src/compiler_llvm/upcall_compiler.h b/src/compiler_llvm/upcall_compiler.h
index 73d00a1..9cb49b0 100644
--- a/src/compiler_llvm/upcall_compiler.h
+++ b/src/compiler_llvm/upcall_compiler.h
@@ -48,6 +48,7 @@
   llvm::Module* module_;
   llvm::LLVMContext* context_;
   IRBuilder& irb_;
+  uint16_t elf_func_idx_;
 };
 
 
diff --git a/src/compiler_llvm/utils_llvm.cc b/src/compiler_llvm/utils_llvm.cc
deleted file mode 100644
index 2a9ccba..0000000
--- a/src/compiler_llvm/utils_llvm.cc
+++ /dev/null
@@ -1,113 +0,0 @@
-/*
- * Copyright (C) 2012 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "utils_llvm.h"
-
-#include <fcntl.h>
-#include <string.h>
-#include <sys/mman.h>
-#include <sys/stat.h>
-#include <sys/types.h>
-#include <unistd.h>
-
-#include "android/librsloader.h"
-#include "class_loader.h"
-#include "object.h"
-#include "object_utils.h"
-#include "runtime_support_llvm.h"
-
-namespace art {
-
-std::string MangleForLLVM(const std::string& s) {
-  std::string result;
-  size_t char_count = CountModifiedUtf8Chars(s.c_str());
-  const char* cp = &s[0];
-  for (size_t i = 0; i < char_count; ++i) {
-    uint16_t ch = GetUtf16FromUtf8(&cp);
-    if (ch == '$' || ch == '<' || ch == '>' || ch > 127) {
-      StringAppendF(&result, "_0%04x", ch);
-    } else {
-      switch (ch) {
-      case '_':
-        result += "_1";
-        break;
-      case ';':
-        result += "_2";
-        break;
-      case '[':
-        result += "_3";
-        break;
-      case ')':
-        result += "_4";
-        break;
-      case '/':
-        result += "_";
-        break;
-      default:
-        result.push_back(ch);
-        break;
-      }
-    }
-  }
-  return result;
-}
-
-std::string LLVMShortName(const Method* m) {
-  MethodHelper mh(m);
-  std::string class_name(mh.GetDeclaringClassDescriptor());
-  // Remove the leading 'L' and trailing ';'...
-  CHECK_EQ(class_name[0], 'L') << class_name;
-  CHECK_EQ(class_name[class_name.size() - 1], ';') << class_name;
-  class_name.erase(0, 1);
-  class_name.erase(class_name.size() - 1, 1);
-
-  std::string method_name(mh.GetName());
-
-  std::string short_name;
-  short_name += "Art_";
-  short_name += MangleForLLVM(class_name);
-  short_name += "_";
-  short_name += MangleForLLVM(method_name);
-  return short_name;
-}
-
-std::string LLVMLongName(const Method* m) {
-  std::string long_name;
-  long_name += LLVMShortName(m);
-  long_name += "__";
-
-  std::string signature(MethodHelper(m).GetSignature());
-  signature.erase(0, 1);
-
-  long_name += MangleForLLVM(signature);
-
-  return long_name;
-}
-
-std::string LLVMStubName(const Method* m) {
-  MethodHelper mh(m);
-  std::string stub_name;
-  if (m->IsStatic()) {
-    stub_name += "ArtSUpcall_";
-  } else {
-    stub_name += "ArtUpcall_";
-  }
-  stub_name += mh.GetShorty();
-
-  return stub_name;
-}
-
-}  // namespace art
diff --git a/src/compiler_llvm/utils_llvm.h b/src/compiler_llvm/utils_llvm.h
index fb4da34..fb9f0cb 100644
--- a/src/compiler_llvm/utils_llvm.h
+++ b/src/compiler_llvm/utils_llvm.h
@@ -17,26 +17,17 @@
 #ifndef ART_SRC_UTILS_LLVM_H_
 #define ART_SRC_UTILS_LLVM_H_
 
-#include "object.h"
+#include "stringprintf.h"
 
+#include <stdint.h>
 #include <string>
 
 namespace art {
 
-// Performs LLVM name mangling (similar to MangleForJni with additional '<' and
-// '>' being mangled).
-std::string MangleForLLVM(const std::string& s);
+inline static std::string ElfFuncName(uint16_t elf_func_idx) {
+  return StringPrintf("Art%u", static_cast<unsigned int>(elf_func_idx));
+}
 
-// Returns the LLVM function name for the non-overloaded method 'm'.
-std::string LLVMShortName(const Method* m);
-
-// Returns the LLVM function name for the overloaded method 'm'.
-std::string LLVMLongName(const Method* m);
-
-// Returns the LLVM stub function name for the overloaded method 'm'.
-std::string LLVMStubName(const Method* m);
-
-void LLVMLinkLoadMethod(const std::string& file_name, Method* method);
 }  // namespace art
 
 #endif  // ART_SRC_UTILS_LLVM_H_
diff --git a/src/compiler_llvm/utils_llvm_test.cc b/src/compiler_llvm/utils_llvm_test.cc
deleted file mode 100644
index f5a2c0e..0000000
--- a/src/compiler_llvm/utils_llvm_test.cc
+++ /dev/null
@@ -1,82 +0,0 @@
-/*
- * Copyright (C) 2012 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "object.h"
-#include "common_test.h"
-#include "utils_llvm.h"
-
-namespace art {
-
-class UtilsLLVMTest : public CommonTest {
-};
-
-TEST_F(UtilsLLVMTest, MangleForLLVM) {
-  // Unit test inheritted from MangleForJni
-  EXPECT_EQ("hello_00024world", MangleForLLVM("hello$world"));
-  EXPECT_EQ("hello_000a9world", MangleForLLVM("hello\xc2\xa9world"));
-  EXPECT_EQ("hello_1world", MangleForLLVM("hello_world"));
-  EXPECT_EQ("Ljava_lang_String_2", MangleForLLVM("Ljava/lang/String;"));
-  EXPECT_EQ("_3C", MangleForLLVM("[C"));
-
-  // MangleForLLVM()-specific unit test
-  EXPECT_EQ("_0003cinit_0003e", MangleForLLVM("<init>"));
-  EXPECT_EQ("_0003cclinit_0003e", MangleForLLVM("<clinit>"));
-}
-
-TEST_F(UtilsLLVMTest, LLVMShortName_LLVMLongName) {
-  Class* c = class_linker_->FindSystemClass("Ljava/lang/String;");
-  ASSERT_TRUE(c != NULL);
-  Method* m;
-
-  // Unit test inheritted from MangleForJni
-  m = c->FindVirtualMethod("charAt", "(I)C");
-  ASSERT_TRUE(m != NULL);
-  EXPECT_EQ("Art_java_lang_String_charAt", LLVMShortName(m));
-  EXPECT_EQ("Art_java_lang_String_charAt__I", LLVMLongName(m));
-
-  m = c->FindVirtualMethod("indexOf", "(Ljava/lang/String;I)I");
-  ASSERT_TRUE(m != NULL);
-  EXPECT_EQ("Art_java_lang_String_indexOf", LLVMShortName(m));
-  EXPECT_EQ("Art_java_lang_String_indexOf__Ljava_lang_String_2I", LLVMLongName(m));
-
-  m = c->FindDirectMethod("copyValueOf", "([CII)Ljava/lang/String;");
-  ASSERT_TRUE(m != NULL);
-  EXPECT_EQ("Art_java_lang_String_copyValueOf", LLVMShortName(m));
-  EXPECT_EQ("Art_java_lang_String_copyValueOf___3CII", LLVMLongName(m));
-
-  // MangleForLLVM()-specific unit test
-  m = c->FindDirectMethod("<init>", "()V");
-  ASSERT_TRUE(m != NULL);
-  EXPECT_EQ("Art_java_lang_String__0003cinit_0003e", LLVMShortName(m));
-  EXPECT_EQ("Art_java_lang_String__0003cinit_0003e__", LLVMLongName(m));
-
-  m = c->FindDirectMethod("<init>", "([C)V");
-  ASSERT_TRUE(m != NULL);
-  EXPECT_EQ("Art_java_lang_String__0003cinit_0003e", LLVMShortName(m));
-  EXPECT_EQ("Art_java_lang_String__0003cinit_0003e___3C", LLVMLongName(m));
-
-  m = c->FindDirectMethod("<init>", "([CII)V");
-  ASSERT_TRUE(m != NULL);
-  EXPECT_EQ("Art_java_lang_String__0003cinit_0003e", LLVMShortName(m));
-  EXPECT_EQ("Art_java_lang_String__0003cinit_0003e___3CII", LLVMLongName(m));
-
-  m = c->FindDirectMethod("<init>", "(Ljava/lang/String;)V");
-  ASSERT_TRUE(m != NULL);
-  EXPECT_EQ("Art_java_lang_String__0003cinit_0003e", LLVMShortName(m));
-  EXPECT_EQ("Art_java_lang_String__0003cinit_0003e__Ljava_lang_String_2", LLVMLongName(m));
-}
-
-}  // namespace art