Verifier improvements.

Make type hierarchy for unresolved and unitialized types explicit.
Tidy and comment code.
Add DexFile::FindStringId that takes UTF-16 to avoid unnecessary UTF-8
conversions during image writing.
Explicitly disable RTTI that causes problems in debug builds.

Change-Id: I701f1c3be8be5854fcabf5ec39e9f9c5d388aab0
diff --git a/build/Android.common.mk b/build/Android.common.mk
index 5c642be..e06c8cd 100644
--- a/build/Android.common.mk
+++ b/build/Android.common.mk
@@ -54,6 +54,7 @@
 	art/src
 
 art_cflags := \
+	-fno-rtti \
 	-O2 \
 	-ggdb3 \
 	-Wall \
diff --git a/src/compiler/dex/quick/gen_invoke.cc b/src/compiler/dex/quick/gen_invoke.cc
index 733fdc9..d74c33f 100644
--- a/src/compiler/dex/quick/gen_invoke.cc
+++ b/src/compiler/dex/quick/gen_invoke.cc
@@ -1225,9 +1225,9 @@
    * method.  By doing this during basic block construction, we can also
    * take advantage of/generate new useful dataflow info.
    */
-  const char* tgt_methods_declaring_class =
-      cu_->dex_file->GetMethodDeclaringClassDescriptor(cu_->dex_file->GetMethodId(info->index));
-  if (strstr(tgt_methods_declaring_class, "Ljava/lang") != NULL) {
+  StringPiece tgt_methods_declaring_class(
+      cu_->dex_file->GetMethodDeclaringClassDescriptor(cu_->dex_file->GetMethodId(info->index)));
+  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)") {
       return GenInlinedDoubleCvt(info);
@@ -1235,12 +1235,17 @@
     if (tgt_method == "double java.lang.Double.longBitsToDouble(long)") {
       return GenInlinedDoubleCvt(info);
     }
