Adding Object::InstanceOf and Class::IsAssignableFrom

Summary:
- Add Object::InstanceOf and Class::IsAssignableFrom
- Fix Cloneable and Serializable interfaces on arrays to be == with FindSystemClass results
- Changed Object::Alloc(Class*) to be Class->NewInstance()

Details:

Add Object::InstanceOf and Class::IsAssignableFrom

	object.h
	common_test.h
	object_test.cc

Fix bug where Cloneable and Serializable where created with AllocClass
and never inserted in the classes table with FindSystemClass by just
creating them directly with FindSystemClass

	class_linker.cc
	object_test.cc

Changed Object::Alloc(Class*) to be Class->NewInstance()

	class_linker.cc
	object.h

Change-Id: I528767fff43aff32c8dc4f7a2d4157598a7dbb89
diff --git a/src/class_linker.cc b/src/class_linker.cc
index 46562ca..925a3b3 100644
--- a/src/class_linker.cc
+++ b/src/class_linker.cc
@@ -132,13 +132,10 @@
 
   // Setup a single, global copy of "interfaces" and "iftable" for
   // reuse across array classes
-  Class* java_lang_Cloneable = AllocClass();
+  Class* java_lang_Cloneable = FindSystemClass("Ljava/lang/Cloneable;");
   CHECK(java_lang_Cloneable != NULL);
-  java_lang_Cloneable->descriptor_ = "Ljava/lang/Cloneable;";
-
-  Class* java_io_Serializable = AllocClass();
+  Class* java_io_Serializable = FindSystemClass("Ljava/io/Serializable;");
   CHECK(java_io_Serializable != NULL);
-  java_io_Serializable->descriptor_ = "Ljava/io/Serializable;";
 
   array_interfaces_ = AllocObjectArray<Class>(2);
   CHECK(array_interfaces_ != NULL);
@@ -157,6 +154,8 @@
   // run Object[] through FindClass to complete initialization
   Class* found_object_array_class = FindSystemClass("[Ljava/lang/Object;");
   CHECK_EQ(object_array_class, found_object_array_class);
+  CHECK_EQ(java_lang_Cloneable, object_array_class->GetInterface(0));
+  CHECK_EQ(java_io_Serializable, object_array_class->GetInterface(1));
 
   // Setup the primitive type classes.
   class_roots_->Set(kPrimitiveByte, CreatePrimitiveClass("B"));
@@ -209,7 +208,7 @@
 }
 
 Class* ClassLinker::AllocClass(Class* java_lang_Class) {
-  return down_cast<Class*>(Object::Alloc(java_lang_Class));
+  return down_cast<Class*>(java_lang_Class->NewInstance());
 }
 
 Class* ClassLinker::AllocClass() {
@@ -217,20 +216,20 @@
 }
 
 StaticField* ClassLinker::AllocStaticField() {
-  return down_cast<StaticField*>(Object::Alloc(GetClassRoot(kJavaLangReflectField)));
+  return down_cast<StaticField*>(GetClassRoot(kJavaLangReflectField)->NewInstance());
 }
 
 InstanceField* ClassLinker::AllocInstanceField() {
-  return down_cast<InstanceField*>(Object::Alloc(GetClassRoot(kJavaLangReflectField)));
+  return down_cast<InstanceField*>(GetClassRoot(kJavaLangReflectField)->NewInstance());
 }
 
 Method* ClassLinker::AllocMethod() {
-  return down_cast<Method*>(Object::Alloc(GetClassRoot(kJavaLangReflectMethod)));
+  return down_cast<Method*>(GetClassRoot(kJavaLangReflectMethod)->NewInstance());
 }
 
 // TODO remove once we can use java.lang.Class.getSystemClassLoader
 PathClassLoader* ClassLinker::AllocPathClassLoader(std::vector<const DexFile*> dex_files) {
-  PathClassLoader* cl = down_cast<PathClassLoader*>(Object::Alloc(GetClassRoot(kDalvikSystemPathClassLoader)));
+  PathClassLoader* cl = down_cast<PathClassLoader*>(GetClassRoot(kDalvikSystemPathClassLoader)->NewInstance());
   cl->SetClassPath(dex_files);
   return cl;
 }
@@ -776,8 +775,7 @@
       if (!DexVerify::VerifyClass(klass)) {
         LG << "Verification failed";  // TODO: ThrowVerifyError
         Object* exception = self->GetException();
-        size_t field_offset = OFFSETOF_MEMBER(Class, verify_error_class_);
-        klass->SetFieldObject(field_offset, exception->GetClass());
+        klass->SetVerifyErrorClass(exception->GetClass());
         klass->SetStatus(Class::kStatusError);
         return false;
       }
