Make unresolved a first class verifier type.

Change-Id: I16631d45c3b2530c72a5751911f72985cb97b177
diff --git a/src/dex_verifier.cc b/src/dex_verifier.cc
index e4d9f84..5a44055 100644
--- a/src/dex_verifier.cc
+++ b/src/dex_verifier.cc
@@ -10,6 +10,7 @@
 #include "dex_instruction.h"
 #include "dex_instruction_visitor.h"
 #include "dex_verifier.h"
+#include "intern_table.h"
 #include "logging.h"
 #include "runtime.h"
 #include "stringpiece.h"
@@ -23,21 +24,55 @@
   return os << (int)rhs;
 }
 
-static const char type_chars[RegType::kRegTypeMAX + 1 /* for '\0' */ ] = "UX01ZyYhHcibBsSCIFNnJjDdL";
+static const char* type_strings[] = {
+    "Unknown",
+    "Conflict",
+    "Boolean",
+    "Byte",
+    "Short",
+    "Char",
+    "Integer",
+    "Float",
+    "Long (Low Half)",
+    "Long (High Half)",
+    "Double (Low Half)",
+    "Double (High Half)",
+    "64-bit Constant (Low Half)",
+    "64-bit Constant (High Half)",
+    "32-bit Constant",
+    "Unresolved Reference",
+    "Uninitialized Reference",
+    "Uninitialized This Reference",
+    "Unresolved And Uninitialized This Reference",
+    "Reference",
+};
 
 std::string RegType::Dump() const {
-  DCHECK(type_ < kRegTypeMAX);
-  std::ostringstream os;
-  os << type_chars[type_];
-  if (type_ == kRegTypeReference) {
-    if (IsUninitializedReference()) {
-      os << "[uninitialized-" << PrettyDescriptor(GetClass()->GetDescriptor())
-          << ", allocated@" << allocation_pc_ <<"]";
+  DCHECK(type_ >=  kRegTypeUnknown && type_ <= kRegTypeReference);
+  std::string result;
+  if (IsConstant()) {
+    uint32_t val = ConstantValue();
+    if (val == 0) {
+      result = "Zero";
     } else {
-      os << "[" << PrettyDescriptor(GetClass()->GetDescriptor()) << "]";
+      if(IsConstantShort()) {
+        result = StringPrintf("32-bit Constant: %d", val);
+      } else {
+        result = StringPrintf("32-bit Constant: 0x%x", val);
+      }
+    }
+  } else {
+    result = type_strings[type_];
+    if (IsReferenceTypes()) {
+      result += ": ";
+      if (IsUnresolvedReference()) {
+        result += PrettyDescriptor(GetDescriptor());
+      } else {
+        result += PrettyDescriptor(GetClass()->GetDescriptor());
+      }
     }
   }
-  return os.str();
+  return result;
 }
 
 const RegType& RegType::HighHalf(RegTypeCache* cache) const {
@@ -145,147 +180,133 @@
       case RegType::kRegTypeDoubleLo:
         return IsDoubleTypes() ? check_type : reg_types->Conflict();
         break;
-      case RegType::kRegTypeReference:
+      default:
+        if (!check_type.IsReferenceTypes()) {
+          LOG(FATAL) << "Unexpected register type verification against " << check_type;
+        }
         if (IsZero()) {
           return check_type;
         } else if (IsUninitializedReference()) {
           return reg_types->Conflict();  // Nonsensical to Join two uninitialized classes
-        } else if (IsReference() && (check_type.GetClass()->IsAssignableFrom(GetClass()) ||
-            (GetClass()->IsObjectClass() && check_type.GetClass()->IsInterface()))) {
+        } else if (IsReference() && check_type.IsReference() &&
+                   (check_type.GetClass()->IsAssignableFrom(GetClass()) ||
+                    (GetClass()->IsObjectClass() && check_type.GetClass()->IsInterface()))) {
           // Either we're assignable or this is trying to assign Object to an Interface, which
-          // is allowed (see comment in ClassJoin)
+          // is allowed (see comment for ClassJoin)
+          return check_type;
+        } else if (IsUnresolvedReference() && check_type.IsReference() &&
+                   check_type.GetClass()->IsObjectClass()) {
+          // We're an unresolved reference being checked to see if we're an Object, which is ok
+          return *this;
+        } else if (check_type.IsUnresolvedReference() && IsReference() &&
+                   GetClass()->IsObjectClass()) {
+          // As with the last case but with the types reversed
           return check_type;
         } else {
           return reg_types->Conflict();
         }
-      default:
-        LOG(FATAL) << "Unexpected register type verification against " << check_type;
-        return reg_types->Conflict();
     }
   }
 }
 
