Various verifier fixes.

Change-Id: Ia73e9f8500c32ec8924afe1099d172bd00fdecbf
diff --git a/src/dex_verifier.cc b/src/dex_verifier.cc
index 5a44055..0338027 100644
--- a/src/dex_verifier.cc
+++ b/src/dex_verifier.cc
@@ -151,59 +151,39 @@
   }
 }
 
-const RegType& RegType::VerifyAgainst(const RegType& check_type, RegTypeCache* reg_types) const {
-  if (Equals(check_type)) {
-    return *this;
+bool RegType::IsAssignableFrom(const RegType& src) const {
+  if (Equals(src)) {
+    return true;
   } else {
-    switch (check_type.GetType()) {
-      case RegType::kRegTypeBoolean:
-        return IsBooleanTypes() ? check_type : reg_types->Conflict();
-        break;
-      case RegType::kRegTypeByte:
-        return IsByteTypes() ? check_type : reg_types->Conflict();
-        break;
-      case RegType::kRegTypeShort:
-        return IsShortTypes() ? check_type : reg_types->Conflict();
-        break;
-      case RegType::kRegTypeChar:
-        return IsCharTypes() ? check_type : reg_types->Conflict();
-        break;
-      case RegType::kRegTypeInteger:
-        return IsIntegralTypes() ? check_type : reg_types->Conflict();
-        break;
-      case RegType::kRegTypeFloat:
-        return IsFloatTypes() ? check_type : reg_types->Conflict();
-        break;
-      case RegType::kRegTypeLongLo:
-        return IsLongTypes() ? check_type : reg_types->Conflict();
-        break;
-      case RegType::kRegTypeDoubleLo:
-        return IsDoubleTypes() ? check_type : reg_types->Conflict();
-        break;
+    switch (GetType()) {
+      case RegType::kRegTypeBoolean:  return IsBooleanTypes();
+      case RegType::kRegTypeByte:     return IsByteTypes();
+      case RegType::kRegTypeShort:    return IsShortTypes();
+      case RegType::kRegTypeChar:     return IsCharTypes();
+      case RegType::kRegTypeInteger:  return IsIntegralTypes();
+      case RegType::kRegTypeFloat:    return IsFloatTypes();
+      case RegType::kRegTypeLongLo:   return IsLongTypes();
+      case RegType::kRegTypeDoubleLo: return IsDoubleTypes();
       default:
-        if (!check_type.IsReferenceTypes()) {
-          LOG(FATAL) << "Unexpected register type verification against " << check_type;
+        if (!IsReferenceTypes()) {
+          LOG(FATAL) << "Unexpected register type in IsAssignableFrom: '" << src << "'";
         }
-        if (IsZero()) {
-          return check_type;
+        if (src.IsZero()) {
+          return true;
         } else if (IsUninitializedReference()) {
-          return reg_types->Conflict();  // Nonsensical to Join two uninitialized classes
-        } else if (IsReference() && check_type.IsReference() &&
-                   (check_type.GetClass()->IsAssignableFrom(GetClass()) ||
-                    (GetClass()->IsObjectClass() && check_type.GetClass()->IsInterface()))) {
+          return false;  // Nonsensical to Join two uninitialized classes
+        } else if (IsReference() && src.IsReference() &&
+                   (GetClass()->IsAssignableFrom(src.GetClass()) ||
+                    (src.GetClass()->IsObjectClass() && GetClass()->IsInterface()) ||
+                    (GetClass()->IsObjectClass() && src.GetClass()->IsInterface()))) {
           // Either we're assignable or this is trying to assign Object to an Interface, which
           // 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;
+          return true;
+        } else if (src.IsUnresolvedReference() && IsReference() && GetClass()->IsObjectClass()) {
+          // We're an object being assigned an unresolved reference, which is ok
+          return true;
         } else {
-          return reg_types->Conflict();
+          return false;
         }
     }
   }
@@ -568,8 +548,7 @@
 bool RegisterLine::VerifyRegisterType(uint32_t vsrc, const RegType& check_type) {
   // Verify the src register type against the check type refining the type of the register
   const RegType& src_type = GetRegisterType(vsrc);
-  const RegType& lub_type = src_type.VerifyAgainst(check_type, verifier_->GetRegTypeCache());
-  if (lub_type.IsConflict()) {
+  if (!check_type.IsAssignableFrom(src_type)) {
     verifier_->Fail(VERIFY_ERROR_GENERIC) << "register v" << vsrc << " has type " << src_type
                                           << " but expected " << check_type;
     return false;
@@ -1929,7 +1908,7 @@
       Class* res_class = ResolveClassAndCheckAccess(dec_insn.vB_);
       if (res_class == NULL) {
         const char* bad_class_desc = dex_file_->dexStringByTypeIdx(dec_insn.vB_);
-        Fail(failure_) << "unable to resolve const-class " << dec_insn.vB_
+        fail_messages_ << "unable to resolve const-class " << dec_insn.vB_
                        << " (" << bad_class_desc << ") in "
                        << PrettyDescriptor(method_->GetDeclaringClass()->GetDescriptor());
         DCHECK(failure_ != VERIFY_ERROR_GENERIC);
@@ -1978,7 +1957,7 @@
       Class* res_class = ResolveClassAndCheckAccess(dec_insn.vB_);
       if (res_class == NULL) {
         const char* bad_class_desc = dex_file_->dexStringByTypeIdx(dec_insn.vB_);
-        Fail(failure_) << "unable to resolve check-cast " << dec_insn.vB_
+        fail_messages_ << "unable to resolve check-cast " << dec_insn.vB_
                        << " (" << bad_class_desc << ") in "
                        << PrettyDescriptor(method_->GetDeclaringClass()->GetDescriptor());
         DCHECK(failure_ != VERIFY_ERROR_GENERIC);
@@ -2002,7 +1981,7 @@
         Class* res_class = ResolveClassAndCheckAccess(dec_insn.vC_);
         if (res_class == NULL) {
           const char* bad_class_desc = dex_file_->dexStringByTypeIdx(dec_insn.vC_);
-          Fail(failure_) << "unable to resolve instance of " << dec_insn.vC_
+          fail_messages_ << "unable to resolve instance of " << dec_insn.vC_
                          << " (" << bad_class_desc << ") in "
                          << PrettyDescriptor(method_->GetDeclaringClass()->GetDescriptor());
           DCHECK(failure_ != VERIFY_ERROR_GENERIC);
@@ -2028,7 +2007,7 @@
       Class* res_class = ResolveClassAndCheckAccess(dec_insn.vB_);
       if (res_class == NULL) {
         const char* bad_class_desc = dex_file_->dexStringByTypeIdx(dec_insn.vB_);
-        Fail(failure_) << "unable to resolve new-instance " << dec_insn.vB_
+        fail_messages_ << "unable to resolve new-instance " << dec_insn.vB_
                        << " (" << bad_class_desc << ") in "
                        << PrettyDescriptor(method_->GetDeclaringClass()->GetDescriptor());
         DCHECK(failure_ != VERIFY_ERROR_GENERIC);
@@ -2054,7 +2033,7 @@
       Class* res_class = ResolveClassAndCheckAccess(dec_insn.vC_);
       if (res_class == NULL) {
         const char* bad_class_desc = dex_file_->dexStringByTypeIdx(dec_insn.vC_);
-        Fail(failure_) << "unable to resolve new-array " << dec_insn.vC_
+        fail_messages_ << "unable to resolve new-array " << dec_insn.vC_
                        << " (" << bad_class_desc << ") in "
                        << PrettyDescriptor(method_->GetDeclaringClass()->GetDescriptor());
         DCHECK(failure_ != VERIFY_ERROR_GENERIC);
@@ -2073,7 +2052,7 @@
       Class* res_class = ResolveClassAndCheckAccess(dec_insn.vB_);
       if (res_class == NULL) {
         const char* bad_class_desc = dex_file_->dexStringByTypeIdx(dec_insn.vB_);
-        Fail(failure_) << "unable to resolve filled-array " << dec_insn.vB_
+        fail_messages_ << "unable to resolve filled-array " << dec_insn.vB_
                        << " (" << bad_class_desc << ") in "
                        << PrettyDescriptor(method_->GetDeclaringClass()->GetDescriptor());
         DCHECK(failure_ != VERIFY_ERROR_GENERIC);
@@ -3002,8 +2981,9 @@
     const char* method_name = dex_file_->GetMethodName(method_id);
     std::string method_signature = dex_file_->GetMethodSignature(method_id);
     const char* class_descriptor = dex_file_->GetMethodDeclaringClassDescriptor(method_id);
-    Fail(VERIFY_ERROR_GENERIC) << "unable to resolve method " << dec_insn.vB_ << ": "
-                               << class_descriptor << "." << method_name << " " << method_signature;
+    DCHECK_NE(failure_, VERIFY_ERROR_NONE);
+    fail_messages_ << "unable to resolve method " << dec_insn.vB_ << ": "
+                   << class_descriptor << "." << method_name << " " << method_signature;
     return NULL;
   }
   // Make sure calls to constructors are "direct". There are additional restrictions but we don't
@@ -3400,12 +3380,13 @@
   const RegType& object_type = work_line_->GetRegisterType(dec_insn.vB_);
   Field* field = GetInstanceField(object_type, dec_insn.vC_);
   if (field != NULL) {
-    Class* field_class = field->GetType();
-    Class* insn_class = insn_type.GetClass();
+    const RegType& field_type =
+        reg_types_.FromDescriptor(field->GetDeclaringClass()->GetClassLoader(),
+                                  field->GetTypeDescriptor());
     if (is_primitive) {
-      if (field_class == insn_class ||
-          (field_class->IsPrimitiveFloat() && insn_class->IsPrimitiveInt()) ||
-          (field_class->IsPrimitiveDouble() && insn_class->IsPrimitiveLong())) {
+      if (field_type.Equals(insn_type) ||
+          (field_type.IsFloat() && insn_type.IsIntegralTypes()) ||
+          (field_type.IsDouble() && insn_type.IsLongTypes())) {
         // expected that read is of the correct primitive type or that int reads are reading
         // floats or long reads are reading doubles
       } else {
@@ -3413,19 +3394,20 @@
         // the descriptors for the type should have been consistent within the same file at
         // compile time
         Fail(VERIFY_ERROR_GENERIC) << "expected field " << PrettyField(field)
-                                   << " to be of type " << PrettyClass(insn_class)
-                                   << " but found type " << PrettyClass(field_class) << " in iget";
+                                   << " to be of type '" << insn_type
+                                   << "' but found type '" << field_type << "' in iget";
         return;
       }
     } else {
-      if (!insn_class->IsAssignableFrom(field_class)) {
+      if (!insn_type.IsAssignableFrom(field_type)) {
         Fail(VERIFY_ERROR_GENERIC) << "expected field " << PrettyField(field)
-                                   << " to be compatible with type " << PrettyClass(insn_class)
-                                   << " but found type " << PrettyClass(field_class) << " in iget-object";
+                                   << " to be compatible with type '" << insn_type
+                                   << "' but found type '" << field_type
+                                   << "' in iget-object";
         return;
       }
     }
-    work_line_->SetRegisterType(dec_insn.vA_, reg_types_.FromClass(field_class));
+    work_line_->SetRegisterType(dec_insn.vA_, field_type);
   }
 }
 
@@ -3439,9 +3421,9 @@
                                << " from other class " << PrettyClass(method_->GetDeclaringClass());
       return;
     }
-    Class* field_class = field->GetType();
-    const RegType& field_type = reg_types_.FromClass(field_class);
-    Class* insn_class = insn_type.GetClass();
+    const RegType& field_type =
+        reg_types_.FromDescriptor(field->GetDeclaringClass()->GetClassLoader(),
+                                  field->GetTypeDescriptor());
     if (is_primitive) {
       // Primitive field assignability rules are weaker than regular assignability rules
       bool instruction_compatible;
@@ -3468,8 +3450,9 @@
         // the descriptors for the type should have been consistent within the same file at
         // compile time
         Fail(VERIFY_ERROR_GENERIC) << "expected field " << PrettyField(field)
-                                   << " to be of type " << PrettyClass(insn_class)
-                                   << " but found type " << PrettyClass(field_class) << " in iput";
+                                   << " to be of type '" << insn_type
+                                   << "' but found type '" << field_type
+                                   << "' in iput";
         return;
       }
       if (!value_compatible) {
@@ -3480,11 +3463,11 @@
         return;
       }
     } else {
-      if (!insn_class->IsAssignableFrom(field_class)) {
+      if (!insn_type.IsAssignableFrom(field_type)) {
         Fail(VERIFY_ERROR_GENERIC) << "expected field " << PrettyField(field)
-                                  << " to be compatible with type " << insn_type
-                                  << " but found type " << PrettyClass(field_class)
-                                  << " in iput-object";
+                                  << " to be compatible with type '" << insn_type
+                                  << "' but found type '" << field_type
+                                  << "' in iput-object";
         return;
       }
       work_line_->VerifyRegisterType(dec_insn.vA_, field_type);
diff --git a/src/dex_verifier.h b/src/dex_verifier.h
index d27be35..e248ed4 100644
--- a/src/dex_verifier.h
+++ b/src/dex_verifier.h
@@ -204,7 +204,7 @@
 
   std::string Dump() const;
 
-  const RegType& VerifyAgainst(const RegType& check_type, RegTypeCache* reg_types) const;
+  bool IsAssignableFrom(const RegType& src) const;
 
   const RegType& Merge(const RegType& incoming_type, RegTypeCache* reg_types) const;