ART: Change RETURN_OBJECT verification for arrays

Arrays appear to be valid (as according to spec), even if their
components are erroneous. If a component is erroneous, it may not
have loaded superclass or interface information, and so fail a
direct check for assignability.

Add a cutout that checks whether the declared return-type or the
actual return-type are arrays with erroneous components (and if so,
have the same 'depth'). In that case, generate a soft instead of a
hard error.

Also includes a fix to DumpClass.

Bug: 19683465
Change-Id: Ie73de03adeb0af7e939370d7363684fe125d7994
diff --git a/runtime/verifier/reg_type.cc b/runtime/verifier/reg_type.cc
index 201169f..97d0cbe 100644
--- a/runtime/verifier/reg_type.cc
+++ b/runtime/verifier/reg_type.cc
@@ -822,5 +822,42 @@
   return os;
 }
 
+bool RegType::CanAssignArray(const RegType& src, RegTypeCache& reg_types,
+                             Handle<mirror::ClassLoader> class_loader, bool* soft_error) const {
+  if (!IsArrayTypes() || !src.IsArrayTypes()) {
+    *soft_error = false;
+    return false;
+  }
+
+  const RegType& cmp1 = reg_types.GetComponentType(*this, class_loader.Get());
+  const RegType& cmp2 = reg_types.GetComponentType(src, class_loader.Get());
+
+  if (cmp1.IsAssignableFrom(cmp2)) {
+    return true;
+  }
+  if (cmp1.IsUnresolvedTypes()) {
+    if (cmp2.IsIntegralTypes() || cmp2.IsFloatTypes() || cmp2.IsArrayTypes()) {
+      *soft_error = false;
+      return false;
+    }
+    *soft_error = true;
+    return false;
+  }
+  if (cmp2.IsUnresolvedTypes()) {
+    if (cmp1.IsIntegralTypes() || cmp1.IsFloatTypes() || cmp1.IsArrayTypes()) {
+      *soft_error = false;
+      return false;
+    }
+    *soft_error = true;
+    return false;
+  }
+  if (!cmp1.IsArrayTypes() || !cmp2.IsArrayTypes()) {
+    *soft_error = false;
+    return false;
+  }
+  return cmp1.CanAssignArray(cmp2, reg_types, class_loader, soft_error);
+}
+
+
 }  // namespace verifier
 }  // namespace art