Assignability checks for SetFieldObject.

Adds check to SetFieldObject that is enabled with VERIFY_OBJECT_ENABLED.
The check verifies that the object being set to the field is assignable
to that field.

Fix bug that iftable was typed to be Object[][] but being assigned a
Object[].

Change-Id: I3d3744347f2dd142ca90db321ed876eaebfe7f7f
diff --git a/src/object.cc b/src/object.cc
index e4b5f98..eb11469 100644
--- a/src/object.cc
+++ b/src/object.cc
@@ -115,6 +115,51 @@
   Monitor::Wait(Thread::Current(), this, ms, ns, true);
 }
 
+#if VERIFY_OBJECT_ENABLED
+void Object::CheckFieldAssignment(MemberOffset field_offset, const Object* new_value) {
+  const Class* c = GetClass();
+  if (Runtime::Current()->GetClassLinker() == NULL ||
+      !Runtime::Current()->GetHeap()->IsObjectValidationEnabled() ||
+      !c->IsResolved()) {
+    return;
+  }
+  for (const Class* cur = c; cur != NULL; cur = cur->GetSuperClass()) {
+    ObjectArray<Field>* fields = cur->GetIFields();
+    if (fields != NULL) {
+      size_t num_ref_ifields = cur->NumReferenceInstanceFields();
+      for (size_t i = 0; i < num_ref_ifields; ++i) {
+        Field* field = fields->Get(i);
+        if (field->GetOffset().Int32Value() == field_offset.Int32Value()) {
+          FieldHelper fh(field);
+          CHECK(fh.GetType()->IsAssignableFrom(new_value->GetClass()));
+          return;
+        }
+      }
+    }
+  }
+  if (c->IsArrayClass()) {
+    // Bounds and assign-ability done in the array setter.
+    return;
+  }
+  if (IsClass()) {
+    ObjectArray<Field>* fields = AsClass()->GetSFields();
+    if (fields != NULL) {
+      size_t num_ref_sfields = AsClass()->NumReferenceStaticFields();
+      for (size_t i = 0; i < num_ref_sfields; ++i) {
+        Field* field = fields->Get(i);
+        if (field->GetOffset().Int32Value() == field_offset.Int32Value()) {
+          FieldHelper fh(field);
+          CHECK(fh.GetType()->IsAssignableFrom(new_value->GetClass()));
+          return;
+        }
+      }
+    }
+  }
+  LOG(FATAL) << "Failed to find field for assignment to " << reinterpret_cast<void*>(this)
+      << " of type " << PrettyDescriptor(c) << " at offset " << field_offset;
+}
+#endif
+
 // TODO: get global references for these
 Class* Field::java_lang_reflect_Field_ = NULL;