Avoid copying and strlen(3) in the FindClass path.

Change-Id: I789f3c883596d1852a2c1954ce7a207e6f937117
diff --git a/src/class_linker.cc b/src/class_linker.cc
index e922d4c..df2e971 100644
--- a/src/class_linker.cc
+++ b/src/class_linker.cc
@@ -136,6 +136,15 @@
   env->Throw(eiie.get());
 }
 
+static size_t Hash(const char* s) {
+  // This is the java.lang.String hashcode for convenience, not interoperability.
+  size_t hash = 0;
+  for (; *s != '\0'; ++s) {
+    hash = hash * 31 + *s;
+  }
+  return hash;
+}
+
 }  // namespace
 
 const char* ClassLinker::class_roots_descriptors_[] = {
@@ -812,8 +821,8 @@
   if (obj->IsClass()) {
     // restore class to ClassLinker::classes_ table
     Class* klass = obj->AsClass();
-    std::string descriptor(ClassHelper(klass, class_linker).GetDescriptor());
-    bool success = class_linker->InsertClass(descriptor, klass, true);
+    ClassHelper kh(klass, class_linker);
+    bool success = class_linker->InsertClass(kh.GetDescriptor(), klass, true);
     DCHECK(success);
     return;
   }
@@ -984,13 +993,12 @@
   return klass;
 }
 
