Don't use UTF16 length as length for MUTF8.

Bug 11367555.

Change-Id: Ia0b07072a1a49d435c3b71ed9a668b316b7ff5d8
diff --git a/compiler/dex/quick/gen_invoke.cc b/compiler/dex/quick/gen_invoke.cc
index 62feade..5a1d3d1 100644
--- a/compiler/dex/quick/gen_invoke.cc
+++ b/compiler/dex/quick/gen_invoke.cc
@@ -1232,7 +1232,7 @@
   const DexFile::MethodId& target_mid = cu_->dex_file->GetMethodId(info->index);
   const DexFile::TypeId& declaring_type = cu_->dex_file->GetTypeId(target_mid.class_idx_);
   StringPiece tgt_methods_declaring_class(
-      cu_->dex_file->StringDataAsStringPieceByIdx(declaring_type.descriptor_idx_));
+      cu_->dex_file->StringDataByIdx(declaring_type.descriptor_idx_));
   if (tgt_methods_declaring_class.starts_with("Ljava/lang/Double;")) {
     std::string tgt_method(PrettyMethod(info->index, *cu_->dex_file));
     if (tgt_method == "long java.lang.Double.doubleToRawLongBits(double)") {
diff --git a/compiler/driver/compiler_driver.cc b/compiler/driver/compiler_driver.cc
index 91b0188..7653d16 100644
--- a/compiler/driver/compiler_driver.cc
+++ b/compiler/driver/compiler_driver.cc
@@ -600,11 +600,11 @@
   UpdateImageClasses(timings);
 }
 
-bool CompilerDriver::IsImageClass(const StringPiece& descriptor) const {
+bool CompilerDriver::IsImageClass(const char* descriptor) const {
   if (!IsImage()) {
     return true;
   } else {
-    return image_classes_->find(descriptor.data()) != image_classes_->end();
+    return image_classes_->find(descriptor) != image_classes_->end();
   }
 }
 
@@ -780,7 +780,7 @@
 bool CompilerDriver::CanAssumeTypeIsPresentInDexCache(const DexFile& dex_file,
                                                       uint32_t type_idx) {
   if (IsImage() &&
-      IsImageClass(dex_file.StringDataAsStringPieceByIdx(dex_file.GetTypeId(type_idx).descriptor_idx_))) {
+      IsImageClass(dex_file.StringDataByIdx(dex_file.GetTypeId(type_idx).descriptor_idx_))) {
     if (kIsDebugBuild) {
       ScopedObjectAccess soa(Thread::Current());
       mirror::DexCache* dex_cache = Runtime::Current()->GetClassLinker()->FindDexCache(dex_file);
@@ -1108,7 +1108,7 @@
   }
   if (!use_dex_cache && compiling_boot) {
     MethodHelper mh(method);
-    if (!IsImageClass(mh.GetDeclaringClassDescriptorAsStringPiece())) {
+    if (!IsImageClass(mh.GetDeclaringClassDescriptor())) {
       // We can only branch directly to Methods that are resolved in the DexCache.
       // Otherwise we won't invoke the resolution trampoline.
       use_dex_cache = true;
@@ -1573,8 +1573,8 @@
     CHECK(soa.Self()->IsExceptionPending());
     mirror::Throwable* exception = soa.Self()->GetException(NULL);
     VLOG(compiler) << "Exception during type resolution: " << exception->Dump();
-    if (ClassHelper(exception->GetClass()).GetDescriptorAsStringPiece() ==
-        "Ljava/lang/OutOfMemoryError;") {
+    if (strcmp("Ljava/lang/OutOfMemoryError;",
+               ClassHelper(exception->GetClass()).GetDescriptor()) == 0) {
       // There's little point continuing compilation if the heap is exhausted.
       LOG(FATAL) << "Out of memory during type resolution for compilation";
     }
@@ -2089,11 +2089,11 @@
   const DexFile* dex_file = manager->GetDexFile();
   const DexFile::ClassDef& class_def = dex_file->GetClassDef(class_def_index);
   const DexFile::TypeId& class_type_id = dex_file->GetTypeId(class_def.class_idx_);
-  StringPiece descriptor(dex_file->StringDataAsStringPieceByIdx(class_type_id.descriptor_idx_));
+  const char* descriptor = dex_file->StringDataByIdx(class_type_id.descriptor_idx_);
 
   ScopedObjectAccess soa(Thread::Current());
   mirror::ClassLoader* class_loader = soa.Decode<mirror::ClassLoader*>(manager->GetClassLoader());
-  mirror::Class* klass = manager->GetClassLinker()->FindClass(descriptor.data(), class_loader);
+  mirror::Class* klass = manager->GetClassLinker()->FindClass(descriptor, class_loader);
   if (klass != NULL) {
     // Only try to initialize classes that were successfully verified.
     if (klass->IsVerified()) {
@@ -2123,7 +2123,7 @@
             bool is_black_listed = StringPiece(descriptor).ends_with("$NoPreloadHolder;");
             if (!is_black_listed) {
               for (size_t i = 0; i < arraysize(class_initializer_black_list); ++i) {
-                if (descriptor == class_initializer_black_list[i]) {
+                if (strcmp(descriptor, class_initializer_black_list[i]) == 0) {
                   is_black_listed = true;
                   break;
                 }
@@ -2131,7 +2131,7 @@
             }
             if (!is_black_listed) {
               VLOG(compiler) << "Initializing: " << descriptor;
-              if (descriptor == "Ljava/lang/Void;") {
+              if (strcmp("Ljava/lang/Void;", descriptor) == 0) {
                 // Hand initialize j.l.Void to avoid Dex file operations in un-started runtime.
                 ObjectLock lock(soa.Self(), klass);
                 mirror::ObjectArray<mirror::ArtField>* fields = klass->GetSFields();
diff --git a/compiler/driver/compiler_driver.h b/compiler/driver/compiler_driver.h
index 971021f..fe21eff 100644
--- a/compiler/driver/compiler_driver.h
+++ b/compiler/driver/compiler_driver.h
@@ -309,7 +309,7 @@
   }
 
   // Checks if class specified by type_idx is one of the image_classes_
-  bool IsImageClass(const StringPiece& descriptor) const;
+  bool IsImageClass(const char* descriptor) const;
 
   void RecordClassStatus(ClassReference ref, mirror::Class::Status status)
       LOCKS_EXCLUDED(compiled_classes_lock_);
diff --git a/compiler/image_writer.cc b/compiler/image_writer.cc
index 871cfd5..e66e214 100644
--- a/compiler/image_writer.cc
+++ b/compiler/image_writer.cc
@@ -244,7 +244,7 @@
 }
 
 bool ImageWriter::IsImageClass(const Class* klass) {
-  return compiler_driver_.IsImageClass(ClassHelper(klass).GetDescriptorAsStringPiece());
+  return compiler_driver_.IsImageClass(ClassHelper(klass).GetDescriptor());
 }
 
 struct NonImageClasses {
@@ -299,7 +299,7 @@
 bool ImageWriter::NonImageClassesVisitor(Class* klass, void* arg) {
   NonImageClasses* context = reinterpret_cast<NonImageClasses*>(arg);
   if (!context->image_writer->IsImageClass(klass)) {
-    context->non_image_classes->insert(ClassHelper(klass).GetDescriptorAsStringPiece().as_string());
+    context->non_image_classes->insert(ClassHelper(klass).GetDescriptor());
   }
   return true;
 }
diff --git a/runtime/class_linker.cc b/runtime/class_linker.cc
index 03f2c9d..55bbf7c 100644
--- a/runtime/class_linker.cc
+++ b/runtime/class_linker.cc
@@ -1878,7 +1878,7 @@
                                            SirtRef<mirror::Class>& klass) {
   uint32_t dex_method_idx = it.GetMemberIndex();
   const DexFile::MethodId& method_id = dex_file.GetMethodId(dex_method_idx);
-  StringPiece method_name(dex_file.StringDataAsStringPieceByIdx(method_id.name_idx_));
+  const char* method_name = dex_file.StringDataByIdx(method_id.name_idx_);
 
   mirror::ArtMethod* dst = AllocArtMethod(self);
   if (UNLIKELY(dst == NULL)) {
@@ -1899,34 +1899,30 @@
 
   uint32_t access_flags = it.GetMemberAccessFlags();
 
-  if (UNLIKELY(method_name == "finalize")) {
+  if (UNLIKELY(strcmp("finalize", method_name) == 0)) {
     // Set finalizable flag on declaring class.
-    const DexFile::ProtoId& proto = dex_file.GetProtoId(method_id.proto_idx_);
-    if (dex_file.GetProtoParameters(proto) == NULL) {  // No arguments
-      const DexFile::TypeId& return_type = dex_file.GetTypeId(proto.return_type_idx_);
-      if (dex_file.StringDataAsStringPieceByIdx(return_type.descriptor_idx_) == "V") {
-        // Void return type.
-        if (klass->GetClassLoader() != NULL) {  // All non-boot finalizer methods are flagged
+    if (strcmp("V", dex_file.GetShorty(method_id.proto_idx_)) == 0) {
+      // Void return type.
+      if (klass->GetClassLoader() != NULL) {  // All non-boot finalizer methods are flagged
+        klass->SetFinalizable();
+      } else {
+        ClassHelper kh(klass.get());
+        const char* klass_descriptor = kh.GetDescriptor();
+        // The Enum class declares a "final" finalize() method to prevent subclasses from
+        // introducing a finalizer. We don't want to set the finalizable flag for Enum or its
+        // subclasses, so we exclude it here.
+        // We also want to avoid setting the flag on Object, where we know that finalize() is
+        // empty.
+        if ((strcmp("Ljava/lang/Object;", klass_descriptor) != 0) &&
+            (strcmp("Ljava/lang/Enum;", klass_descriptor) != 0)) {
           klass->SetFinalizable();
-        } else {
-          ClassHelper kh(klass.get());
-          StringPiece klass_descriptor(kh.GetDescriptorAsStringPiece());
-          // The Enum class declares a "final" finalize() method to prevent subclasses from
-          // introducing a finalizer. We don't want to set the finalizable flag for Enum or its
-          // subclasses, so we exclude it here.
-          // We also want to avoid setting the flag on Object, where we know that finalize() is
-          // empty.
-          if (klass_descriptor != "Ljava/lang/Object;" &&
-              klass_descriptor != "Ljava/lang/Enum;") {
-            klass->SetFinalizable();
-          }
         }
       }
     }
   } else if (method_name[0] == '<') {
     // Fix broken access flags for initializers. Bug 11157540.
-    bool is_init = (method_name == "<init>");
-    bool is_clinit = !is_init && (method_name == "<clinit>");
+    bool is_init = (strcmp("<init>", method_name) == 0);
+    bool is_clinit = !is_init && (strcmp("<clinit>", method_name) == 0);
     if (UNLIKELY(!is_init && !is_clinit)) {
       LOG(WARNING) << "Unexpected '<' at start of method name " << method_name;
     } else {
@@ -2265,7 +2261,8 @@
        ++it) {
     mirror::Class* klass = it->second;
     kh.ChangeClass(klass);
-    if (kh.GetDescriptorAsStringPiece() == descriptor && klass->GetClassLoader() == class_loader) {
+    if ((klass->GetClassLoader() == class_loader) &&
+        (strcmp(descriptor, kh.GetDescriptor()) == 0)) {
       class_table_.erase(it);
       return true;
     }
@@ -2311,14 +2308,15 @@
   for (auto it = class_table_.lower_bound(hash); it != end && it->first == hash; ++it) {
     mirror::Class* klass = it->second;
     kh.ChangeClass(klass);
-    if (klass->GetClassLoader() == class_loader && kh.GetDescriptorAsStringPiece() == descriptor) {
+    if ((klass->GetClassLoader() == class_loader) &&
+        (strcmp(descriptor, kh.GetDescriptor()) == 0)) {
       if (kIsDebugBuild) {
         // Check for duplicates in the table.
         for (++it; it != end && it->first == hash; ++it) {
           mirror::Class* klass2 = it->second;
           kh.ChangeClass(klass2);
-          CHECK(!(kh.GetDescriptorAsStringPiece() == descriptor &&
-                  klass2->GetClassLoader() == class_loader))
+          CHECK(!((klass2->GetClassLoader() == class_loader) &&
+                  (strcmp(descriptor, kh.GetDescriptor()) == 0)))
               << PrettyClass(klass) << " " << klass << " " << klass->GetClassLoader() << " "
               << PrettyClass(klass2) << " " << klass2 << " " << klass2->GetClassLoader();
         }
@@ -2426,7 +2424,7 @@
       it != end && it->first == hash; ++it) {
     mirror::Class* klass = it->second;
     kh.ChangeClass(klass);
-    if (kh.GetDescriptorAsStringPiece() == descriptor) {
+    if (strcmp(descriptor, kh.GetDescriptor()) == 0) {
       result.push_back(klass);
     }
   }
@@ -3885,7 +3883,7 @@
 
   // We lie to the GC about the java.lang.ref.Reference.referent field, so it doesn't scan it.
   if (!is_static &&
-      (ClassHelper(klass.get(), this).GetDescriptorAsStringPiece() == "Ljava/lang/ref/Reference;")) {
+      (strcmp("Ljava/lang/ref/Reference;", ClassHelper(klass.get(), this).GetDescriptor()) == 0)) {
     // We know there are no non-reference fields in the Reference classes, and we know
     // that 'referent' is alphabetically last, so this is easy...
     CHECK_EQ(num_reference_fields, num_fields);
@@ -3910,8 +3908,8 @@
       fh.ChangeField(field);
       Primitive::Type type = fh.GetTypeAsPrimitiveType();
       bool is_primitive = type != Primitive::kPrimNot;
-      if (ClassHelper(klass.get(), this).GetDescriptorAsStringPiece() == "Ljava/lang/ref/Reference;" &&
-          fh.GetNameAsStringPiece() == "referent") {
+      if ((strcmp("Ljava/lang/ref/Reference;", ClassHelper(klass.get(), this).GetDescriptor()) == 0)
+          && (strcmp("referent", fh.GetName()) == 0)) {
         is_primitive = true;  // We lied above, so we have to expect a lie here.
       }
       if (is_primitive) {
@@ -4006,9 +4004,8 @@
   if (resolved != NULL) {
     return resolved;
   }
-  const DexFile::StringId& string_id = dex_file.GetStringId(string_idx);
-  int32_t utf16_length = dex_file.GetStringLength(string_id);
-  const char* utf8_data = dex_file.GetStringData(string_id);
+  uint32_t utf16_length;
+  const char* utf8_data = dex_file.StringDataAndUtf16LengthByIdx(string_idx, &utf16_length);
   mirror::String* string = intern_table_->InternStrong(utf16_length, utf8_data);
   dex_cache->SetResolvedString(string_idx, string);
   return string;
@@ -4249,8 +4246,8 @@
     return NULL;
   }
 
-  StringPiece name(dex_file.StringDataAsStringPieceByIdx(field_id.name_idx_));
-  StringPiece type(dex_file.StringDataAsStringPieceByIdx(
+  StringPiece name(dex_file.StringDataByIdx(field_id.name_idx_));
+  StringPiece type(dex_file.StringDataByIdx(
       dex_file.GetTypeId(field_id.type_idx_).descriptor_idx_));
   resolved = klass->FindField(name, type);
   if (resolved != NULL) {
diff --git a/runtime/debugger.cc b/runtime/debugger.cc
index 57bd57e..4b30a15 100644
--- a/runtime/debugger.cc
+++ b/runtime/debugger.cc
@@ -891,7 +891,7 @@
   }
 
   if (pDescriptor != NULL) {
-    *pDescriptor = ClassHelper(c).GetDescriptorAsStringPiece().as_string();
+    *pDescriptor = ClassHelper(c).GetDescriptor();
   }
   return JDWP::ERR_NONE;
 }
@@ -934,7 +934,7 @@
   if (c == NULL) {
     return status;
   }
-  *signature = ClassHelper(c).GetDescriptorAsStringPiece().as_string();
+  *signature = ClassHelper(c).GetDescriptor();
   return JDWP::ERR_NONE;
 }
 
@@ -2289,7 +2289,7 @@
   int state = JDWP::CS_VERIFIED | JDWP::CS_PREPARED;
   JDWP::JdwpTypeTag tag = c->IsInterface() ? JDWP::TT_INTERFACE : JDWP::TT_CLASS;
   gJdwpState->PostClassPrepare(tag, gRegistry->Add(c),
-                               ClassHelper(c).GetDescriptorAsStringPiece().as_string(), state);
+                               ClassHelper(c).GetDescriptor(), state);
 }
 
 void Dbg::UpdateDebugger(Thread* thread, mirror::Object* this_object,
diff --git a/runtime/dex_file-inl.h b/runtime/dex_file-inl.h
index c57a1e7..3b2135c 100644
--- a/runtime/dex_file-inl.h
+++ b/runtime/dex_file-inl.h
@@ -18,7 +18,6 @@
 #define ART_RUNTIME_DEX_FILE_INL_H_
 
 #include "base/logging.h"
-#include "base/stringpiece.h"
 #include "dex_file.h"
 #include "leb128.h"
 #include "utils.h"
@@ -30,23 +29,14 @@
   return DecodeUnsignedLeb128(&ptr);
 }
 
-inline const char* DexFile::GetStringDataAndLength(const StringId& string_id, uint32_t* length) const {
-  DCHECK(length != NULL) << GetLocation();
+inline const char* DexFile::GetStringDataAndUtf16Length(const StringId& string_id,
+                                                        uint32_t* utf16_length) const {
+  DCHECK(utf16_length != NULL) << GetLocation();
   const byte* ptr = begin_ + string_id.string_data_off_;
-  *length = DecodeUnsignedLeb128(&ptr);
+  *utf16_length = DecodeUnsignedLeb128(&ptr);
   return reinterpret_cast<const char*>(ptr);
 }
 
-inline StringPiece DexFile::StringDataAsStringPieceByIdx(uint32_t idx) const {
-  if (idx == kDexNoIndex) {
-    return StringPiece();
-  }
-  const StringId& string_id = GetStringId(idx);
-  uint32_t length;
-  const char* data = GetStringDataAndLength(string_id, &length);
-  return StringPiece(data, static_cast<int>(length));
-}
-
 inline const Signature DexFile::GetMethodSignature(const MethodId& method_id) const {
   return Signature(this, GetProtoId(method_id.proto_idx_));
 }
@@ -57,6 +47,71 @@
       (RoundUp(reinterpret_cast<uint32_t>(insns_end_), 4)) + offset;
 }
 
+static inline bool DexFileStringEquals(const DexFile* df1, uint32_t sidx1,
+                                       const DexFile* df2, uint32_t sidx2) {
+  uint32_t s1_len;  // Note: utf16 length != mutf8 length.
+  const char* s1_data = df1->StringDataAndUtf16LengthByIdx(sidx1, &s1_len);
+  uint32_t s2_len;
+  const char* s2_data = df2->StringDataAndUtf16LengthByIdx(sidx2, &s2_len);
+  return (s1_len == s2_len) && (strcmp(s1_data, s2_data) == 0);
+}
+
+inline bool Signature::operator==(const Signature& rhs) const {
+  if (dex_file_ == nullptr) {
+    return rhs.dex_file_ == nullptr;
+  }
+  if (rhs.dex_file_ == nullptr) {
+    return false;
+  }
+  if (dex_file_ == rhs.dex_file_) {
+    return proto_id_ == rhs.proto_id_;
+  }
+  uint32_t lhs_shorty_len;  // For a shorty utf16 length == mutf8 length.
+  const char* lhs_shorty_data = dex_file_->StringDataAndUtf16LengthByIdx(proto_id_->shorty_idx_,
+                                                                         &lhs_shorty_len);
+  StringPiece lhs_shorty(lhs_shorty_data, lhs_shorty_len);
+  {
+    uint32_t rhs_shorty_len;
+    const char* rhs_shorty_data =
+        rhs.dex_file_->StringDataAndUtf16LengthByIdx(rhs.proto_id_->shorty_idx_,
+                                                     &rhs_shorty_len);
+    StringPiece rhs_shorty(rhs_shorty_data, rhs_shorty_len);
+    if (lhs_shorty != rhs_shorty) {
+      return false;  // Shorty mismatch.
+    }
+  }
+  if (lhs_shorty[0] == 'L') {
+    const DexFile::TypeId& return_type_id = dex_file_->GetTypeId(proto_id_->return_type_idx_);
+    const DexFile::TypeId& rhs_return_type_id =
+        rhs.dex_file_->GetTypeId(rhs.proto_id_->return_type_idx_);
+    if (!DexFileStringEquals(dex_file_, return_type_id.descriptor_idx_,
+                             rhs.dex_file_, rhs_return_type_id.descriptor_idx_)) {
+      return false;  // Return type mismatch.
+    }
+  }
+  if (lhs_shorty.find('L', 1) != StringPiece::npos) {
+    const DexFile::TypeList* params = dex_file_->GetProtoParameters(*proto_id_);
+    const DexFile::TypeList* rhs_params = rhs.dex_file_->GetProtoParameters(*rhs.proto_id_);
+    // Both lists are empty or have contents, or else shorty is broken.
+    DCHECK_EQ(params == nullptr, rhs_params == nullptr);
+    if (params != nullptr) {
+      uint32_t params_size = params->Size();
+      DCHECK_EQ(params_size, rhs_params->Size());  // Parameter list size must match.
+      for (uint32_t i = 0; i < params_size; ++i) {
+        const DexFile::TypeId& param_id = dex_file_->GetTypeId(params->GetTypeItem(i).type_idx_);
+        const DexFile::TypeId& rhs_param_id =
+            rhs.dex_file_->GetTypeId(rhs_params->GetTypeItem(i).type_idx_);
+        if (!DexFileStringEquals(dex_file_, param_id.descriptor_idx_,
+                                 rhs.dex_file_, rhs_param_id.descriptor_idx_)) {
+          return false;  // Parameter type mismatch.
+        }
+      }
+    }
+  }
+  return true;
+}
+
+
 }  // namespace art
 
 #endif  // ART_RUNTIME_DEX_FILE_INL_H_
diff --git a/runtime/dex_file.cc b/runtime/dex_file.cc
index a0f5601..d3bb483 100644
--- a/runtime/dex_file.cc
+++ b/runtime/dex_file.cc
@@ -459,7 +459,7 @@
     int32_t mid = (hi + lo) / 2;
     uint32_t length;
     const DexFile::StringId& str_id = GetStringId(mid);
-    const char* str = GetStringDataAndLength(str_id, &length);
+    const char* str = GetStringDataAndUtf16Length(str_id, &length);
     int compare = CompareModifiedUtf8ToModifiedUtf8AsUtf16CodePointValues(string, str);
     if (compare > 0) {
       lo = mid + 1;
@@ -479,7 +479,7 @@
     int32_t mid = (hi + lo) / 2;
     uint32_t length;
     const DexFile::StringId& str_id = GetStringId(mid);
-    const char* str = GetStringDataAndLength(str_id, &length);
+    const char* str = GetStringDataAndUtf16Length(str_id, &length);
     int compare = CompareModifiedUtf8ToUtf16AsCodePointValues(str, string);
     if (compare > 0) {
       lo = mid + 1;
diff --git a/runtime/dex_file.h b/runtime/dex_file.h
index 035a691..7901ea7 100644
--- a/runtime/dex_file.h
+++ b/runtime/dex_file.h
@@ -418,29 +418,29 @@
 
   int32_t GetStringLength(const StringId& string_id) const;
 
-  // Returns a pointer to the UTF-8 string data referred to by the given string_id.
-  const char* GetStringDataAndLength(const StringId& string_id, uint32_t* length) const;
+  // Returns a pointer to the UTF-8 string data referred to by the given string_id as well as the
+  // length of the string when decoded as a UTF-16 string. Note the UTF-16 length is not the same
+  // as the string length of the string data.
+  const char* GetStringDataAndUtf16Length(const StringId& string_id, uint32_t* utf16_length) const;
 
   const char* GetStringData(const StringId& string_id) const {
-    uint32_t length;
-    return GetStringDataAndLength(string_id, &length);
+    uint32_t ignored;
+    return GetStringDataAndUtf16Length(string_id, &ignored);
   }
 
-  // return the UTF-8 encoded string with the specified string_id index
-  const char* StringDataAndLengthByIdx(uint32_t idx, uint32_t* unicode_length) const {
+  // Index version of GetStringDataAndUtf16Length.
+  const char* StringDataAndUtf16LengthByIdx(uint32_t idx, uint32_t* utf16_length) const {
     if (idx == kDexNoIndex) {
-      *unicode_length = 0;
+      *utf16_length = 0;
       return NULL;
     }
     const StringId& string_id = GetStringId(idx);
-    return GetStringDataAndLength(string_id, unicode_length);
+    return GetStringDataAndUtf16Length(string_id, utf16_length);
   }
 
-  StringPiece StringDataAsStringPieceByIdx(uint32_t idx) const;
-
   const char* StringDataByIdx(uint32_t idx) const {
     uint32_t unicode_length;
-    return StringDataAndLengthByIdx(idx, &unicode_length);
+    return StringDataAndUtf16LengthByIdx(idx, &unicode_length);
   }
 
   // Looks up a string id for a given modified utf8 string.
@@ -472,7 +472,7 @@
   // Get the descriptor string associated with a given type index.
   const char* StringByTypeIdx(uint32_t idx, uint32_t* unicode_length) const {
     const TypeId& type_id = GetTypeId(idx);
-    return StringDataAndLengthByIdx(type_id.descriptor_idx_, unicode_length);
+    return StringDataAndUtf16LengthByIdx(type_id.descriptor_idx_, unicode_length);
   }
 
   const char* StringByTypeIdx(uint32_t idx) const {
@@ -575,7 +575,7 @@
     return StringDataByIdx(GetProtoId(method_id.proto_idx_).shorty_idx_);
   }
   const char* GetMethodShorty(const MethodId& method_id, uint32_t* length) const {
-    return StringDataAndLengthByIdx(GetProtoId(method_id.proto_idx_).shorty_idx_, length);
+    return StringDataAndUtf16LengthByIdx(GetProtoId(method_id.proto_idx_).shorty_idx_, length);
   }
   // Returns the number of class definitions in the .dex file.
   size_t NumClassDefs() const {
@@ -952,51 +952,7 @@
     return Signature();
   }
 
-  bool operator==(const Signature& rhs) const {
-    if (dex_file_ == nullptr) {
-      return rhs.dex_file_ == nullptr;
-    }
-    if (rhs.dex_file_ == nullptr) {
-      return false;
-    }
-    if (dex_file_ == rhs.dex_file_) {
-      return proto_id_ == rhs.proto_id_;
-    }
-    StringPiece shorty(dex_file_->StringDataAsStringPieceByIdx(proto_id_->shorty_idx_));
-    if (shorty != rhs.dex_file_->StringDataAsStringPieceByIdx(rhs.proto_id_->shorty_idx_)) {
-      return false;  // Shorty mismatch.
-    }
-    if (shorty[0] == 'L') {
-      const DexFile::TypeId& return_type_id = dex_file_->GetTypeId(proto_id_->return_type_idx_);
-      const DexFile::TypeId& rhs_return_type_id =
-          rhs.dex_file_->GetTypeId(rhs.proto_id_->return_type_idx_);
-      if (dex_file_->StringDataAsStringPieceByIdx(return_type_id.descriptor_idx_) !=
-          rhs.dex_file_->StringDataAsStringPieceByIdx(rhs_return_type_id.descriptor_idx_)) {
-        return false;  // Return type mismatch.
-      }
-    }
-    if (shorty.find('L', 1) != StringPiece::npos) {
-      const DexFile::TypeList* params = dex_file_->GetProtoParameters(*proto_id_);
-      const DexFile::TypeList* rhs_params = rhs.dex_file_->GetProtoParameters(*rhs.proto_id_);
-      // Both lists are empty or have contents, or else shorty is broken.
-      DCHECK_EQ(params == nullptr, rhs_params == nullptr);
-      if (params != nullptr) {
-        uint32_t params_size = params->Size();
-        DCHECK_EQ(params_size, rhs_params->Size());  // Parameter list size must match.
-        for (uint32_t i = 0; i < params_size; ++i) {
-          const DexFile::TypeId& param_id = dex_file_->GetTypeId(params->GetTypeItem(i).type_idx_);
-          const DexFile::TypeId& rhs_param_id =
-              rhs.dex_file_->GetTypeId(rhs_params->GetTypeItem(i).type_idx_);
-          if (dex_file_->StringDataAsStringPieceByIdx(param_id.descriptor_idx_) !=
-              rhs.dex_file_->StringDataAsStringPieceByIdx(rhs_param_id.descriptor_idx_)) {
-            return false;  // Parameter type mismatch.
-          }
-        }
-      }
-    }
-    return true;
-  }
-
+  bool operator==(const Signature& rhs) const;
   bool operator!=(const Signature& rhs) const {
     return !(*this == rhs);
   }
diff --git a/runtime/gc/heap-inl.h b/runtime/gc/heap-inl.h
index b7ef77c..873eadc 100644
--- a/runtime/gc/heap-inl.h
+++ b/runtime/gc/heap-inl.h
@@ -127,7 +127,7 @@
 inline void Heap::DebugCheckPreconditionsForAllobObject(mirror::Class* c, size_t byte_count) {
   DCHECK(c == NULL || (c->IsClassClass() && byte_count >= sizeof(mirror::Class)) ||
          (c->IsVariableSize() || c->GetObjectSize() == byte_count) ||
-         ClassHelper(c).GetDescriptorAsStringPiece().length() == 0);
+         strlen(ClassHelper(c).GetDescriptor()) == 0);
   DCHECK_GE(byte_count, sizeof(mirror::Object));
 }
 
diff --git a/runtime/mirror/class.cc b/runtime/mirror/class.cc
index 319ca4a..f3cb54a 100644
--- a/runtime/mirror/class.cc
+++ b/runtime/mirror/class.cc
@@ -135,7 +135,7 @@
   if (name != NULL) {
     return name;
   }
-  std::string descriptor(ClassHelper(this).GetDescriptorAsStringPiece().as_string());
+  std::string descriptor(ClassHelper(this).GetDescriptor());
   if ((descriptor[0] != 'L') && (descriptor[0] != '[')) {
     // The descriptor indicates that this is the class for
     // a primitive type; special-case the return value.
@@ -294,8 +294,8 @@
     return true;
   }
   // Compare the package part of the descriptor string.
-  return IsInSamePackage(ClassHelper(klass1).GetDescriptorAsStringPiece(),
-                         ClassHelper(klass2).GetDescriptorAsStringPiece());
+  return IsInSamePackage(ClassHelper(klass1).GetDescriptor(),
+                         ClassHelper(klass2).GetDescriptor());
 }
 
 bool Class::IsClassClass() const {
@@ -366,7 +366,7 @@
   for (size_t i = 0; i < NumDirectMethods(); ++i) {
     ArtMethod* method = GetDirectMethod(i);
     mh.ChangeMethod(method);
-    if (name == mh.GetNameAsStringPiece() && mh.GetSignature() == signature) {
+    if (name == mh.GetName() && mh.GetSignature() == signature) {
       return method;
     }
   }
@@ -378,7 +378,7 @@
   for (size_t i = 0; i < NumDirectMethods(); ++i) {
     ArtMethod* method = GetDirectMethod(i);
     mh.ChangeMethod(method);
-    if (name == mh.GetNameAsStringPiece() && signature == mh.GetSignature()) {
+    if (name == mh.GetName() && signature == mh.GetSignature()) {
       return method;
     }
   }
@@ -432,7 +432,7 @@
   for (size_t i = 0; i < NumVirtualMethods(); ++i) {
     ArtMethod* method = GetVirtualMethod(i);
     mh.ChangeMethod(method);
-    if (name == mh.GetNameAsStringPiece() && mh.GetSignature() == signature) {
+    if (name == mh.GetName() && mh.GetSignature() == signature) {
       return method;
     }
   }
@@ -445,7 +445,7 @@
   for (size_t i = 0; i < NumVirtualMethods(); ++i) {
     ArtMethod* method = GetVirtualMethod(i);
     mh.ChangeMethod(method);
-    if (name == mh.GetNameAsStringPiece() && signature == mh.GetSignature()) {
+    if (name == mh.GetName() && signature == mh.GetSignature()) {
       return method;
     }
   }
@@ -517,7 +517,7 @@
   for (size_t i = 0; i < NumInstanceFields(); ++i) {
     ArtField* f = GetInstanceField(i);
     fh.ChangeField(f);
-    if (name == fh.GetNameAsStringPiece() && type == fh.GetTypeDescriptorAsStringPiece()) {
+    if (name == fh.GetName() && type == fh.GetTypeDescriptor()) {
       return f;
     }
   }
@@ -566,7 +566,7 @@
   for (size_t i = 0; i < NumStaticFields(); ++i) {
     ArtField* f = GetStaticField(i);
     fh.ChangeField(f);
-    if (name == fh.GetNameAsStringPiece() && type == fh.GetTypeDescriptorAsStringPiece()) {
+    if (name == fh.GetName() && type == fh.GetTypeDescriptor()) {
       return f;
     }
   }
diff --git a/runtime/native/dalvik_system_VMRuntime.cc b/runtime/native/dalvik_system_VMRuntime.cc
index 4629dbd..71ed95c 100644
--- a/runtime/native/dalvik_system_VMRuntime.cc
+++ b/runtime/native/dalvik_system_VMRuntime.cc
@@ -222,7 +222,7 @@
   }
   const DexFile* dex_file = dex_cache->GetDexFile();
   uint32_t utf16Size;
-  const char* utf8 = dex_file->StringDataAndLengthByIdx(string_idx, &utf16Size);
+  const char* utf8 = dex_file->StringDataAndUtf16LengthByIdx(string_idx, &utf16Size);
   string = strings[utf8];
   if (string == NULL) {
     return;
diff --git a/runtime/object_utils.h b/runtime/object_utils.h
index 3ca3c0b..b0a4ce5 100644
--- a/runtime/object_utils.h
+++ b/runtime/object_utils.h
@@ -112,17 +112,6 @@
     }
   }
 
-  StringPiece GetDescriptorAsStringPiece() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
-    CHECK(klass_ != NULL);
-    if (UNLIKELY(klass_->IsArrayClass() || klass_->IsPrimitive() || klass_->IsProxyClass())) {
-      return StringPiece(GetDescriptor());
-    } else {
-      const DexFile& dex_file = GetDexFile();
-      const DexFile::TypeId& type_id = dex_file.GetTypeId(GetClassDef()->class_idx_);
-      return dex_file.StringDataAsStringPieceByIdx(type_id.descriptor_idx_);
-    }
-  }
-
   const char* GetArrayDescriptor() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
     std::string result("[");
     const mirror::Class* saved_klass = klass_;
@@ -194,7 +183,7 @@
   }
 
   const char* GetSourceFile() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
-    std::string descriptor(GetDescriptorAsStringPiece().as_string());
+    std::string descriptor(GetDescriptor());
     const DexFile& dex_file = GetDexFile();
     const DexFile::ClassDef* dex_class_def = GetClassDef();
     CHECK(dex_class_def != NULL);
@@ -291,16 +280,6 @@
     return dex_file.GetFieldName(dex_file.GetFieldId(field_index));
   }
 
-  StringPiece GetNameAsStringPiece() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
-    uint32_t field_index = field_->GetDexFieldIndex();
-    if (UNLIKELY(field_->GetDeclaringClass()->IsProxyClass())) {
-      return StringPiece(GetName());
-    }
-    const DexFile& dex_file = GetDexFile();
-    const DexFile::FieldId& field_id = dex_file.GetFieldId(field_index);
-    return dex_file.StringDataAsStringPieceByIdx(field_id.name_idx_);
-  }
-
   mirror::Class* GetType(bool resolve = true) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
     uint32_t field_index = field_->GetDexFieldIndex();
     if (UNLIKELY(field_->GetDeclaringClass()->IsProxyClass())) {
@@ -329,17 +308,6 @@
     return dex_file.GetFieldTypeDescriptor(field_id);
   }
 
-  StringPiece GetTypeDescriptorAsStringPiece() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
-    uint32_t field_index = field_->GetDexFieldIndex();
-    if (UNLIKELY(field_->GetDeclaringClass()->IsProxyClass())) {
-      return StringPiece(GetTypeDescriptor());
-    }
-    const DexFile& dex_file = GetDexFile();
-    const DexFile::FieldId& field_id = dex_file.GetFieldId(field_index);
-    const DexFile::TypeId& type_id = dex_file.GetTypeId(field_id.type_idx_);
-    return dex_file.StringDataAsStringPieceByIdx(type_id.descriptor_idx_);
-  }
-
   Primitive::Type GetTypeAsPrimitiveType()
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
     return Primitive::GetType(GetTypeDescriptor()[0]);
@@ -365,7 +333,7 @@
       DCHECK_LT(field_index, 2U);
       // 0 == Class[] interfaces; 1 == Class[][] throws;
       ClassHelper kh(field_->GetDeclaringClass());
-      declaring_class_descriptor_ = kh.GetDescriptorAsStringPiece().as_string();
+      declaring_class_descriptor_ = kh.GetDescriptor();
       return declaring_class_descriptor_.c_str();
     }
     const DexFile& dex_file = GetDexFile();
@@ -470,16 +438,6 @@
     }
   }
 
-  StringPiece GetNameAsStringPiece() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
-    const DexFile& dex_file = GetDexFile();
-    uint32_t dex_method_idx = method_->GetDexMethodIndex();
-    if (UNLIKELY(dex_method_idx == DexFile::kDexNoIndex)) {
-      return StringPiece(GetName());
-    }
-    const DexFile::MethodId& method_id = dex_file.GetMethodId(dex_method_idx);
-    return dex_file.StringDataAsStringPieceByIdx(method_id.name_idx_);
-  }
-
   mirror::String* GetNameAsString() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
     const DexFile& dex_file = GetDexFile();
     uint32_t dex_method_idx = method_->GetDexMethodIndex();
@@ -559,18 +517,6 @@
     return dex_file.GetMethodDeclaringClassDescriptor(dex_file.GetMethodId(dex_method_idx));
   }
 
-  StringPiece GetDeclaringClassDescriptorAsStringPiece()
-      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
-    const DexFile& dex_file = GetDexFile();
-    uint32_t dex_method_idx = method_->GetDexMethodIndex();
-    if (UNLIKELY(dex_method_idx == DexFile::kDexNoIndex)) {
-      return StringPiece("<runtime method>");
-    }
-    const DexFile::MethodId& mid = dex_file.GetMethodId(dex_method_idx);
-    const DexFile::TypeId& type_id = dex_file.GetTypeId(mid.class_idx_);
-    return dex_file.StringDataAsStringPieceByIdx(type_id.descriptor_idx_);
-  }
-
   const char* GetDeclaringClassSourceFile() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
     return ClassHelper(method_->GetDeclaringClass()).GetSourceFile();
   }
@@ -635,8 +581,8 @@
     const DexFile& other_dex_file = other->GetDexFile();
     const DexFile::MethodId& other_mid =
         other_dex_file.GetMethodId(other->method_->GetDexMethodIndex());
-    if (dex_file.StringDataAsStringPieceByIdx(mid.name_idx_) !=
-        other_dex_file.StringDataAsStringPieceByIdx(other_mid.name_idx_)) {
+    if (!DexFileStringEquals(&dex_file, mid.name_idx_,
+                             &other_dex_file, other_mid.name_idx_)) {
       return false;  // Name mismatch.
     }
     return dex_file.GetMethodSignature(mid) == other_dex_file.GetMethodSignature(other_mid);
diff --git a/runtime/reflection.cc b/runtime/reflection.cc
index 4ff7349..80e16aa 100644
--- a/runtime/reflection.cc
+++ b/runtime/reflection.cc
@@ -323,7 +323,7 @@
   }
 
   JValue boxed_value;
-  const StringPiece src_descriptor(ClassHelper(o->GetClass()).GetDescriptorAsStringPiece());
+  const StringPiece src_descriptor(ClassHelper(o->GetClass()).GetDescriptor());
   mirror::Class* src_class = NULL;
   ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
   mirror::ArtField* primitive_field = o->GetClass()->GetIFields()->Get(0);
diff --git a/runtime/verifier/method_verifier.cc b/runtime/verifier/method_verifier.cc
index 7d2ee19..563c8438 100644
--- a/runtime/verifier/method_verifier.cc
+++ b/runtime/verifier/method_verifier.cc
@@ -90,7 +90,7 @@
     return kNoFailure;
   }
   mirror::Class* super = klass->GetSuperClass();
-  if (super == NULL && ClassHelper(klass).GetDescriptorAsStringPiece() != "Ljava/lang/Object;") {
+  if (super == NULL && strcmp("Ljava/lang/Object;", ClassHelper(klass).GetDescriptor()) != 0) {
     *error = "Verifier rejected class ";
     *error += PrettyDescriptor(klass);
     *error += " that has no super class";
@@ -2188,7 +2188,7 @@
       if (called_method == NULL) {
         uint32_t method_idx = (is_range) ? inst->VRegB_3rc() : inst->VRegB_35c();
         const DexFile::MethodId& method_id = dex_file_->GetMethodId(method_idx);
-        is_constructor = dex_file_->StringDataAsStringPieceByIdx(method_id.name_idx_) == "<init>";
+        is_constructor = strcmp("<init>", dex_file_->StringDataByIdx(method_id.name_idx_)) == 0;
         uint32_t return_type_idx = dex_file_->GetProtoId(method_id.proto_idx_).return_type_idx_;
         return_type_descriptor =  dex_file_->StringByTypeIdx(return_type_idx);
       } else {