* src/vm/class.cpp (class_is_assignable_from): Fixed for array classes.
[cacao.git] / src / vm / class.cpp
index ec8a9538bf336cf5b4036f90ea5999307c7edec9..0c1739a3c0ed7089cc206e1cecebdac9218af788 100644 (file)
@@ -34,7 +34,7 @@
 
 #include "arch.h"
 
-#include "mm/memory.h"
+#include "mm/memory.hpp"
 
 #include "native/llni.h"
 
@@ -1445,8 +1445,7 @@ bool class_issubclass(classinfo *sub, classinfo *super)
 
 bool class_isanysubclass(classinfo *sub, classinfo *super)
 {
-       uint32_t diffval;
-       bool     result;
+       bool result;
 
        /* This is the trivial case. */
 
@@ -1471,18 +1470,70 @@ bool class_isanysubclass(classinfo *sub, classinfo *super)
                if (sub->flags & ACC_INTERFACE)
                        return (super == class_java_lang_Object);
 
-               linker_classrenumber_mutex->lock();
+#if USES_NEW_SUBTYPE
+               result = fast_subtype_check(sub->vftbl, super->vftbl);
+#else
+               LOCK_CLASSRENUMBER_LOCK;
 
-               diffval = sub->vftbl->baseval - super->vftbl->baseval;
-               result  = diffval <= (uint32_t) super->vftbl->diffval;
+               uint32_t diffval = sub->vftbl->baseval - super->vftbl->baseval;
+               result = diffval <= (uint32_t) super->vftbl->diffval;
 
-               linker_classrenumber_mutex->unlock();
+               UNLOCK_CLASSRENUMBER_LOCK;
+#endif
        }
 
        return result;
 }
 
 
+/* class_is_arraycompatible ****************************************************
+
+   Checks if two array type descriptors are assignment compatible.
+
+   RETURN VALUE:
+      true .... target = desc is possible
+      false ... otherwise
+                       
+*******************************************************************************/
+
+bool class_is_arraycompatible(arraydescriptor *desc, arraydescriptor *target)
+{
+       if (desc == target)
+               return true;
+
+       if (desc->arraytype != target->arraytype)
+               return false;
+
+       if (desc->arraytype != ARRAYTYPE_OBJECT)
+               return true;
+       
+       /* {both arrays are arrays of references} */
+
+       if (desc->dimension == target->dimension) {
+               if (!desc->elementvftbl)
+                       return false;
+
+               /* an array which contains elements of interface types is
+                  allowed to be casted to array of Object (JOWENN) */
+
+               if ((desc->elementvftbl->baseval < 0) &&
+                       (target->elementvftbl->baseval == 1))
+                       return true;
+
+               return class_isanysubclass(desc->elementvftbl->clazz,
+                                                                  target->elementvftbl->clazz);
+       }
+
+       if (desc->dimension < target->dimension)
+               return false;
+
+       /* {desc has higher dimension than target} */
+
+       return class_isanysubclass(pseudo_class_Arraystub,
+                                                          target->elementvftbl->clazz);
+}
+
+
 /* class_is_assignable_from ****************************************************
 
    Return whether an instance of the "from" class parameter would be
@@ -1508,7 +1559,12 @@ bool class_is_assignable_from(classinfo *to, classinfo *from)
                if (!link_class(from))
                        return false;
 
-       return class_isanysubclass(from, to);
+       /* Decide whether we are dealing with array types or object types. */
+
+       if (class_is_array(to) && class_is_array(from))
+               return class_is_arraycompatible(from->vftbl->arraydesc, to->vftbl->arraydesc);
+       else
+               return class_isanysubclass(from, to);
 }
 
 
@@ -1532,7 +1588,12 @@ bool class_is_instance(classinfo *c, java_handle_t *h)
                if (!link_class(c))
                        return false;
 
-       return builtin_instanceof(h, c);
+       /* Decide whether we are dealing with array types or object types. */
+
+       if (class_is_array(c))
+               return builtin_arrayinstanceof(h, c);
+       else
+               return builtin_instanceof(h, c);
 }