PR162: Make class init protection aware of multiple threads.
[cacao.git] / src / vm / class.cpp
index 07329bc319a48b57526a7f76160dff1d050bd332..8491efa889913e6c6a03544ffd777d02bd3b870c 100644 (file)
@@ -1,6 +1,6 @@
 /* src/vm/class.cpp - class related functions
 
-   Copyright (C) 1996-2005, 2006, 2007, 2008
+   Copyright (C) 1996-2011
    CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
 
    This file is part of CACAO.
@@ -177,7 +177,7 @@ classinfo *class_create_classinfo(utf *classname)
        if (classname != utf_not_named_yet)
                class_set_packagename(c);
 
-       c->object.header.lockword.init();
+       Lockword(c->object.header.lockword).init();
 
        return c;
 }
@@ -612,7 +612,7 @@ bool class_load_attributes(classbuffer *cb)
 
 static void class_freecpool(classinfo *c)
 {
-       u4 idx;
+       int idx;
        u4 tag;
        void* info;
        
@@ -669,7 +669,7 @@ void* class_getconstant(classinfo *c, u4 pos, u4 ctype)
        /* check index and type of constantpool entry */
        /* (pos == 0 is caught by type comparison) */
 
-       if ((pos >= c->cpcount) || (c->cptags[pos] != ctype)) {
+       if (((int) pos >= c->cpcount) || (c->cptags[pos] != ctype)) {
                exceptions_throw_classformaterror(c, "Illegal constant pool index");
                return NULL;
        }
@@ -688,7 +688,7 @@ void* innerclass_getconstant(classinfo *c, u4 pos, u4 ctype)
 {
        /* invalid position in constantpool */
 
-       if (pos >= c->cpcount) {
+       if ((int) pos >= c->cpcount) {
                exceptions_throw_classformaterror(c, "Illegal constant pool index");
                return NULL;
        }
@@ -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. */
 
@@ -1476,8 +1475,8 @@ bool class_isanysubclass(classinfo *sub, classinfo *super)
 #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;
 
                UNLOCK_CLASSRENUMBER_LOCK;
 #endif
@@ -1487,6 +1486,54 @@ bool class_isanysubclass(classinfo *sub, classinfo *super)
 }
 
 
+/* 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
@@ -1512,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);
 }
 
 
@@ -1536,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);
 }
 
 
@@ -2047,7 +2104,7 @@ java_handle_t* class_get_enclosingmethod(classinfo *c)
 java_handle_objectarray_t* class_get_interfaces(classinfo *c)
 {
        classinfo* ic;
-       u4         i;
+       int        i;
 
        if (!(c->state & CLASS_LINKED))
                if (!link_class(c))
@@ -2154,6 +2211,15 @@ int32_t class_get_modifiers(classinfo *c, bool ignoreInnerClassesAttrib)
 }
 
 
+/**
+ * Helper function for the CLASS_IS_OR_ALMOST_INITIALIZED macro.
+ */
+bool class_initializing_thread_is_self(classinfo *c)
+{
+    threadobject *t = thread_get_current();
+    return t == c->initializing_thread;
+}
+
 /* class_get_signature *********************************************************
 
    Return the signature of the given class.  For array and primitive
@@ -2323,13 +2389,13 @@ void class_classref_or_classinfo_println(classref_or_classinfo c)
 #if !defined(NDEBUG)
 void class_showconstantpool (classinfo *c) 
 {
-       u4 i;
+       int i;
        void* e;
 
        printf ("---- dump of constant pool ----\n");
 
        for (i=0; i<c->cpcount; i++) {
-               printf ("#%d:  ", (int) i);
+               printf ("#%d:  ", i);
                
                e = c -> cpinfos [i];
                if (e) {