diff --git a/src/common_test.h b/src/common_test.h
index 13f92d1..2555005 100644
--- a/src/common_test.h
+++ b/src/common_test.h
@@ -221,6 +221,20 @@
   "AAMAAAADAAAA2AAAAAUAAAAEAAAA/AAAAAYAAAABAAAAHAEAAAEgAAADAAAAPAEAAAEQAAACAAAA"
   "fAEAAAIgAAAQAAAAlAEAAAMgAAADAAAAJAIAAAAgAAABAAAAOgIAAAAQAAABAAAATAIAAA==";
 
+// class X {}
+// class Y extends X {}
+static const char kXandY[] =
+  "ZGV4CjAzNQAlLMqyB72TxJW4zl5w75F072u4Ig6KvCMEAgAAcAAAAHhWNBIAAAAAAAAAAHwBAAAG"
+  "AAAAcAAAAAQAAACIAAAAAQAAAJgAAAAAAAAAAAAAAAMAAACkAAAAAgAAALwAAAAIAQAA/AAAACwB"
+  "AAA0AQAAOQEAAD4BAABSAQAAVQEAAAEAAAACAAAAAwAAAAQAAAAEAAAAAwAAAAAAAAAAAAAAAAAA"
+  "AAEAAAAAAAAAAgAAAAAAAAAAAAAAAAAAAAIAAAAAAAAABQAAAAAAAABnAQAAAAAAAAEAAAAAAAAA"
+  "AAAAAAAAAAAFAAAAAAAAAHEBAAAAAAAAAQABAAEAAABdAQAABAAAAHAQAgAAAA4AAQABAAEAAABi"
+  "AQAABAAAAHAQAAAAAA4ABjxpbml0PgADTFg7AANMWTsAEkxqYXZhL2xhbmcvT2JqZWN0OwABVgAG"
+  "WC5qYXZhAAIABw4AAwAHDgAAAAEAAICABPwBAAABAAGAgASUAgALAAAAAAAAAAEAAAAAAAAAAQAA"
+  "AAYAAABwAAAAAgAAAAQAAACIAAAAAwAAAAEAAACYAAAABQAAAAMAAACkAAAABgAAAAIAAAC8AAAA"
+  "ASAAAAIAAAD8AAAAAiAAAAYAAAAsAQAAAyAAAAIAAABdAQAAACAAAAIAAABnAQAAABAAAAEAAAB8"
+  "AQAA";
+
 static inline DexFile* OpenDexFileBase64(const char* base64) {
   CHECK(base64 != NULL);
   size_t length;
diff --git a/src/object.cc b/src/object.cc
index 2369954..514eef5 100644
--- a/src/object.cc
+++ b/src/object.cc
@@ -13,6 +13,100 @@
 
 namespace art {
 
+bool Class::Implements(const Class* klass) const {
+  DCHECK(klass != NULL);
+  DCHECK(klass->IsInterface());
+  // All interfaces implemented directly and by our superclass, and
+  // recursively all super-interfaces of those interfaces, are listed
+  // in iftable_, so we can just do a linear scan through that.
+  for (size_t i = 0; i < iftable_count_; i++) {
+    if (iftable_[i].GetClass() == klass) {
+      return true;
+    }
+  }
+  return false;
+}
+
+// Determine whether "this" is assignable from "klazz", where both of these
+// are array classes.
+//
+// Consider an array class, e.g. Y[][], where Y is a subclass of X.
+//   Y[][]            = Y[][] --> true (identity)
+//   X[][]            = Y[][] --> true (element superclass)
+//   Y                = Y[][] --> false
+//   Y[]              = Y[][] --> false
+//   Object           = Y[][] --> true (everything is an object)
+//   Object[]         = Y[][] --> true
+//   Object[][]       = Y[][] --> true
+//   Object[][][]     = Y[][] --> false (too many []s)
+//   Serializable     = Y[][] --> true (all arrays are Serializable)
+//   Serializable[]   = Y[][] --> true
+//   Serializable[][] = Y[][] --> false (unless Y is Serializable)
+//
+// Don't forget about primitive types.
+//   int[] instanceof Object[]     --> false
+//
+bool Class::IsArrayAssignableFromArray(const Class* klass) const {
+  DCHECK(IsArray());
+  DCHECK(klass->IsArray());
+  DCHECK_GT(array_rank_, 0);
+  DCHECK_GT(klass->array_rank_, 0);
+  DCHECK(component_type_ != NULL);
+  DCHECK(klass->component_type_ != NULL);
+  if (array_rank_ > klass->array_rank_) {
+    // Too many []s.
+    return false;
+  }
+  if (array_rank_ == klass->array_rank_) {
+    return component_type_->IsAssignableFrom(klass->component_type_);
+  }
+  DCHECK_LT(array_rank_, klass->array_rank_);
+  // The thing we might be assignable from has more dimensions.  We
+  // must be an Object or array of Object, or a standard array
+  // interface or array of standard array interfaces (the standard
+  // interfaces being java/lang/Cloneable and java/io/Serializable).
+  if (component_type_->IsInterface()) {
+    // See if we implement our component type.  We know the
+    // base element is an interface; if the array class implements
+    // it, we know it's a standard array interface.
+    return Implements(component_type_);
+  }
+  // See if this is an array of Object, Object[], etc.  We know
+  // that the superclass of an array is always Object, so we
+  // just compare the element type to that.
+  Class* java_lang_Object = GetSuperClass();
+  DCHECK(java_lang_Object != NULL);
+  DCHECK(java_lang_Object->GetSuperClass() == NULL);
+  return (component_type_ == java_lang_Object);
+}
+
+bool Class::IsAssignableFromArray(const Class* klass) const {
+  DCHECK(!IsInterface());  // handled first in IsAssignableFrom
+  DCHECK(klass->IsArray());
+  if (!IsArray()) {
+    // If "this" is not also an array, it must be Object.
+    // klass's super should be java_lang_Object, since it is an array.
+    Class* java_lang_Object = klass->GetSuperClass();
+    DCHECK(java_lang_Object != NULL);
+    DCHECK(java_lang_Object->GetSuperClass() == NULL);
+    return this == java_lang_Object;
+  }
+  return IsArrayAssignableFromArray(klass);
+}
+
+bool Class::IsSubClass(const Class* klass) const {
+  DCHECK(!IsInterface());
+  DCHECK(!klass->IsArray());
+  const Class* current = this;
+  do {
+    if (current == klass) {
+      return true;
+    }
+    current = current->GetSuperClass();
+  } while (current != NULL);
+  return false;
+}
+
 bool Class::IsInSamePackage(const StringPiece& descriptor1,
                             const StringPiece& descriptor2) {
   size_t i = 0;
diff --git a/src/object.h b/src/object.h
index 5e6c175..c1682ec 100644
--- a/src/object.h
+++ b/src/object.h
@@ -110,12 +110,19 @@
 
 class Object {
  public:
-  static Object* Alloc(Class* klass);
+  static bool InstanceOf(const Object* object, const Class* klass) {
+    if (object == NULL) {
+      return false;
+    }
+    return object->InstanceOf(klass);
+  }
 
   Class* GetClass() const {
     return klass_;
   }
 
+  bool InstanceOf(const Class* klass) const;
+
   void MonitorEnter() {
     monitor_->Enter();
   }
@@ -739,6 +746,10 @@
     kPrimNot = -1
   };
 
+  Object* NewInstance() {
+    return Heap::AllocObject(this, this->object_size_);
+  }
+
   Class* GetSuperClass() const {
     return super_class_;
   }
@@ -751,6 +762,20 @@
     return super_class_ != NULL;
   }
 
+  bool IsAssignableFrom(const Class* klass) const {
+    DCHECK(klass != NULL);
+    if (this == klass) {
+      return true;
+    }
+    if (IsInterface()) {
+      return klass->Implements(this);
+    }
+    if (klass->IsArray()) {
+      return IsAssignableFromArray(klass);
+    }
+    return klass->IsSubClass(this);
+  }
+
   ClassLoader* GetClassLoader() const {
     return class_loader_;
   }
@@ -898,7 +923,7 @@
     return num_reference_instance_fields_;
   }
 
-  InstanceField* GetInstanceField(uint32_t i) {  // TODO: uint16_t
+  InstanceField* GetInstanceField(uint32_t i) const {  // TODO: uint16_t
     DCHECK_NE(NumInstanceFields(), 0U);
     return ifields_->Get(i);
   }
@@ -944,6 +969,18 @@
     interfaces_->Set(i, f);
   }
 
+  void SetVerifyErrorClass(Class* klass) {
+    // Note SetFieldObject is used rather than verify_error_class_ directly for the barrier
+    size_t field_offset = OFFSETOF_MEMBER(Class, verify_error_class_);
+    klass->SetFieldObject(field_offset, klass);
+  }
+
+ private:
+  bool Implements(const Class* klass) const;
+  bool IsArrayAssignableFromArray(const Class* klass) const;
+  bool IsAssignableFromArray(const Class* klass) const;
+  bool IsSubClass(const Class* klass) const;
+
  public:  // TODO: private
   // leave space for instance data; we could access fields directly if
   // we freeze the definition of java/lang/Class
@@ -970,8 +1007,9 @@
   // state of class initialization
   Status status_;
 
-  // if class verify fails, we must return same error on subsequent tries
-  Class* verify_error_class_;
+  // If class verify fails, we must return same error on subsequent tries.
+  // Update with SetVerifyErrorClass to ensure a write barrier is used.
+  const Class* verify_error_class_;
 
   // threadId, used to check for recursive <clinit> invocation
   uint32_t clinit_thread_id_;
@@ -1075,11 +1113,13 @@
 };
 std::ostream& operator<<(std::ostream& os, const Class::Status& rhs);
 