-Class* ClassLinker::FindClass(const std::string& descriptor,
-                              const ClassLoader* class_loader) {
-  CHECK_NE(descriptor.size(), 0U);
+Class* ClassLinker::FindClass(const char* descriptor, const ClassLoader* class_loader) {
+  DCHECK(*descriptor != '\0') << "descriptor is empty string";
   Thread* self = Thread::Current();
   DCHECK(self != NULL);
   CHECK(!self->IsExceptionPending()) << PrettyTypeOf(self->GetException());
-  if (descriptor.size() == 1) {
+  if (descriptor[1] == '\0') {
     // only the descriptors of primitive types should be 1 character long, also avoid class lookup
     // for primitive classes that aren't backed by dex files.
     return FindPrimitiveClass(descriptor[0]);
@@ -1050,11 +1058,11 @@
     }
   }
 
-  ThrowNoClassDefFoundError("Class %s not found", PrintableString(descriptor).c_str());
+  ThrowNoClassDefFoundError("Class %s not found", PrintableString(StringPiece(descriptor)).c_str());
   return NULL;
 }
 
-Class* ClassLinker::DefineClass(const std::string& descriptor,
+Class* ClassLinker::DefineClass(const StringPiece& descriptor,
                                 const ClassLoader* class_loader,
                                 const DexFile& dex_file,
                                 const DexFile::ClassDef& dex_class_def) {
@@ -1094,7 +1102,7 @@
   if (!success) {
     // We may fail to insert if we raced with another thread.
     klass->SetClinitThreadId(0);
-    klass.reset(LookupClass(descriptor, class_loader));
+    klass.reset(LookupClass(descriptor.data(), class_loader));
     CHECK(klass.get() != NULL);
     return klass.get();
   }
@@ -1454,12 +1462,11 @@
 // array class; that always comes from the base element class.
 //
 // Returns NULL with an exception raised on failure.
-Class* ClassLinker::CreateArrayClass(const std::string& descriptor,
-                                     const ClassLoader* class_loader) {
+Class* ClassLinker::CreateArrayClass(const std::string& descriptor, const ClassLoader* class_loader) {
   CHECK_EQ('[', descriptor[0]);
 
   // Identify the underlying component type
-  Class* component_type = FindClass(descriptor.substr(1), class_loader);
+  Class* component_type = FindClass(descriptor.substr(1).c_str(), class_loader);
   if (component_type == NULL) {
     DCHECK(Thread::Current()->IsExceptionPending());
     return NULL;
@@ -1483,7 +1490,7 @@
   // class to the hash table --- necessary because of possible races with
   // other threads.)
   if (class_loader != component_type->GetClassLoader()) {
-    Class* new_class = LookupClass(descriptor, component_type->GetClassLoader());
+    Class* new_class = LookupClass(descriptor.c_str(), component_type->GetClassLoader());
     if (new_class != NULL) {
       return new_class;
     }
@@ -1564,7 +1571,7 @@
   // (Yes, this happens.)
 
   // Grab the winning class.
-  Class* other_class = LookupClass(descriptor, component_type->GetClassLoader());
+  Class* other_class = LookupClass(descriptor.c_str(), component_type->GetClassLoader());
   DCHECK(other_class != NULL);
   return other_class;
 }
@@ -1597,7 +1604,7 @@
   return NULL;
 }
 
-bool ClassLinker::InsertClass(const std::string& descriptor, Class* klass, bool image_class) {
+bool ClassLinker::InsertClass(const StringPiece& descriptor, Class* klass, bool image_class) {
   if (VLOG_IS_ON(class_linker)) {
     DexCache* dex_cache = klass->GetDexCache();
     std::string source;
@@ -1620,8 +1627,8 @@
   return ((*it).second == klass);
 }
 
-bool ClassLinker::RemoveClass(const std::string& descriptor, const ClassLoader* class_loader) {
-  size_t hash = StringPieceHash()(descriptor);
+bool ClassLinker::RemoveClass(const char* descriptor, const ClassLoader* class_loader) {
+  size_t hash = Hash(descriptor);
   MutexLock mu(classes_lock_);
   typedef Table::const_iterator It;  // TODO: C++0x auto
   // TODO: determine if its better to search classes_ or image_classes_ first
@@ -1629,7 +1636,7 @@
   for (It it = classes_.find(hash), end = classes_.end(); it != end; ++it) {
     Class* klass = it->second;
     kh.ChangeClass(klass);
-    if (kh.GetDescriptor() == descriptor && klass->GetClassLoader() == class_loader) {
+    if (strcmp(kh.GetDescriptor(), descriptor) == 0 && klass->GetClassLoader() == class_loader) {
       classes_.erase(it);
       return true;
     }
@@ -1637,7 +1644,7 @@
   for (It it = image_classes_.find(hash), end = image_classes_.end(); it != end; ++it) {
     Class* klass = it->second;
     kh.ChangeClass(klass);
-    if (kh.GetDescriptor() == descriptor && klass->GetClassLoader() == class_loader) {
+    if (strcmp(kh.GetDescriptor(), descriptor) == 0 && klass->GetClassLoader() == class_loader) {
       image_classes_.erase(it);
       return true;
     }
@@ -1645,8 +1652,8 @@
   return false;
 }
 
-Class* ClassLinker::LookupClass(const std::string& descriptor, const ClassLoader* class_loader) {
-  size_t hash = StringPieceHash()(descriptor);
+Class* ClassLinker::LookupClass(const char* descriptor, const ClassLoader* class_loader) {
+  size_t hash = Hash(descriptor);
   MutexLock mu(classes_lock_);
   typedef Table::const_iterator It;  // TODO: C++0x auto
   // TODO: determine if its better to search classes_ or image_classes_ first
@@ -1654,23 +1661,23 @@
   for (It it = classes_.find(hash), end = classes_.end(); it != end; ++it) {
     Class* klass = it->second;
     kh.ChangeClass(klass);
-    if (descriptor == kh.GetDescriptor() && klass->GetClassLoader() == class_loader) {
+    if (strcmp(descriptor, kh.GetDescriptor()) == 0 && klass->GetClassLoader() == class_loader) {
       return klass;
     }
   }
   for (It it = image_classes_.find(hash), end = image_classes_.end(); it != end; ++it) {
     Class* klass = it->second;
     kh.ChangeClass(klass);
-    if (descriptor == kh.GetDescriptor() && klass->GetClassLoader() == class_loader) {
+    if (strcmp(descriptor, kh.GetDescriptor()) == 0 && klass->GetClassLoader() == class_loader) {
       return klass;
     }
   }
   return NULL;
 }
 
-void ClassLinker::LookupClasses(const std::string& descriptor, std::vector<Class*>& classes) {
+void ClassLinker::LookupClasses(const char* descriptor, std::vector<Class*>& classes) {
   classes.clear();
-  size_t hash = StringPieceHash()(descriptor);
+  size_t hash = Hash(descriptor);
   MutexLock mu(classes_lock_);
   typedef Table::const_iterator It;  // TODO: C++0x auto
   // TODO: determine if its better to search classes_ or image_classes_ first
@@ -1678,14 +1685,14 @@
   for (It it = classes_.find(hash), end = classes_.end(); it != end; ++it) {
     Class* klass = it->second;
     kh.ChangeClass(klass);
-    if (descriptor == kh.GetDescriptor()) {
+    if (strcmp(descriptor, kh.GetDescriptor()) == 0) {
       classes.push_back(klass);
     }
   }
   for (It it = image_classes_.find(hash), end = image_classes_.end(); it != end; ++it) {
     Class* klass = it->second;
     kh.ChangeClass(klass);
-    if (descriptor == kh.GetDescriptor()) {
+    if (strcmp(descriptor, kh.GetDescriptor()) == 0) {
       classes.push_back(klass);
     }
   }