* src/vmcore/linker.c (build_display): Removed superfluous recursion; return
[cacao.git] / src / vmcore / class.c
index 68297048201ea4b043c93934fd21170440a11f6e..983339f99fa1019b599878d4c5edea9f2427d322 100644 (file)
@@ -1,9 +1,7 @@
 /* src/vmcore/class.c - class related functions
 
-   Copyright (C) 1996-2005, 2006, 2007 R. Grafl, A. Krall, C. Kruegel,
-   C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
-   E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
-   J. Wenninger, Institut f. Computersprachen - TU Wien
+   Copyright (C) 1996-2005, 2006, 2007, 2008
+   CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
 
    This file is part of CACAO.
 
 #include "vmcore/utf8.h"
 
 
+#if defined(ENABLE_JAVASE)
+/* We need to define some reflection functions here since we cannot
+   include native/vm/reflect.h as it includes generated header
+   files. */
+
+java_object_t *reflect_constructor_new(methodinfo *m);
+java_object_t *reflect_field_new(fieldinfo *f);
+java_object_t *reflect_method_new(methodinfo *m);
+#endif
+
+
 /* global variables ***********************************************************/
 
 /* frequently used classes ****************************************************/
 
-/* important system classes */
+/* Important system classes. */
 
 classinfo *class_java_lang_Object;
 classinfo *class_java_lang_Class;
@@ -84,13 +93,19 @@ classinfo *class_java_lang_ThreadGroup;
 classinfo *class_java_lang_Throwable;
 classinfo *class_java_io_Serializable;
 
-#if defined(WITH_CLASSPATH_GNU)
+#if defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
 classinfo *class_java_lang_VMSystem;
 classinfo *class_java_lang_VMThread;
 classinfo *class_java_lang_VMThrowable;
 #endif
 
-#if defined(WITH_CLASSPATH_SUN)
+/* Important system exceptions. */
+
+classinfo *class_java_lang_Exception;
+classinfo *class_java_lang_ClassNotFoundException;
+classinfo *class_java_lang_RuntimeException;
+
+#if defined(WITH_JAVA_RUNTIME_LIBRARY_OPENJDK)
 classinfo *class_sun_reflect_MagicAccessorImpl;
 #endif
 
@@ -115,12 +130,19 @@ classinfo *class_java_lang_reflect_Field;
 classinfo *class_java_lang_reflect_Method;
 classinfo *class_java_security_PrivilegedAction;
 classinfo *class_java_util_Vector;
+classinfo *class_java_util_HashMap;
+
+# if defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
+classinfo *class_java_lang_reflect_VMConstructor;
+classinfo *class_java_lang_reflect_VMField;
+classinfo *class_java_lang_reflect_VMMethod;
+# endif
 
 classinfo *arrayclass_java_lang_Object;
 
 # if defined(ENABLE_ANNOTATIONS)
 classinfo *class_sun_reflect_ConstantPool;
-#  if defined(WITH_CLASSPATH_GNU)
+#  if defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
 classinfo *class_sun_reflect_annotation_AnnotationParser;
 #  endif
 # endif
@@ -209,14 +231,15 @@ classinfo *class_create_classinfo(utf *classname)
                log_message_utf("Creating class: ", classname);
 #endif
 
-       /* GCNEW_UNCOLLECTABLE clears the allocated memory */
-
-#if defined(ENABLE_GC_CACAO)
+#if !defined(ENABLE_GC_BOEHM)
        c = (classinfo *) heap_alloc_uncollectable(sizeof(classinfo));
+       /*c = NEW(classinfo);
+       MZERO(c, classinfo, 1);*/
 #else
        c = GCNEW_UNCOLLECTABLE(classinfo, 1);
-       /*c=NEW(classinfo);*/
+       /* GCNEW_UNCOLLECTABLE clears the allocated memory */
 #endif
+
        c->name = classname;
 
        /* Set the header.vftbl of all loaded classes to the one of
@@ -290,7 +313,7 @@ void class_postset_header_vftbl(void)
 
 *******************************************************************************/
 