+  } else if (tgt_methods_declaring_class.starts_with("Ljava/lang/Float;")) {
+    std::string tgt_method(PrettyMethod(info->index, *cu_->dex_file));
     if (tgt_method == "int java.lang.Float.float_to_raw_int_bits(float)") {
       return GenInlinedFloatCvt(info);
     }
     if (tgt_method == "float java.lang.Float.intBitsToFloat(int)") {
       return GenInlinedFloatCvt(info);
     }
+  } else if (tgt_methods_declaring_class.starts_with("Ljava/lang/Math;") ||
+             tgt_methods_declaring_class.starts_with("Ljava/lang/StrictMath;")) {
+    std::string tgt_method(PrettyMethod(info->index, *cu_->dex_file));
     if (tgt_method == "int java.lang.Math.abs(int)" ||
         tgt_method == "int java.lang.StrictMath.abs(int)") {
       return GenInlinedAbsInt(info);
@@ -1261,6 +1266,8 @@
         tgt_method == "double java.lang.StrictMath.sqrt(double)") {
       return GenInlinedSqrt(info);
     }
+  } else if (tgt_methods_declaring_class.starts_with("Ljava/lang/String;")) {
+    std::string tgt_method(PrettyMethod(info->index, *cu_->dex_file));
     if (tgt_method == "char java.lang.String.charAt(int)") {
       return GenInlinedCharAt(info);
     }
@@ -1279,10 +1286,12 @@
     if (tgt_method == "int java.lang.String.length()") {
       return GenInlinedStringIsEmptyOrLength(info, false /* is_empty */);
     }
+  } else if (tgt_methods_declaring_class.starts_with("Ljava/lang/Thread;")) {
+    std::string tgt_method(PrettyMethod(info->index, *cu_->dex_file));
     if (tgt_method == "java.lang.Thread java.lang.Thread.currentThread()") {
       return GenInlinedCurrentThread(info);
     }
-  } else if (strstr(tgt_methods_declaring_class, "Lsun/misc/Unsafe;") != NULL) {
+  } else if (tgt_methods_declaring_class.starts_with("Lsun/misc/Unsafe;")) {
     std::string tgt_method(PrettyMethod(info->index, *cu_->dex_file));
     if (tgt_method == "boolean sun.misc.Unsafe.compareAndSwapInt(java.lang.Object, long, int, int)") {
       return GenInlinedCas32(info, false);
diff --git a/src/compiler/driver/compiler_driver.cc b/src/compiler/driver/compiler_driver.cc
index 6feda17..aad77ad 100644
--- a/src/compiler/driver/compiler_driver.cc
+++ b/src/compiler/driver/compiler_driver.cc
@@ -752,9 +752,8 @@
           }
           // Search dex file for localized ssb index, may fail if field's class is a parent
           // of the class mentioned in the dex file and there is no dex cache entry.
-          std::string descriptor(FieldHelper(resolved_field).GetDeclaringClassDescriptor());
           const DexFile::StringId* string_id =
-          mUnit->GetDexFile()->FindStringId(descriptor);
+              mUnit->GetDexFile()->FindStringId(FieldHelper(resolved_field).GetDeclaringClassDescriptor());
           if (string_id != NULL) {
             const DexFile::TypeId* type_id =
                mUnit->GetDexFile()->FindTypeId(mUnit->GetDexFile()->GetIndexForStringId(*string_id));
diff --git a/src/dex_file.cc b/src/dex_file.cc
index a8fb0e0..dad083c 100644
--- a/src/dex_file.cc
+++ b/src/dex_file.cc
@@ -436,7 +436,7 @@
   return NULL;
 }
 
-const DexFile::StringId* DexFile::FindStringId(const std::string& string) const {
+const DexFile::StringId* DexFile::FindStringId(const char* string) const {
   int32_t lo = 0;
   int32_t hi = NumStringIds() - 1;
   while (hi >= lo) {
@@ -444,7 +444,27 @@
     uint32_t length;
     const DexFile::StringId& str_id = GetStringId(mid);
     const char* str = GetStringDataAndLength(str_id, &length);
-    int compare = CompareModifiedUtf8ToModifiedUtf8AsUtf16CodePointValues(string.c_str(), str);
+    int compare = CompareModifiedUtf8ToModifiedUtf8AsUtf16CodePointValues(string, str);
+    if (compare > 0) {
+      lo = mid + 1;
+    } else if (compare < 0) {
+      hi = mid - 1;
+    } else {
+      return &str_id;
+    }
+  }
+  return NULL;
+}
+
+const DexFile::StringId* DexFile::FindStringId(const uint16_t* string) const {
+  int32_t lo = 0;
+  int32_t hi = NumStringIds() - 1;
+  while (hi >= lo) {
+    int32_t mid = (hi + lo) / 2;
+    uint32_t length;
+    const DexFile::StringId& str_id = GetStringId(mid);
+    const char* str = GetStringDataAndLength(str_id, &length);
+    int compare = CompareModifiedUtf8ToUtf16AsCodePointValues(str, string);
     if (compare > 0) {
       lo = mid + 1;
     } else if (compare < 0) {
@@ -544,7 +564,7 @@
         descriptor += c;
       } while (c != ';');
     }
-    const DexFile::StringId* string_id = FindStringId(descriptor);
+    const DexFile::StringId* string_id = FindStringId(descriptor.c_str());
     if (string_id == NULL) {
       return false;
     }
diff --git a/src/dex_file.h b/src/dex_file.h
index 6e34b57..ecc985f 100644
--- a/src/dex_file.h
+++ b/src/dex_file.h
@@ -436,8 +436,11 @@
     return StringDataAndLengthByIdx(idx, &unicode_length);
   }
 
-  // Looks up a string id for a given string
-  const StringId* FindStringId(const std::string& string) const;
+  // Looks up a string id for a given modified utf8 string.
+  const StringId* FindStringId(const char* string) const;
+
+  // Looks up a string id for a given utf16 string.
+  const StringId* FindStringId(const uint16_t* string) const;
 
   // Returns the number of type identifiers in the .dex file.
   size_t NumTypeIds() const {
@@ -974,7 +977,7 @@
   bool HasNext() const {
     return pos_ < EndOfVirtualMethodsPos();
   }
-  void Next() {
+  inline void Next() {
     pos_++;
     if (pos_ < EndOfStaticFieldsPos()) {
       last_idx_ = GetMemberIndex();
diff --git a/src/image_writer.cc b/src/image_writer.cc
index bda0138..faa13f7 100644
--- a/src/image_writer.cc
+++ b/src/image_writer.cc
@@ -168,13 +168,13 @@
     return;
   }
   String* string = obj->AsString();
-  std::string utf8_string(string->ToModifiedUtf8());
+  const uint16_t* utf16_string = string->GetCharArray()->GetData() + string->GetOffset();
   ImageWriter* writer = reinterpret_cast<ImageWriter*>(arg);
   typedef Set::const_iterator CacheIt;  // TODO: C++0x auto
   for (CacheIt it = writer->dex_caches_.begin(), end = writer->dex_caches_.end(); it != end; ++it) {
     DexCache* dex_cache = *it;
     const DexFile& dex_file = *dex_cache->GetDexFile();
-    const DexFile::StringId* string_id = dex_file.FindStringId(utf8_string);
+    const DexFile::StringId* string_id = dex_file.FindStringId(utf16_string);
     if (string_id != NULL) {
       // This string occurs in this dex file, assign the dex cache entry.
       uint32_t string_idx = dex_file.GetIndexForStringId(*string_id);
diff --git a/src/utf.cc b/src/utf.cc
index 8d3547e..1add7d9 100644
--- a/src/utf.cc
+++ b/src/utf.cc
@@ -119,6 +119,23 @@
   }
 }
 
+int CompareModifiedUtf8ToUtf16AsCodePointValues(const char* utf8_1, const uint16_t* utf8_2) {
+  for (;;) {
+    if (*utf8_1 == '\0') {
+      return (*utf8_2 == '\0') ? 0 : -1;
+    } else if (*utf8_2 == '\0') {
+      return 1;
+    }
+
+    int c1 = GetUtf16FromUtf8(&utf8_1);
+    int c2 = *utf8_2;
+
+    if (c1 != c2) {
+      return c1 > c2 ? 1 : -1;
+    }
+  }
+}
+
 size_t CountUtf8Bytes(const uint16_t* chars, size_t char_count) {
   size_t result = 0;
   while (char_count--) {
diff --git a/src/utf.h b/src/utf.h
index 44899bf..57c811f 100644
--- a/src/utf.h
+++ b/src/utf.h
@@ -56,6 +56,12 @@
 int CompareModifiedUtf8ToModifiedUtf8AsUtf16CodePointValues(const char* utf8_1, const char* utf8_2);
 
 /*
+ * Compare a modified UTF-8 string with a UTF-16 string as code point values in a non-locale
+ * sensitive manner.
+ */
+int CompareModifiedUtf8ToUtf16AsCodePointValues(const char* utf8_1, const uint16_t* utf8_2);
+
+/*
  * Convert from UTF-16 to Modified UTF-8. Note that the output is _not_
  * NUL-terminated. You probably need to call CountUtf8Bytes before calling
  * this anyway, so if you want a NUL-terminated string, you know where to
diff --git a/src/verifier/method_verifier.cc b/src/verifier/method_verifier.cc
index ce65829..fc285bc 100644
--- a/src/verifier/method_verifier.cc
+++ b/src/verifier/method_verifier.cc
@@ -19,6 +19,7 @@
 #include <iostream>
 
 #include "base/logging.h"
+#include "base/mutex-inl.h"
 #include "base/stringpiece.h"
 #include "class_linker.h"
 #include "compiler/driver/compiler_driver.h"
@@ -267,13 +268,14 @@
     : reg_types_(can_load_classes),
       work_insn_idx_(-1),
       dex_method_idx_(dex_method_idx),
-      foo_method_(method),
+      mirror_method_(method),
       method_access_flags_(method_access_flags),
       dex_file_(dex_file),
       dex_cache_(dex_cache),
       class_loader_(class_loader),
       class_def_idx_(class_def_idx),
       code_item_(code_item),
+      declaring_class_(NULL),
       interesting_dex_pc_(-1),
       monitor_enter_dex_pcs_(NULL),
       have_pending_hard_failure_(false),
@@ -896,6 +898,7 @@
 
 static const std::vector<uint8_t>* CreateLengthPrefixedDexGcMap(const std::vector<uint8_t>& gc_map) {
   std::vector<uint8_t>* length_prefixed_gc_map = new std::vector<uint8_t>;
+  length_prefixed_gc_map->reserve(gc_map.size() + 4);
   length_prefixed_gc_map->push_back((gc_map.size() & 0xff000000) >> 24);
   length_prefixed_gc_map->push_back((gc_map.size() & 0x00ff0000) >> 16);
   length_prefixed_gc_map->push_back((gc_map.size() & 0x0000ff00) >> 8);
@@ -2542,7 +2545,7 @@
   const RegType& referrer = GetDeclaringClass();
   mirror::Class* klass = dex_cache_->GetResolvedType(class_idx);
   const RegType& result =
-      klass != NULL ? reg_types_.FromClass(klass, klass->IsFinal())
+      klass != NULL ? reg_types_.FromClass(descriptor, klass, klass->IsFinal())
                     : reg_types_.FromDescriptor(class_loader_, descriptor, false);
   if (result.IsConflict()) {
     Fail(VERIFY_ERROR_BAD_CLASS_SOFT) << "accessing broken descriptor '" << descriptor
@@ -2756,7 +2759,8 @@
     }
     if (method_type != METHOD_INTERFACE && !actual_arg_type.IsZero()) {
       mirror::Class* klass = res_method->GetDeclaringClass();
-      const RegType& res_method_class = reg_types_.FromClass(klass, klass->IsFinal());
+      const RegType& res_method_class = reg_types_.FromClass(ClassHelper(klass).GetDescriptor(),
+                                                             klass, klass->IsFinal());
       if (!res_method_class.IsAssignableFrom(actual_arg_type)) {
         Fail(VERIFY_ERROR_BAD_CLASS_SOFT) << "'this' argument '" << actual_arg_type
             << "' not instance of '" << res_method_class << "'";
@@ -2935,7 +2939,7 @@
   mirror::Field* field = Runtime::Current()->GetClassLinker()->ResolveFieldJLS(*dex_file_, field_idx,
                                                                        dex_cache_, class_loader_);
   if (field == NULL) {
-    LOG(INFO) << "unable to resolve static field " << field_idx << " ("
+    LOG(INFO) << "Unable to resolve static field " << field_idx << " ("
               << dex_file_->GetFieldName(field_id) << ") in "
               << dex_file_->GetFieldDeclaringClassDescriptor(field_id);
     DCHECK(Thread::Current()->IsExceptionPending());
@@ -2970,7 +2974,7 @@
   mirror::Field* field = Runtime::Current()->GetClassLinker()->ResolveFieldJLS(*dex_file_, field_idx,
                                                                        dex_cache_, class_loader_);
   if (field == NULL) {
-    LOG(INFO) << "unable to resolve instance field " << field_idx << " ("
+    LOG(INFO) << "Unable to resolve instance field " << field_idx << " ("
               << dex_file_->GetFieldName(field_id) << ") in "
               << dex_file_->GetFieldDeclaringClassDescriptor(field_id);
     DCHECK(Thread::Current()->IsExceptionPending());
@@ -2990,7 +2994,9 @@
     return field;
   } else {
     mirror::Class* klass = field->GetDeclaringClass();
-    const RegType& field_klass = reg_types_.FromClass(klass, klass->IsFinal());
+    const RegType& field_klass =
+        reg_types_.FromClass(dex_file_->GetFieldDeclaringClassDescriptor(field_id),
+                             klass, klass->IsFinal());
     if (obj_type.IsUninitializedTypes() &&
         (!IsConstructor() || GetDeclaringClass().Equals(obj_type) ||
             !field_klass.Equals(GetDeclaringClass()))) {
@@ -3198,14 +3204,17 @@
 }
 
 const RegType& MethodVerifier::GetDeclaringClass() {
-  if (foo_method_ != NULL) {
-    mirror::Class* klass = foo_method_->GetDeclaringClass();
-    return reg_types_.FromClass(klass, klass->IsFinal());
-  } else {
+  if (declaring_class_ == NULL) {
     const DexFile::MethodId& method_id = dex_file_->GetMethodId(dex_method_idx_);
     const char* descriptor = dex_file_->GetTypeDescriptor(dex_file_->GetTypeId(method_id.class_idx_));
-    return reg_types_.FromDescriptor(class_loader_, descriptor, false);
+    if (mirror_method_ != NULL) {
+      mirror::Class* klass = mirror_method_->GetDeclaringClass();
+      declaring_class_ = &reg_types_.FromClass(descriptor, klass, klass->IsFinal());
+    } else {
+      declaring_class_ = &reg_types_.FromDescriptor(class_loader_, descriptor, false);
+    }
   }
+  return *declaring_class_;
 }
 
 void MethodVerifier::ComputeGcMapSizes(size_t* gc_points, size_t* ref_bitmap_bits,
@@ -3396,9 +3405,10 @@
   }
 }
 
-void MethodVerifier::SetDexGcMap(CompilerDriver::MethodReference ref, const std::vector<uint8_t>& gc_map) {
+void MethodVerifier::SetDexGcMap(CompilerDriver::MethodReference ref,
+                                 const std::vector<uint8_t>& gc_map) {
   {
-    MutexLock mu(Thread::Current(), *dex_gc_maps_lock_);
+    WriterMutexLock mu(Thread::Current(), *dex_gc_maps_lock_);
     DexGcMapTable::iterator it = dex_gc_maps_->find(ref);
     if (it != dex_gc_maps_->end()) {
       delete it->second;
@@ -3409,9 +3419,20 @@
   DCHECK(GetDexGcMap(ref) != NULL);
 }
 
-void  MethodVerifier::SetDevirtMap(CompilerDriver::MethodReference ref, const PcToConcreteMethod* devirt_map) {
+const std::vector<uint8_t>* MethodVerifier::GetDexGcMap(CompilerDriver::MethodReference ref) {
+  ReaderMutexLock mu(Thread::Current(), *dex_gc_maps_lock_);
+  DexGcMapTable::const_iterator it = dex_gc_maps_->find(ref);
+  if (it == dex_gc_maps_->end()) {
+    LOG(WARNING) << "Didn't find GC map for: " << PrettyMethod(ref.dex_method_index, *ref.dex_file);
+    return NULL;
+  }
+  CHECK(it->second != NULL);
+  return it->second;
+}
 
-  MutexLock mu(Thread::Current(), *devirt_maps_lock_);
+void  MethodVerifier::SetDevirtMap(CompilerDriver::MethodReference ref,
+                                   const PcToConcreteMethod* devirt_map) {
+  WriterMutexLock mu(Thread::Current(), *devirt_maps_lock_);
   DevirtualizationMapTable::iterator it = devirt_maps_->find(ref);
   if (it != devirt_maps_->end()) {
     delete it->second;
@@ -3422,20 +3443,9 @@
   CHECK(devirt_maps_->find(ref) != devirt_maps_->end());
 }
 
-const std::vector<uint8_t>* MethodVerifier::GetDexGcMap(CompilerDriver::MethodReference ref) {
-  MutexLock mu(Thread::Current(), *dex_gc_maps_lock_);
-  DexGcMapTable::const_iterator it = dex_gc_maps_->find(ref);
-  if (it == dex_gc_maps_->end()) {
-    LOG(WARNING) << "Didn't find GC map for: " << PrettyMethod(ref.dex_method_index, *ref.dex_file);
-    return NULL;
-  }
-  CHECK(it->second != NULL);
-  return it->second;
-}
-
 const CompilerDriver::MethodReference* MethodVerifier::GetDevirtMap(const CompilerDriver::MethodReference& ref,
                                                                     uint32_t dex_pc) {
-  MutexLock mu(Thread::Current(), *devirt_maps_lock_);
+  ReaderMutexLock mu(Thread::Current(), *devirt_maps_lock_);
   DevirtualizationMapTable::const_iterator it = devirt_maps_->find(ref);
   if (it == devirt_maps_->end()) {
     return NULL;
@@ -3494,26 +3504,26 @@
   return result;
 }
 
-Mutex* MethodVerifier::dex_gc_maps_lock_ = NULL;
+ReaderWriterMutex* MethodVerifier::dex_gc_maps_lock_ = NULL;
 MethodVerifier::DexGcMapTable* MethodVerifier::dex_gc_maps_ = NULL;
 
-Mutex* MethodVerifier::devirt_maps_lock_ = NULL;
+ReaderWriterMutex* MethodVerifier::devirt_maps_lock_ = NULL;
 MethodVerifier::DevirtualizationMapTable* MethodVerifier::devirt_maps_ = NULL;
 
 Mutex* MethodVerifier::rejected_classes_lock_ = NULL;
 MethodVerifier::RejectedClassesTable* MethodVerifier::rejected_classes_ = NULL;
 
 void MethodVerifier::Init() {
-  dex_gc_maps_lock_ = new Mutex("verifier GC maps lock");
+  dex_gc_maps_lock_ = new ReaderWriterMutex("verifier GC maps lock");
   Thread* self = Thread::Current();
   {
-    MutexLock mu(self, *dex_gc_maps_lock_);
+    WriterMutexLock mu(self, *dex_gc_maps_lock_);
     dex_gc_maps_ = new MethodVerifier::DexGcMapTable;
   }
 
-  devirt_maps_lock_ = new Mutex("verifier Devirtualization lock");
+  devirt_maps_lock_ = new ReaderWriterMutex("verifier Devirtualization lock");
   {
-    MutexLock mu(self, *devirt_maps_lock_);
+    WriterMutexLock mu(self, *devirt_maps_lock_);
     devirt_maps_ = new MethodVerifier::DevirtualizationMapTable();
   }
 
@@ -3528,7 +3538,7 @@
 void MethodVerifier::Shutdown() {
   Thread* self = Thread::Current();
   {
-    MutexLock mu(self, *dex_gc_maps_lock_);
+    WriterMutexLock mu(self, *dex_gc_maps_lock_);
     STLDeleteValues(dex_gc_maps_);
     delete dex_gc_maps_;
     dex_gc_maps_ = NULL;
@@ -3537,7 +3547,7 @@
   dex_gc_maps_lock_ = NULL;
 
   {
-    MutexLock mu(self, *devirt_maps_lock_);
+    WriterMutexLock mu(self, *devirt_maps_lock_);
     STLDeleteValues(devirt_maps_);
     delete devirt_maps_;
     devirt_maps_ = NULL;
diff --git a/src/verifier/method_verifier.h b/src/verifier/method_verifier.h
index 9b4b8e5..75f94ea 100644
--- a/src/verifier/method_verifier.h
+++ b/src/verifier/method_verifier.h
@@ -577,7 +577,7 @@
   // All the GC maps that the verifier has created
   typedef SafeMap<const CompilerDriver::MethodReference, const std::vector<uint8_t>*,
       CompilerDriver::MethodReferenceComparator> DexGcMapTable;
-  static Mutex* dex_gc_maps_lock_ DEFAULT_MUTEX_ACQUIRED_AFTER;
+  static ReaderWriterMutex* dex_gc_maps_lock_ DEFAULT_MUTEX_ACQUIRED_AFTER;
   static DexGcMapTable* dex_gc_maps_ GUARDED_BY(dex_gc_maps_lock_);
   static void SetDexGcMap(CompilerDriver::MethodReference ref, const std::vector<uint8_t>& dex_gc_map)
       LOCKS_EXCLUDED(dex_gc_maps_lock_);
@@ -590,7 +590,7 @@
   MethodVerifier::PcToConcreteMethod* GenerateDevirtMap()
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
-  static Mutex* devirt_maps_lock_ DEFAULT_MUTEX_ACQUIRED_AFTER;
+  static ReaderWriterMutex* devirt_maps_lock_ DEFAULT_MUTEX_ACQUIRED_AFTER;
   static DevirtualizationMapTable* devirt_maps_ GUARDED_BY(devirt_maps_lock_);
   static void SetDevirtMap(CompilerDriver::MethodReference ref,
                            const PcToConcreteMethod* pc_method_map)
@@ -616,20 +616,20 @@
   // Storage for the register status we're saving for later.
   UniquePtr<RegisterLine> saved_line_;
 
-  uint32_t dex_method_idx_;  // The method we're working on.
+  const uint32_t dex_method_idx_;  // The method we're working on.
   // Its object representation if known.
-  mirror::AbstractMethod* foo_method_ GUARDED_BY(Locks::mutator_lock_);
-  uint32_t method_access_flags_;  // Method's access flags.
-  const DexFile* dex_file_;  // The dex file containing the method.
+  mirror::AbstractMethod* mirror_method_ GUARDED_BY(Locks::mutator_lock_);
+  const uint32_t method_access_flags_;  // Method's access flags.
+  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_);
   // The class loader for the declaring class of the method.
   mirror::ClassLoader* class_loader_ GUARDED_BY(Locks::mutator_lock_);
-  uint32_t class_def_idx_;  // The class def index of the declaring class of the method.
-  const DexFile::CodeItem* code_item_;  // The code item containing the code for the method.
+  const uint32_t class_def_idx_;  // The class def index of the declaring class of the method.
+  const DexFile::CodeItem* const code_item_;  // The code item containing the code for the method.
+  const RegType* declaring_class_;  // Lazily computed reg type of the method's declaring class.
   // Instruction widths and flags, one entry per code unit.
   UniquePtr<InstructionFlags[]> insn_flags_;
-
   // The dex PC of a FindLocksAtDexPc request, -1 otherwise.
   uint32_t interesting_dex_pc_;
   // The container into which FindLocksAtDexPc should write the registers containing held locks,
diff --git a/src/verifier/reg_type.cc b/src/verifier/reg_type.cc
index 5db6aff..e738e80 100644
--- a/src/verifier/reg_type.cc
+++ b/src/verifier/reg_type.cc
@@ -25,6 +25,7 @@
 #include "mirror/object_array-inl.h"
 #include "object_utils.h"
 #include "reg_type_cache-inl.h"
+#include "scoped_thread_state_change.h"
 
 #include <limits>
 #include <sstream>
@@ -45,6 +46,41 @@
 DoubleHiType* DoubleHiType::instance_ = NULL;
 IntegerType* IntegerType::instance_ = NULL;
 
+int32_t RegType::ConstantValue() const {
+  ScopedObjectAccess soa(Thread::Current());
+  LOG(FATAL) << "Unexpected call to ConstantValue: " << *this;
+  return 0;
+}
+
+int32_t RegType::ConstantValueLo() const {
+  ScopedObjectAccess soa(Thread::Current());
+  LOG(FATAL) << "Unexpected call to ConstantValueLo: " << *this;
+  return 0;
+}
+
+int32_t RegType::ConstantValueHi() const {
+  ScopedObjectAccess soa(Thread::Current());
+  LOG(FATAL) << "Unexpected call to ConstantValueHi: " << *this;
+  return 0;
+}
+
+PrimitiveType::PrimitiveType(mirror::Class* klass, const std::string& descriptor, uint16_t cache_id)
+    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_)
+    : RegType(klass, descriptor, cache_id) {
+  CHECK(klass != NULL);
+  CHECK(!descriptor.empty());
+}
+
+Cat1Type::Cat1Type(mirror::Class* klass, const std::string& descriptor, uint16_t cache_id)
+    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_)
+    : PrimitiveType(klass, descriptor, cache_id) {
+}
+
+Cat2Type::Cat2Type(mirror::Class* klass, const std::string& descriptor, uint16_t cache_id)
+    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_)
+    : PrimitiveType(klass, descriptor, cache_id) {
+}
+
 std::string PreciseConstType::Dump() const {
   std::stringstream result;
   uint32_t val = ConstantValue();
@@ -349,6 +385,12 @@
   }
 }
 
+PreciseReferenceType::PreciseReferenceType(mirror::Class* klass, const std::string& descriptor,
+                                           uint16_t cache_id)
+    : RegType(klass, descriptor, cache_id) {
+  DCHECK(klass->IsInstantiable());
+}
+
 std::string UnresolvedMergedType::Dump() const {
   std::stringstream result;
   std::set<uint16_t> types = GetMergedTypes();
@@ -486,80 +528,10 @@
   return result.str();
 }
 
-BooleanType::BooleanType(mirror::Class* klass, const std::string& descriptor, uint16_t cache_id)
-    : RegType(klass, descriptor, cache_id) {
-}
-
-ConflictType::ConflictType(mirror::Class* klass, const std::string& descriptor, uint16_t cache_id)
-    : RegType(klass, descriptor, cache_id) {
-}
-
-ByteType::ByteType(mirror::Class* klass, const std::string& descriptor, uint16_t cache_id)
-    : RegType(klass, descriptor, cache_id) {
-}
-
-ShortType::ShortType(mirror::Class* klass, const std::string& descriptor, uint16_t cache_id)
-    : RegType(klass, descriptor, cache_id) {
-}
-
-CharType::CharType(mirror::Class* klass, const std::string& descriptor, uint16_t cache_id)
-    : RegType(klass, descriptor, cache_id) {
-}
-
-IntegerType::IntegerType(mirror::Class* klass, const std::string& descriptor, uint16_t cache_id)
-    : RegType(klass, descriptor, cache_id) {
-}
-
 ConstantType::ConstantType(uint32_t constant, uint16_t cache_id)
     : RegType(NULL, "", cache_id), constant_(constant) {
 }
 
-ReferenceType::ReferenceType(mirror::Class* klass, const std::string& descriptor, uint16_t cache_id)
-    : RegType(klass, descriptor, cache_id) {
-}
-
-PreciseReferenceType::PreciseReferenceType(mirror::Class* klass, const std::string& descriptor,
-                                           uint16_t cache_id)
-    : RegType(klass, descriptor, cache_id) {
-  DCHECK(klass->IsInstantiable());
-}
-
-UnresolvedUninitializedThisRefType::UnresolvedUninitializedThisRefType(const std::string& descriptor,
-                                                                       uint16_t cache_id)
-    : UninitializedType(NULL, descriptor, 0, cache_id) {
-}
-
-UnresolvedUninitializedRefType::UnresolvedUninitializedRefType(const std::string& descriptor,
-                                                         uint32_t allocation_pc, uint16_t cache_id)
-    : UninitializedType(NULL, descriptor, allocation_pc, cache_id) {
-}
-
-UninitializedReferenceType::UninitializedReferenceType(mirror::Class* klass,
-                                                       const std::string& descriptor,
-                                                       uint32_t allocation_pc, uint16_t cache_id)
-    : UninitializedType(klass, descriptor, allocation_pc, cache_id) {
-}
-
-LongHiType::LongHiType(mirror::Class* klass, const std::string& descriptor, uint16_t cache_id)
-    : RegType(klass, descriptor, cache_id) {
-}
-
-FloatType::FloatType(mirror::Class* klass, const std::string& descriptor, uint16_t cache_id)
-    : RegType(klass, descriptor, cache_id) {
-}
-
-DoubleLoType::DoubleLoType(mirror::Class* klass,  const std::string& descriptor, uint16_t cache_id)
-    : RegType(klass, descriptor, cache_id) {
-}
-
-DoubleHiType::DoubleHiType(mirror::Class* klass, const std::string& descriptor, uint16_t cache_id)
-    : RegType(klass, descriptor, cache_id) {
-}
-
-LongLoType::LongLoType(mirror::Class* klass, const std::string& descriptor, uint16_t cache_id)
-    : RegType(klass, descriptor, cache_id) {
-}
-
 const RegType& UndefinedType::Merge(const RegType& incoming_type, RegTypeCache* reg_types) const
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
   if (incoming_type.IsUndefined()) {
@@ -603,6 +575,17 @@
   }
 }
 
+bool UninitializedType::IsUninitializedTypes() const {
+  return true;
+}
+
+bool UninitializedType::IsNonZeroReferenceTypes() const {
+  return true;
+}
+
+bool UnresolvedType::IsNonZeroReferenceTypes() const {
+  return true;
+}
 std::set<uint16_t> UnresolvedMergedType::GetMergedTypes() const {
   std::pair<uint16_t, uint16_t> refs = GetTopMergedTypes();
   const RegType& _left(reg_type_cache_->GetFromId(refs.first));
@@ -640,7 +623,7 @@
     if (super_klass != NULL) {
       // A super class of a precise type isn't precise as a precise type indicates the register
       // holds exactly that type.
-      return cache->FromClass(super_klass, false);
+      return cache->FromClass(ClassHelper(super_klass).GetDescriptor(), super_klass, false);
     } else {
       return cache->Zero();
     }
@@ -915,7 +898,7 @@
       } else if (c2 == join_class && !incoming_type.IsPreciseReference()) {
         return incoming_type;
       } else {
-        return reg_types->FromClass(join_class, false);
+        return reg_types->FromClass(ClassHelper(join_class).GetDescriptor(), join_class, false);
       }
     }
   } else {
@@ -980,33 +963,22 @@
     CHECK(descriptor_.empty()) << *this;
     CHECK(klass_ == NULL) << *this;
   }
-}
-
-UninitializedType::UninitializedType(mirror::Class* klass, const std::string& descriptor,
-                                     uint32_t allocation_pc, uint16_t cache_id)
-    : RegType(klass, descriptor, cache_id), allocation_pc_(allocation_pc) {
-}
-
-void UninitializedType::CheckInvariants() const {
-  CHECK_EQ(allocation_pc_, 0U) << *this;
+  if (klass_ != NULL) {
+    CHECK(!descriptor_.empty()) << *this;
+  }
 }
 
 void UninitializedThisReferenceType::CheckInvariants() const {
-  UninitializedType::CheckInvariants();
-}
-
-UninitializedThisReferenceType::UninitializedThisReferenceType(mirror::Class* klass,
-  const std::string& descriptor, uint16_t cache_id) : UninitializedType(klass, descriptor, 0, cache_id) {
+  CHECK_EQ(GetAllocationPc(), 0U) << *this;
 }
 
 void UnresolvedUninitializedThisRefType::CheckInvariants() const {
-  UninitializedType::CheckInvariants();
+  CHECK_EQ(GetAllocationPc(), 0U) << *this;
   CHECK(!descriptor_.empty()) << *this;
   CHECK(klass_ == NULL) << *this;
 }
 
 void UnresolvedUninitializedRefType::CheckInvariants() const {
-  UninitializedType::CheckInvariants();
   CHECK(!descriptor_.empty()) << *this;
   CHECK(klass_ == NULL) << *this;
 }
diff --git a/src/verifier/reg_type.h b/src/verifier/reg_type.h
index 39c33c6..424b071 100644
--- a/src/verifier/reg_type.h
+++ b/src/verifier/reg_type.h
@@ -18,6 +18,7 @@
 #define ART_SRC_VERIFIER_REG_TYPE_H_
 
 #include "base/macros.h"
+#include "globals.h"
 #include "primitive.h"
 
 #include "jni.h"
@@ -39,105 +40,43 @@
  */
 class RegType {
  public:
-  // The high half that corresponds to this low half
-  const RegType& HighHalf(RegTypeCache* cache) const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
-  inline virtual bool IsUndefined() const {
-    return false;
-  }
-  inline virtual bool IsConflict() const {
-    return false;
-  }
-  inline virtual bool IsBoolean() const {
-    return false;
-  }
-  inline virtual bool IsByte() const {
-    return false;
-  }
-  inline virtual bool IsChar() const {
-    return false;
-  }
-  inline virtual bool IsShort() const {
-    return false;
-  }
-  inline virtual bool IsInteger() const {
-    return false;
-  }
-  inline virtual bool IsLongLo() const {
-    return false;
-  }
-  inline virtual bool IsLongHi() const {
-    return false;
-  }
-  inline virtual bool IsFloat() const {
-    return false;
-  }
-  inline virtual bool IsDouble() const {
-    return false;
-  }
-  inline virtual bool IsDoubleLo() const {
-    return false;
-  }
-  inline virtual bool IsDoubleHi() const {
-    return false;
-  }
-  inline virtual bool IsUnresolvedReference() const {
-    return false;
-  }
-  inline virtual bool IsUninitializedReference() const {
-    return false;
-  }
-  inline virtual bool IsUninitializedThisReference() const {
-    return false;
-  }
-  inline virtual bool IsUnresolvedAndUninitializedReference() const {
-    return false;
-  }
-  inline virtual bool IsUnresolvedAndUninitializedThisReference() const {
-    return false;
-  }
-  inline virtual bool IsUnresolvedMergedReference() const {
-    return false;
-  }
-  inline virtual bool IsUnresolvedSuperClass() const {
-    return false;
-  }
-  inline virtual bool IsReference() const {
-    return false;
-  }
-  inline virtual bool IsPreciseReference() const {
-    return false;
-  }
-  inline virtual bool IsPreciseConstant() const {
-    return false;
-  }
-  inline virtual bool IsPreciseConstantLo() const {
-    return false;
-  }
-  inline virtual bool IsPreciseConstantHi() const {
-    return false;
-  }
-  inline virtual bool IsImpreciseConstantLo() const {
-    return false;
-  }
-  inline virtual bool IsImpreciseConstantHi() const {
-    return false;
-  }
-  virtual bool IsImpreciseConstant() const {
-    return false;
-  }
-
-  inline virtual bool IsConstantTypes() const {
-    return false;
-  }
+  virtual bool IsUndefined() const { return false; }
+  virtual bool IsConflict() const { return false; }
+  virtual bool IsBoolean() const { return false; }
+  virtual bool IsByte() const { return false; }
+  virtual bool IsChar() const { return false; }
+  virtual bool IsShort() const { return false; }
+  virtual bool IsInteger() const { return false; }
+  virtual bool IsLongLo() const { return false; }
+  virtual bool IsLongHi() const { return false; }
+  virtual bool IsFloat() const { return false; }
+  virtual bool IsDouble() const { return false; }
+  virtual bool IsDoubleLo() const { return false; }
+  virtual bool IsDoubleHi() const { return false; }
+  virtual bool IsUnresolvedReference() const { return false; }
+  virtual bool IsUninitializedReference() const { return false; }
+  virtual bool IsUninitializedThisReference() const { return false; }
+  virtual bool IsUnresolvedAndUninitializedReference() const { return false; }
+  virtual bool IsUnresolvedAndUninitializedThisReference() const { return false; }
+  virtual bool IsUnresolvedMergedReference() const { return false; }
+  virtual bool IsUnresolvedSuperClass() const { return false; }
+  virtual bool IsReference() const { return false; }
+  virtual bool IsPreciseReference() const { return false; }
+  virtual bool IsPreciseConstant() const { return false; }
+  virtual bool IsPreciseConstantLo() const { return false; }
+  virtual bool IsPreciseConstantHi() const { return false; }
+  virtual bool IsImpreciseConstantLo() const { return false; }
+  virtual bool IsImpreciseConstantHi() const { return false; }
+  virtual bool IsImpreciseConstant() const { return false; }
+  virtual bool IsConstantTypes() const { return false; }
   bool IsConstant() const {
-    return (IsPreciseConstant() || IsImpreciseConstant());
+    return IsPreciseConstant() || IsImpreciseConstant();
   }
   bool IsConstantLo() const {
-    return (IsPreciseConstantLo() || IsImpreciseConstantLo());
+    return IsPreciseConstantLo() || IsImpreciseConstantLo();
   }
   bool IsPrecise() const {
-    return (IsPreciseConstantLo() || IsPreciseConstant() ||
-            IsPreciseConstantHi());
+    return IsPreciseConstantLo() || IsPreciseConstant() || IsPreciseConstantHi();
   }
   bool IsLongConstant() const {
     return IsConstantLo();
@@ -148,11 +87,7 @@
   bool IsLongConstantHigh() const {
     return IsConstantHi();
   }
-  bool IsUninitializedTypes() const {
-    return IsUninitializedReference() || IsUninitializedThisReference() ||
-           IsUnresolvedAndUninitializedReference() ||
-           IsUnresolvedAndUninitializedThisReference();
-  }
+  virtual bool IsUninitializedTypes() const { return false; }
   bool IsUnresolvedTypes() const {
     return IsUnresolvedReference() || IsUnresolvedAndUninitializedReference() ||
            IsUnresolvedAndUninitializedThisReference() ||
@@ -170,7 +105,7 @@
   bool IsLongOrDoubleTypes() const {
     return IsLowHalf();
   }
-  // Check this is the low half, and that type_h is its matching high-half
+  // Check this is the low half, and that type_h is its matching high-half.
   inline bool CheckWidePair(const RegType& type_h) const {
     if (IsLowHalf()) {
       return ((IsPreciseConstantLo() && type_h.IsPreciseConstantHi()) ||
@@ -182,37 +117,36 @@
     }
     return false;
   }
+  // The high half that corresponds to this low half
+  const RegType& HighHalf(RegTypeCache* cache) const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+
   bool IsConstantBoolean() const {
     return IsConstant() && (ConstantValue() >= 0) && (ConstantValue() <= 1);
   }
-  inline virtual bool IsConstantChar() const {
+  virtual bool IsConstantChar() const {
     return false;
   }
-  inline virtual bool IsConstantByte() const {
+  virtual bool IsConstantByte() const {
     return false;
   }
-  inline virtual bool IsConstantShort() const {
+  virtual bool IsConstantShort() const {
     return false;
   }
-  inline virtual bool IsOne() const {
+  virtual bool IsOne() const {
     return false;
   }
-  inline virtual bool IsZero() const {
+  virtual bool IsZero() const {
     return false;
   }
   bool IsReferenceTypes() const {
     return IsNonZeroReferenceTypes() || IsZero();
   }
-  bool IsNonZeroReferenceTypes() const {
-    return IsReference() || IsPreciseReference() ||
-           IsUninitializedReference() || IsUninitializedThisReference() ||
-           IsUnresolvedReference() || IsUnresolvedAndUninitializedReference() ||
-           IsUnresolvedAndUninitializedThisReference() ||
-           IsUnresolvedMergedReference() || IsUnresolvedSuperClass();
+  virtual bool IsNonZeroReferenceTypes() const {
+    return false;
   }
   bool IsCategory1Types() const {
-    return (IsChar() || IsInteger() || IsFloat() || IsConstant() || IsByte() ||
-        IsShort() || IsBoolean()  );
+    return IsChar() || IsInteger() || IsFloat() || IsConstant() || IsByte() || IsShort() ||
+        IsBoolean();
   }
   bool IsCategory2Types() const {
     return IsLowHalf();  // Don't expect explicit testing of high halves
@@ -230,20 +164,12 @@
     return IsChar() || IsBooleanTypes() || IsConstantChar();
   }
   bool IsIntegralTypes() const {
-    return (IsInteger() || IsConstant() || IsByte() || IsShort() || IsChar() || IsBoolean() );
+    return IsInteger() || IsConstant() || IsByte() || IsShort() || IsChar() || IsBoolean();
   }
-  inline virtual int32_t ConstantValue() const {
-    DCHECK(IsConstant());
-    return -1;
-  }
-  inline virtual int32_t ConstantValueLo() const {
-    DCHECK(IsConstantLo());
-    return -1;
-  }
-  inline virtual int32_t ConstantValueHi() const {
-    DCHECK(IsConstantHi());
-    return -1;
-  }
+  // Give the constant value encoded, but this shouldn't be called in the general case.
+  virtual int32_t ConstantValue() const;
+  virtual int32_t ConstantValueLo() const;
+  virtual int32_t ConstantValueHi() const;
   bool IsArrayIndexTypes() const {
     return IsIntegralTypes();
   }
@@ -265,7 +191,7 @@
   bool IsDoubleHighTypes() const {
     return (IsDoubleHi() || IsPreciseConstantHi() || IsImpreciseConstantHi());
   }
-  inline virtual bool IsLong() const {
+  virtual bool IsLong() const {
     return false;
   }
   virtual bool HasClass() const {
@@ -278,34 +204,43 @@
   bool IsJavaLangObjectArray() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
   bool IsInstantiableTypes() const;
   const std::string& GetDescriptor() const {
-    DCHECK(IsUnresolvedTypes() && !IsUnresolvedMergedReference() && !IsUnresolvedSuperClass());
+    DCHECK(HasClass() || (IsUnresolvedTypes() && !IsUnresolvedMergedReference() &&
+                          !IsUnresolvedSuperClass()));
     return descriptor_;
   }
-  uint16_t GetId() const {
-    return cache_id_;
-  }
-  const RegType& GetSuperClass(RegTypeCache* cache) const
-      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
-  virtual std::string Dump() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) = 0;
-  // Can this type access other?
-  bool CanAccess(const RegType& other) const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
-  // Can this type access a member with the given properties?
-  bool CanAccessMember(mirror::Class* klass, uint32_t access_flags) const
-    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
-  // Can this type be assigned by src?
-  bool IsAssignableFrom(const RegType& src) const  SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
-  bool Equals(const RegType& other) const {
-    return GetId() == other.GetId();
-  }
-  // Compute the merge of this register from one edge (path) with incoming_type from another.
-  virtual const RegType& Merge(const RegType& incoming_type, RegTypeCache* reg_types) const
-      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
   mirror::Class* GetClass() const {
     DCHECK(!IsUnresolvedReference());
     DCHECK(klass_ != NULL);
     DCHECK(HasClass());
     return klass_;
   }
+  uint16_t GetId() const {
+    return cache_id_;
+  }
+  const RegType& GetSuperClass(RegTypeCache* cache) const
+      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+
+  virtual std::string Dump() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) = 0;
+
+  // Can this type access other?
+  bool CanAccess(const RegType& other) const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+
+  // Can this type access a member with the given properties?
+  bool CanAccessMember(mirror::Class* klass, uint32_t access_flags) const
+    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+
+  // Can this type be assigned by src?
+  bool IsAssignableFrom(const RegType& src) const  SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+
+  // Are these RegTypes the same?
+  bool Equals(const RegType& other) const {
+    return GetId() == other.GetId();
+  }
+
+  // Compute the merge of this register from one edge (path) with incoming_type from another.
+  virtual const RegType& Merge(const RegType& incoming_type, RegTypeCache* reg_types) const
+      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+
     /*
      * A basic Join operation on classes. For a pair of types S and T the Join, written S v T = J, is
      * S <: J, T <: J and for-all U such that S <: U, T <: U then J <: U. That is J is the parent of
@@ -325,62 +260,103 @@
 
   static mirror::Class* ClassJoin(mirror::Class* s, mirror::Class* t)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+
+  virtual ~RegType() {}
+
+ protected:
   RegType(mirror::Class* klass, const std::string& descriptor, uint16_t cache_id)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_)
       : descriptor_(descriptor), klass_(klass), cache_id_(cache_id) {
+    if (kIsDebugBuild) {
+      CheckInvariants();
+    }
   }
-  inline virtual ~RegType() {
-  }
-  virtual void CheckInvariants() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
-  friend class RegTypeCache;
 
- protected:
+  void CheckInvariants() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+
+
   const std::string descriptor_;
-  mirror::Class* klass_;
+  mirror::Class* const klass_;
   const uint16_t cache_id_;
 
+  friend class RegTypeCache;
+
   DISALLOW_COPY_AND_ASSIGN(RegType);
 };
 
+// Bottom type.
 class ConflictType : public RegType {
  public:
   bool IsConflict() const {
     return true;
   }
+
   std::string Dump() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+
+  // Get the singleton Conflict instance.
+  static ConflictType* GetInstance();
+
+  // Create the singleton instance.
   static ConflictType* CreateInstance(mirror::Class* klass, const std::string& descriptor,
                                       uint16_t cache_id)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
-  static ConflictType* GetInstance();
+
+  // Destroy the singleton instance.
   static void Destroy();
  private:
   ConflictType(mirror::Class* klass, const std::string& descriptor, uint16_t cache_id)
-      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_)
+      : RegType(klass, descriptor, cache_id) {
+  }
+
   static ConflictType* instance_;
 };
 
+// A variant of the bottom type used to specify an undefined value in the incoming registers.
+// Merging with UndefinedType yields ConflictType which is the true bottom.
 class UndefinedType : public RegType {
  public:
   bool IsUndefined() const {
     return true;
   }
+
   std::string Dump() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+
+  // Get the singleton Undefined instance.
+  static UndefinedType* GetInstance();
+
+  // Create the singleton instance.
   static UndefinedType* CreateInstance(mirror::Class* klass, const std::string& descriptor,
                                        uint16_t cache_id)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
-  static UndefinedType* GetInstance();
+
+  // Destroy the singleton instance.
   static void Destroy();
  private:
   UndefinedType(mirror::Class* klass, const std::string& descriptor, uint16_t cache_id)
      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_)
       : RegType(klass, descriptor, cache_id) {
   }
+
   virtual const RegType& Merge(const RegType& incoming_type, RegTypeCache* reg_types) const
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+
   static UndefinedType* instance_;
 };
 
-class IntegerType : public RegType {
+class PrimitiveType : public RegType {
+ public:
+  PrimitiveType(mirror::Class* klass, const std::string& descriptor, uint16_t cache_id)
+      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+};
+
+class Cat1Type : public PrimitiveType {
+ public:
+  Cat1Type(mirror::Class* klass, const std::string& descriptor, uint16_t cache_id)
+      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+};
+
+class IntegerType : public Cat1Type {
  public:
   bool IsInteger() const {
     return true;
@@ -393,11 +369,13 @@
   static void Destroy();
  private:
   IntegerType(mirror::Class* klass, const std::string& descriptor, uint16_t cache_id)
-      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_)
+      : Cat1Type(klass, descriptor, cache_id) {
+  }
   static IntegerType* instance_;
 };
 
-class BooleanType : public RegType {
+class BooleanType : public Cat1Type {
  public:
   bool IsBoolean() const {
     return true;
@@ -410,11 +388,14 @@
   static void Destroy();
  private:
   BooleanType(mirror::Class* klass, const std::string& descriptor, uint16_t cache_id)
-      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_)
+      : Cat1Type(klass, descriptor, cache_id) {
+  }
+
   static BooleanType* instance;
 };
 
-class ByteType : public RegType {
+class ByteType : public Cat1Type {
  public:
   bool IsByte() const {
     return true;
@@ -427,11 +408,13 @@
   static void Destroy();
  private:
   ByteType(mirror::Class* klass, const std::string& descriptor, uint16_t cache_id)
-      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_)
+      : Cat1Type(klass, descriptor, cache_id) {
+  }
   static ByteType* instance_;
 };
 
-class ShortType : public RegType {
+class ShortType : public Cat1Type {
  public:
   bool IsShort() const {
     return true;
@@ -444,11 +427,13 @@
   static void Destroy();
  private:
   ShortType(mirror::Class* klass, const std::string& descriptor, uint16_t cache_id)
-      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_)
+      : Cat1Type(klass, descriptor, cache_id) {
+  }
   static ShortType* instance_;
 };
 
-class CharType : public RegType {
+class CharType : public Cat1Type {
  public:
   bool IsChar() const {
     return true;
@@ -461,11 +446,13 @@
   static void Destroy();
  private:
   CharType(mirror::Class* klass, const std::string& descriptor, uint16_t cache_id)
-      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_)
+      : Cat1Type(klass, descriptor, cache_id) {
+  }
   static CharType* instance_;
 };
 
-class FloatType : public RegType {
+class FloatType : public Cat1Type {
  public:
   bool IsFloat() const {
     return true;
@@ -478,11 +465,19 @@
   static void Destroy();
  private:
   FloatType(mirror::Class* klass, const std::string& descriptor, uint16_t cache_id)
-      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_)
+      : Cat1Type(klass, descriptor, cache_id) {
+  }
   static FloatType* instance_;
 };
 
-class LongLoType : public RegType {
+class Cat2Type : public PrimitiveType {
+ public:
+  Cat2Type(mirror::Class* klass, const std::string& descriptor, uint16_t cache_id)
+      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+};
+
+class LongLoType : public Cat2Type {
  public:
   std::string Dump() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
   bool IsLongLo() const {
@@ -498,11 +493,13 @@
   static void Destroy();
  private:
   LongLoType(mirror::Class* klass, const std::string& descriptor, uint16_t cache_id)
-      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_)
+      : Cat2Type(klass, descriptor, cache_id) {
+  }
   static LongLoType* instance_;
 };
 
-class LongHiType : public RegType {
+class LongHiType : public Cat2Type {
  public:
   std::string Dump() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
   bool IsLongHi() const {
@@ -515,11 +512,13 @@
   static void Destroy();
  private:
   LongHiType(mirror::Class* klass, const std::string& descriptor, uint16_t cache_id)
-      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_)
+      : Cat2Type(klass, descriptor, cache_id) {
+  }
   static LongHiType* instance_;
 };
 
-class DoubleLoType : public RegType {
+class DoubleLoType : public Cat2Type {
  public:
   std::string Dump() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
   bool IsDoubleLo() const {
@@ -535,11 +534,13 @@
   static void Destroy();
  private:
   DoubleLoType(mirror::Class* klass, const std::string& descriptor, uint16_t cache_id)
-      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_)
+      : Cat2Type(klass, descriptor, cache_id) {
+  }
   static DoubleLoType* instance_;
 };
 
-class DoubleHiType : public RegType {
+class DoubleHiType : public Cat2Type {
  public:
   std::string Dump() const;
   virtual bool IsDoubleHi() const {
@@ -552,7 +553,9 @@
   static void Destroy();
  private:
   DoubleHiType(mirror::Class* klass, const std::string& descriptor, uint16_t cache_id)
-      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_)
+      : Cat2Type(klass, descriptor, cache_id) {
+  }
   static DoubleHiType* instance_;
 };
 
@@ -560,9 +563,6 @@
  public:
   ConstantType(uint32_t constat, uint16_t cache_id) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
-  inline virtual ~ConstantType() {
-  }
-  const uint32_t constant_;
   // 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;
@@ -590,7 +590,10 @@
            ConstantValue() >= std::numeric_limits<jshort>::min() &&
            ConstantValue() <= std::numeric_limits<jshort>::max();
   }
-  inline virtual bool IsConstantTypes() const { return true; }
+  virtual bool IsConstantTypes() const { return true; }
+
+ private:
+  const uint32_t constant_;
 };
 
 class PreciseConstType : public ConstantType {
@@ -662,159 +665,254 @@
   std::string Dump() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 };
 
+// Common parent of all uninitialized types. Uninitialized types are created by "new" dex
+// instructions and must be passed to a constructor.
 class UninitializedType : public RegType {
  public:
   UninitializedType(mirror::Class* klass, const std::string& descriptor, uint32_t allocation_pc,
-                    uint16_t cache_id);
-  inline virtual ~UninitializedType() {
+                    uint16_t cache_id)
+      : RegType(klass, descriptor, cache_id), allocation_pc_(allocation_pc) {
   }
 
+  bool IsUninitializedTypes() const;
+  bool IsNonZeroReferenceTypes() const;
+
   uint32_t GetAllocationPc() const {
     DCHECK(IsUninitializedTypes());
     return allocation_pc_;
   }
-  virtual void CheckInvariants() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
  private:
   const uint32_t allocation_pc_;
 };
 
+// Similar to ReferenceType but not yet having been passed to a constructor.
 class UninitializedReferenceType : public UninitializedType {
  public:
-  UninitializedReferenceType(mirror::Class* klass, const std::string& descriptor, uint32_t allocation_pc,
-                             uint16_t cache_id) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+  UninitializedReferenceType(mirror::Class* klass, const std::string& descriptor,
+                             uint32_t allocation_pc, uint16_t cache_id)
+      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_)
+      : UninitializedType(klass, descriptor, allocation_pc, cache_id) {
+  }
 
   bool IsUninitializedReference() const {
     return true;
   }
+
   bool HasClass() const {
     return true;
   }
+
   std::string Dump() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 };
 
+// Similar to UnresolvedReferenceType but not yet having been passed to a constructor.
 class UnresolvedUninitializedRefType : public UninitializedType {
  public:
   UnresolvedUninitializedRefType(const std::string& descriptor, uint32_t allocation_pc,
-                                 uint16_t cache_id) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
-  void CheckInvariants() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+                                 uint16_t cache_id)
+      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_)
+      : UninitializedType(NULL, descriptor, allocation_pc, cache_id) {
+    if (kIsDebugBuild) {
+      CheckInvariants();
+    }
+  }
+
   bool IsUnresolvedAndUninitializedReference() const {
     return true;
   }
+
   std::string Dump() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+ private:
+  void CheckInvariants() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 };
 
+// Similar to UninitializedReferenceType but special case for the this argument of a constructor.
 class UninitializedThisReferenceType : public UninitializedType {
  public:
-  UninitializedThisReferenceType(mirror::Class* klass, const std::string& descriptor, uint16_t cache_id)
-      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
-  std::string Dump() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
-  void CheckInvariants() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+  UninitializedThisReferenceType(mirror::Class* klass, const std::string& descriptor,
+                                 uint16_t cache_id)
+      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_)
+      : UninitializedType(klass, descriptor, 0, cache_id) {
+    if (kIsDebugBuild) {
+      CheckInvariants();
+    }
+  }
+
   virtual bool IsUninitializedThisReference() const {
     return true;
   }
+
   bool HasClass() const {
     return true;
   }
+
+  std::string Dump() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+
+ private:
+  void CheckInvariants() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 };
 
 class UnresolvedUninitializedThisRefType : public UninitializedType {
  public:
   UnresolvedUninitializedThisRefType(const std::string& descriptor, uint16_t cache_id)
-      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
-  void CheckInvariants() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
-  std::string Dump() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_)
+      : UninitializedType(NULL, descriptor, 0, cache_id) {
+    if (kIsDebugBuild) {
+      CheckInvariants();
+    }
+  }
+
   bool IsUnresolvedAndUninitializedThisReference() const {
     return true;
   }
+
+  std::string Dump() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+ private:
+  void CheckInvariants() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 };
 
+// A type of register holding a reference to an Object of type GetClass or a sub-class.
 class ReferenceType : public RegType {
  public:
   ReferenceType(mirror::Class* klass, const std::string& descriptor, uint16_t cache_id)
-     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_)
+     : RegType(klass, descriptor, cache_id) {
+  }
+
   bool IsReference() const {
     return true;
   }
+
+  bool IsNonZeroReferenceTypes() const {
+    return true;
+  }
+
   bool HasClass() const {
     return true;
   }
+
   std::string Dump() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 };
 
+// A type of register holding a reference to an Object of type GetClass and only an object of that
+// type.
 class PreciseReferenceType : public RegType {
  public:
   PreciseReferenceType(mirror::Class* klass, const std::string& descriptor, uint16_t cache_id)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
-  std::string Dump() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+
   bool IsPreciseReference() const {
     return true;
   }
+
+  bool IsNonZeroReferenceTypes() const {
+    return true;
+  }
+
   bool HasClass() const {
     return true;
   }
+
+  std::string Dump() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 };
 
-class UnresolvedReferenceType : public RegType {
+// Common parent of unresolved types.
+class UnresolvedType : public RegType {
+ public:
+  UnresolvedType(const std::string& descriptor, uint16_t cache_id)
+      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) : RegType(NULL, descriptor, cache_id) {
+  }
+
+  bool IsNonZeroReferenceTypes() const;
+};
+
+// Similar to ReferenceType except the Class couldn't be loaded. Assignability and other tests made
+// of this type must be conservative.
+class UnresolvedReferenceType : public UnresolvedType {
  public:
   UnresolvedReferenceType(const std::string& descriptor, uint16_t cache_id)
-     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) : RegType(NULL, descriptor, cache_id) {
+     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) : UnresolvedType(descriptor, cache_id) {
+    if (kIsDebugBuild) {
+      CheckInvariants();
+    }
   }
-  std::string Dump() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
-  void CheckInvariants() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+
   bool IsUnresolvedReference() const {
     return true;
   }
+
+  std::string Dump() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+ private:
+  void CheckInvariants() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 };
 
-class UnresolvedSuperClass : public RegType {
+// Type representing the super-class of an unresolved type.
+class UnresolvedSuperClass : public UnresolvedType {
  public:
   UnresolvedSuperClass(uint16_t child_id, RegTypeCache* reg_type_cache, uint16_t cache_id)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_)
-      : RegType(NULL, "", cache_id), unresolved_child_id_(child_id),
+      : UnresolvedType("", cache_id), unresolved_child_id_(child_id),
         reg_type_cache_(reg_type_cache) {
+    if (kIsDebugBuild) {
+      CheckInvariants();
+    }
   }
+
   bool IsUnresolvedSuperClass() const {
     return true;
   }
+
   uint16_t GetUnresolvedSuperClassChildId() const {
     DCHECK(IsUnresolvedSuperClass());
     return static_cast<uint16_t>(unresolved_child_id_ & 0xFFFF);
   }
-  void CheckInvariants() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
-  std::string Dump() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
+  std::string Dump() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
  private:
+  void CheckInvariants() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+
   const uint16_t unresolved_child_id_;
   const RegTypeCache* const reg_type_cache_;
 };
 
-class UnresolvedMergedType : public RegType {
+// A merge of two unresolved types. If the types were resolved this may be Conflict or another
+// known ReferenceType.
+class UnresolvedMergedType : public UnresolvedType {
  public:
-  UnresolvedMergedType(uint16_t left_id, uint16_t right_id, const RegTypeCache* reg_type_cache, uint16_t cache_id)
+  UnresolvedMergedType(uint16_t left_id, uint16_t right_id, const RegTypeCache* reg_type_cache,
+                       uint16_t cache_id)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_)
-      : RegType(NULL, "", cache_id), reg_type_cache_(reg_type_cache) ,merged_types_(left_id, right_id) {
+      : UnresolvedType("", cache_id), reg_type_cache_(reg_type_cache) ,merged_types_(left_id, right_id) {
+    if (kIsDebugBuild) {
+      CheckInvariants();
+    }
   }
+
   // The top of a tree of merged types.
   std::pair<uint16_t, uint16_t> GetTopMergedTypes() const {
     DCHECK(IsUnresolvedMergedReference());
     return merged_types_;
   }
+
   // The complete set of merged types.
   std::set<uint16_t> GetMergedTypes() const;
+
   bool IsUnresolvedMergedReference() const {
     return true;
   }
-  void CheckInvariants() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
-  std::string Dump() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
+  std::string Dump() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
  private:
+  void CheckInvariants() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+
   const RegTypeCache* const reg_type_cache_;
   const std::pair<uint16_t, uint16_t> merged_types_;
 };
 
 std::ostream& operator<<(std::ostream& os, const RegType& rhs)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+
 }  // namespace verifier
 }  // namespace art
 
diff --git a/src/verifier/reg_type_cache.cc b/src/verifier/reg_type_cache.cc
index 57a825b..a575f77 100644
--- a/src/verifier/reg_type_cache.cc
+++ b/src/verifier/reg_type_cache.cc
@@ -108,29 +108,14 @@
 }
 
 bool RegTypeCache::MatchDescriptor(size_t idx, const char* descriptor, bool precise) {
-  RegType* cur_entry = entries_[idx];
-  if (cur_entry->HasClass()) {
-    // Check the descriptor in the reg_type if available.
-    if(!cur_entry->descriptor_.empty()) {
-      if (cur_entry->descriptor_ == descriptor && MatchingPrecisionForClass(cur_entry, precise)) {
-        return true;
-      }
-    } else {
-      // TODO: maintain an invariant that when we have a Class the descriptor is computed from that.
-      // Descriptor not found in reg_type, maybe available in Class object.
-      // So we might have cases where we have the class but not the descriptor
-      // for that class we need the class helper to get the descriptor
-      // and match it with the one we are given.
-      ClassHelper kh(cur_entry->GetClass());
-      if ((strcmp(descriptor, kh.GetDescriptor()) == 0) &&
-          MatchingPrecisionForClass(cur_entry, precise)) {
-        return true;
-      }
-    }
-  } else if (cur_entry->IsUnresolvedReference() && cur_entry->GetDescriptor() == descriptor) {
+  RegType* entry = entries_[idx];
+  if (entry->descriptor_ != descriptor) {
+    return false;
+  }
+  if (entry->HasClass() && MatchingPrecisionForClass(entry, precise)) {
     return true;
   }
-  return false;
+  return entry->IsUnresolvedReference();
 }
 
 mirror::Class* RegTypeCache::ResolveClass(const char* descriptor, mirror::ClassLoader* loader) {
@@ -206,24 +191,23 @@
   }
 }
 
-const RegType& RegTypeCache::FromClass(mirror::Class* klass, bool precise) {
+const RegType& RegTypeCache::FromClass(const char* descriptor, mirror::Class* klass, bool precise) {
   if (klass->IsPrimitive()) {
     return RegTypeFromPrimitiveType(klass->GetPrimitiveType());
   } else {
     // Look for the reference in the list of entries to have.
     for (size_t i = primitive_count_; i < entries_.size(); i++) {
       RegType* cur_entry = entries_[i];
-      if ((cur_entry->HasClass()) && cur_entry->GetClass() == klass &&
-          MatchingPrecisionForClass(cur_entry, precise)) {
+      if (cur_entry->klass_ == klass && MatchingPrecisionForClass(cur_entry, precise)) {
         return *cur_entry;
       }
     }
     // No reference to the class was found, create new reference.
     RegType* entry;
     if (precise) {
-      entry = new PreciseReferenceType(klass, "", entries_.size());
+      entry = new PreciseReferenceType(klass, descriptor, entries_.size());
     } else {
-      entry = new ReferenceType(klass, "", entries_.size());
+      entry = new ReferenceType(klass, descriptor, entries_.size());
     }
     entries_.push_back(entry);
     return *entry;
@@ -335,8 +319,8 @@
 const RegType& RegTypeCache::Uninitialized(const RegType& type, uint32_t allocation_pc) {
   RegType* entry = NULL;
   RegType* cur_entry = NULL;
+  const std::string& descriptor(type.GetDescriptor());
   if (type.IsUnresolvedTypes()) {
-    const std::string& descriptor(type.GetDescriptor());
     for (size_t i = primitive_count_; i < entries_.size(); i++) {
       cur_entry = entries_[i];
       if (cur_entry->IsUnresolvedAndUninitializedReference() &&
@@ -345,7 +329,7 @@
         return *cur_entry;
       }
     }
-    entry = new UnresolvedUninitializedRefType(descriptor.c_str(), allocation_pc, entries_.size());
+    entry = new UnresolvedUninitializedRefType(descriptor, allocation_pc, entries_.size());
   } else {
     mirror::Class* klass = type.GetClass();
     for (size_t i = primitive_count_; i < entries_.size(); i++) {
@@ -357,7 +341,7 @@
         return *cur_entry;
       }
     }
-    entry = new UninitializedReferenceType(klass, "", allocation_pc, entries_.size());
+    entry = new UninitializedReferenceType(klass, descriptor, allocation_pc, entries_.size());
   }
   entries_.push_back(entry);
   return *entry;
@@ -432,8 +416,8 @@
 
 const RegType& RegTypeCache::UninitializedThisArgument(const RegType& type) {
   RegType* entry;
+  const std::string& descriptor(type.GetDescriptor());
   if (type.IsUnresolvedTypes()) {
-    const std::string& descriptor(type.GetDescriptor());
     for (size_t i = primitive_count_; i < entries_.size(); i++) {
       RegType* cur_entry = entries_[i];
       if (cur_entry->IsUnresolvedAndUninitializedThisReference() &&
@@ -451,7 +435,7 @@
         return *cur_entry;
       }
     }
-    entry = new UninitializedThisReferenceType(klass, "", entries_.size());
+    entry = new UninitializedThisReferenceType(klass, descriptor, entries_.size());
   }
   entries_.push_back(entry);
   return *entry;
@@ -460,7 +444,8 @@
 const RegType& RegTypeCache::FromCat1Const(int32_t value, bool precise) {
   for (size_t i = primitive_count_; i < entries_.size(); i++) {
     RegType* cur_entry = entries_[i];
-    if (cur_entry->IsConstant() && cur_entry->IsPreciseConstant() == precise &&
+    if (cur_entry->klass_ == NULL && cur_entry->IsConstant() &&
+        cur_entry->IsPreciseConstant() == precise &&
         (down_cast<ConstantType*>(cur_entry))->ConstantValue() == value) {
       return *cur_entry;
     }
@@ -519,7 +504,7 @@
     return FromDescriptor(loader, component.c_str(), false);
   } else {
     mirror::Class* klass = array.GetClass()->GetComponentType();
-    return FromClass(klass, klass->IsFinal());
+    return FromClass(ClassHelper(klass).GetDescriptor(), klass, klass->IsFinal());
   }
 }
 
diff --git a/src/verifier/reg_type_cache.h b/src/verifier/reg_type_cache.h
index a5304db..d70123c 100644
--- a/src/verifier/reg_type_cache.h
+++ b/src/verifier/reg_type_cache.h
@@ -39,6 +39,7 @@
 class RegTypeCache {
  public:
   explicit RegTypeCache(bool can_load_classes) : can_load_classes_(can_load_classes) {
+    entries_.reserve(64);
     FillPrimitiveTypes();
   }
   ~RegTypeCache();
@@ -58,7 +59,7 @@
   static Type* CreatePrimitiveTypeInstance(const std::string& descriptor)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
   void FillPrimitiveTypes() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
-  const RegType& FromClass(mirror::Class* klass, bool precise)
+  const RegType& FromClass(const char* descriptor, mirror::Class* klass, bool precise)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
   const RegType& FromCat1Const(int32_t value, bool precise)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
diff --git a/src/verifier/reg_type_test.cc b/src/verifier/reg_type_test.cc
index 9b46a7f..f37edff 100644
--- a/src/verifier/reg_type_test.cc
+++ b/src/verifier/reg_type_test.cc
@@ -74,7 +74,6 @@
 }
 
 TEST_F(RegTypeTest, Primitives) {
-
   ScopedObjectAccess soa(Thread::Current());
   RegTypeCache cache(true);
 
@@ -108,6 +107,7 @@
   EXPECT_FALSE(bool_reg_type.IsLongTypes());
   EXPECT_FALSE(bool_reg_type.IsDoubleTypes());
   EXPECT_TRUE(bool_reg_type.IsArrayIndexTypes());
+  EXPECT_FALSE(bool_reg_type.IsNonZeroReferenceTypes());
 
   const RegType& byte_reg_type = cache.Byte();
   EXPECT_FALSE(byte_reg_type.IsUndefined());
@@ -139,6 +139,7 @@
   EXPECT_FALSE(byte_reg_type.IsLongTypes());
   EXPECT_FALSE(byte_reg_type.IsDoubleTypes());
   EXPECT_TRUE(byte_reg_type.IsArrayIndexTypes());
+  EXPECT_FALSE(byte_reg_type.IsNonZeroReferenceTypes());
 
   const RegType& char_reg_type = cache.Char();
   EXPECT_FALSE(char_reg_type.IsUndefined());
@@ -170,6 +171,7 @@
   EXPECT_FALSE(char_reg_type.IsLongTypes());
   EXPECT_FALSE(char_reg_type.IsDoubleTypes());
   EXPECT_TRUE(char_reg_type.IsArrayIndexTypes());
+  EXPECT_FALSE(char_reg_type.IsNonZeroReferenceTypes());
 
   const RegType& short_reg_type = cache.Short();
   EXPECT_FALSE(short_reg_type.IsUndefined());
@@ -201,6 +203,7 @@
   EXPECT_FALSE(short_reg_type.IsLongTypes());
   EXPECT_FALSE(short_reg_type.IsDoubleTypes());
   EXPECT_TRUE(short_reg_type.IsArrayIndexTypes());
+  EXPECT_FALSE(short_reg_type.IsNonZeroReferenceTypes());
 
   const RegType& int_reg_type = cache.Integer();
   EXPECT_FALSE(int_reg_type.IsUndefined());
@@ -232,6 +235,7 @@
   EXPECT_FALSE(int_reg_type.IsLongTypes());
   EXPECT_FALSE(int_reg_type.IsDoubleTypes());
   EXPECT_TRUE(int_reg_type.IsArrayIndexTypes());
+  EXPECT_FALSE(int_reg_type.IsNonZeroReferenceTypes());
 
   const RegType& long_reg_type = cache.LongLo();
   EXPECT_FALSE(long_reg_type.IsUndefined());
@@ -263,6 +267,7 @@
   EXPECT_TRUE(long_reg_type.IsLongTypes());
   EXPECT_FALSE(long_reg_type.IsDoubleTypes());
   EXPECT_FALSE(long_reg_type.IsArrayIndexTypes());
+  EXPECT_FALSE(long_reg_type.IsNonZeroReferenceTypes());
 
   const RegType& float_reg_type = cache.Float();
   EXPECT_FALSE(float_reg_type.IsUndefined());
@@ -294,6 +299,7 @@
   EXPECT_FALSE(float_reg_type.IsLongTypes());
   EXPECT_FALSE(float_reg_type.IsDoubleTypes());
   EXPECT_FALSE(float_reg_type.IsArrayIndexTypes());
+  EXPECT_FALSE(float_reg_type.IsNonZeroReferenceTypes());
 
   const RegType& double_reg_type = cache.DoubleLo();
   EXPECT_FALSE(double_reg_type.IsUndefined());
@@ -325,6 +331,7 @@
   EXPECT_FALSE(double_reg_type.IsLongTypes());
   EXPECT_TRUE(double_reg_type.IsDoubleTypes());
   EXPECT_FALSE(double_reg_type.IsArrayIndexTypes());
+  EXPECT_FALSE(double_reg_type.IsNonZeroReferenceTypes());
 }
 
 
@@ -352,12 +359,14 @@
   RegTypeCache cache(true);
   const RegType& ref_type_0 = cache.FromDescriptor(NULL, "Ljava/lang/DoesNotExist;", true);
   EXPECT_TRUE(ref_type_0.IsUnresolvedReference());
+  EXPECT_TRUE(ref_type_0.IsNonZeroReferenceTypes());
 
   const RegType& ref_type_1 = cache.FromDescriptor(NULL, "Ljava/lang/DoesNotExist;", true);
   EXPECT_TRUE(ref_type_0.Equals(ref_type_1));
 
   const RegType& unresolved_super_class =  cache.FromUnresolvedSuperClass(ref_type_0);
   EXPECT_TRUE(unresolved_super_class.IsUnresolvedSuperClass());
+  EXPECT_TRUE(unresolved_super_class.IsNonZeroReferenceTypes());
 }
 
 TEST_F(RegTypeReferenceTest, UnresolvedUnintializedType) {
@@ -372,6 +381,7 @@
   const RegType& unresolved_unintialised = cache.Uninitialized(ref_type, 1101ull);
   EXPECT_TRUE(unresolved_unintialised.IsUnresolvedAndUninitializedReference());
   EXPECT_TRUE(unresolved_unintialised.IsUninitializedTypes());
+  EXPECT_TRUE(unresolved_unintialised.IsNonZeroReferenceTypes());
   // Create an uninitialized type of this unresolved type with different  PC
   const RegType& ref_type_unresolved_unintialised_1 =  cache.Uninitialized(ref_type, 1102ull);
   EXPECT_TRUE(unresolved_unintialised.IsUnresolvedAndUninitializedReference());