Merge "Refactor and improve mod-union tables." into dalvik-dev
diff --git a/compiler/dex/quick/gen_invoke.cc b/compiler/dex/quick/gen_invoke.cc
index 72ae91e..ed83863 100644
--- a/compiler/dex/quick/gen_invoke.cc
+++ b/compiler/dex/quick/gen_invoke.cc
@@ -1219,8 +1219,10 @@
    * method.  By doing this during basic block construction, we can also
    * take advantage of/generate new useful dataflow info.
    */
+  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->GetMethodDeclaringClassDescriptor(cu_->dex_file->GetMethodId(info->index)));
+      cu_->dex_file->StringDataAsStringPieceByIdx(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 658370f..e227715 100644
--- a/compiler/driver/compiler_driver.cc
+++ b/compiler/driver/compiler_driver.cc
@@ -600,12 +600,11 @@
   UpdateImageClasses(timings);
 }
 
-bool CompilerDriver::IsImageClass(const char* descriptor) const {
-  DCHECK(descriptor != NULL);
+bool CompilerDriver::IsImageClass(const StringPiece& descriptor) const {
   if (!IsImage()) {
     return true;
   } else {
-    return image_classes_->find(descriptor) != image_classes_->end();
+    return image_classes_->find(descriptor.data()) != image_classes_->end();
   }
 }
 
@@ -780,7 +779,8 @@
 
 bool CompilerDriver::CanAssumeTypeIsPresentInDexCache(const DexFile& dex_file,
                                                       uint32_t type_idx) {
-  if (IsImage() && IsImageClass(dex_file.GetTypeDescriptor(dex_file.GetTypeId(type_idx)))) {
+  if (IsImage() &&
+      IsImageClass(dex_file.StringDataAsStringPieceByIdx(dex_file.GetTypeId(type_idx).descriptor_idx_))) {
     if (kIsDebugBuild) {
       ScopedObjectAccess soa(Thread::Current());
       mirror::DexCache* dex_cache = Runtime::Current()->GetClassLinker()->FindDexCache(dex_file);
@@ -1098,7 +1098,7 @@
   if (compiling_boot) {
     if (support_boot_image_fixup_) {
       MethodHelper mh(method);
-      if (IsImageClass(mh.GetDeclaringClassDescriptor())) {
+      if (IsImageClass(mh.GetDeclaringClassDescriptorAsStringPiece())) {
         // We can only branch directly to Methods that are resolved in the DexCache.
         // Otherwise we won't invoke the resolution trampoline.
         *direct_method = -1;
@@ -1474,6 +1474,24 @@
   // generated code.
   const DexFile::ClassDef& class_def = dex_file.GetClassDef(class_def_index);
   if (!SkipClass(class_linker, jclass_loader, dex_file, class_def)) {
+    ScopedObjectAccess soa(self);
+    mirror::ClassLoader* class_loader = soa.Decode<mirror::ClassLoader*>(jclass_loader);
+    mirror::DexCache* dex_cache = class_linker->FindDexCache(dex_file);
+
+    // Resolve the class.
+    mirror::Class* klass = class_linker->ResolveType(dex_file, class_def.class_idx_, dex_cache,
+                                                     class_loader);
+
+    bool resolve_fields_and_methods;
+    if (klass == NULL) {
+      // Class couldn't be resolved, for example, super-class is in a different dex file. Don't
+      // attempt to resolve methods and fields when there is no declaring class.
+      CHECK(soa.Self()->IsExceptionPending());
+      soa.Self()->ClearException();
+      resolve_fields_and_methods = false;
+    } else {
+      resolve_fields_and_methods = manager->GetCompiler()->IsImage();
+    }
     // Note the class_data pointer advances through the headers,
     // static fields, instance fields, direct methods, and virtual
     // methods.
@@ -1482,24 +1500,6 @@
       // Empty class such as a marker interface.
       requires_constructor_barrier = false;
     } else {
-      ScopedObjectAccess soa(self);
-      mirror::ClassLoader* class_loader = soa.Decode<mirror::ClassLoader*>(jclass_loader);
-      mirror::DexCache* dex_cache = class_linker->FindDexCache(dex_file);
-
-      // Resolve the class.
-      mirror::Class* klass = class_linker->ResolveType(dex_file, class_def.class_idx_, dex_cache,
-                                                       class_loader);
-
-      bool resolve_fields_and_methods;
-      if (klass == NULL) {
-        // Class couldn't be resolved, for example, super-class is in a different dex file. Don't
-        // attempt to resolve methods and fields when there is no declaring class.
-        CHECK(soa.Self()->IsExceptionPending());
-        soa.Self()->ClearException();
-        resolve_fields_and_methods = false;
-      } else {
-        resolve_fields_and_methods = manager->GetCompiler()->IsImage();
-      }
       ClassDataItemIterator it(dex_file, class_data);
       while (it.HasNextStaticField()) {
         if (resolve_fields_and_methods) {
@@ -1572,8 +1572,8 @@
     CHECK(soa.Self()->IsExceptionPending());
     mirror::Throwable* exception = soa.Self()->GetException(NULL);
     VLOG(compiler) << "Exception during type resolution: " << exception->Dump();
-    if (strcmp(ClassHelper(exception->GetClass()).GetDescriptor(),
-               "Ljava/lang/OutOfMemoryError;") == 0) {
+    if (ClassHelper(exception->GetClass()).GetDescriptorAsStringPiece() ==
+        "Ljava/lang/OutOfMemoryError;") {
       // There's little point continuing compilation if the heap is exhausted.
       LOG(FATAL) << "Out of memory during type resolution for compilation";
     }
@@ -2084,11 +2084,14 @@
 static void InitializeClass(const ParallelCompilationManager* manager, size_t class_def_index)
     LOCKS_EXCLUDED(Locks::mutator_lock_) {
   ATRACE_CALL();
-  const DexFile::ClassDef& class_def = manager->GetDexFile()->GetClassDef(class_def_index);
+  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_));
+
   ScopedObjectAccess soa(Thread::Current());
   mirror::ClassLoader* class_loader = soa.Decode<mirror::ClassLoader*>(manager->GetClassLoader());
-  const char* descriptor = manager->GetDexFile()->GetClassDescriptor(class_def);
-  mirror::Class* klass = manager->GetClassLinker()->FindClass(descriptor, class_loader);
+  mirror::Class* klass = manager->GetClassLinker()->FindClass(descriptor.data(), class_loader);
   if (klass != NULL) {
     // Only try to initialize classes that were successfully verified.
     if (klass->IsVerified()) {
@@ -2118,7 +2121,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 (StringPiece(descriptor) == class_initializer_black_list[i]) {
+                if (descriptor == class_initializer_black_list[i]) {
                   is_black_listed = true;
                   break;
                 }
@@ -2126,7 +2129,7 @@
             }
             if (!is_black_listed) {
               VLOG(compiler) << "Initializing: " << descriptor;
-              if (StringPiece(descriptor) == "Ljava/lang/Void;") {
+              if (descriptor == "Ljava/lang/Void;") {
                 // 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 66c9cbf..7657af5 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 char* descriptor) const;
+  bool IsImageClass(const StringPiece& 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 f82c6fb..bcdc1c1 100644
--- a/compiler/image_writer.cc
+++ b/compiler/image_writer.cc
@@ -241,7 +241,7 @@
 }
 
 bool ImageWriter::IsImageClass(const Class* klass) {
-  return compiler_driver_.IsImageClass(ClassHelper(klass).GetDescriptor());
+  return compiler_driver_.IsImageClass(ClassHelper(klass).GetDescriptorAsStringPiece());
 }
 
 struct NonImageClasses {
@@ -296,7 +296,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).GetDescriptor());
+    context->non_image_classes->insert(ClassHelper(klass).GetDescriptorAsStringPiece().as_string());
   }
   return true;
 }
diff --git a/oatdump/oatdump.cc b/oatdump/oatdump.cc
index fc9e00c..cc6b5d7 100644
--- a/oatdump/oatdump.cc
+++ b/oatdump/oatdump.cc
@@ -1119,7 +1119,7 @@
     typedef SafeMap<std::string, SizeAndCount> SizeAndCountTable;
     SizeAndCountTable sizes_and_counts;
 
-    void Update(const std::string& descriptor, size_t object_bytes) {
+    void Update(const char* descriptor, size_t object_bytes) {
       SizeAndCountTable::iterator it = sizes_and_counts.find(descriptor);
       if (it != sizes_and_counts.end()) {
         it->second.bytes += object_bytes;
diff --git a/runtime/class_linker.cc b/runtime/class_linker.cc
index 15eab9d..6aae63e 100644
--- a/runtime/class_linker.cc
+++ b/runtime/class_linker.cc
@@ -1840,7 +1840,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.GetMethodName(method_id));
+  StringPiece method_name(dex_file.StringDataAsStringPieceByIdx(method_id.name_idx_));
 
   mirror::ArtMethod* dst = AllocArtMethod(self);
   if (UNLIKELY(dst == NULL)) {
@@ -1869,7 +1869,7 @@
             klass->SetFinalizable();
           } else {
             ClassHelper kh(klass.get());
-            StringPiece klass_descriptor(kh.GetDescriptor());
+            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.
@@ -2219,7 +2219,7 @@
        ++it) {
     mirror::Class* klass = it->second;
     kh.ChangeClass(klass);
-    if (strcmp(kh.GetDescriptor(), descriptor) == 0 && klass->GetClassLoader() == class_loader) {
+    if (kh.GetDescriptorAsStringPiece() == descriptor && klass->GetClassLoader() == class_loader) {
       class_table_.erase(it);
       return true;
     }
@@ -2265,15 +2265,16 @@
   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 && strcmp(descriptor, kh.GetDescriptor()) == 0) {
+    if (klass->GetClassLoader() == class_loader && kh.GetDescriptorAsStringPiece() == descriptor) {
       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(!(strcmp(descriptor, kh.GetDescriptor()) == 0 && klass2->GetClassLoader() == class_loader))
-          << PrettyClass(klass) << " " << klass << " " << klass->GetClassLoader() << " "
-          << PrettyClass(klass2) << " " << klass2 << " " << klass2->GetClassLoader();
+          CHECK(!(kh.GetDescriptorAsStringPiece() == descriptor &&
+                  klass2->GetClassLoader() == class_loader))
+              << PrettyClass(klass) << " " << klass << " " << klass->GetClassLoader() << " "
+              << PrettyClass(klass2) << " " << klass2 << " " << klass2->GetClassLoader();
         }
       }
       return klass;
@@ -2379,7 +2380,7 @@
       it != end && it->first == hash; ++it) {
     mirror::Class* klass = it->second;
     kh.ChangeClass(klass);
-    if (strcmp(descriptor, kh.GetDescriptor()) == 0) {
+    if (kh.GetDescriptorAsStringPiece() == descriptor) {
       result.push_back(klass);
     }
   }
@@ -2538,11 +2539,11 @@
   CHECK(oat_file != NULL) << dex_file.GetLocation() << " " << PrettyClass(klass);
   const OatFile::OatDexFile* oat_dex_file = oat_file->GetOatDexFile(dex_file.GetLocation());
   CHECK(oat_dex_file != NULL) << dex_file.GetLocation() << " " << PrettyClass(klass);
-  const char* descriptor = ClassHelper(klass).GetDescriptor();
   uint16_t class_def_index = klass->GetDexClassDefIndex();
   UniquePtr<const OatFile::OatClass> oat_class(oat_dex_file->GetOatClass(class_def_index));
   CHECK(oat_class.get() != NULL)
-          << dex_file.GetLocation() << " " << PrettyClass(klass) << " " << descriptor;
+          << dex_file.GetLocation() << " " << PrettyClass(klass) << " "
+          << ClassHelper(klass).GetDescriptor();
   oat_file_class_status = oat_class->GetStatus();
   if (oat_file_class_status == mirror::Class::kStatusVerified ||
       oat_file_class_status == mirror::Class::kStatusInitialized) {
@@ -2581,7 +2582,8 @@
     return false;
   }
   LOG(FATAL) << "Unexpected class status: " << oat_file_class_status
-             << " " << dex_file.GetLocation() << " " << PrettyClass(klass) << " " << descriptor;
+             << " " << dex_file.GetLocation() << " " << PrettyClass(klass) << " "
+             << ClassHelper(klass).GetDescriptor();
 
   return false;
 }
@@ -3727,10 +3729,10 @@
 
     // same basic group? then sort by string.
     fh_->ChangeField(field1);
-    StringPiece name1(fh_->GetName());
+    const char* name1 = fh_->GetName();
     fh_->ChangeField(field2);
-    StringPiece name2(fh_->GetName());
-    return name1 < name2;
+    const char* name2 = fh_->GetName();
+    return strcmp(name1, name2) < 0;
   }
 
   FieldHelper* fh_;
@@ -3764,7 +3766,9 @@
   // minimizes disruption of C++ version such as Class and Method.
   std::deque<mirror::ArtField*> grouped_and_sorted_fields;
   for (size_t i = 0; i < num_fields; i++) {
-    grouped_and_sorted_fields.push_back(fields->Get(i));
+    mirror::ArtField* f = fields->Get(i);
+    CHECK(f != NULL);
+    grouped_and_sorted_fields.push_back(f);
   }
   FieldHelper fh(NULL, this);
   std::sort(grouped_and_sorted_fields.begin(),
@@ -3831,7 +3835,7 @@
 
   // We lie to the GC about the java.lang.ref.Reference.referent field, so it doesn't scan it.
   if (!is_static &&
-      StringPiece(ClassHelper(klass.get(), this).GetDescriptor()) == "Ljava/lang/ref/Reference;") {
+      (ClassHelper(klass.get(), this).GetDescriptorAsStringPiece() == "Ljava/lang/ref/Reference;")) {
     // 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);
@@ -3840,39 +3844,39 @@
     --num_reference_fields;
   }
 
-#ifndef NDEBUG
-  // Make sure that all reference fields appear before
-  // non-reference fields, and all double-wide fields are aligned.
-  bool seen_non_ref = false;
-  for (size_t i = 0; i < num_fields; i++) {
-    mirror::ArtField* field = fields->Get(i);
-    if (false) {  // enable to debug field layout
-      LOG(INFO) << "LinkFields: " << (is_static ? "static" : "instance")
-                << " class=" << PrettyClass(klass.get())
-                << " field=" << PrettyField(field)
-                << " offset=" << field->GetField32(MemberOffset(mirror::ArtField::OffsetOffset()),
-                                                   false);
-    }
-    fh.ChangeField(field);
-    Primitive::Type type = fh.GetTypeAsPrimitiveType();
-    bool is_primitive = type != Primitive::kPrimNot;
-    if (StringPiece(ClassHelper(klass.get(), this).GetDescriptor()) == "Ljava/lang/ref/Reference;" &&
-        StringPiece(fh.GetName()) == "referent") {
-      is_primitive = true;  // We lied above, so we have to expect a lie here.
-    }
-    if (is_primitive) {
-      if (!seen_non_ref) {
-        seen_non_ref = true;
-        DCHECK_EQ(num_reference_fields, i);
+  if (kIsDebugBuild) {
+    // Make sure that all reference fields appear before
+    // non-reference fields, and all double-wide fields are aligned.
+    bool seen_non_ref = false;
+    for (size_t i = 0; i < num_fields; i++) {
+      mirror::ArtField* field = fields->Get(i);
+      if (false) {  // enable to debug field layout
+        LOG(INFO) << "LinkFields: " << (is_static ? "static" : "instance")
+                    << " class=" << PrettyClass(klass.get())
+                    << " field=" << PrettyField(field)
+                    << " offset=" << field->GetField32(MemberOffset(mirror::ArtField::OffsetOffset()),
+                                                       false);
       }
-    } else {
-      DCHECK(!seen_non_ref);
+      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") {
+        is_primitive = true;  // We lied above, so we have to expect a lie here.
+      }
+      if (is_primitive) {
+        if (!seen_non_ref) {
+          seen_non_ref = true;
+          DCHECK_EQ(num_reference_fields, i);
+        }
+      } else {
+        DCHECK(!seen_non_ref);
+      }
+    }
+    if (!seen_non_ref) {
+      DCHECK_EQ(num_fields, num_reference_fields);
     }
   }
-  if (!seen_non_ref) {
-    DCHECK_EQ(num_fields, num_reference_fields);
-  }
-#endif
   size = field_offset.Uint32Value();
   // Update klass
   if (is_static) {
@@ -3982,6 +3986,8 @@
       }
     }
   }
+  DCHECK((resolved == NULL) || resolved->IsResolved() || resolved->IsErroneous())
+          << PrettyDescriptor(resolved) << " " << resolved->GetStatus();
   return resolved;
 }
 
@@ -4173,9 +4179,9 @@
 }
 
 mirror::ArtField* ClassLinker::ResolveFieldJLS(const DexFile& dex_file,
-                                            uint32_t field_idx,
-                                            mirror::DexCache* dex_cache,
-                                            mirror::ClassLoader* class_loader) {
+                                               uint32_t field_idx,
+                                               mirror::DexCache* dex_cache,
+                                               mirror::ClassLoader* class_loader) {
   DCHECK(dex_cache != NULL);
   mirror::ArtField* resolved = dex_cache->GetResolvedField(field_idx);
   if (resolved != NULL) {
@@ -4188,8 +4194,9 @@
     return NULL;
   }
 
-  const char* name = dex_file.GetFieldName(field_id);
-  const char* type = dex_file.GetFieldTypeDescriptor(field_id);
+  StringPiece name(dex_file.StringDataAsStringPieceByIdx(field_id.name_idx_));
+  StringPiece type(dex_file.StringDataAsStringPieceByIdx(
+      dex_file.GetTypeId(field_id.type_idx_).descriptor_idx_));
   resolved = klass->FindField(name, type);
   if (resolved != NULL) {
     dex_cache->SetResolvedField(field_idx, resolved);
diff --git a/runtime/debugger.cc b/runtime/debugger.cc
index 88269e5..2eca734 100644
--- a/runtime/debugger.cc
+++ b/runtime/debugger.cc
@@ -891,7 +891,7 @@
   }
 
   if (pDescriptor != NULL) {
-    *pDescriptor = ClassHelper(c).GetDescriptor();
+    *pDescriptor = ClassHelper(c).GetDescriptorAsStringPiece().as_string();
   }
   return JDWP::ERR_NONE;
 }
@@ -928,13 +928,13 @@
   return JDWP::ERR_NONE;
 }
 
-JDWP::JdwpError Dbg::GetSignature(JDWP::RefTypeId class_id, std::string& signature) {
+JDWP::JdwpError Dbg::GetSignature(JDWP::RefTypeId class_id, std::string* signature) {
   JDWP::JdwpError status;
   mirror::Class* c = DecodeClass(class_id, status);
   if (c == NULL) {
     return status;
   }
-  signature = ClassHelper(c).GetDescriptor();
+  *signature = ClassHelper(c).GetDescriptorAsStringPiece().as_string();
   return JDWP::ERR_NONE;
 }
 
@@ -1065,8 +1065,8 @@
     LOG(WARNING) << __FUNCTION__ << " access out of bounds: offset=" << offset << "; count=" << count;
     return JDWP::ERR_INVALID_LENGTH;
   }
-  std::string descriptor(ClassHelper(dst->GetClass()).GetDescriptor());
-  JDWP::JdwpTag tag = BasicTagFromDescriptor(descriptor.c_str() + 1);
+  const char* descriptor = ClassHelper(dst->GetClass()).GetDescriptor();
+  JDWP::JdwpTag tag = BasicTagFromDescriptor(descriptor + 1);
 
   if (IsPrimitiveTag(tag)) {
     size_t width = GetTagWidth(tag);
@@ -2287,7 +2287,8 @@
   // since the class may not yet be verified.
   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).GetDescriptor(), state);
+  gJdwpState->PostClassPrepare(tag, gRegistry->Add(c),
+                               ClassHelper(c).GetDescriptorAsStringPiece().as_string(), state);
 }
 
 void Dbg::UpdateDebugger(Thread* thread, mirror::Object* this_object,
diff --git a/runtime/debugger.h b/runtime/debugger.h
index d0fe445..8574a33 100644
--- a/runtime/debugger.h
+++ b/runtime/debugger.h
@@ -149,7 +149,7 @@
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
   static JDWP::JdwpError GetReferenceType(JDWP::ObjectId object_id, JDWP::ExpandBuf* pReply)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
-  static JDWP::JdwpError GetSignature(JDWP::RefTypeId ref_type_id, std::string& signature)
+  static JDWP::JdwpError GetSignature(JDWP::RefTypeId ref_type_id, std::string* signature)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
   static JDWP::JdwpError GetSourceFile(JDWP::RefTypeId ref_type_id, std::string& source_file)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
diff --git a/runtime/dex_file-inl.h b/runtime/dex_file-inl.h
index dee8026..2ee9244 100644
--- a/runtime/dex_file-inl.h
+++ b/runtime/dex_file-inl.h
@@ -18,6 +18,7 @@
 #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"
@@ -36,6 +37,16 @@
   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 DexFile::TryItem* DexFile::GetTryItems(const CodeItem& code_item, uint32_t offset) {
   const uint16_t* insns_end_ = &code_item.insns_[code_item.insns_size_in_code_units_];
   return reinterpret_cast<const TryItem*>
diff --git a/runtime/dex_file.h b/runtime/dex_file.h
index 7be5cb8..4534b41 100644
--- a/runtime/dex_file.h
+++ b/runtime/dex_file.h
@@ -40,6 +40,7 @@
   class DexCache;
 }  // namespace mirror
 class ClassLinker;
+class StringPiece;
 class ZipArchive;
 
 // TODO: move all of the macro functionality into the DexCache class.
@@ -432,6 +433,8 @@
     return GetStringDataAndLength(string_id, unicode_length);
   }
 
+  StringPiece StringDataAsStringPieceByIdx(uint32_t idx) const;
+
   const char* StringDataByIdx(uint32_t idx) const {
     uint32_t unicode_length;
     return StringDataAndLengthByIdx(idx, &unicode_length);
diff --git a/runtime/gc/heap.cc b/runtime/gc/heap.cc
index 49a8c3a..cefde04 100644
--- a/runtime/gc/heap.cc
+++ b/runtime/gc/heap.cc
@@ -554,7 +554,7 @@
 mirror::Object* Heap::AllocObject(Thread* self, mirror::Class* c, size_t byte_count) {
   DCHECK(c == NULL || (c->IsClassClass() && byte_count >= sizeof(mirror::Class)) ||
          (c->IsVariableSize() || c->GetObjectSize() == byte_count) ||
-         strlen(ClassHelper(c).GetDescriptor()) == 0);
+         ClassHelper(c).GetDescriptorAsStringPiece().length() == 0);
   DCHECK_GE(byte_count, sizeof(mirror::Object));
 
   mirror::Object* obj = NULL;
diff --git a/runtime/interpreter/interpreter.cc b/runtime/interpreter/interpreter.cc
index f35cfa3..fd92e06 100644
--- a/runtime/interpreter/interpreter.cc
+++ b/runtime/interpreter/interpreter.cc
@@ -82,7 +82,7 @@
   }
 }
 
-static void InterpreterJni(Thread* self, ArtMethod* method, StringPiece shorty,
+static void InterpreterJni(Thread* self, ArtMethod* method, const StringPiece& shorty,
                            Object* receiver, uint32_t* args, JValue* result)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
   // TODO: The following enters JNI code using a typedef-ed function rather than the JNI compiler,
diff --git a/runtime/interpreter/interpreter_common.cc b/runtime/interpreter/interpreter_common.cc
index 86a6aea..36b250c 100644
--- a/runtime/interpreter/interpreter_common.cc
+++ b/runtime/interpreter/interpreter_common.cc
@@ -22,6 +22,7 @@
 template<InvokeType type, bool is_range, bool do_access_check>
 bool DoInvoke(Thread* self, ShadowFrame& shadow_frame,
               const Instruction* inst, JValue* result) {
+  bool do_assignability_check = do_access_check;
   uint32_t method_idx = (is_range) ? inst->VRegB_3rc() : inst->VRegB_35c();
   uint32_t vregC = (is_range) ? inst->VRegC_3rc() : inst->VRegC_35c();
   Object* receiver = (type == kStatic) ? NULL : shadow_frame.GetVRegReference(vregC);
@@ -61,6 +62,10 @@
     ++cur_reg;
   }
 
+  const DexFile::TypeList* params;
+  if (do_assignability_check) {
+    params = mh.GetParameterTypeList();
+  }
   size_t arg_offset = (receiver == NULL) ? 0 : 1;
   const char* shorty = mh.GetShorty();
   uint32_t arg[5];
@@ -73,6 +78,23 @@
     switch (shorty[shorty_pos + 1]) {
       case 'L': {
         Object* o = shadow_frame.GetVRegReference(arg_pos);
+        if (do_assignability_check && o != NULL) {
+          Class* arg_type = mh.GetClassFromTypeIdx(params->GetTypeItem(shorty_pos).type_idx_);
+          if (arg_type == NULL) {
+            CHECK(self->IsExceptionPending());
+            return false;
+          }
+          if (!o->VerifierInstanceOf(arg_type)) {
+            // This should never happen.
+            self->ThrowNewExceptionF(self->GetCurrentLocationForThrow(),
+                                     "Ljava/lang/VirtualMachineError;",
+                                     "Invoking %s with bad arg %d, type '%s' not instance of '%s'",
+                                     mh.GetName(), shorty_pos,
+                                     ClassHelper(o->GetClass()).GetDescriptor(),
+                                     ClassHelper(arg_type).GetDescriptor());
+            return false;
+          }
+        }
         new_shadow_frame->SetVRegReference(cur_reg, o);
         break;
       }
diff --git a/runtime/interpreter/interpreter_common.h b/runtime/interpreter/interpreter_common.h
index a6c5e62..3ad1935 100644
--- a/runtime/interpreter/interpreter_common.h
+++ b/runtime/interpreter/interpreter_common.h
@@ -215,6 +215,7 @@
 template<FindFieldType find_type, Primitive::Type field_type, bool do_access_check>
 static inline bool DoFieldPut(Thread* self, const ShadowFrame& shadow_frame,
                               const Instruction* inst, uint16_t inst_data) {
+  bool do_assignability_check = do_access_check;
   bool is_static = (find_type == StaticObjectWrite) || (find_type == StaticPrimitiveWrite);
   uint32_t field_idx = is_static ? inst->VRegB_21c() : inst->VRegC_22c();
   ArtField* f = FindFieldFromCode(field_idx, shadow_frame.GetMethod(), self,
@@ -255,9 +256,24 @@
     case Primitive::kPrimLong:
       f->SetLong(obj, shadow_frame.GetVRegLong(vregA));
       break;
-    case Primitive::kPrimNot:
-      f->SetObj(obj, shadow_frame.GetVRegReference(vregA));
+    case Primitive::kPrimNot: {
+      Object* reg = shadow_frame.GetVRegReference(vregA);
+      if (do_assignability_check && reg != NULL) {
+        Class* field_class = FieldHelper(f).GetType();
+        if (!reg->VerifierInstanceOf(field_class)) {
+          // This should never happen.
+          self->ThrowNewExceptionF(self->GetCurrentLocationForThrow(),
+                                   "Ljava/lang/VirtualMachineError;",
+                                   "Put '%s' that is not instance of field '%s' in '%s'",
+                                   ClassHelper(reg->GetClass()).GetDescriptor(),
+                                   ClassHelper(field_class).GetDescriptor(),
+                                   ClassHelper(f->GetDeclaringClass()).GetDescriptor());
+          return false;
+        }
+      }
+      f->SetObj(obj, reg);
       break;
+    }
     default:
       LOG(FATAL) << "Unreachable: " << field_type;
   }
@@ -479,7 +495,8 @@
 }
 
 static inline void TraceExecution(const ShadowFrame& shadow_frame, const Instruction* inst,
-                                  const uint32_t dex_pc, MethodHelper& mh) {
+                                  const uint32_t dex_pc, MethodHelper& mh)
+    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
   const bool kTracing = false;
   if (kTracing) {
 #define TRACE_LOG std::cerr
diff --git a/runtime/interpreter/interpreter_goto_table_impl.cc b/runtime/interpreter/interpreter_goto_table_impl.cc
index d70b80e..018add3 100644
--- a/runtime/interpreter/interpreter_goto_table_impl.cc
+++ b/runtime/interpreter/interpreter_goto_table_impl.cc
@@ -74,6 +74,7 @@
 template<bool do_access_check>
 JValue ExecuteGotoImpl(Thread* self, MethodHelper& mh, const DexFile::CodeItem* code_item,
                        ShadowFrame& shadow_frame, JValue result_register) {
+  bool do_assignability_check = do_access_check;
   if (UNLIKELY(!shadow_frame.HasReferenceArray())) {
     LOG(FATAL) << "Invalid shadow frame for interpreter use";
     return JValue();
@@ -264,11 +265,28 @@
 
   HANDLE_INSTRUCTION_START(RETURN_OBJECT) {
     JValue result;
+    Object* obj_result = shadow_frame.GetVRegReference(inst->VRegA_11x(inst_data));
     result.SetJ(0);
-    result.SetL(shadow_frame.GetVRegReference(inst->VRegA_11x(inst_data)));
+    result.SetL(obj_result);
     if (UNLIKELY(self->TestAllFlags())) {
       CheckSuspend(self);
     }
+    if (do_assignability_check && obj_result != NULL) {
+      Class* return_type = MethodHelper(shadow_frame.GetMethod()).GetReturnType();
+      if (return_type == NULL) {
+        // Return the pending exception.
+        HANDLE_PENDING_EXCEPTION();
+      }
+      if (!obj_result->VerifierInstanceOf(return_type)) {
+        // This should never happen.
+        self->ThrowNewExceptionF(self->GetCurrentLocationForThrow(),
+                                 "Ljava/lang/VirtualMachineError;",
+                                 "Returning '%s' that is not instance of return type '%s'",
+                                 ClassHelper(obj_result->GetClass()).GetDescriptor(),
+                                 ClassHelper(return_type).GetDescriptor());
+        HANDLE_PENDING_EXCEPTION();
+      }
+    }
     if (UNLIKELY(instrumentation->HasMethodExitListeners())) {
       instrumentation->MethodExitEvent(self, shadow_frame.GetThisObject(code_item->ins_size_),
                                        shadow_frame.GetMethod(), dex_pc,
@@ -512,6 +530,12 @@
     Object* exception = shadow_frame.GetVRegReference(inst->VRegA_11x(inst_data));
     if (UNLIKELY(exception == NULL)) {
       ThrowNullPointerException(NULL, "throw with null exception");
+    } else if (do_assignability_check && !exception->GetClass()->IsThrowableClass()) {
+      // This should never happen.
+      self->ThrowNewExceptionF(self->GetCurrentLocationForThrow(),
+                               "Ljava/lang/VirtualMachineError;",
+                               "Throwing '%s' that is not instance of Throwable",
+                               ClassHelper(exception->GetClass()).GetDescriptor());
     } else {
       self->SetException(shadow_frame.GetCurrentLocationForThrow(), exception->AsThrowable());
     }
diff --git a/runtime/interpreter/interpreter_switch_impl.cc b/runtime/interpreter/interpreter_switch_impl.cc
index d49807c..2d658b3 100644
--- a/runtime/interpreter/interpreter_switch_impl.cc
+++ b/runtime/interpreter/interpreter_switch_impl.cc
@@ -53,6 +53,7 @@
 template<bool do_access_check>
 static JValue ExecuteSwitchImpl(Thread* self, MethodHelper& mh, const DexFile::CodeItem* code_item,
                                 ShadowFrame& shadow_frame, JValue result_register) {
+  bool do_assignability_check = do_access_check;
   if (UNLIKELY(!shadow_frame.HasReferenceArray())) {
     LOG(FATAL) << "Invalid shadow frame for interpreter use";
     return JValue();
@@ -226,11 +227,28 @@
       case Instruction::RETURN_OBJECT: {
         PREAMBLE();
         JValue result;
+        Object* obj_result = shadow_frame.GetVRegReference(inst->VRegA_11x(inst_data));
         result.SetJ(0);
-        result.SetL(shadow_frame.GetVRegReference(inst->VRegA_11x(inst_data)));
+        result.SetL(obj_result);
         if (UNLIKELY(self->TestAllFlags())) {
           CheckSuspend(self);
         }
+        if (do_assignability_check && obj_result != NULL) {
+          Class* return_type = MethodHelper(shadow_frame.GetMethod()).GetReturnType();
+          if (return_type == NULL) {
+            // Return the pending exception.
+            HANDLE_PENDING_EXCEPTION();
+          }
+          if (!obj_result->VerifierInstanceOf(return_type)) {
+            // This should never happen.
+            self->ThrowNewExceptionF(self->GetCurrentLocationForThrow(),
+                                     "Ljava/lang/VirtualMachineError;",
+                                     "Returning '%s' that is not instance of return type '%s'",
+                                     ClassHelper(obj_result->GetClass()).GetDescriptor(),
+                                     ClassHelper(return_type).GetDescriptor());
+            HANDLE_PENDING_EXCEPTION();
+          }
+        }
         if (UNLIKELY(instrumentation->HasMethodExitListeners())) {
           instrumentation->MethodExitEvent(self, shadow_frame.GetThisObject(code_item->ins_size_),
                                            shadow_frame.GetMethod(), inst->GetDexPc(insns),
@@ -472,6 +490,12 @@
         Object* exception = shadow_frame.GetVRegReference(inst->VRegA_11x(inst_data));
         if (UNLIKELY(exception == NULL)) {
           ThrowNullPointerException(NULL, "throw with null exception");
+        } else if (do_assignability_check && !exception->GetClass()->IsThrowableClass()) {
+          // This should never happen.
+          self->ThrowNewExceptionF(self->GetCurrentLocationForThrow(),
+                                   "Ljava/lang/VirtualMachineError;",
+                                   "Throwing '%s' that is not instance of Throwable",
+                                   ClassHelper(exception->GetClass()).GetDescriptor());
         } else {
           self->SetException(shadow_frame.GetCurrentLocationForThrow(), exception->AsThrowable());
         }
diff --git a/runtime/jdwp/jdwp_handler.cc b/runtime/jdwp/jdwp_handler.cc
index a2efc48..523d892 100644
--- a/runtime/jdwp/jdwp_handler.cc
+++ b/runtime/jdwp/jdwp_handler.cc
@@ -47,7 +47,7 @@
 
 std::string DescribeRefTypeId(const RefTypeId& ref_type_id) {
   std::string signature("unknown");
-  Dbg::GetSignature(ref_type_id, signature);
+  Dbg::GetSignature(ref_type_id, &signature);
   return StringPrintf("%#llx (%s)", ref_type_id, signature.c_str());
 }
 
@@ -547,7 +547,7 @@
   RefTypeId refTypeId = request.ReadRefTypeId();
 
   std::string signature;
-  JdwpError status = Dbg::GetSignature(refTypeId, signature);
+  JdwpError status = Dbg::GetSignature(refTypeId, &signature);
   if (status != ERR_NONE) {
     return status;
   }
diff --git a/runtime/mirror/class.cc b/runtime/mirror/class.cc
index c128ede..287e8b0 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).GetDescriptor());
+  std::string descriptor(ClassHelper(this).GetDescriptorAsStringPiece().as_string());
   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).GetDescriptor(),
-                         ClassHelper(klass2).GetDescriptor());
+  return IsInSamePackage(ClassHelper(klass1).GetDescriptorAsStringPiece(),
+                         ClassHelper(klass2).GetDescriptorAsStringPiece());
 }
 
 bool Class::IsClassClass() const {
@@ -367,7 +367,7 @@
   for (size_t i = 0; i < NumDirectMethods(); ++i) {
     ArtMethod* method = GetDirectMethod(i);
     mh.ChangeMethod(method);
-    if (name == mh.GetName() && signature == mh.GetSignature()) {
+    if (name == mh.GetNameAsStringPiece() && signature == mh.GetSignature()) {
       return method;
     }
   }
@@ -412,7 +412,7 @@
   for (size_t i = 0; i < NumVirtualMethods(); ++i) {
     ArtMethod* method = GetVirtualMethod(i);
     mh.ChangeMethod(method);
-    if (name == mh.GetName() && signature == mh.GetSignature()) {
+    if (name == mh.GetNameAsStringPiece() && signature == mh.GetSignature()) {
       return method;
     }
   }
@@ -458,7 +458,7 @@
   for (size_t i = 0; i < NumInstanceFields(); ++i) {
     ArtField* f = GetInstanceField(i);
     fh.ChangeField(f);
-    if (name == fh.GetName() && type == fh.GetTypeDescriptor()) {
+    if (name == fh.GetNameAsStringPiece() && type == fh.GetTypeDescriptorAsStringPiece()) {
       return f;
     }
   }
@@ -507,7 +507,7 @@
   for (size_t i = 0; i < NumStaticFields(); ++i) {
     ArtField* f = GetStaticField(i);
     fh.ChangeField(f);
-    if (name == fh.GetName() && type == fh.GetTypeDescriptor()) {
+    if (name == fh.GetNameAsStringPiece() && type == fh.GetTypeDescriptorAsStringPiece()) {
       return f;
     }
   }
diff --git a/runtime/mirror/object-inl.h b/runtime/mirror/object-inl.h
index 63396d2..5ed3db3 100644
--- a/runtime/mirror/object-inl.h
+++ b/runtime/mirror/object-inl.h
@@ -71,6 +71,12 @@
   Monitor::Wait(self, this, ms, ns, true, kTimedWaiting);
 }
 
+inline bool Object::VerifierInstanceOf(const Class* klass) const {
+  DCHECK(klass != NULL);
+  DCHECK(GetClass() != NULL);
+  return klass->IsInterface() || InstanceOf(klass);
+}
+
 inline bool Object::InstanceOf(const Class* klass) const {
   DCHECK(klass != NULL);
   DCHECK(GetClass() != NULL);
diff --git a/runtime/mirror/object.h b/runtime/mirror/object.h
index 4db0c40..003581a 100644
--- a/runtime/mirror/object.h
+++ b/runtime/mirror/object.h
@@ -71,6 +71,11 @@
 
   void SetClass(Class* new_klass);
 
+  // The verifier treats all interfaces as java.lang.Object and relies on runtime checks in
+  // invoke-interface to detect incompatible interface types.
+  bool VerifierInstanceOf(const Class* klass) const
+        SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+
   bool InstanceOf(const Class* klass) const
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
diff --git a/runtime/native/org_apache_harmony_dalvik_ddmc_DdmVmInternal.cc b/runtime/native/org_apache_harmony_dalvik_ddmc_DdmVmInternal.cc
index 13cd978..0676968 100644
--- a/runtime/native/org_apache_harmony_dalvik_ddmc_DdmVmInternal.cc
+++ b/runtime/native/org_apache_harmony_dalvik_ddmc_DdmVmInternal.cc
@@ -109,8 +109,10 @@
    * be removed from a future version.
    */
   char native_thread_state;
-  int utime, stime, task_cpu;
-  GetTaskStats(t->GetTid(), native_thread_state, utime, stime, task_cpu);
+  int utime;
+  int stime;
+  int task_cpu;
+  GetTaskStats(t->GetTid(), &native_thread_state, &utime, &stime, &task_cpu);
 
   std::vector<uint8_t>& bytes = *reinterpret_cast<std::vector<uint8_t>*>(context);
   JDWP::Append4BE(bytes, t->GetThinLockId());
diff --git a/runtime/object_utils.h b/runtime/object_utils.h
index c55e10e..9e107a4 100644
--- a/runtime/object_utils.h
+++ b/runtime/object_utils.h
@@ -111,6 +111,17 @@
     }
   }
 
+  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_;
@@ -182,7 +193,7 @@
   }
 
   const char* GetSourceFile() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
-    std::string descriptor(GetDescriptor());
+    std::string descriptor(GetDescriptorAsStringPiece().as_string());
     const DexFile& dex_file = GetDexFile();
     const DexFile::ClassDef* dex_class_def = GetClassDef();
     CHECK(dex_class_def != NULL);
@@ -267,53 +278,77 @@
     }
     field_ = new_f;
   }
+
   const char* GetName() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
     uint32_t field_index = field_->GetDexFieldIndex();
-    if (!field_->GetDeclaringClass()->IsProxyClass()) {
-      const DexFile& dex_file = GetDexFile();
-      return dex_file.GetFieldName(dex_file.GetFieldId(field_index));
-    } else {
+    if (UNLIKELY(field_->GetDeclaringClass()->IsProxyClass())) {
       DCHECK(field_->IsStatic());
       DCHECK_LT(field_index, 2U);
       return field_index == 0 ? "interfaces" : "throws";
     }
+    const DexFile& dex_file = GetDexFile();
+    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 (!field_->GetDeclaringClass()->IsProxyClass()) {
-      const DexFile& dex_file = GetDexFile();
-      const DexFile::FieldId& field_id = dex_file.GetFieldId(field_index);
-      mirror::Class* type = GetDexCache()->GetResolvedType(field_id.type_idx_);
-      if (resolve && (type == NULL)) {
-        type = GetClassLinker()->ResolveType(field_id.type_idx_, field_);
-        CHECK(type != NULL || Thread::Current()->IsExceptionPending());
-      }
-      return type;
-    } else {
+    if (UNLIKELY(field_->GetDeclaringClass()->IsProxyClass())) {
       return GetClassLinker()->FindSystemClass(GetTypeDescriptor());
     }
+    const DexFile& dex_file = GetDexFile();
+    const DexFile::FieldId& field_id = dex_file.GetFieldId(field_index);
+    mirror::Class* type = GetDexCache()->GetResolvedType(field_id.type_idx_);
+    if (resolve && (type == NULL)) {
+      type = GetClassLinker()->ResolveType(field_id.type_idx_, field_);
+      CHECK(type != NULL || Thread::Current()->IsExceptionPending());
+    }
+    return type;
   }
+
   const char* GetTypeDescriptor() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
     uint32_t field_index = field_->GetDexFieldIndex();
-    if (!field_->GetDeclaringClass()->IsProxyClass()) {
-      const DexFile& dex_file = GetDexFile();
-      const DexFile::FieldId& field_id = dex_file.GetFieldId(field_index);
-      return dex_file.GetFieldTypeDescriptor(field_id);
-    } else {
+    if (UNLIKELY(field_->GetDeclaringClass()->IsProxyClass())) {
       DCHECK(field_->IsStatic());
       DCHECK_LT(field_index, 2U);
       // 0 == Class[] interfaces; 1 == Class[][] throws;
       return field_index == 0 ? "[Ljava/lang/Class;" : "[[Ljava/lang/Class;";
     }
+    const DexFile& dex_file = GetDexFile();
+    const DexFile::FieldId& field_id = dex_file.GetFieldId(field_index);
+    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]);
   }
+
   bool IsPrimitiveType() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
     Primitive::Type type = GetTypeAsPrimitiveType();
     return type != Primitive::kPrimNot;
   }
+
   size_t FieldSize() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
     Primitive::Type type = GetTypeAsPrimitiveType();
     return Primitive::FieldSize(type);
@@ -324,18 +359,17 @@
   const char* GetDeclaringClassDescriptor()
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
     uint32_t field_index = field_->GetDexFieldIndex();
-    if (!field_->GetDeclaringClass()->IsProxyClass()) {
-      const DexFile& dex_file = GetDexFile();
-      const DexFile::FieldId& field_id = dex_file.GetFieldId(field_index);
-      return dex_file.GetFieldDeclaringClassDescriptor(field_id);
-    } else {
+    if (UNLIKELY(field_->GetDeclaringClass()->IsProxyClass())) {
       DCHECK(field_->IsStatic());
       DCHECK_LT(field_index, 2U);
       // 0 == Class[] interfaces; 1 == Class[][] throws;
       ClassHelper kh(field_->GetDeclaringClass());
-      declaring_class_descriptor_ = kh.GetDescriptor();
+      declaring_class_descriptor_ = kh.GetDescriptorAsStringPiece().as_string();
       return declaring_class_descriptor_.c_str();
     }
+    const DexFile& dex_file = GetDexFile();
+    const DexFile::FieldId& field_id = dex_file.GetFieldId(field_index);
+    return dex_file.GetFieldDeclaringClassDescriptor(field_id);
   }
 
  private:
@@ -417,7 +451,7 @@
   const char* GetName() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
     const DexFile& dex_file = GetDexFile();
     uint32_t dex_method_idx = method_->GetDexMethodIndex();
-    if (dex_method_idx != DexFile::kDexNoIndex) {
+    if (LIKELY(dex_method_idx != DexFile::kDexNoIndex)) {
       return dex_file.GetMethodName(dex_file.GetMethodId(dex_method_idx));
     } else {
       Runtime* runtime = Runtime::Current();
@@ -435,6 +469,16 @@
     }
   }
 
+  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();
@@ -508,11 +552,22 @@
   const char* GetDeclaringClassDescriptor() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
     const DexFile& dex_file = GetDexFile();
     uint32_t dex_method_idx = method_->GetDexMethodIndex();
-    if (dex_method_idx != DexFile::kDexNoIndex) {
-      return dex_file.GetMethodDeclaringClassDescriptor(dex_file.GetMethodId(dex_method_idx));
-    } else {
+    if (UNLIKELY(dex_method_idx == DexFile::kDexNoIndex)) {
       return "<runtime method>";
     }
+    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_) {
@@ -536,7 +591,7 @@
   }
 
   bool IsClassInitializer() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
-    return IsStatic() && StringPiece(GetName()) == "<clinit>";
+    return IsStatic() && GetNameAsStringPiece() == "<clinit>";
   }
 
   size_t NumArgs() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
@@ -579,27 +634,21 @@
     const DexFile& other_dex_file = other->GetDexFile();
     const DexFile::MethodId& other_mid =
         other_dex_file.GetMethodId(other->method_->GetDexMethodIndex());
-    uint32_t length, other_length;
-    const char* data = dex_file.StringDataAndLengthByIdx(mid.name_idx_, &length);
-    const char* other_data = other_dex_file.StringDataAndLengthByIdx(other_mid.name_idx_,
-                                                                     &other_length);
-    if ((length != other_length) || (strcmp(data, other_data) != 0)) {
+    if (dex_file.StringDataAsStringPieceByIdx(mid.name_idx_) !=
+        other_dex_file.StringDataAsStringPieceByIdx(other_mid.name_idx_)) {
       return false;  // Name mismatch.
     }
     const DexFile::ProtoId& proto_id = dex_file.GetMethodPrototype(mid);
     const DexFile::ProtoId& other_proto_id = other_dex_file.GetMethodPrototype(other_mid);
-    data = dex_file.StringDataAndLengthByIdx(proto_id.shorty_idx_, &length);
-    other_data = dex_file.StringDataAndLengthByIdx(proto_id.shorty_idx_, &other_length);
-    if ((length != other_length) || (strcmp(data, other_data) != 0)) {
+    if (dex_file.StringDataAsStringPieceByIdx(proto_id.shorty_idx_) !=
+        other_dex_file.StringDataAsStringPieceByIdx(other_proto_id.shorty_idx_)) {
       return false;  // Shorty mismatch.
     }
     const DexFile::TypeId& return_type_id = dex_file.GetTypeId(proto_id.return_type_idx_);
     const DexFile::TypeId& other_return_type_id =
         other_dex_file.GetTypeId(other_proto_id.return_type_idx_);
-    data = dex_file.StringDataAndLengthByIdx(return_type_id.descriptor_idx_, &length);
-    other_data = other_dex_file.StringDataAndLengthByIdx(other_return_type_id.descriptor_idx_,
-                                                         &other_length);
-    if ((length != other_length) || (strcmp(data, other_data) != 0)) {
+    if (dex_file.StringDataAsStringPieceByIdx(return_type_id.descriptor_idx_) !=
+        other_dex_file.StringDataAsStringPieceByIdx(other_return_type_id.descriptor_idx_)) {
       return false;  // Return type mismatch.
     }
     const DexFile::TypeList* params = dex_file.GetProtoParameters(proto_id);
@@ -619,10 +668,8 @@
       const DexFile::TypeId& param_id = dex_file.GetTypeId(params->GetTypeItem(i).type_idx_);
       const DexFile::TypeId& other_param_id =
           other_dex_file.GetTypeId(other_params->GetTypeItem(i).type_idx_);
-      data = dex_file.StringDataAndLengthByIdx(param_id.descriptor_idx_, &length);
-      other_data = other_dex_file.StringDataAndLengthByIdx(other_param_id.descriptor_idx_,
-                                                     &other_length);
-      if ((length != other_length) || (strcmp(data, other_data) != 0)) {
+      if (dex_file.StringDataAsStringPieceByIdx(param_id.descriptor_idx_) !=
+          other_dex_file.StringDataAsStringPieceByIdx(other_param_id.descriptor_idx_)) {
         return false;  // Parameter type mismatch.
       }
     }
diff --git a/runtime/reflection.cc b/runtime/reflection.cc
index 3e58b4b..4ff7349 100644
--- a/runtime/reflection.cc
+++ b/runtime/reflection.cc
@@ -323,7 +323,7 @@
   }
 
   JValue boxed_value;
-  std::string src_descriptor(ClassHelper(o->GetClass()).GetDescriptor());
+  const StringPiece src_descriptor(ClassHelper(o->GetClass()).GetDescriptorAsStringPiece());
   mirror::Class* src_class = NULL;
   ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
   mirror::ArtField* primitive_field = o->GetClass()->GetIFields()->Get(0);
@@ -356,7 +356,7 @@
                                   StringPrintf("%s has type %s, got %s",
                                                UnboxingFailureKind(m, index, f).c_str(),
                                                PrettyDescriptor(dst_class).c_str(),
-                                               PrettyDescriptor(src_descriptor.c_str()).c_str()).c_str());
+                                               PrettyDescriptor(src_descriptor.data()).c_str()).c_str());
     return false;
   }
 
diff --git a/runtime/sirt_ref.h b/runtime/sirt_ref.h
index 25d6fb3..a1f8a66 100644
--- a/runtime/sirt_ref.h
+++ b/runtime/sirt_ref.h
@@ -30,7 +30,8 @@
     self_->PushSirt(&sirt_);
   }
   ~SirtRef() {
-    CHECK_EQ(self_->PopSirt(), &sirt_);
+    StackIndirectReferenceTable* top_sirt = self_->PopSirt();
+    DCHECK_EQ(top_sirt, &sirt_);
   }
 
   T& operator*() const { return *get(); }
diff --git a/runtime/thread.cc b/runtime/thread.cc
index 5559a39..7e79ce1 100644
--- a/runtime/thread.cc
+++ b/runtime/thread.cc
@@ -417,7 +417,7 @@
 void Thread::InitStackHwm() {
   void* stack_base;
   size_t stack_size;
-  GetThreadStack(pthread_self_, stack_base, stack_size);
+  GetThreadStack(pthread_self_, &stack_base, &stack_size);
 
   // TODO: include this in the thread dumps; potentially useful in SIGQUIT output?
   VLOG(threads) << StringPrintf("Native stack is at %p (%s)", stack_base, PrettySize(stack_size).c_str());
@@ -757,7 +757,7 @@
   int utime = 0;
   int stime = 0;
   int task_cpu = 0;
-  GetTaskStats(tid, native_thread_state, utime, stime, task_cpu);
+  GetTaskStats(tid, &native_thread_state, &utime, &stime, &task_cpu);
 
   os << "  | state=" << native_thread_state
      << " schedstat=( " << scheduler_stats << " )"
diff --git a/runtime/utils.cc b/runtime/utils.cc
index 28ee58c..23dcde3 100644
--- a/runtime/utils.cc
+++ b/runtime/utils.cc
@@ -79,23 +79,23 @@
   return result;
 }
 
-void GetThreadStack(pthread_t thread, void*& stack_base, size_t& stack_size) {
+void GetThreadStack(pthread_t thread, void** stack_base, size_t* stack_size) {
 #if defined(__APPLE__)
-  stack_size = pthread_get_stacksize_np(thread);
+  *stack_size = pthread_get_stacksize_np(thread);
   void* stack_addr = pthread_get_stackaddr_np(thread);
 
   // Check whether stack_addr is the base or end of the stack.
   // (On Mac OS 10.7, it's the end.)
   int stack_variable;
   if (stack_addr > &stack_variable) {
-    stack_base = reinterpret_cast<byte*>(stack_addr) - stack_size;
+    *stack_base = reinterpret_cast<byte*>(stack_addr) - *stack_size;
   } else {
-    stack_base = stack_addr;
+    *stack_base = stack_addr;
   }
 #else
   pthread_attr_t attributes;
   CHECK_PTHREAD_CALL(pthread_getattr_np, (thread, &attributes), __FUNCTION__);
-  CHECK_PTHREAD_CALL(pthread_attr_getstack, (&attributes, &stack_base, &stack_size), __FUNCTION__);
+  CHECK_PTHREAD_CALL(pthread_attr_getstack, (&attributes, stack_base, stack_size), __FUNCTION__);
   CHECK_PTHREAD_CALL(pthread_attr_destroy, (&attributes), __FUNCTION__);
 #endif
 }
@@ -955,8 +955,8 @@
 #endif
 }
 
-void GetTaskStats(pid_t tid, char& state, int& utime, int& stime, int& task_cpu) {
-  utime = stime = task_cpu = 0;
+void GetTaskStats(pid_t tid, char* state, int* utime, int* stime, int* task_cpu) {
+  *utime = *stime = *task_cpu = 0;
   std::string stats;
   if (!ReadFileToString(StringPrintf("/proc/self/task/%d/stat", tid), &stats)) {
     return;
@@ -966,10 +966,10 @@
   // Extract the three fields we care about.
   std::vector<std::string> fields;
   Split(stats, ' ', fields);
-  state = fields[0][0];
-  utime = strtoull(fields[11].c_str(), NULL, 10);
-  stime = strtoull(fields[12].c_str(), NULL, 10);
-  task_cpu = strtoull(fields[36].c_str(), NULL, 10);
+  *state = fields[0][0];
+  *utime = strtoull(fields[11].c_str(), NULL, 10);
+  *stime = strtoull(fields[12].c_str(), NULL, 10);
+  *task_cpu = strtoull(fields[36].c_str(), NULL, 10);
 }
 
 std::string GetSchedulerGroupName(pid_t tid) {
diff --git a/runtime/utils.h b/runtime/utils.h
index c506fba..34e9459 100644
--- a/runtime/utils.h
+++ b/runtime/utils.h
@@ -323,10 +323,10 @@
 std::string GetThreadName(pid_t tid);
 
 // Returns details of the given thread's stack.
-void GetThreadStack(pthread_t thread, void*& stack_base, size_t& stack_size);
+void GetThreadStack(pthread_t thread, void** stack_base, size_t* stack_size);
 
 // Reads data from "/proc/self/task/${tid}/stat".
-void GetTaskStats(pid_t tid, char& state, int& utime, int& stime, int& task_cpu);
+void GetTaskStats(pid_t tid, char* state, int* utime, int* stime, int* task_cpu);
 
 // Returns the name of the scheduler group for the given thread the current process, or the empty string.
 std::string GetSchedulerGroupName(pid_t tid);
diff --git a/runtime/verifier/method_verifier.cc b/runtime/verifier/method_verifier.cc
index 9811926..6b13517 100644
--- a/runtime/verifier/method_verifier.cc
+++ b/runtime/verifier/method_verifier.cc
@@ -51,7 +51,8 @@
                                  uint32_t insns_size, uint16_t registers_size,
                                  MethodVerifier* verifier) {
   DCHECK_GT(insns_size, 0U);
-
+  register_lines_.reset(new RegisterLine*[insns_size]());
+  size_ = insns_size;
   for (uint32_t i = 0; i < insns_size; i++) {
     bool interesting = false;
     switch (mode) {
@@ -68,7 +69,16 @@
         break;
     }
     if (interesting) {
-      pc_to_register_line_.Put(i, new RegisterLine(registers_size, verifier));
+      register_lines_[i] = RegisterLine::Create(registers_size, verifier);
+    }
+  }
+}
+
+PcToRegisterLineTable::~PcToRegisterLineTable() {
+  for (size_t i = 0; i < size_; i++) {
+    delete register_lines_[i];
+    if (kIsDebugBuild) {
+      register_lines_[i] = nullptr;
     }
   }
 }
@@ -80,7 +90,7 @@
     return kNoFailure;
   }
   mirror::Class* super = klass->GetSuperClass();
-  if (super == NULL && StringPiece(ClassHelper(klass).GetDescriptor()) != "Ljava/lang/Object;") {
+  if (super == NULL && ClassHelper(klass).GetDescriptorAsStringPiece() != "Ljava/lang/Object;") {
     *error = "Verifier rejected class ";
     *error += PrettyDescriptor(klass);
     *error += " that has no super class";
@@ -293,6 +303,7 @@
       dex_method_idx_(dex_method_idx),
       mirror_method_(method),
       method_access_flags_(method_access_flags),
+      return_type_(nullptr),
       dex_file_(dex_file),
       dex_cache_(dex_cache),
       class_loader_(class_loader),
@@ -300,7 +311,7 @@
       code_item_(code_item),
       declaring_class_(NULL),
       interesting_dex_pc_(-1),
-      monitor_enter_dex_pcs_(NULL),
+      monitor_enter_dex_pcs_(nullptr),
       have_pending_hard_failure_(false),
       have_pending_runtime_throw_failure_(false),
       new_instance_count_(0),
@@ -309,7 +320,7 @@
       allow_soft_failures_(allow_soft_failures),
       has_check_casts_(false),
       has_virtual_or_interface_invokes_(false) {
-  DCHECK(class_def != NULL);
+  DCHECK(class_def != nullptr);
 }
 
 void MethodVerifier::FindLocksAtDexPc(mirror::ArtMethod* m, uint32_t dex_pc,
@@ -439,6 +450,8 @@
         // to an interpreter.
         error = VERIFY_ERROR_BAD_CLASS_SOFT;
       } else {
+        // If we fail again at runtime, mark that this instruction would throw and force this
+        // method to be executed using the interpreter with checks.
         have_pending_runtime_throw_failure_ = true;
       }
       break;
@@ -1032,8 +1045,8 @@
                   this);
 
 
-  work_line_.reset(new RegisterLine(registers_size, this));
-  saved_line_.reset(new RegisterLine(registers_size, this));
+  work_line_.reset(RegisterLine::Create(registers_size, this));
+  saved_line_.reset(RegisterLine::Create(registers_size, this));
 
   /* Initialize register types of method arguments. */
   if (!SetTypesFromSignature()) {
@@ -1580,11 +1593,13 @@
             Fail(VERIFY_ERROR_BAD_CLASS_SOFT) << "returning uninitialized object '"
                                               << reg_type << "'";
           } else if (!return_type.IsAssignableFrom(reg_type)) {
-            Fail(reg_type.IsUnresolvedTypes() ?
-                 VERIFY_ERROR_BAD_CLASS_SOFT :
-                 VERIFY_ERROR_BAD_CLASS_HARD)
-                    << "returning '" << reg_type << "', but expected from declaration '"
-                    << return_type << "'";
+            if (reg_type.IsUnresolvedTypes() || return_type.IsUnresolvedTypes()) {
+              Fail(VERIFY_ERROR_NO_CLASS) << " can't resolve returned type '" << return_type
+                  << "' or '" << reg_type << "'";
+            } else {
+              Fail(VERIFY_ERROR_BAD_CLASS_HARD) << "returning '" << reg_type
+                  << "', but expected from declaration '" << return_type << "'";
+            }
           }
         }
       }
@@ -1804,8 +1819,8 @@
     case Instruction::THROW: {
       const RegType& res_type = work_line_->GetRegisterType(inst->VRegA_11x());
       if (!reg_types_.JavaLangThrowable(false).IsAssignableFrom(res_type)) {
-        Fail(VERIFY_ERROR_BAD_CLASS_SOFT) << "thrown class " << res_type
-                                          << " not instanceof Throwable";
+        Fail(res_type.IsUnresolvedTypes() ? VERIFY_ERROR_NO_CLASS : VERIFY_ERROR_BAD_CLASS_SOFT)
+            << "thrown class " << res_type << " not instanceof Throwable";
       }
       break;
     }
@@ -1929,9 +1944,9 @@
         const RegType& orig_type = work_line_->GetRegisterType(instance_of_inst->VRegB_22c());
         const RegType& cast_type = ResolveClassAndCheckAccess(instance_of_inst->VRegC_22c());
 
-        if (!cast_type.IsUnresolvedTypes() && !cast_type.GetClass()->IsInterface() &&
-            !cast_type.IsAssignableFrom(orig_type)) {
-          RegisterLine* update_line = new RegisterLine(code_item_->registers_size_, this);
+        if (!cast_type.IsUnresolvedTypes() && !orig_type.IsUnresolvedTypes() &&
+            !cast_type.GetClass()->IsInterface() && !cast_type.IsAssignableFrom(orig_type)) {
+          RegisterLine* update_line = RegisterLine::Create(code_item_->registers_size_, this);
           if (inst->Opcode() == Instruction::IF_EQZ) {
             fallthrough_line.reset(update_line);
           } else {
@@ -2127,20 +2142,30 @@
                         inst->Opcode() == Instruction::INVOKE_SUPER_RANGE);
       mirror::ArtMethod* called_method = VerifyInvocationArgs(inst, METHOD_VIRTUAL,
                                                                    is_range, is_super);
-      const char* descriptor;
-      if (called_method == NULL) {
+      const RegType* return_type = nullptr;
+      if (called_method != nullptr) {
+        MethodHelper mh(called_method);
+        mirror::Class* return_type_class = mh.GetReturnType();
+        if (return_type_class != nullptr) {
+          return_type = &reg_types_.FromClass(mh.GetReturnTypeDescriptor(), return_type_class,
+                                              return_type_class->CannotBeAssignedFromOtherTypes());
+        } else {
+          Thread* self = Thread::Current();
+          DCHECK(self->IsExceptionPending());
+          self->ClearException();
+        }
+      }
+      if (return_type == nullptr) {
         uint32_t method_idx = (is_range) ? inst->VRegB_3rc() : inst->VRegB_35c();
         const DexFile::MethodId& method_id = dex_file_->GetMethodId(method_idx);
         uint32_t return_type_idx = dex_file_->GetProtoId(method_id.proto_idx_).return_type_idx_;
-        descriptor =  dex_file_->StringByTypeIdx(return_type_idx);
-      } else {
-        descriptor = MethodHelper(called_method).GetReturnTypeDescriptor();
+        const char* descriptor = dex_file_->StringByTypeIdx(return_type_idx);
+        return_type = &reg_types_.FromDescriptor(class_loader_, descriptor, false);
       }
-      const RegType& return_type = reg_types_.FromDescriptor(class_loader_, descriptor, false);
-      if (!return_type.IsLowHalf()) {
-        work_line_->SetResultRegisterType(return_type);
+      if (!return_type->IsLowHalf()) {
+        work_line_->SetResultRegisterType(*return_type);
       } else {
-        work_line_->SetResultRegisterTypeWide(return_type, return_type.HighHalf(&reg_types_));
+        work_line_->SetResultRegisterTypeWide(*return_type, return_type->HighHalf(&reg_types_));
       }
       just_set_result = true;
       break;
@@ -2155,7 +2180,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 = StringPiece(dex_file_->GetMethodName(method_id)) == "<init>";
+        is_constructor = dex_file_->StringDataAsStringPieceByIdx(method_id.name_idx_) == "<init>";
         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 {
@@ -2610,7 +2635,7 @@
     info_messages_ << "Rejecting opcode " << inst->DumpString(dex_file_);
     return false;
   } else if (have_pending_runtime_throw_failure_) {
-    /* slow path will throw, mark following code as unreachable */
+    /* checking interpreter will throw, mark following code as unreachable */
     opcode_flags = Instruction::kThrow;
   }
   /*
@@ -2861,7 +2886,8 @@
             } else if (!reg_types_.JavaLangThrowable(false).IsAssignableFrom(exception)) {
               // We don't know enough about the type and the common path merge will result in
               // Conflict. Fail here knowing the correct thing can be done at runtime.
-              Fail(VERIFY_ERROR_BAD_CLASS_SOFT) << "unexpected non-exception class " << exception;
+              Fail(exception.IsUnresolvedTypes() ? VERIFY_ERROR_NO_CLASS :
+                  VERIFY_ERROR_BAD_CLASS_SOFT) << "unexpected non-exception class " << exception;
               return reg_types_.Conflict();
             } else if (common_super->Equals(exception)) {
               // odd case, but nothing to do
@@ -3042,7 +3068,8 @@
           reg_types_.FromClass(ClassHelper(klass).GetDescriptor(), klass,
                                klass->CannotBeAssignedFromOtherTypes());
       if (!res_method_class.IsAssignableFrom(actual_arg_type)) {
-        Fail(VERIFY_ERROR_BAD_CLASS_SOFT) << "'this' argument '" << actual_arg_type
+        Fail(actual_arg_type.IsUnresolvedTypes() ? VERIFY_ERROR_NO_CLASS:
+            VERIFY_ERROR_BAD_CLASS_SOFT) << "'this' argument '" << actual_arg_type
             << "' not instance of '" << res_method_class << "'";
         return NULL;
       }
@@ -3166,7 +3193,8 @@
         reg_types_.FromClass(ClassHelper(klass).GetDescriptor(), klass,
                              klass->CannotBeAssignedFromOtherTypes());
     if (!res_method_class.IsAssignableFrom(actual_arg_type)) {
-      Fail(VERIFY_ERROR_BAD_CLASS_SOFT) << "'this' argument '" << actual_arg_type
+      Fail(actual_arg_type.IsUnresolvedTypes() ? VERIFY_ERROR_NO_CLASS :
+          VERIFY_ERROR_BAD_CLASS_SOFT) << "'this' argument '" << actual_arg_type
           << "' not instance of '" << res_method_class << "'";
       return NULL;
     }
@@ -3490,22 +3518,26 @@
     const RegType& object_type = work_line_->GetRegisterType(inst->VRegB_22c());
     field = GetInstanceField(object_type, field_idx);
   }
-  const char* descriptor;
-  mirror::ClassLoader* loader;
+  const RegType* field_type = nullptr;
   if (field != NULL) {
-    descriptor = FieldHelper(field).GetTypeDescriptor();
-    loader = field->GetDeclaringClass()->GetClassLoader();
-  } else {
-    const DexFile::FieldId& field_id = dex_file_->GetFieldId(field_idx);
-    descriptor = dex_file_->GetFieldTypeDescriptor(field_id);
-    loader = class_loader_;
+    FieldHelper fh(field);
+    mirror::Class* field_type_class = fh.GetType(false);
+    if (field_type_class != nullptr) {
+      field_type = &reg_types_.FromClass(fh.GetTypeDescriptor(), field_type_class,
+                                         field_type_class->CannotBeAssignedFromOtherTypes());
+    }
   }
-  const RegType& field_type = reg_types_.FromDescriptor(loader, descriptor, false);
+  if (field_type == nullptr) {
+    const DexFile::FieldId& field_id = dex_file_->GetFieldId(field_idx);
+    const char* descriptor = dex_file_->GetFieldTypeDescriptor(field_id);
+    mirror::ClassLoader* loader = class_loader_;
+    field_type = &reg_types_.FromDescriptor(loader, descriptor, false);
+  }
   const uint32_t vregA = (is_static) ? inst->VRegA_21c() : inst->VRegA_22c();
   if (is_primitive) {
-    if (field_type.Equals(insn_type) ||
-        (field_type.IsFloat() && insn_type.IsInteger()) ||
-        (field_type.IsDouble() && insn_type.IsLong())) {
+    if (field_type->Equals(insn_type) ||
+        (field_type->IsFloat() && insn_type.IsInteger()) ||
+        (field_type->IsDouble() && insn_type.IsLong())) {
       // expected that read is of the correct primitive type or that int reads are reading
       // floats or long reads are reading doubles
     } else {
@@ -3518,7 +3550,7 @@
       return;
     }
   } else {
-    if (!insn_type.IsAssignableFrom(field_type)) {
+    if (!insn_type.IsAssignableFrom(*field_type)) {
       Fail(VERIFY_ERROR_BAD_CLASS_SOFT) << "expected field " << PrettyField(field)
                                         << " to be compatible with type '" << insn_type
                                         << "' but found type '" << field_type
@@ -3527,10 +3559,10 @@
       return;
     }
   }
-  if (!field_type.IsLowHalf()) {
-    work_line_->SetRegisterType(vregA, field_type);
+  if (!field_type->IsLowHalf()) {
+    work_line_->SetRegisterType(vregA, *field_type);
   } else {
-    work_line_->SetRegisterTypeWide(vregA, field_type, field_type.HighHalf(&reg_types_));
+    work_line_->SetRegisterTypeWide(vregA, *field_type, field_type->HighHalf(&reg_types_));
   }
 }
 
@@ -3544,36 +3576,38 @@
     const RegType& object_type = work_line_->GetRegisterType(inst->VRegB_22c());
     field = GetInstanceField(object_type, field_idx);
   }
-  const char* descriptor;
-  mirror::ClassLoader* loader;
-  if (field != NULL) {
-    descriptor = FieldHelper(field).GetTypeDescriptor();
-    loader = field->GetDeclaringClass()->GetClassLoader();
-  } else {
-    const DexFile::FieldId& field_id = dex_file_->GetFieldId(field_idx);
-    descriptor = dex_file_->GetFieldTypeDescriptor(field_id);
-    loader = class_loader_;
-  }
-  const RegType& field_type = reg_types_.FromDescriptor(loader, descriptor, false);
+  const RegType* field_type = nullptr;
   if (field != NULL) {
     if (field->IsFinal() && field->GetDeclaringClass() != GetDeclaringClass().GetClass()) {
       Fail(VERIFY_ERROR_ACCESS_FIELD) << "cannot modify final field " << PrettyField(field)
                                       << " from other class " << GetDeclaringClass();
       return;
     }
+    FieldHelper fh(field);
+    mirror::Class* field_type_class = fh.GetType(false);
+    if (field_type_class != nullptr) {
+      field_type = &reg_types_.FromClass(fh.GetTypeDescriptor(), field_type_class,
+                                         field_type_class->CannotBeAssignedFromOtherTypes());
+    }
+  }
+  if (field_type == nullptr) {
+    const DexFile::FieldId& field_id = dex_file_->GetFieldId(field_idx);
+    const char* descriptor = dex_file_->GetFieldTypeDescriptor(field_id);
+    mirror::ClassLoader* loader = class_loader_;
+    field_type = &reg_types_.FromDescriptor(loader, descriptor, false);
   }
   const uint32_t vregA = (is_static) ? inst->VRegA_21c() : inst->VRegA_22c();
   if (is_primitive) {
-    VerifyPrimitivePut(field_type, insn_type, vregA);
+    VerifyPrimitivePut(*field_type, insn_type, vregA);
   } else {
-    if (!insn_type.IsAssignableFrom(field_type)) {
+    if (!insn_type.IsAssignableFrom(*field_type)) {
       Fail(VERIFY_ERROR_BAD_CLASS_SOFT) << "expected field " << PrettyField(field)
                                         << " to be compatible with type '" << insn_type
                                         << "' but found type '" << field_type
                                         << "' in put-object";
       return;
     }
-    work_line_->VerifyRegisterType(vregA, field_type);
+    work_line_->VerifyRegisterType(vregA, *field_type);
   }
 }
 
@@ -3641,14 +3675,21 @@
     Fail(VERIFY_ERROR_BAD_CLASS_HARD) << "Cannot infer field from " << inst->Name();
     return;
   }
-  const char* descriptor = FieldHelper(field).GetTypeDescriptor();
-  mirror::ClassLoader* loader = field->GetDeclaringClass()->GetClassLoader();
-  const RegType& field_type = reg_types_.FromDescriptor(loader, descriptor, false);
+  FieldHelper fh(field);
+  mirror::Class* field_type_class = fh.GetType(false);
+  const RegType* field_type;
+  if (field_type_class != nullptr) {
+    field_type = &reg_types_.FromClass(fh.GetTypeDescriptor(), field_type_class,
+                                       field_type_class->CannotBeAssignedFromOtherTypes());
+  } else {
+    field_type = &reg_types_.FromDescriptor(field->GetDeclaringClass()->GetClassLoader(),
+                                            fh.GetTypeDescriptor(), false);
+  }
   const uint32_t vregA = inst->VRegA_22c();
   if (is_primitive) {
-    if (field_type.Equals(insn_type) ||
-        (field_type.IsFloat() && insn_type.IsIntegralTypes()) ||
-        (field_type.IsDouble() && insn_type.IsLongTypes())) {
+    if (field_type->Equals(insn_type) ||
+        (field_type->IsFloat() && insn_type.IsIntegralTypes()) ||
+        (field_type->IsDouble() && insn_type.IsLongTypes())) {
       // expected that read is of the correct primitive type or that int reads are reading
       // floats or long reads are reading doubles
     } else {
@@ -3661,7 +3702,7 @@
       return;
     }
   } else {
-    if (!insn_type.IsAssignableFrom(field_type)) {
+    if (!insn_type.IsAssignableFrom(*field_type)) {
       Fail(VERIFY_ERROR_BAD_CLASS_SOFT) << "expected field " << PrettyField(field)
                                         << " to be compatible with type '" << insn_type
                                         << "' but found type '" << field_type
@@ -3670,10 +3711,10 @@
       return;
     }
   }
-  if (!field_type.IsLowHalf()) {
-    work_line_->SetRegisterType(vregA, field_type);
+  if (!field_type->IsLowHalf()) {
+    work_line_->SetRegisterType(vregA, *field_type);
   } else {
-    work_line_->SetRegisterTypeWide(vregA, field_type, field_type.HighHalf(&reg_types_));
+    work_line_->SetRegisterTypeWide(vregA, *field_type, field_type->HighHalf(&reg_types_));
   }
 }
 
@@ -3787,7 +3828,7 @@
     }
   } else {
     UniquePtr<RegisterLine> copy(gDebugVerify ?
-                                 new RegisterLine(target_line->NumRegs(), this) :
+                                 RegisterLine::Create(target_line->NumRegs(), this) :
                                  NULL);
     if (gDebugVerify) {
       copy->CopyFromLine(target_line);
@@ -3815,11 +3856,28 @@
 }
 
 const RegType& MethodVerifier::GetMethodReturnType() {
-  const DexFile::MethodId& method_id = dex_file_->GetMethodId(dex_method_idx_);
-  const DexFile::ProtoId& proto_id = dex_file_->GetMethodPrototype(method_id);
-  uint16_t return_type_idx = proto_id.return_type_idx_;
-  const char* descriptor = dex_file_->GetTypeDescriptor(dex_file_->GetTypeId(return_type_idx));
-  return reg_types_.FromDescriptor(class_loader_, descriptor, false);
+  if (return_type_ == nullptr) {
+    if (mirror_method_ != NULL) {
+      MethodHelper mh(mirror_method_);
+      mirror::Class* return_type_class = mh.GetReturnType();
+      if (return_type_class != nullptr) {
+        return_type_ =&reg_types_.FromClass(mh.GetReturnTypeDescriptor(), return_type_class,
+                                            return_type_class->CannotBeAssignedFromOtherTypes());
+      } else {
+        Thread* self = Thread::Current();
+        DCHECK(self->IsExceptionPending());
+        self->ClearException();
+      }
+    }
+    if (return_type_ == nullptr) {
+      const DexFile::MethodId& method_id = dex_file_->GetMethodId(dex_method_idx_);
+      const DexFile::ProtoId& proto_id = dex_file_->GetMethodPrototype(method_id);
+      uint16_t return_type_idx = proto_id.return_type_idx_;
+      const char* descriptor = dex_file_->GetTypeDescriptor(dex_file_->GetTypeId(return_type_idx));
+      return_type_ = &reg_types_.FromDescriptor(class_loader_, descriptor, false);
+    }
+  }
+  return *return_type_;
 }
 
 const RegType& MethodVerifier::GetDeclaringClass() {
diff --git a/runtime/verifier/method_verifier.h b/runtime/verifier/method_verifier.h
index 073a2f7..7f33741 100644
--- a/runtime/verifier/method_verifier.h
+++ b/runtime/verifier/method_verifier.h
@@ -110,10 +110,8 @@
 // execution of that instruction.
 class PcToRegisterLineTable {
  public:
-  PcToRegisterLineTable() {}
-  ~PcToRegisterLineTable() {
-    STLDeleteValues(&pc_to_register_line_);
-  }
+  PcToRegisterLineTable() : size_(0) {}
+  ~PcToRegisterLineTable();
 
   // Initialize the RegisterTable. Every instruction address can have a different set of information
   // about what's in which register, but for verification purposes we only need to store it at
@@ -122,17 +120,13 @@
             uint16_t registers_size, MethodVerifier* verifier);
 
   RegisterLine* GetLine(size_t idx) {
-    auto result = pc_to_register_line_.find(idx);
-    if (result == pc_to_register_line_.end()) {
-      return NULL;
-    } else {
-      return result->second;
-    }
+    DCHECK_LT(idx, size_);
+    return register_lines_[idx];
   }
 
  private:
-  typedef SafeMap<int32_t, RegisterLine*> Table;
-  Table pc_to_register_line_;
+  UniquePtr<RegisterLine*[]> register_lines_;
+  size_t size_;
 };
 
 // The verifier
@@ -688,6 +682,7 @@
   // Its object representation if known.
   mirror::ArtMethod* mirror_method_ GUARDED_BY(Locks::mutator_lock_);
   const uint32_t method_access_flags_;  // Method's access flags.
+  const RegType* return_type_;  // Lazily computed return type of the method.
   const DexFile* const dex_file_;  // The dex file containing the method.
   // The dex_cache for the declaring class of the method.
   mirror::DexCache* dex_cache_ GUARDED_BY(Locks::mutator_lock_);
diff --git a/runtime/verifier/reg_type.cc b/runtime/verifier/reg_type.cc
index 857acb8..50d1583 100644
--- a/runtime/verifier/reg_type.cc
+++ b/runtime/verifier/reg_type.cc
@@ -761,11 +761,6 @@
   return AssignableFrom(*this, src, true);
 }
 
-int32_t ConstantType::ConstantValue() const {
-  DCHECK(IsConstantTypes());
-  return constant_;
-}
-
 int32_t ConstantType::ConstantValueLo() const {
   DCHECK(IsConstantLo());
   return constant_;
diff --git a/runtime/verifier/reg_type.h b/runtime/verifier/reg_type.h
index 865ba20..f371733 100644
--- a/runtime/verifier/reg_type.h
+++ b/runtime/verifier/reg_type.h
@@ -574,9 +574,12 @@
 
   // If this is a 32-bit constant, what is the value? This value may be imprecise in which case
   // the value represents part of the integer range of values that may be held in the register.
-  virtual int32_t ConstantValue() const;
-  virtual int32_t ConstantValueLo() const;
-  virtual int32_t ConstantValueHi() const;
+  int32_t ConstantValue() const {
+    DCHECK(IsConstantTypes());
+    return constant_;
+  }
+  int32_t ConstantValueLo() const;
+  int32_t ConstantValueHi() const;
 
   bool IsZero() const {
     return IsPreciseConstant() && ConstantValue() == 0;
diff --git a/runtime/verifier/reg_type_cache.cc b/runtime/verifier/reg_type_cache.cc
index ce465a4..fd70300 100644
--- a/runtime/verifier/reg_type_cache.cc
+++ b/runtime/verifier/reg_type_cache.cc
@@ -210,6 +210,7 @@
 }
 
 const RegType& RegTypeCache::FromClass(const char* descriptor, mirror::Class* klass, bool precise) {
+  DCHECK(klass != nullptr);
   if (klass->IsPrimitive()) {
     // Note: precise isn't used for primitive classes. A char is assignable to an int. All
     // primitive classes are final.
diff --git a/runtime/verifier/register_line.cc b/runtime/verifier/register_line.cc
index 5affe47..1a41657 100644
--- a/runtime/verifier/register_line.cc
+++ b/runtime/verifier/register_line.cc
@@ -44,12 +44,6 @@
   } else if (new_type.IsConflict()) {  // should only be set during a merge
     verifier_->Fail(VERIFY_ERROR_BAD_CLASS_SOFT) << "Set register to unknown type " << new_type;
     return false;
-  } else if (verifier_->CanLoadClasses() && !Runtime::Current()->IsCompiler() &&
-      new_type.IsUnresolvedTypes()) {
-    // Unresolvable classes at runtime are bad and marked as a rewrite error.
-    verifier_->Fail(VERIFY_ERROR_NO_CLASS) << "Set register to unresolved class '"
-                                           << new_type << "' at runtime";
-    return false;
   } else {
     line_[vdst] = new_type.GetId();
   }
@@ -116,11 +110,15 @@
   // Verify the src register type against the check type refining the type of the register
   const RegType& src_type = GetRegisterType(vsrc);
   if (!(check_type.IsAssignableFrom(src_type))) {
-    // Hard fail if one of the types is primitive, since they are concretely known.
-    enum VerifyError fail_type = (!check_type.IsNonZeroReferenceTypes() ||
-                                  !src_type.IsNonZeroReferenceTypes())
-                                 ? VERIFY_ERROR_BAD_CLASS_HARD
-                                 : VERIFY_ERROR_BAD_CLASS_SOFT;
+    enum VerifyError fail_type;
+    if (!check_type.IsNonZeroReferenceTypes() || !src_type.IsNonZeroReferenceTypes()) {
+      // Hard fail if one of the types is primitive, since they are concretely known.
+      fail_type = VERIFY_ERROR_BAD_CLASS_HARD;
+    } else if (check_type.IsUnresolvedTypes() || src_type.IsUnresolvedTypes()) {
+      fail_type = VERIFY_ERROR_NO_CLASS;
+    } else {
+      fail_type = VERIFY_ERROR_BAD_CLASS_SOFT;
+    }
     verifier_->Fail(fail_type) << "register v" << vsrc << " has type "
                                << src_type << " but expected " << check_type;
     return false;
@@ -458,8 +456,7 @@
 
 bool RegisterLine::MergeRegisters(const RegisterLine* incoming_line) {
   bool changed = false;
-  CHECK(NULL != incoming_line);
-  CHECK(NULL != line_.get());
+  DCHECK(incoming_line != nullptr);
   for (size_t idx = 0; idx < num_regs_; idx++) {
     if (line_[idx] != incoming_line->line_[idx]) {
       const RegType& incoming_reg_type = incoming_line->GetRegisterType(idx);
diff --git a/runtime/verifier/register_line.h b/runtime/verifier/register_line.h
index f19dcca..8b2dadb 100644
--- a/runtime/verifier/register_line.h
+++ b/runtime/verifier/register_line.h
@@ -17,7 +17,6 @@
 #ifndef ART_RUNTIME_VERIFIER_REGISTER_LINE_H_
 #define ART_RUNTIME_VERIFIER_REGISTER_LINE_H_
 
-#include <deque>
 #include <vector>
 
 #include "dex_instruction.h"
@@ -51,12 +50,10 @@
 // stack of entered monitors (identified by code unit offset).
 class RegisterLine {
  public:
-  RegisterLine(size_t num_regs, MethodVerifier* verifier)
-      : line_(new uint16_t[num_regs]),
-        verifier_(verifier),
-        num_regs_(num_regs) {
-    memset(line_.get(), 0, num_regs_ * sizeof(uint16_t));
-    SetResultTypeToUnknown();
+  static RegisterLine* Create(size_t num_regs, MethodVerifier* verifier) {
+    uint8_t* memory = new uint8_t[sizeof(RegisterLine) + (num_regs * sizeof(uint16_t))];
+    RegisterLine* rl = new (memory) RegisterLine(num_regs, verifier);
+    return rl;
   }
 
   // Implement category-1 "move" instructions. Copy a 32-bit value from "vsrc" to "vdst".
@@ -108,7 +105,7 @@
 
   void CopyFromLine(const RegisterLine* src) {
     DCHECK_EQ(num_regs_, src->num_regs_);
-    memcpy(line_.get(), src->line_.get(), num_regs_ * sizeof(uint16_t));
+    memcpy(&line_, &src->line_, num_regs_ * sizeof(uint16_t));
     monitors_ = src->monitors_;
     reg_to_lock_depths_ = src->reg_to_lock_depths_;
   }
@@ -116,7 +113,7 @@
   std::string Dump() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
   void FillWithGarbage() {
-    memset(line_.get(), 0xf1, num_regs_ * sizeof(uint16_t));
+    memset(&line_, 0xf1, num_regs_ * sizeof(uint16_t));
     while (!monitors_.empty()) {
       monitors_.pop_back();
     }
@@ -161,7 +158,7 @@
   int CompareLine(const RegisterLine* line2) const {
     DCHECK(monitors_ == line2->monitors_);
     // TODO: DCHECK(reg_to_lock_depths_ == line2->reg_to_lock_depths_);
-    return memcmp(line_.get(), line2->line_.get(), num_regs_ * sizeof(uint16_t));
+    return memcmp(&line_, &line2->line_, num_regs_ * sizeof(uint16_t));
   }
 
   size_t NumRegs() const {
@@ -339,23 +336,30 @@
     reg_to_lock_depths_.erase(reg);
   }
 
+  RegisterLine(size_t num_regs, MethodVerifier* verifier)
+      : verifier_(verifier),
+        num_regs_(num_regs) {
+    memset(&line_, 0, num_regs_ * sizeof(uint16_t));
+    SetResultTypeToUnknown();
+  }
+
   // Storage for the result register's type, valid after an invocation
   uint16_t result_[2];
 
-  // An array of RegType Ids associated with each dex register
-  UniquePtr<uint16_t[]> line_;
-
   // Back link to the verifier
   MethodVerifier* verifier_;
 
   // Length of reg_types_
   const uint32_t num_regs_;
   // A stack of monitor enter locations
-  std::deque<uint32_t> monitors_;
+  std::vector<uint32_t> monitors_;
   // A map from register to a bit vector of indices into the monitors_ stack. As we pop the monitor
   // stack we verify that monitor-enter/exit are correctly nested. That is, if there was a
   // monitor-enter on v5 and then on v6, we expect the monitor-exit to be on v6 then on v5
   SafeMap<uint32_t, uint32_t> reg_to_lock_depths_;
+
+  // An array of RegType Ids associated with each dex register.
+  uint16_t line_[0];
 };
 std::ostream& operator<<(std::ostream& os, const RegisterLine& rhs);