-inline Object* Object::Alloc(Class* klass) {
+inline bool Object::InstanceOf(const Class* klass) const {
   DCHECK(klass != NULL);
-  return Heap::AllocObject(klass, klass->object_size_);
+  DCHECK(klass_ != NULL);
+  return klass->IsAssignableFrom(klass_);
 }
 
+
 class DataObject : public Object {
  public:
   uint32_t fields_[0];
@@ -1190,7 +1230,7 @@
   static String* Alloc(Class* java_lang_String,
                        Class* char_array,
                        int32_t utf16_length) {
-    String* string = down_cast<String*>(Object::Alloc(java_lang_String));
+    String* string = down_cast<String*>(java_lang_String->NewInstance());
     CharArray* array = CharArray::Alloc(char_array, utf16_length);
     string->array_ = array;
     string->count_ = utf16_length;
diff --git a/src/object_test.cc b/src/object_test.cc
index cf59776..7167732 100644
--- a/src/object_test.cc
+++ b/src/object_test.cc
@@ -55,16 +55,23 @@
 }
 
 TEST_F(ObjectTest, AllocObjectArray) {
-    ObjectArray<Object>* oa = class_linker_->AllocObjectArray<Object>(2);
-    EXPECT_EQ(2U, oa->GetLength());
-    EXPECT_TRUE(oa->Get(0) == NULL);
-    EXPECT_TRUE(oa->Get(1) == NULL);
-    oa->Set(0, oa);
-    EXPECT_TRUE(oa->Get(0) == oa);
-    EXPECT_TRUE(oa->Get(1) == NULL);
-    oa->Set(1, oa);
-    EXPECT_TRUE(oa->Get(0) == oa);
-    EXPECT_TRUE(oa->Get(1) == oa);
+  ObjectArray<Object>* oa = class_linker_->AllocObjectArray<Object>(2);
+  EXPECT_EQ(2U, oa->GetLength());
+  EXPECT_TRUE(oa->Get(0) == NULL);
+  EXPECT_TRUE(oa->Get(1) == NULL);
+  oa->Set(0, oa);
+  EXPECT_TRUE(oa->Get(0) == oa);
+  EXPECT_TRUE(oa->Get(1) == NULL);
+  oa->Set(1, oa);
+  EXPECT_TRUE(oa->Get(0) == oa);
+  EXPECT_TRUE(oa->Get(1) == oa);
+
+  ASSERT_TRUE(oa->GetClass() != NULL);
+  ASSERT_EQ(2U, oa->GetClass()->NumInterfaces());
+  EXPECT_EQ(class_linker_->FindSystemClass("Ljava/lang/Cloneable;"),
+            oa->GetClass()->GetInterface(0));
+  EXPECT_EQ(class_linker_->FindSystemClass("Ljava/io/Serializable;"),
+            oa->GetClass()->GetInterface(1));
 }
 
 TEST_F(ObjectTest, String) {
@@ -169,4 +176,95 @@
   EXPECT_EQ(64578U, String::AllocFromAscii("ABC")->GetHashCode());
 }
 
+TEST_F(ObjectTest, InstanceOf) {
+  scoped_ptr<DexFile> dex(OpenDexFileBase64(kXandY));
+  PathClassLoader* class_loader = AllocPathClassLoader(dex.get());
+  Class* X = class_linker_->FindClass("LX;", class_loader);
+  Class* Y = class_linker_->FindClass("LY;", class_loader);
+  ASSERT_TRUE(X != NULL);
+  ASSERT_TRUE(Y != NULL);
+
+  EXPECT_FALSE(Object::InstanceOf(NULL, X));
+  EXPECT_FALSE(Object::InstanceOf(NULL, Y));
+
+  Object* x = X->NewInstance();
+  Object* y = Y->NewInstance();
+  ASSERT_TRUE(x != NULL);
+  ASSERT_TRUE(y != NULL);
+
+  EXPECT_TRUE(Object::InstanceOf(x, X));
+  EXPECT_FALSE(Object::InstanceOf(x, Y));
+  EXPECT_TRUE(Object::InstanceOf(y, X));
+  EXPECT_TRUE(Object::InstanceOf(y, Y));
+
+  EXPECT_TRUE(x->InstanceOf(X));
+  EXPECT_FALSE(x->InstanceOf(Y));
+  EXPECT_TRUE(y->InstanceOf(X));
+  EXPECT_TRUE(y->InstanceOf(Y));
+}
+
+TEST_F(ObjectTest, IsAssignableFrom) {
+  scoped_ptr<DexFile> dex(OpenDexFileBase64(kXandY));
+  PathClassLoader* class_loader = AllocPathClassLoader(dex.get());
+  Class* X = class_linker_->FindClass("LX;", class_loader);
+  Class* Y = class_linker_->FindClass("LY;", class_loader);
+
+  EXPECT_TRUE(X->IsAssignableFrom(X));
+  EXPECT_TRUE(X->IsAssignableFrom(Y));
+  EXPECT_FALSE(Y->IsAssignableFrom(X));
+  EXPECT_TRUE(Y->IsAssignableFrom(Y));
+}
+
+TEST_F(ObjectTest, IsAssignableFromArray) {
+  scoped_ptr<DexFile> dex(OpenDexFileBase64(kXandY));
+  PathClassLoader* class_loader = AllocPathClassLoader(dex.get());
+  Class* X = class_linker_->FindClass("LX;", class_loader);
+  Class* Y = class_linker_->FindClass("LY;", class_loader);
+  ASSERT_TRUE(X != NULL);
+  ASSERT_TRUE(Y != NULL);
+
+  Class* YA = class_linker_->FindClass("[LY;", class_loader);
+  Class* YAA = class_linker_->FindClass("[[LY;", class_loader);
+  ASSERT_TRUE(YA != NULL);
+  ASSERT_TRUE(YAA != NULL);
+
+  Class* XAA = class_linker_->FindClass("[[LX;", class_loader);
+  ASSERT_TRUE(XAA != NULL);
+
+  Class* O = class_linker_->FindSystemClass("Ljava/lang/Object;");
+  Class* OA = class_linker_->FindSystemClass("[Ljava/lang/Object;");
+  Class* OAA = class_linker_->FindSystemClass("[[Ljava/lang/Object;");
+  Class* OAAA = class_linker_->FindSystemClass("[[[Ljava/lang/Object;");
+  ASSERT_TRUE(O != NULL);
+  ASSERT_TRUE(OA != NULL);
+  ASSERT_TRUE(OAA != NULL);
+  ASSERT_TRUE(OAAA != NULL);
+
+  Class* S = class_linker_->FindSystemClass("Ljava/io/Serializable;");
+  Class* SA = class_linker_->FindSystemClass("[Ljava/io/Serializable;");
+  Class* SAA = class_linker_->FindSystemClass("[[Ljava/io/Serializable;");
+  ASSERT_TRUE(S != NULL);
+  ASSERT_TRUE(SA != NULL);
+  ASSERT_TRUE(SAA != NULL);
+
+  Class* IA = class_linker_->FindSystemClass("[I");
+  ASSERT_TRUE(IA != NULL);
+
+  EXPECT_TRUE(YAA->IsAssignableFrom(YAA));  // identity
+  EXPECT_TRUE(XAA->IsAssignableFrom(YAA));  // element superclass
+  EXPECT_FALSE(YAA->IsAssignableFrom(XAA));
+  EXPECT_FALSE(Y->IsAssignableFrom(YAA));
+  EXPECT_FALSE(YA->IsAssignableFrom(YAA));
+  EXPECT_TRUE(O->IsAssignableFrom(YAA));  // everything is an Object
+  EXPECT_TRUE(OA->IsAssignableFrom(YAA));
+  EXPECT_TRUE(OAA->IsAssignableFrom(YAA));
+  EXPECT_TRUE(S->IsAssignableFrom(YAA));  // all arrays are Serializable
+  EXPECT_TRUE(SA->IsAssignableFrom(YAA));
+  EXPECT_FALSE(SAA->IsAssignableFrom(YAA));  // unless Y was Serializable
+
+  EXPECT_FALSE(IA->IsAssignableFrom(OA));
+  EXPECT_FALSE(OA->IsAssignableFrom(IA));
+  EXPECT_TRUE(O->IsAssignableFrom(IA));
+}
+
 }  // namespace art