-classinfo *class_define(utf *name, classloader *cl, int32_t length, const uint8_t *data, java_handle_t *pd)
+classinfo *class_define(utf *name, classloader_t *cl, int32_t length, uint8_t *data, java_handle_t *pd)
 {
        classinfo   *c;
        classinfo   *r;
@@ -322,7 +345,7 @@ classinfo *class_define(utf *name, classloader *cl, int32_t length, const uint8_
 
        cb = NEW(classbuffer);
 
-       cb->class = c;
+       cb->clazz = c;
        cb->size  = length;
        cb->data  = data;
        cb->pos   = cb->data;
@@ -357,7 +380,7 @@ classinfo *class_define(utf *name, classloader *cl, int32_t length, const uint8_
        }
 
 #if defined(ENABLE_JAVASE)
-# if defined(WITH_CLASSPATH_SUN)
+# if defined(WITH_JAVA_RUNTIME_LIBRARY_OPENJDK)
        /* Store the protection domain. */
 
        c->protectiondomain = pd;
@@ -400,7 +423,7 @@ static bool class_load_attribute_sourcefile(classbuffer *cb)
 
        /* get classinfo */
 
-       c = cb->class;
+       c = cb->clazz;
 
        /* check buffer size */
 
@@ -462,7 +485,7 @@ static bool class_load_attribute_enclosingmethod(classbuffer *cb)
 
        /* get classinfo */
 
-       c = cb->class;
+       c = cb->clazz;
 
        /* check buffer size */
 
@@ -535,7 +558,7 @@ bool class_load_attributes(classbuffer *cb)
        uint16_t               flags;
        int                    i, j;
 
-       c = cb->class;
+       c = cb->clazz;
 
        /* get attributes count */
 
@@ -785,7 +808,7 @@ void class_free(classinfo *c)
 {
        s4 i;
        vftbl_t *v;
-               
+
        class_freecpool(c);
 
        if (c->interfaces != NULL)
@@ -794,9 +817,7 @@ void class_free(classinfo *c)
        if (c->fields) {
                for (i = 0; i < c->fieldscount; i++)
                        field_free(&(c->fields[i]));
-#if defined(ENABLE_CACAO_GC)
                MFREE(c->fields, fieldinfo, c->fieldscount);
-#endif
        }
        
        if (c->methods) {
@@ -841,8 +862,8 @@ void class_free(classinfo *c)
 
 *******************************************************************************/
 
-static classinfo *get_array_class(utf *name,classloader *initloader,
-                                                                                       classloader *defloader,bool link)
+static classinfo *get_array_class(utf *name,classloader_t *initloader,
+                                                                                       classloader_t *defloader,bool link)
 {
        classinfo *c;
        
@@ -882,16 +903,16 @@ static classinfo *get_array_class(utf *name,classloader *initloader,
 
 classinfo *class_array_of(classinfo *component, bool link)
 {
-       classloader       *cl;
+       classloader_t     *cl;
     s4                 namelen;
     char              *namebuf;
        utf               *u;
        classinfo         *c;
-       s4                 dumpsize;
+       int32_t            dumpmarker;
 
        cl = component->classloader;
 
-       dumpsize = dump_size();
+       DMARKER;
 
     /* Assemble the array class name */
     namelen = component->name->blength;
@@ -917,7 +938,7 @@ classinfo *class_array_of(classinfo *component, bool link)
 
        c = get_array_class(u, cl, cl, link);
 
-       dump_release(dumpsize);
+       DRELEASE;
 
        return c;
 }
@@ -934,10 +955,10 @@ classinfo *class_multiarray_of(s4 dim, classinfo *element, bool link)
 {
     s4 namelen;
     char *namebuf;
-       s4 dumpsize;
        classinfo *c;
+       int32_t    dumpmarker;
 
-       dumpsize = dump_size();
+       DMARKER;
 
        if (dim < 1) {
                log_text("Invalid array dimension requested");
@@ -968,7 +989,7 @@ classinfo *class_multiarray_of(s4 dim, classinfo *element, bool link)
                                                element->classloader,
                                                link);
 
-       dump_release(dumpsize);
+       DRELEASE;
 
        return c;
 }
@@ -1096,13 +1117,13 @@ constant_classref *class_get_classref_multiarray_of(s4 dim, constant_classref *r
 {
     s4 namelen;
     char *namebuf;
-       s4 dumpsize;
        constant_classref *cr;
+       int32_t            dumpmarker;
 
        assert(ref);
        assert(dim >= 1 && dim <= 255);
 
-       dumpsize = dump_size();
+       DMARKER;
 
     /* Assemble the array class name */
     namelen = ref->name->blength;
@@ -1125,7 +1146,7 @@ constant_classref *class_get_classref_multiarray_of(s4 dim, constant_classref *r
 
     cr = class_get_classref(ref->referer,utf_new(namebuf, namelen));
 
-       dump_release(dumpsize);
+       DRELEASE;
 
        return cr;
 }
@@ -1570,145 +1591,72 @@ bool class_isanysubclass(classinfo *sub, classinfo *super)
                if (sub->flags & ACC_INTERFACE)
                        return (super == class_java_lang_Object);
 
-               LOCK_MONITOR_ENTER(linker_classrenumber_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;
 
-               LOCK_MONITOR_EXIT(linker_classrenumber_lock);
+               UNLOCK_CLASSRENUMBER_LOCK;
+#endif
        }
 
        return result;
 }
 
 
-/* class_is_primitive **********************************************************
-
-   Checks if the given class is a primitive class.
-
-*******************************************************************************/
-
-bool class_is_primitive(classinfo *c)
-{
-       if (c->flags & ACC_CLASS_PRIMITIVE)
-               return true;
-
-       return false;
-}
-
-
-/* class_is_anonymousclass *****************************************************
-
-   Checks if the given class is an anonymous class.
-
-*******************************************************************************/
-
-bool class_is_anonymousclass(classinfo *c)
-{
-       if (c->flags & ACC_CLASS_ANONYMOUS)
-               return true;
-
-       return false;
-}
+/* class_is_assignable_from ****************************************************
 
+   Return whether an instance of the "from" class parameter would be
+   an instance of this class "to" as well.
 
-/* class_is_array **************************************************************
+   ARGUMENTS:
+       to ..... class
+          from ... class
 
-   Checks if the given class is an array class.
+   RETURN:
+       true .... is assignable
+          false ... is not assignable
 
 *******************************************************************************/
 
-bool class_is_array(classinfo *c)
+bool class_is_assignable_from(classinfo *to, classinfo *from)
 {
-       if (!(c->state & CLASS_LINKED))
-               if (!link_class(c))
+       if (!(to->state & CLASS_LINKED))
+               if (!link_class(to))
                        return false;
 
-       return (c->vftbl->arraydesc != NULL);
-}
-
-
-/* class_is_interface **********************************************************
-
-   Checks if the given class is an interface.
-
-*******************************************************************************/
-
-bool class_is_interface(classinfo *c)
-{
-       if (c->flags & ACC_INTERFACE)
-               return true;
-
-       return false;
-}
-
-
-/* class_is_localclass *********************************************************
-
-   Checks if the given class is a local class.
-
-*******************************************************************************/
-
-bool class_is_localclass(classinfo *c)
-{
-       if ((c->enclosingmethod != NULL) && !class_is_anonymousclass(c))
-               return true;
-
-       return false;
-}
-
-
-/* class_is_memberclass ********************************************************
-
-   Checks if the given class is a member class.
-
-*******************************************************************************/
-
-bool class_is_memberclass(classinfo *c)
-{
-       if (c->flags & ACC_CLASS_MEMBER)
-               return true;
+       if (!(from->state & CLASS_LINKED))
+               if (!link_class(from))
+                       return false;
 
-       return false;
+       return class_isanysubclass(from, to);
 }
 
 
-/* class_get_classloader *******************************************************
-
-   Return the classloader of the given class.
-
-*******************************************************************************/
-
-classloader *class_get_classloader(classinfo *c)
-{
-       classloader *cl;
-
-       cl = c->classloader;
-
-       if (cl == NULL)
-               return NULL;
-
-       return cl;
-}
+/* class_is_instance ***********************************************************
 
+   Return if the given Java object is an instance of the given class.
 
-/* class_get_superclass ********************************************************
+   ARGUMENTS:
+       c ... class
+          h ... Java object
 
-   Return the super class of the given class.
+   RETURN:
+       true .... is instance
+          false ... is not instance
 
 *******************************************************************************/
 
-classinfo *class_get_superclass(classinfo *c)
+bool class_is_instance(classinfo *c, java_handle_t *h)
 {
-       /* For interfaces we return NULL. */
-
-       if (c->flags & ACC_INTERFACE)
-               return NULL;
-
-       /* For java/lang/Object, primitive-type and Void classes c->super
-          is NULL and we return NULL. */
+       if (!(c->state & CLASS_LINKED))
+               if (!link_class(c))
+                       return false;
 
-       return c->super;
+       return builtin_instanceof(h, c);
 }
 
 
@@ -1737,7 +1685,7 @@ classinfo *class_get_componenttype(classinfo *c)
                return NULL;
        
        if (ad->arraytype == ARRAYTYPE_OBJECT)
-               component = ad->componentvftbl->class;
+               component = ad->componentvftbl->clazz;
        else
                component = primitive_class_get_by_type(ad->arraytype);
                
@@ -1833,6 +1781,210 @@ java_handle_objectarray_t *class_get_declaredclasses(classinfo *c, bool publicOn
 }
 
 
+/**
+ * Return an array of declared constructors of the given class.
+ *
+ * @param c          class to get the constructors of
+ * @param publicOnly show only public fields
+ *
+ * @return array of java.lang.reflect.Constructor
+ */
+#if defined(ENABLE_JAVASE)
+java_handle_objectarray_t *class_get_declaredconstructors(classinfo *c, bool publicOnly)
+{
+       methodinfo*                m;
+       java_handle_objectarray_t* oa;
+       java_handle_t*             rc;
+       int                        count;
+       int                        index;
+       int                        i;
+
+       /* Determine number of constructors. */
+
+       count = 0;
+
+       for (i = 0; i < c->methodscount; i++) {
+               m = &(c->methods[i]);
+
+               if (((m->flags & ACC_PUBLIC) || (publicOnly == 0)) &&
+                       (m->name == utf_init))
+                       count++;
+       }
+
+       /* Create array of constructors. */
+
+       oa = builtin_anewarray(count, class_java_lang_reflect_Constructor);
+
+       if (oa == NULL)
+               return NULL;
+
+       /* Get the constructors and store them in the array. */
+
+       for (i = 0, index = 0; i < c->methodscount; i++) {
+               m = &(c->methods[i]);
+
+               if (((m->flags & ACC_PUBLIC) || (publicOnly == 0)) &&
+                       (m->name == utf_init)) {
+                       /* Create Constructor object.  This is actualy a
+                          java_lang_reflect_Constructor pointer, but we use a
+                          java_handle_t here, because we don't have the header
+                          available when building vmcore. */
+
+                       rc = reflect_constructor_new(m);
+
+                       /* Store object into array. */
+
+                       array_objectarray_element_set(oa, index, rc);
+                       index++;
+               }
+       }
+
+       return oa;
+}
+#endif
+
+
+/* class_get_declaredfields ****************************************************
+
+   Return an array of declared fields of the given class.
+
+   ARGUMENTS:
+       c ............ class to get the fields of
+          publicOnly ... show only public fields
+
+   RETURN:
+       array of java.lang.reflect.Field
+
+*******************************************************************************/
+
+#if defined(ENABLE_JAVASE)
+java_handle_objectarray_t *class_get_declaredfields(classinfo *c, bool publicOnly)
+{
+       java_handle_objectarray_t *oa;
+       fieldinfo                 *f;
+       java_handle_t             *h;
+       int                        count;
+       int                        index;
+       int                        i;
+
+       /* Determine number of fields. */
+
+       count = 0;
+
+       for (i = 0; i < c->fieldscount; i++)
+               if ((c->fields[i].flags & ACC_PUBLIC) || (publicOnly == 0))
+                       count++;
+
+       /* Create array of fields. */
+
+       oa = builtin_anewarray(count, class_java_lang_reflect_Field);
+
+       if (oa == NULL)
+               return NULL;
+
+       /* Get the fields and store them in the array. */
+
+       for (i = 0, index = 0; i < c->fieldscount; i++) {
+               f = &(c->fields[i]);
+
+               if ((f->flags & ACC_PUBLIC) || (publicOnly == 0)) {
+                       /* Create Field object.  This is actualy a
+                          java_lang_reflect_Field pointer, but we use a
+                          java_handle_t here, because we don't have the header
+                          available when building vmcore. */
+
+                       h = reflect_field_new(f);
+
+                       /* Store object into array. */
+
+                       array_objectarray_element_set(oa, index, h);
+                       index++;
+               }
+       }
+
+       return oa;
+}
+#endif
+
+
+/* class_get_declaredmethods ***************************************************
+
+   Return an array of declared methods of the given class.
+
+   ARGUMENTS:
+       c ............ class to get the methods of
+          publicOnly ... show only public methods
+
+   RETURN:
+       array of java.lang.reflect.Method
+
+*******************************************************************************/
+
+#if defined(ENABLE_JAVASE)
+java_handle_objectarray_t *class_get_declaredmethods(classinfo *c, bool publicOnly)
+{
+       java_handle_objectarray_t *oa;         /* result: array of Method-objects */
+       methodinfo                *m;     /* the current method to be represented */
+       java_handle_t             *h;
+       int                        count;
+       int                        index;
+       int                        i;
+
+       /* JOWENN: array classes do not declare methods according to mauve
+          test.  It should be considered, if we should return to my old
+          clone method overriding instead of declaring it as a member
+          function. */
+
+       if (class_is_array(c))
+               return builtin_anewarray(0, class_java_lang_reflect_Method);
+
+       /* Determine number of methods. */
+
+       count = 0;
+
+       for (i = 0; i < c->methodscount; i++) {
+               m = &(c->methods[i]);
+
+               if (((m->flags & ACC_PUBLIC) || (publicOnly == false)) &&
+                       ((m->name != utf_init) && (m->name != utf_clinit)) &&
+                       !(m->flags & ACC_MIRANDA))
+                       count++;
+       }
+
+       /* Create array of methods. */
+
+       oa = builtin_anewarray(count, class_java_lang_reflect_Method);
+
+       if (oa == NULL)
+               return NULL;
+
+       /* Get the methods and store them in the array. */
+
+       for (i = 0, index = 0; i < c->methodscount; i++) {
+               m = &(c->methods[i]);
+
+               if (((m->flags & ACC_PUBLIC) || (publicOnly == false)) && 
+                       ((m->name != utf_init) && (m->name != utf_clinit)) &&
+                       !(m->flags & ACC_MIRANDA)) {
+                       /* Create method object.  This is actualy a
+                          java_lang_reflect_Method pointer, but we use a
+                          java_handle_t here, because we don't have the header
+                          available when building vmcore. */
+
+                       h = reflect_method_new(m);
+
+                       /* Store object into array. */
+
+                       array_objectarray_element_set(oa, index, h);
+                       index++;
+               }
+       }
+
+       return oa;
+}
+#endif
+
+
 /* class_get_declaringclass ****************************************************
 
    If the class or interface given is a member of another class,
@@ -1911,6 +2063,117 @@ classinfo *class_get_enclosingclass(classinfo *c)
 }
 
 
+/**
+ * Return the enclosing constructor as java.lang.reflect.Constructor
+ * object for the given class.
+ *
+ * @param c class to return the enclosing constructor for
+ *
+ * @return java.lang.reflect.Constructor object of the enclosing
+ * constructor
+ */
+#if defined(ENABLE_JAVASE)
+java_handle_t* class_get_enclosingconstructor(classinfo *c)
+{
+       methodinfo*    m;
+       java_handle_t* rc;
+
+       m = class_get_enclosingmethod_raw(c);
+
+       if (m == NULL)
+               return NULL;
+
+       /* Check for <init>. */
+
+       if (m->name != utf_init)
+               return NULL;
+
+       /* Create Constructor object. */
+
+       rc = reflect_constructor_new(m);
+
+       return rc;
+}
+#endif
+
+
+/* class_get_enclosingmethod ***************************************************
+
+   Return the enclosing method for the given class.
+
+   IN:
+       c ... class to return the enclosing method for
+
+   RETURN:
+       methodinfo of the enclosing method
+
+*******************************************************************************/
+
+methodinfo *class_get_enclosingmethod_raw(classinfo *c)
+{
+       constant_nameandtype *cn;
+       classinfo            *ec;
+       methodinfo           *m;
+
+       /* get enclosing class and method */
+
+       ec = class_get_enclosingclass(c);
+       cn = c->enclosingmethod;
+
+       /* check for enclosing class and method */
+
+       if (ec == NULL)
+               return NULL;
+
+       if (cn == NULL)
+               return NULL;
+
+       /* find method in enclosing class */
+
+       m = class_findmethod(ec, cn->name, cn->descriptor);
+
+       if (m == NULL) {
+               exceptions_throw_internalerror("Enclosing method doesn't exist");
+               return NULL;
+       }
+
+       return m;
+}
+
+
+/**
+ * Return the enclosing method as java.lang.reflect.Method object for
+ * the given class.
+ *
+ * @param c class to return the enclosing method for
+ *
+ * @return java.lang.reflect.Method object of the enclosing method
+ */
+#if defined(ENABLE_JAVASE)
+java_handle_t* class_get_enclosingmethod(classinfo *c)
+{
+       methodinfo*    m;
+       java_handle_t* rm;
+
+       m = class_get_enclosingmethod_raw(c);
+
+       if (m == NULL)
+               return NULL;
+
+       /* check for <init> */
+
+       if (m->name == utf_init)
+               return NULL;
+
+       /* create java.lang.reflect.Method object */
+
+       rm = reflect_method_new(m);
+
+       return rm;
+}
+#endif
+
+
 /* class_get_interfaces ********************************************************
 
    Return an array of interfaces of the given class.