-#define k_  RegType::kRegTypeUnknown
-#define kX  RegType::kRegTypeConflict
-#define k0  RegType::kRegTypeZero
-#define k1  RegType::kRegTypeOne
-#define kZ  RegType::kRegTypeBoolean
-#define ky  RegType::kRegTypeConstPosByte
-#define kY  RegType::kRegTypeConstByte
-#define kh  RegType::kRegTypeConstPosShort
-#define kH  RegType::kRegTypeConstShort
-#define kc  RegType::kRegTypeConstChar
-#define ki  RegType::kRegTypeConstInteger
-#define kb  RegType::kRegTypePosByte
-#define kB  RegType::kRegTypeByte
-#define ks  RegType::kRegTypePosShort
-#define kS  RegType::kRegTypeShort
-#define kC  RegType::kRegTypeChar
-#define kI  RegType::kRegTypeInteger
-#define kF  RegType::kRegTypeFloat
-#define kN  RegType::kRegTypeConstLo
-#define kn  RegType::kRegTypeConstHi
-#define kJ  RegType::kRegTypeLongLo
-#define kj  RegType::kRegTypeLongHi
-#define kD  RegType::kRegTypeDoubleLo
-#define kd  RegType::kRegTypeDoubleHi
-
-const RegType::Type RegType::merge_table_[kRegTypeReference][kRegTypeReference] =
-  {
-    /* chk:  _ X  0  1  Z  y  Y  h  H  c  i  b  B  s  S  C  I  F  N  n  J  j  D  d */
-    { /*_*/ k_,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX },
-    { /*X*/ kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX },
-    { /*0*/ kX,kX,k0,kZ,kZ,ky,kY,kh,kH,kc,ki,kb,kB,ks,kS,kC,kI,kF,kX,kX,kX,kX,kX,kX },
-    { /*1*/ kX,kX,kZ,k1,kZ,ky,kY,kh,kH,kc,ki,kb,kB,ks,kS,kC,kI,kF,kX,kX,kX,kX,kX,kX },
-    { /*Z*/ kX,kX,kZ,kZ,kZ,ky,kY,kh,kH,kc,ki,kb,kB,ks,kS,kC,kI,kF,kX,kX,kX,kX,kX,kX },
-    { /*y*/ kX,kX,ky,ky,ky,ky,kY,kh,kH,kc,ki,kb,kB,ks,kS,kC,kI,kF,kX,kX,kX,kX,kX,kX },
-    { /*Y*/ kX,kX,kY,kY,kY,kY,kY,kh,kH,kc,ki,kB,kB,kS,kS,kI,kI,kF,kX,kX,kX,kX,kX,kX },
-    { /*h*/ kX,kX,kh,kh,kh,kh,kh,kh,kH,kc,ki,ks,kS,ks,kS,kC,kI,kF,kX,kX,kX,kX,kX,kX },
-    { /*H*/ kX,kX,kH,kH,kH,kH,kH,kH,kH,kc,ki,kS,kS,kS,kS,kI,kI,kF,kX,kX,kX,kX,kX,kX },
-    { /*c*/ kX,kX,kc,kc,kc,kc,kc,kc,kc,kc,ki,kC,kI,kC,kI,kC,kI,kF,kX,kX,kX,kX,kX,kX },
-    { /*i*/ kX,kX,ki,ki,ki,ki,ki,ki,ki,ki,ki,kI,kI,kI,kI,kI,kI,kF,kX,kX,kX,kX,kX,kX },
-    { /*b*/ kX,kX,kb,kb,kb,kb,kB,ks,kS,kC,kI,kb,kB,ks,kS,kC,kI,kX,kX,kX,kX,kX,kX,kX },
-    { /*B*/ kX,kX,kB,kB,kB,kB,kB,kS,kS,kI,kI,kB,kB,kS,kS,kI,kI,kX,kX,kX,kX,kX,kX,kX },
-    { /*s*/ kX,kX,ks,ks,ks,ks,kS,ks,kS,kC,kI,ks,kS,ks,kS,kC,kI,kX,kX,kX,kX,kX,kX,kX },
-    { /*S*/ kX,kX,kS,kS,kS,kS,kS,kS,kS,kI,kI,kS,kS,kS,kS,kI,kI,kX,kX,kX,kX,kX,kX,kX },
-    { /*C*/ kX,kX,kC,kC,kC,kC,kI,kC,kI,kC,kI,kC,kI,kC,kI,kC,kI,kX,kX,kX,kX,kX,kX,kX },
-    { /*I*/ kX,kX,kI,kI,kI,kI,kI,kI,kI,kI,kI,kI,kI,kI,kI,kI,kI,kX,kX,kX,kX,kX,kX,kX },
-    { /*F*/ kX,kX,kF,kF,kF,kF,kF,kF,kF,kF,kF,kX,kX,kX,kX,kX,kX,kF,kX,kX,kX,kX,kX,kX },
-    { /*N*/ kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kN,kX,kJ,kX,kD,kX },
-    { /*n*/ kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kn,kX,kj,kX,kd },
-    { /*J*/ kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kJ,kX,kJ,kX,kX,kX },
-    { /*j*/ kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kj,kX,kj,kX,kX },
-    { /*D*/ kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kD,kX,kX,kX,kD,kX },
-    { /*d*/ kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kd,kX,kX,kX,kd },
-  };
-
-#undef k_
-#undef kX
-#undef k0
-#undef k1
-#undef kZ
-#undef ky
-#undef kY
-#undef kh
-#undef kH
-#undef kc
-#undef ki
-#undef kb
-#undef kB
-#undef ks
-#undef kS
-#undef kC
-#undef kI
-#undef kF
-#undef kN
-#undef kn
-#undef kJ
-#undef kj
-#undef kD
-#undef kd
+static const RegType& SelectNonConstant(const RegType& a, const RegType& b) {
+  return a.IsConstant() ? b : a;
+}
 
 const RegType& RegType::Merge(const RegType& incoming_type, RegTypeCache* reg_types) const {
   DCHECK(!Equals(incoming_type));  // Trivial equality handled by caller
-  if (type_ < kRegTypeReference) {
-    if (incoming_type.type_ < kRegTypeReference) {
-      // Merge of primitive types, unknown or conflict use lookup table
-      RegType::Type table_type = merge_table_[type_][incoming_type.type_];
-      // Check if we got an identity result before hitting the cache
-      if (type_ == table_type) {
+  if (IsUnknown() && incoming_type.IsUnknown()) {
+    return *this;  // Unknown MERGE Unknown => Unknown
+  } else if (IsConflict()) {
+    return *this;  // Conflict MERGE * => Conflict
+  } else if (incoming_type.IsConflict()) {
+    return incoming_type;  // * MERGE Conflict => Conflict
+  } else if (IsUnknown() || incoming_type.IsUnknown()) {
+    return reg_types->Conflict();  // Unknown MERGE * => Conflict
+  } else if(IsConstant() && incoming_type.IsConstant()) {
+    int32_t val1 = ConstantValue();
+    int32_t val2 = incoming_type.ConstantValue();
+    if (val1 >= 0 && val2 >= 0) {
+      // +ve1 MERGE +ve2 => MAX(+ve1, +ve2)
+      if (val1 >= val2) {
         return *this;
-      } else if (incoming_type.type_ == table_type) {
+      } else {
+        return incoming_type;
+      }
+    } else if (val1 < 0 && val2 < 0) {
+      // -ve1 MERGE -ve2 => MIN(-ve1, -ve2)
+      if (val1 <= val2) {
+        return *this;
+      } else {
+        return incoming_type;
+      }
+    } else {
+      // Values are +ve and -ve, choose smallest signed type in which they both fit
+      if (IsConstantByte()) {
+        if (incoming_type.IsConstantByte()) {
+          return reg_types->ByteConstant();
+        } else if (incoming_type.IsConstantShort()) {
+          return reg_types->ShortConstant();
+        } else {
+          return reg_types->IntConstant();
+        }
+      } else if (IsConstantShort()) {
+        if (incoming_type.IsShort()) {
+          return reg_types->ShortConstant();
+        } else {
+          return reg_types->IntConstant();
+        }
+      } else {
+        return reg_types->IntConstant();
+      }
+    }
+  } else if (IsIntegralTypes() && incoming_type.IsIntegralTypes()) {
+    if (IsBooleanTypes() && incoming_type.IsBooleanTypes()) {
+      return reg_types->Boolean();  // boolean MERGE boolean => boolean
+    }
+    if (IsByteTypes() && incoming_type.IsByteTypes()) {
+      return reg_types->Byte();  // byte MERGE byte => byte
+    }
+    if (IsShortTypes() && incoming_type.IsShortTypes()) {
+      return reg_types->Short();  // short MERGE short => short
+    }
+    if (IsCharTypes() && incoming_type.IsCharTypes()) {
+      return reg_types->Char();  // char MERGE char => char
+    }
+    return reg_types->Integer();  // int MERGE * => int
+  } else if ((IsFloatTypes() && incoming_type.IsFloatTypes()) ||
+             (IsLongTypes() && incoming_type.IsLongTypes()) ||
+             (IsLongHighTypes() && incoming_type.IsLongHighTypes()) ||
+             (IsDoubleTypes() && incoming_type.IsDoubleTypes()) ||
+             (IsDoubleHighTypes() && incoming_type.IsDoubleHighTypes())) {
+    // check constant case was handled prior to entry
+    DCHECK(!IsConstant() || !incoming_type.IsConstant());
+    // float/long/double MERGE float/long/double_constant => float/long/double
+    return SelectNonConstant(*this, incoming_type);
+  } else if (IsReferenceTypes() && incoming_type.IsReferenceTypes()) {
+    if (IsZero() | incoming_type.IsZero()) {
+      return SelectNonConstant(*this, incoming_type);  // 0 MERGE ref => ref
+    } else  if (IsUnresolvedReference() || IsUninitializedReference() ||
+                IsUninitializedThisReference()) {
+      // Can only merge an uninitialized or unresolved type with itself or 0, we've already checked
+      // these so => Conflict
+      return reg_types->Conflict();
+    } else {  // Two reference types, compute Join
+      Class* c1 = GetClass();
+      Class* c2 = incoming_type.GetClass();
+      DCHECK(c1 != NULL && !c1->IsPrimitive());
+      DCHECK(c2 != NULL && !c2->IsPrimitive());
+      Class* join_class = ClassJoin(c1, c2);
+      if (c1 == join_class) {
+        return *this;
+      } else if (c2 == join_class) {
         return incoming_type;
       } else {
-        return reg_types->FromType(table_type);
+        return reg_types->FromClass(join_class);
       }
-    } else if (IsZero()) {  // Merge of primitive zero and reference => reference
-      return incoming_type;
-    } else {  // Merge with non-zero with reference => conflict
-      return reg_types->Conflict();
     }
-  } else if (!incoming_type.IsReference()) {
-    DCHECK(IsReference());
-    if (incoming_type.IsZero()) {  // Merge of primitive zero and reference => reference
-      return *this;
-    } else {  // Merge with non-zero with reference => conflict
-      return reg_types->Conflict();
-    }
-  } else if (IsUninitializedReference()) {
-    // Can only merge an uninitialized type with itself, but we already checked this
-    return reg_types->Conflict();
-  } else {  // Two reference types, compute Join
-    Class* c1 = GetClass();
-    Class* c2 = incoming_type.GetClass();
-    DCHECK(c1 != NULL && !c1->IsPrimitive());
-    DCHECK(c2 != NULL && !c2->IsPrimitive());
-    Class* join_class = ClassJoin(c1, c2);
-    if (c1 == join_class) {
-      return *this;
-    } else if (c2 == join_class) {
-      return incoming_type;
-    } else {
-      return reg_types->FromClass(join_class);
-    }
+  } else {
+    return reg_types->Conflict();  // Unexpected types => Conflict
   }
 }
 
@@ -337,36 +358,47 @@
 
 const RegType& RegTypeCache::From(RegType::Type type, const ClassLoader* loader,
                                   const std::string& descriptor) {
-  if (type < RegType::kRegTypeReference) {
+  if (type <= RegType::kRegTypeLastFixedLocation) {
     // entries should be sized greater than primitive types
     DCHECK_GT(entries_.size(), static_cast<size_t>(type));
     RegType* entry = entries_[type];
     if (entry == NULL) {
-      Class *klass = NULL;
+      Class* klass = NULL;
       if (descriptor.size() != 0) {
         klass = Runtime::Current()->GetClassLinker()->FindSystemClass(descriptor);
       }
-      entry = new RegType(type, klass, RegType::kInitArgAddr, type);
+      entry = new RegType(type, klass, 0, type);
       entries_[type] = entry;
     }
     return *entry;
   } else {
     DCHECK (type == RegType::kRegTypeReference);
-    for (size_t i = RegType::kRegTypeReference; i < entries_.size(); i++) {
+    for (size_t i = RegType::kRegTypeLastFixedLocation + 1; i < entries_.size(); i++) {
       RegType* cur_entry = entries_[i];
-      if (cur_entry->IsInitialized() &&
-          cur_entry->GetClass()->GetDescriptor()->Equals(descriptor)) {
+      // check resolved and unresolved references, ignore uninitialized references
+      if (cur_entry->IsReference() && cur_entry->GetClass()->GetDescriptor()->Equals(descriptor)) {
+        return *cur_entry;
+      } else if (cur_entry->IsUnresolvedReference() &&
+                 cur_entry->GetDescriptor()->Equals(descriptor)) {
         return *cur_entry;
       }
     }
     Class* klass = Runtime::Current()->GetClassLinker()->FindClass(descriptor, loader);
     if (klass != NULL) {
-      RegType* entry = new RegType(type, klass, RegType::kInitArgAddr, entries_.size());
+      // Able to resolve so create resolved register type
+      RegType* entry = new RegType(type, klass, 0, entries_.size());
       entries_.push_back(entry);
       return *entry;
     } else {
+      // Unable to resolve so create unresolved register type
       DCHECK(Thread::Current()->IsExceptionPending());
-      return FromType(RegType::kRegTypeUnknown);
+      Thread::Current()->ClearException();
+      String* string_descriptor =
+          Runtime::Current()->GetInternTable()->InternStrong(descriptor.c_str());
+      RegType* entry = new RegType(RegType::kRegTypeUnresolvedReference, string_descriptor, 0,
+                                   entries_.size());
+      entries_.push_back(entry);
+      return *entry;
     }
   }
 }
@@ -378,44 +410,44 @@
     DCHECK_GT(entries_.size(), static_cast<size_t>(type));
     RegType* entry = entries_[type];
     if (entry == NULL) {
-      entry = new RegType(type, klass, RegType::kInitArgAddr, type);
+      entry = new RegType(type, klass, 0, type);
       entries_[type] = entry;
     }
     return *entry;
   } else {
-    for (size_t i = RegType::kRegTypeReference; i < entries_.size(); i++) {
+    for (size_t i = RegType::kRegTypeLastFixedLocation + 1; i < entries_.size(); i++) {
       RegType* cur_entry = entries_[i];
-      if (cur_entry->IsInitialized() && cur_entry->GetClass() == klass) {
+      if (cur_entry->IsReference() && cur_entry->GetClass() == klass) {
         return *cur_entry;
       }
     }
-    RegType* entry = new RegType(RegType::kRegTypeReference, klass, RegType::kInitArgAddr,
-                                 entries_.size());
+    RegType* entry = new RegType(RegType::kRegTypeReference, klass, 0, entries_.size());
     entries_.push_back(entry);
     return *entry;
   }
 }
 
 const RegType& RegTypeCache::Uninitialized(Class* klass, uint32_t allocation_pc) {
-  for (size_t i = RegType::kRegTypeReference; i < entries_.size(); i++) {
+  for (size_t i = RegType::kRegTypeLastFixedLocation + 1; i < entries_.size(); i++) {
     RegType* cur_entry = entries_[i];
-    if (cur_entry->allocation_pc_ == allocation_pc && cur_entry->GetClass() == klass) {
+    if (cur_entry->IsUninitializedReference() && cur_entry->GetAllocationPc() == allocation_pc &&
+        cur_entry->GetClass() == klass) {
       return *cur_entry;
     }
   }
-  RegType* entry = new RegType(RegType::kRegTypeReference, klass, allocation_pc, entries_.size());
+  RegType* entry = new RegType(RegType::kRegTypeUninitializedReference, klass, allocation_pc, entries_.size());
   entries_.push_back(entry);
   return *entry;
 }
 
 const RegType& RegTypeCache::UninitializedThisArgument(Class* klass) {
-  for (size_t i = RegType::kRegTypeReference; i < entries_.size(); i++) {
+  for (size_t i = RegType::kRegTypeLastFixedLocation + 1; i < entries_.size(); i++) {
     RegType* cur_entry = entries_[i];
     if (cur_entry->IsUninitializedThisReference() && cur_entry->GetClass() == klass) {
       return *cur_entry;
     }
   }
-  RegType* entry = new RegType(RegType::kRegTypeReference, klass, RegType::kUninitThisArgAddr,
+  RegType* entry = new RegType(RegType::kRegTypeUninitializedThisReference, klass, 0,
                                entries_.size());
   entries_.push_back(entry);
   return *entry;
@@ -439,25 +471,15 @@
 }
 
 const RegType& RegTypeCache::FromCat1Const(int32_t value) {
-  if (value < -32768) {
-    return FromType(RegType::kRegTypeConstInteger);
-  } else if (value < -128) {
-    return FromType(RegType::kRegTypeConstShort);
-  } else if (value < 0) {
-    return FromType(RegType::kRegTypeConstByte);
-  } else if (value == 0) {
-    return FromType(RegType::kRegTypeZero);
-  } else if (value == 1) {
-    return FromType(RegType::kRegTypeOne);
-  } else if (value < 128) {
-    return FromType(RegType::kRegTypeConstPosByte);
-  } else if (value < 32768) {
-    return FromType(RegType::kRegTypeConstPosShort);
-  } else if (value < 65536) {
-    return FromType(RegType::kRegTypeConstChar);
-  } else {
-    return FromType(RegType::kRegTypeConstInteger);
+  for (size_t i = RegType::kRegTypeLastFixedLocation + 1; i < entries_.size(); i++) {
+    RegType* cur_entry = entries_[i];
+    if (cur_entry->IsConstant() && cur_entry->ConstantValue() == value) {
+      return *cur_entry;
+    }
   }
+  RegType* entry = new RegType(RegType::kRegTypeConst, NULL, value, entries_.size());
+  entries_.push_back(entry);
+  return *entry;
 }
 
 bool RegisterLine::CheckConstructorReturn() const {
@@ -778,7 +800,7 @@
     uint8_t val = 0;
     for (size_t j = 0; j < 8 && (i + j) < num_regs_; j++) {
       // Note: we write 1 for a Reference but not for Null
-      if (GetRegisterType(i + j).IsReference()) {
+      if (GetRegisterType(i + j).IsNonZeroReferenceTypes()) {
         val |= 1 << j;
       }
     }
@@ -1515,15 +1537,7 @@
         {
           const RegType& reg_type =
               reg_types_.FromDescriptor(method_->GetDeclaringClass()->GetClassLoader(), descriptor);
-          if (!reg_type.IsUnknown()) {
-            reg_line->SetRegisterType(arg_start + cur_arg, reg_type);
-          } else {
-            DCHECK(Thread::Current()->IsExceptionPending());
-            Thread::Current()->ClearException();
-            LOG(WARNING) << "Unable to resolve descriptor in signature " << descriptor
-                << " using Object";
-            reg_line->SetRegisterType(arg_start + cur_arg, reg_types_.JavaLangObject());
-          }
+          reg_line->SetRegisterType(arg_start + cur_arg, reg_type);
         }
         break;
       case 'Z':
@@ -1842,7 +1856,7 @@
           /* check the register contents */
           work_line_->VerifyRegisterType(dec_insn.vA_, use_src ? src_type : return_type);
           if (failure_ != VERIFY_ERROR_NONE) {
-            Fail(VERIFY_ERROR_GENERIC) << "return-1nr on invalid register v" << dec_insn.vA_;
+            fail_messages_ << " return-1nr on invalid register v" << dec_insn.vA_;
           }
         }
       }
@@ -1857,7 +1871,7 @@
           /* check the register contents */
           work_line_->VerifyRegisterType(dec_insn.vA_, return_type);
           if (failure_ != VERIFY_ERROR_NONE) {
-            Fail(failure_) << "return-wide on invalid register pair v" << dec_insn.vA_;
+            fail_messages_ << " return-wide on invalid register pair v" << dec_insn.vA_;
           }
         }
       }
@@ -2382,17 +2396,15 @@
           }
 
           /* arg must be an uninitialized reference */
-          if (this_type.IsInitialized()) {
+          if (!this_type.IsUninitializedTypes()) {
             Fail(VERIFY_ERROR_GENERIC) << "Expected initialization on uninitialized reference "
                 << this_type;
             break;
           }
 
           /*
-           * Replace the uninitialized reference with an initialized
-           * one, and clear the entry in the uninit map. We need to
-           * do this for all registers that have the same object
-           * instance in them, not just the "this" register.
+           * Replace the uninitialized reference with an initialized one. We need to do this for all
+           * registers that have the same object instance in them, not just the "this" register.
            */
           work_line_->MarkRefsAsInitialized(this_type);
           if (failure_ != VERIFY_ERROR_NONE)
@@ -3109,20 +3121,9 @@
     }
     const RegType& reg_type =
         reg_types_.FromDescriptor(method_->GetDeclaringClass()->GetClassLoader(), descriptor);
-    if (reg_type.IsUnknown()) {
-      DCHECK(Thread::Current()->IsExceptionPending());
-      Thread::Current()->ClearException();
-      LOG(WARNING) << "Unable to resolve descriptor in signature " << descriptor
-          << " using Object";
-      uint32_t get_reg = is_range ? dec_insn.vC_ + actual_args : dec_insn.arg_[actual_args];
-      if (!work_line_->VerifyRegisterType(get_reg, reg_types_.JavaLangObject())) {
-        return NULL;
-      }
-    } else {
-      uint32_t get_reg = is_range ? dec_insn.vC_ + actual_args : dec_insn.arg_[actual_args];
-      if (!work_line_->VerifyRegisterType(get_reg, reg_type)) {
-        return NULL;
-      }
+    uint32_t get_reg = is_range ? dec_insn.vC_ + actual_args : dec_insn.arg_[actual_args];
+    if (!work_line_->VerifyRegisterType(get_reg, reg_type)) {
+      return NULL;
     }
     actual_args = reg_type.IsLongOrDoubleTypes() ? actual_args + 2 : actual_args + 1;
   }
@@ -3644,7 +3645,7 @@
       local_gc_points++;
       max_insn = i;
       RegisterLine* line = reg_table_.GetLine(i);
-      max_ref_reg = line->GetMaxReferenceReg(max_ref_reg);
+      max_ref_reg = line->GetMaxNonZeroReferenceReg(max_ref_reg);
     }
   }
   *gc_points = local_gc_points;
@@ -3732,7 +3733,7 @@
       map_index++;
       RegisterLine* line = reg_table_.GetLine(i);
       for(size_t j = 0; j < code_item_->registers_size_; j++) {
-        if (line->GetRegisterType(j).IsReference()) {
+        if (line->GetRegisterType(j).IsNonZeroReferenceTypes()) {
           CHECK_LT(j / 8, map.RegWidth());
           CHECK_EQ((reg_bitmap[j / 8] >> (j % 8)) & 1, 1);
         } else if ((j / 8) < map.RegWidth()) {
diff --git a/src/dex_verifier.h b/src/dex_verifier.h
index 0d86eb5..d27be35 100644
--- a/src/dex_verifier.h
+++ b/src/dex_verifier.h
@@ -11,6 +11,7 @@
 #include "stl_util.h"
 #include "UniquePtr.h"
 
+#include <limits>
 #include <map>
 #include <stack>
 #include <vector>
@@ -34,104 +35,44 @@
 #endif
 
 /*
- * RegType holds information about the type of data held in a register. For most types it's a simple
- * enum. For reference types it holds a pointer to the Class*, and for uninitialized references
- * it holds an index into the UninitInstanceMap.
+ * RegType holds information about the "type" of data held in a register.
  */
 class RegType {
  public:
-  /*
-   * Enumeration for register type values. The "hi" piece of a 64-bit value MUST immediately follow
-   * the "lo" piece in the enumeration, so we can check that hi==lo+1.
-   *
-   * Assignment of constants:
-   *   [-MAXINT,-32768)   : integer
-   *   [-32768,-128)      : short
-   *   [-128,0)           : byte
-   *   0                  : zero
-   *   1                  : one
-   *   [2,128)            : posbyte
-   *   [128,32768)        : posshort
-   *   [32768,65536)      : char
-   *   [65536,MAXINT]     : integer
-   *
-   * Allowed "implicit" widening conversions:
-   *   zero -> boolean, posbyte, byte, posshort, short, char, integer, ref (null)
-   *   one -> boolean, posbyte, byte, posshort, short, char, integer
-   *   boolean -> posbyte, byte, posshort, short, char, integer
-   *   posbyte -> posshort, short, integer, char
-   *   byte -> short, integer
-   *   posshort -> integer, char
-   *   short -> integer
-   *   char -> integer
-   *
-   * In addition, all of the above can convert to "float".
-   *
-   * We're more careful with integer values than the spec requires. The motivation is to restrict
-   * byte/char/short to the correct range of values. For example, if a method takes a byte argument,
-   * we don't want to allow the code to load the constant "1024" and pass it in.
-   */
   enum Type {
     kRegTypeUnknown = 0,    /* initial state */
     kRegTypeConflict,       /* merge clash makes this reg's type unknowable */
-
-    /*
-     * Category-1nr types. The order of these is chiseled into a couple of tables, so don't add,
-     * remove, or reorder if you can avoid it.
-     */
-    kRegTypeZero,           /* 0 - 32-bit 0, could be Boolean, Int, Float, or Ref */
-    kRegType1nrSTART = kRegTypeZero,
-    kRegTypeIntegralSTART = kRegTypeZero,
-    kRegTypeOne,            /* 1 - 32-bit 1, could be Boolean, Int, Float */
-    kRegTypeBoolean,        /* Z - must be 0 or 1 */
-    kRegTypeConstPosByte,   /* y - const derived byte, known positive */
-    kRegTypeConstByte,      /* Y - const derived byte */
-    kRegTypeConstPosShort,  /* h - const derived short, known positive */
-    kRegTypeConstShort,     /* H - const derived short */
-    kRegTypeConstChar,      /* c - const derived char */
-    kRegTypeConstInteger,   /* i - const derived integer */
-    kRegTypePosByte,        /* b - byte, known positive (can become char) */
+    kRegTypeBoolean,        /* Z */
+    kRegType1nrSTART = kRegTypeBoolean,
+    kRegTypeIntegralSTART = kRegTypeBoolean,
     kRegTypeByte,           /* B */
-    kRegTypePosShort,       /* s - short, known positive (can become char) */
     kRegTypeShort,          /* S */
     kRegTypeChar,           /* C */
     kRegTypeInteger,        /* I */
     kRegTypeIntegralEND = kRegTypeInteger,
     kRegTypeFloat,          /* F */
     kRegType1nrEND = kRegTypeFloat,
+    kRegTypeLongLo,         /* J - lower-numbered register; endian-independent */
+    kRegTypeLongHi,
+    kRegTypeDoubleLo,       /* D */
+    kRegTypeDoubleHi,
     kRegTypeConstLo,        /* const derived wide, lower half - could be long or double */
     kRegTypeConstHi,        /* const derived wide, upper half - could be long or double */
-    kRegTypeLongLo,         /* lower-numbered register; endian-independent */
-    kRegTypeLongHi,
-    kRegTypeDoubleLo,
-    kRegTypeDoubleHi,
-    kRegTypeReference,      // Reference type
-    kRegTypeMAX = kRegTypeReference + 1,
+    kRegTypeLastFixedLocation = kRegTypeConstHi,
+    kRegTypeConst,          /* 32-bit constant derived value - could be float or int */
+    kRegTypeUnresolvedReference,        // Reference type that couldn't be resolved
+    kRegTypeUninitializedReference,     // Freshly allocated reference type
+    kRegTypeUninitializedThisReference, // Freshly allocated reference passed as "this"
+    kRegTypeUnresolvedAndUninitializedReference, // Freshly allocated unresolved reference type
+    kRegTypeReference,                  // Reference type
   };
 
-  bool IsUninitializedThisReference() const {
-    return allocation_pc_ == kUninitThisArgAddr;
-  }
-
   Type GetType() const {
     return type_;
   }
 
-  std::string Dump() const;
-
-  Class* GetClass() const {
-    DCHECK(klass_ != NULL);
-    return klass_;
-  }
-
-  bool IsInitialized() const { return allocation_pc_ == kInitArgAddr; }
-  bool IsUninitializedReference() const { return allocation_pc_ != kInitArgAddr; }
-
   bool IsUnknown() const { return type_ == kRegTypeUnknown; }
   bool IsConflict() const { return type_ == kRegTypeConflict; }
-  bool IsZero()    const { return type_ == kRegTypeZero; }
-  bool IsOne()     const { return type_ == kRegTypeOne; }
-  bool IsConstLo() const { return type_ == kRegTypeConstLo; }
   bool IsBoolean() const { return type_ == kRegTypeBoolean; }
   bool IsByte()    const { return type_ == kRegTypeByte; }
   bool IsChar()    const { return type_ == kRegTypeChar; }
@@ -140,7 +81,17 @@
   bool IsLong()    const { return type_ == kRegTypeLongLo; }
   bool IsFloat()   const { return type_ == kRegTypeFloat; }
   bool IsDouble()  const { return type_ == kRegTypeDoubleLo; }
+  bool IsUnresolvedReference() const { return type_ == kRegTypeUnresolvedReference; }
+  bool IsUninitializedReference() const { return type_ == kRegTypeUninitializedReference; }
+  bool IsUninitializedThisReference() const { return type_ == kRegTypeUninitializedThisReference; }
+  bool IsUnresolvedAndUninitializedReference() const {
+    return type_ == kRegTypeUnresolvedAndUninitializedReference;
+  }
   bool IsReference() const { return type_ == kRegTypeReference; }
+  bool IsUninitializedTypes() const {
+    return IsUninitializedReference() || IsUninitializedThisReference() ||
+        IsUnresolvedAndUninitializedReference();
+  }
 
   bool IsLowHalf() const { return type_ == kRegTypeLongLo ||
                                   type_ == kRegTypeDoubleLo ||
@@ -149,79 +100,115 @@
                                    type_ == kRegTypeDoubleHi ||
                                    type_ == kRegTypeConstHi; }
 
-  const RegType& HighHalf(RegTypeCache* cache) const;
+  bool IsLongOrDoubleTypes() const { return IsLowHalf(); }
 
+  // Check this is the low half, and that type_h is its matching high-half
   bool CheckWidePair(const RegType& type_h) const {
     return IsLowHalf() && (type_h.type_ == type_ + 1);
   }
 
+  // The high half that corresponds to this low half
+  const RegType& HighHalf(RegTypeCache* cache) const;
+
+  bool IsConstant() const { return type_ == kRegTypeConst; }
+  bool IsLongConstant() const { return type_ == kRegTypeConstLo; }
+  bool IsLongConstantHigh() const { return type_ == kRegTypeConstHi; }
+
+  // If this is a 32-bit constant, what is the value? This value may just
+  // approximate to the actual constant value by virtue of merging.
+  int32_t ConstantValue() const {
+    DCHECK(IsConstant());
+    return allocation_pc_or_constant_;
+  }
+
+  bool IsZero()         const { return IsConstant() && ConstantValue() == 0; }
+  bool IsOne()          const { return IsConstant() && ConstantValue() == 1; }
+  bool IsConstantBoolean() const { return IsZero() || IsOne(); }
+  bool IsConstantByte() const {
+    return IsConstant() &&
+        ConstantValue() >= std::numeric_limits<jbyte>::min() &&
+        ConstantValue() <= std::numeric_limits<jbyte>::max();
+  }
+  bool IsConstantShort() const {
+    return IsConstant() &&
+        ConstantValue() >= std::numeric_limits<jshort>::min() &&
+        ConstantValue() <= std::numeric_limits<jshort>::max();
+  }
+  bool IsConstantChar() const {
+    return IsConstant() && ConstantValue() >= 0 &&
+        ConstantValue() <= std::numeric_limits<jchar>::max();
+  }
+
+  bool IsReferenceTypes() const {
+    return IsReference() || IsUnresolvedReference() || IsUninitializedReference() ||
+        IsUninitializedThisReference() || IsZero();
+  }
+  bool IsNonZeroReferenceTypes() const {
+    return IsReference() || IsUnresolvedReference() || IsUninitializedReference() ||
+        IsUninitializedThisReference();
+  }
+  bool IsCategory1Types() const {
+    return (type_ >= kRegType1nrSTART && type_ <= kRegType1nrEND) || IsConstant();
+  }
+  bool IsCategory2Types() const {
+    return IsLowHalf();  // Don't expect explicit testing of high halves
+  }
+
+  bool IsBooleanTypes() const { return IsBoolean() || IsConstantBoolean(); }
+  bool IsByteTypes() const { return IsByte() || IsBoolean() || IsConstantByte(); }
+  bool IsShortTypes() const { return IsShort() || IsByte() || IsBoolean() || IsConstantShort(); }
+  bool IsCharTypes() const { return IsChar() || IsBooleanTypes() || IsConstantChar(); }
+  bool IsIntegralTypes() const {
+    return (type_ >= kRegTypeIntegralSTART && type_ <= kRegTypeIntegralEND) || IsConstant();
+  }
+  bool IsArrayIndexTypes() const { return IsIntegralTypes(); }
+
+  // Float type may be derived from any constant type
+  bool IsFloatTypes() const { return IsFloat() || IsConstant(); }
+
+  bool IsLongTypes() const {
+    return IsLong() || IsLongConstant();
+  }
+  bool IsLongHighTypes() const {
+    return type_ == kRegTypeLongHi || type_ == kRegTypeConstHi;
+  }
+  bool IsDoubleTypes() const {
+    return IsDouble() || IsLongConstant();
+  }
+  bool IsDoubleHighTypes() const {
+    return type_ == kRegTypeDoubleHi || type_ == kRegTypeConstHi;
+  }
+
+  uint32_t GetAllocationPc() const {
+    DCHECK(IsUninitializedReference());
+    return allocation_pc_or_constant_;
+  }
+
+  Class* GetClass() const {
+    DCHECK(!IsUnresolvedReference());
+    DCHECK(klass_or_descriptor_ != NULL);
+    DCHECK(klass_or_descriptor_->IsClass());
+    return down_cast<Class*>(klass_or_descriptor_);
+  }
+
+  String* GetDescriptor() const {
+    DCHECK(IsUnresolvedReference());
+    DCHECK(klass_or_descriptor_ != NULL);
+    DCHECK(klass_or_descriptor_->IsString());
+    return down_cast<String*>(klass_or_descriptor_);
+  }
+
   uint16_t GetId() const {
     return cache_id_;
   }
 
-  bool IsLongOrDoubleTypes() const { return IsLowHalf(); }
-
-  bool IsReferenceTypes() const {
-    return type_ == kRegTypeReference || type_ == kRegTypeZero;
-  }
-
-  bool IsCategory1Types() const {
-    return type_ >= kRegType1nrSTART && type_ <= kRegType1nrEND;
-  }
-
-  bool IsCategory2Types() const {
-    return IsLowHalf();  // Don't expect explicit testing of high halves
-  }
-
-  bool IsBooleanTypes() const { return IsBoolean() || IsZero() || IsOne(); }
-
-  bool IsByteTypes() const {
-    return IsByte() || IsBooleanTypes() || type_ == kRegTypeConstPosByte ||
-        type_ == kRegTypeConstByte || type_ == kRegTypePosByte;
-  }
-
-  bool IsShortTypes() const {
-    return IsShort() || IsByteTypes() || type_ == kRegTypeConstPosShort ||
-        type_ == kRegTypeConstShort || type_ == kRegTypePosShort;
-  }
-
-  bool IsCharTypes() const {
-    return IsChar() || IsBooleanTypes() || type_ == kRegTypeConstPosByte ||
-        type_ == kRegTypePosByte || type_ == kRegTypeConstPosShort || type_ == kRegTypePosShort ||
-        type_ == kRegTypeConstChar;
-  }
-
-  bool IsIntegralTypes() const {
-    return type_ >= kRegTypeIntegralSTART && type_ <= kRegTypeIntegralEND;
-  }
-
-  bool IsArrayIndexTypes() const {
-    return IsIntegralTypes();
-  }
-
-  // Float type may be derived from any constant type
-  bool IsFloatTypes() const {
-    return IsFloat() || IsZero() || IsOne() ||
-        type_ == kRegTypeConstPosByte || type_ == kRegTypeConstByte ||
-        type_ == kRegTypeConstPosShort || type_ == kRegTypeConstShort ||
-        type_ == kRegTypeConstChar || type_ == kRegTypeConstInteger;
-  }
-
-  bool IsLongTypes() const {
-    return IsLong() || type_ == kRegTypeConstLo;
-  }
-
-  bool IsDoubleTypes() const {
-    return IsDouble() || type_ == kRegTypeConstLo;
-  }
+  std::string Dump() const;
 
   const RegType& VerifyAgainst(const RegType& check_type, RegTypeCache* reg_types) const;
 
   const RegType& Merge(const RegType& incoming_type, RegTypeCache* reg_types) const;
 
-  bool Equals(const RegType& other) const {
-    return type_ == other.type_ && klass_ == other.klass_ && allocation_pc_ == other.allocation_pc_;
-  }
+  bool Equals(const RegType& other) const { return GetId() == other.GetId(); }
 
   /*
    * A basic Join operation on classes. For a pair of types S and T the Join, written S v T = J, is
@@ -244,58 +231,39 @@
  private:
   friend class RegTypeCache;
 
-  // Address given to an allocation_pc for an initialized object.
-  static const uint32_t kInitArgAddr = -2;
-
-  // Address given to an uninitialized allocation_pc if an object is uninitialized through being
-  // a constructor.
-  static const uint32_t kUninitThisArgAddr = -1;
-
-  RegType(Type type, Class* klass, uint32_t allocation_pc, uint16_t cache_id) :
-    type_(type), klass_(klass), allocation_pc_(allocation_pc), cache_id_(cache_id) {
-    DCHECK(type >= kRegTypeReference || allocation_pc_ == kInitArgAddr);
-    if (type >= kRegTypeReference) DCHECK(klass != NULL);
+  RegType(Type type, Object* klass_or_descriptor, uint32_t allocation_pc_or_constant, uint16_t cache_id) :
+    type_(type), klass_or_descriptor_(klass_or_descriptor), allocation_pc_or_constant_(allocation_pc_or_constant),
+    cache_id_(cache_id) {
+    DCHECK(IsConstant() || IsUninitializedReference() || allocation_pc_or_constant == 0);
+    if (!IsConstant() && !IsLongConstant() && !IsLongConstantHigh() && !IsUnknown() &&
+        !IsConflict()) {
+      DCHECK(klass_or_descriptor != NULL);
+      DCHECK(IsUnresolvedReference() || klass_or_descriptor_->IsClass());
+      DCHECK(!IsUnresolvedReference() || klass_or_descriptor_->IsString());
+    }
   }
 
   const Type type_;  // The current type of the register
 
-  // If known the type of the register
-  Class* klass_;
+  // If known the type of the register, else a String for the descriptor
+  Object* klass_or_descriptor_;
 
-  // Address an uninitialized reference was created
-  const uint32_t allocation_pc_;
+  // Overloaded field that:
+  //   - if IsConstant() holds a 32bit constant value
+  //   - is IsReference() holds the allocation_pc or kInitArgAddr for an initialized reference or
+  //     kUninitThisArgAddr for an uninitialized this ptr
+  const uint32_t allocation_pc_or_constant_;
 
   // A RegType cache densely encodes types, this is the location in the cache for this type
   const uint16_t cache_id_;
 
-  /*
-   * Merge result table for primitive values. The table is symmetric along the diagonal.
-   *
-   * Note that 32-bit int/float do not merge into 64-bit long/double. This is a register merge, not
-   * a widening conversion. Only the "implicit" widening within a category, e.g. byte to short, is
-   * allowed.
-   *
-   * Dalvik does not draw a distinction between int and float, but we enforce that once a value is
-   * used as int, it can't be used as float, and vice-versa. We do not allow free exchange between
-   * 32-bit int/float and 64-bit long/double.
-   *
-   * Note that Uninit + Uninit = Uninit. This holds true because we only use this when the RegType
-   * value is exactly equal to kRegTypeUninit, which can only happen for the zeroth entry in the
-   * table.
-   *
-   * "Unknown" never merges with anything known. The only time a register transitions from "unknown"
-   * to "known" is when we're executing code for the first time, and we handle that with a simple
-   * copy.
-   */
-  static const RegType::Type merge_table_[kRegTypeReference][kRegTypeReference];
-
   DISALLOW_COPY_AND_ASSIGN(RegType);
 };
 std::ostream& operator<<(std::ostream& os, const RegType& rhs);
 
 class RegTypeCache {
  public:
-  explicit RegTypeCache() : entries_(RegType::kRegTypeReference) {
+  explicit RegTypeCache() : entries_(RegType::kRegTypeLastFixedLocation + 1) {
     Unknown();  // ensure Unknown is initialized
   }
   ~RegTypeCache() {
@@ -330,12 +298,18 @@
 
   const RegType& Unknown()  { return FromType(RegType::kRegTypeUnknown); }
   const RegType& Conflict() { return FromType(RegType::kRegTypeConflict); }
-  const RegType& Zero()     { return FromType(RegType::kRegTypeZero); }
   const RegType& ConstLo()  { return FromType(RegType::kRegTypeConstLo); }
+  const RegType& Zero()     { return FromCat1Const(0); }
 
   const RegType& Uninitialized(Class* klass, uint32_t allocation_pc);
   const RegType& UninitializedThisArgument(Class* klass);
 
+  // Representatives of various constant types. When merging constants we can't infer a type,
+  // (an int may later be used as a float) so we select these representative values meaning future
+  // merges won't know the exact constant value but have some notion of its size.
+  const RegType& ByteConstant() { return FromCat1Const(std::numeric_limits<jbyte>::min()); }
+  const RegType& ShortConstant() { return FromCat1Const(std::numeric_limits<jshort>::min()); }
+  const RegType& IntConstant() { return FromCat1Const(std::numeric_limits<jint>::max()); }
  private:
   // The allocated entries
   std::vector<RegType*> entries_;
@@ -573,7 +547,9 @@
   std::string Dump() const {
     std::string result;
     for (size_t i = 0; i < num_regs_; i++) {
+      result += StringPrintf("%d:[", i);
       result += GetRegisterType(i).Dump();
+      result += "],";
     }
     return result;
   }
@@ -690,10 +666,10 @@
 
   bool MergeRegisters(const RegisterLine* incoming_line);
 
-  size_t GetMaxReferenceReg(size_t max_ref_reg) {
+  size_t GetMaxNonZeroReferenceReg(size_t max_ref_reg) {
     size_t i = static_cast<int>(max_ref_reg) < 0 ? 0 : max_ref_reg;
     for(; i < num_regs_; i++) {
-      if (line_[i] >= RegType::kRegTypeReference) {
+      if (GetRegisterType(i).IsNonZeroReferenceTypes()) {
         max_ref_reg = i;
       }
     }
diff --git a/src/dex_verifier_test.cc b/src/dex_verifier_test.cc
index e6447ba..a074b72 100644
--- a/src/dex_verifier_test.cc
+++ b/src/dex_verifier_test.cc
@@ -52,7 +52,7 @@
   EXPECT_FALSE(bool_reg_type.IsConflict());
   EXPECT_FALSE(bool_reg_type.IsZero());
   EXPECT_FALSE(bool_reg_type.IsOne());
-  EXPECT_FALSE(bool_reg_type.IsConstLo());
+  EXPECT_FALSE(bool_reg_type.IsLongConstant());
   EXPECT_TRUE(bool_reg_type.IsBoolean());
   EXPECT_FALSE(bool_reg_type.IsByte());
   EXPECT_FALSE(bool_reg_type.IsChar());
@@ -83,7 +83,7 @@
   EXPECT_FALSE(byte_reg_type.IsConflict());
   EXPECT_FALSE(byte_reg_type.IsZero());
   EXPECT_FALSE(byte_reg_type.IsOne());
-  EXPECT_FALSE(byte_reg_type.IsConstLo());
+  EXPECT_FALSE(byte_reg_type.IsLongConstant());
   EXPECT_FALSE(byte_reg_type.IsBoolean());
   EXPECT_TRUE(byte_reg_type.IsByte());
   EXPECT_FALSE(byte_reg_type.IsChar());
@@ -114,7 +114,7 @@
   EXPECT_FALSE(char_reg_type.IsConflict());
   EXPECT_FALSE(char_reg_type.IsZero());
   EXPECT_FALSE(char_reg_type.IsOne());
-  EXPECT_FALSE(char_reg_type.IsConstLo());
+  EXPECT_FALSE(char_reg_type.IsLongConstant());
   EXPECT_FALSE(char_reg_type.IsBoolean());
   EXPECT_FALSE(char_reg_type.IsByte());
   EXPECT_TRUE(char_reg_type.IsChar());
@@ -145,7 +145,7 @@
   EXPECT_FALSE(short_reg_type.IsConflict());
   EXPECT_FALSE(short_reg_type.IsZero());
   EXPECT_FALSE(short_reg_type.IsOne());
-  EXPECT_FALSE(short_reg_type.IsConstLo());
+  EXPECT_FALSE(short_reg_type.IsLongConstant());
   EXPECT_FALSE(short_reg_type.IsBoolean());
   EXPECT_FALSE(short_reg_type.IsByte());
   EXPECT_FALSE(short_reg_type.IsChar());
@@ -176,7 +176,7 @@
   EXPECT_FALSE(int_reg_type.IsConflict());
   EXPECT_FALSE(int_reg_type.IsZero());
   EXPECT_FALSE(int_reg_type.IsOne());
-  EXPECT_FALSE(int_reg_type.IsConstLo());
+  EXPECT_FALSE(int_reg_type.IsLongConstant());
   EXPECT_FALSE(int_reg_type.IsBoolean());
   EXPECT_FALSE(int_reg_type.IsByte());
   EXPECT_FALSE(int_reg_type.IsChar());
@@ -207,7 +207,7 @@
   EXPECT_FALSE(long_reg_type.IsConflict());
   EXPECT_FALSE(long_reg_type.IsZero());
   EXPECT_FALSE(long_reg_type.IsOne());
-  EXPECT_FALSE(long_reg_type.IsConstLo());
+  EXPECT_FALSE(long_reg_type.IsLongConstant());
   EXPECT_FALSE(long_reg_type.IsBoolean());
   EXPECT_FALSE(long_reg_type.IsByte());
   EXPECT_FALSE(long_reg_type.IsChar());
@@ -238,7 +238,7 @@
   EXPECT_FALSE(float_reg_type.IsConflict());
   EXPECT_FALSE(float_reg_type.IsZero());
   EXPECT_FALSE(float_reg_type.IsOne());
-  EXPECT_FALSE(float_reg_type.IsConstLo());
+  EXPECT_FALSE(float_reg_type.IsLongConstant());
   EXPECT_FALSE(float_reg_type.IsBoolean());
   EXPECT_FALSE(float_reg_type.IsByte());
   EXPECT_FALSE(float_reg_type.IsChar());
@@ -269,7 +269,7 @@
   EXPECT_FALSE(double_reg_type.IsConflict());
   EXPECT_FALSE(double_reg_type.IsZero());
   EXPECT_FALSE(double_reg_type.IsOne());
-  EXPECT_FALSE(double_reg_type.IsConstLo());
+  EXPECT_FALSE(double_reg_type.IsLongConstant());
   EXPECT_FALSE(double_reg_type.IsBoolean());
   EXPECT_FALSE(double_reg_type.IsByte());
   EXPECT_FALSE(double_reg_type.IsChar());