This commit introduces C++ wrapper classes for Java heap objects.
[cacao.git] / src / vmcore / class.c
index 45ea039924af9032db688ab9feac5ce426f7208a..bdbdb21a75f8ab275cdbcfac09f0ae373e91a763 100644 (file)
@@ -44,7 +44,7 @@
 
 #include "vm/array.h"
 #include "vm/builtin.h"
-#include "vm/exceptions.h"
+#include "vm/exceptions.hpp"
 #include "vm/global.h"
 #include "vm/resolve.h"
 
@@ -52,6 +52,8 @@
 
 #include "vmcore/class.h"
 #include "vmcore/classcache.h"
+#include "vmcore/globals.hpp"
+#include "vmcore/javaobjects.hpp"
 #include "vmcore/linker.h"
 #include "vmcore/loader.h"
 #include "vmcore/options.h"
 #include "vmcore/utf8.h"
 
 
-/* global variables ***********************************************************/
-
-/* frequently used classes ****************************************************/
-
-/* Important system classes. */
-
-classinfo *class_java_lang_Object;
-classinfo *class_java_lang_Class;
-classinfo *class_java_lang_ClassLoader;
-classinfo *class_java_lang_Cloneable;
-classinfo *class_java_lang_SecurityManager;
-classinfo *class_java_lang_String;
-classinfo *class_java_lang_System;
-classinfo *class_java_lang_Thread;
-classinfo *class_java_lang_ThreadGroup;
-classinfo *class_java_lang_Throwable;
-classinfo *class_java_io_Serializable;
-
-#if defined(WITH_CLASSPATH_GNU)
-classinfo *class_java_lang_VMSystem;
-classinfo *class_java_lang_VMThread;
-classinfo *class_java_lang_VMThrowable;
-#endif
-
-/* Important system exceptions. */
-
-classinfo *class_java_lang_Exception;
-classinfo *class_java_lang_ClassNotFoundException;
-classinfo *class_java_lang_RuntimeException;
-
-#if defined(WITH_CLASSPATH_SUN)
-classinfo *class_sun_reflect_MagicAccessorImpl;
-#endif
-
-#if defined(ENABLE_JAVASE)
-classinfo *class_java_lang_Void;
-#endif
-classinfo *class_java_lang_Boolean;
-classinfo *class_java_lang_Byte;
-classinfo *class_java_lang_Character;
-classinfo *class_java_lang_Short;
-classinfo *class_java_lang_Integer;
-classinfo *class_java_lang_Long;
-classinfo *class_java_lang_Float;
-classinfo *class_java_lang_Double;
-
-/* some classes which may be used more often */
-
-#if defined(ENABLE_JAVASE)
-classinfo *class_java_lang_StackTraceElement;
-classinfo *class_java_lang_reflect_Constructor;
-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_CLASSPATH_GNU)
-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)
-classinfo *class_sun_reflect_annotation_AnnotationParser;
-#  endif
-# endif
-#endif
-
-/* pseudo classes for the typechecker */
-
-classinfo *pseudo_class_Arraystub;
-classinfo *pseudo_class_Null;
-classinfo *pseudo_class_New;
-
-
 /* class_set_packagename *******************************************************
 
    Derive the package name from the class name and store it in the
@@ -369,7 +291,7 @@ classinfo *class_define(utf *name, classloader_t *cl, int32_t length, uint8_t *d
        }
 
 #if defined(ENABLE_JAVASE)
-# if defined(WITH_CLASSPATH_SUN)
+# if defined(WITH_JAVA_RUNTIME_LIBRARY_OPENJDK)
        /* Store the protection domain. */
 
        c->protectiondomain = pd;
@@ -692,7 +614,7 @@ static void class_freecpool(classinfo *c)
 {
        u4 idx;
        u4 tag;
-       voidptr info;
+       void* info;
        
        if (c->cptags && c->cpinfos) {
                for (idx = 0; idx < c->cpcount; idx++) {
@@ -730,7 +652,7 @@ static void class_freecpool(classinfo *c)
                MFREE(c->cptags, u1, c->cpcount);
 
        if (c->cpinfos)
-               MFREE(c->cpinfos, voidptr, c->cpcount);
+               MFREE(c->cpinfos, void*, c->cpcount);
 }
 
 
@@ -742,7 +664,7 @@ static void class_freecpool(classinfo *c)
 
 *******************************************************************************/
 
-voidptr class_getconstant(classinfo *c, u4 pos, u4 ctype)
+void* class_getconstant(classinfo *c, u4 pos, u4 ctype)
 {
        /* check index and type of constantpool entry */
        /* (pos == 0 is caught by type comparison) */
@@ -762,7 +684,7 @@ voidptr class_getconstant(classinfo *c, u4 pos, u4 ctype)
        
 *******************************************************************************/
 
-voidptr innerclass_getconstant(classinfo *c, u4 pos, u4 ctype)
+void* innerclass_getconstant(classinfo *c, u4 pos, u4 ctype)
 {
        /* invalid position in constantpool */
 
@@ -1404,41 +1326,18 @@ fieldinfo *class_findfield(classinfo *c, utf *name, utf *desc)
 
 *******************************************************************************/
  
-fieldinfo *class_findfield_by_name(classinfo *c, utf *name)
-{
-       s4 i;
-
-       /* get field index */
-
-       i = class_findfield_index_by_name(c, name);
-
-       /* field was not found, return */
-
-       if (i == -1)
-               return NULL;
-
-       /* return field address */
-
-       return &(c->fields[i]);
-}
-
-
-s4 class_findfield_index_by_name(classinfo *c, utf *name)
+fieldinfo *class_findfield_by_name(classinfo* c, utf* name)
 {
-       s4 i;
-
-       for (i = 0; i < c->fieldscount; i++) {
-               /* compare field names */
+       for (int32_t i = 0; i < c->fieldscount; i++) {
+               fieldinfo* f = &(c->fields[i]);
 
-               if ((c->fields[i].name == name))
-                       return i;
+               if (f->name == name)
+                       return f;
        }
 
-       /* field was not found, raise exception */      
-
+       // Field not found.
        exceptions_throw_nosuchfielderror(c, name);
-
-       return -1;
+       return NULL;
 }
 
 
@@ -1488,22 +1387,19 @@ static fieldinfo *class_resolvefield_int(classinfo *c, utf *name, utf *desc)
        
        Resolves a reference from REFERER to a field with NAME and DESC in class C.
 
-    If the field cannot be resolved the return value is NULL. If EXCEPT is
-    true *exceptionptr is set, too.
+    If the field cannot be resolved, an exception is thrown and the
+    return value is NULL.
 
 *******************************************************************************/
 
-fieldinfo *class_resolvefield(classinfo *c, utf *name, utf *desc,
-                                                         classinfo *referer, bool throwexception)
+fieldinfo *class_resolvefield(classinfo *c, utf *name, utf *desc, classinfo *referer)
 {
        fieldinfo *fi;
 
        fi = class_resolvefield_int(c, name, desc);
 
        if (!fi) {
-               if (throwexception)
-                       exceptions_throw_nosuchfielderror(c, name);
-
+               exceptions_throw_nosuchfielderror(c, name);
                return NULL;
        }
 
@@ -1592,6 +1488,59 @@ bool class_isanysubclass(classinfo *sub, classinfo *super)
 }
 
 
+/* class_is_assignable_from ****************************************************
+
+   Return whether an instance of the "from" class parameter would be
+   an instance of this class "to" as well.
+
+   ARGUMENTS:
+       to ..... class
+          from ... class
+
+   RETURN:
+       true .... is assignable
+          false ... is not assignable
+
+*******************************************************************************/
+
+bool class_is_assignable_from(classinfo *to, classinfo *from)
+{
+       if (!(to->state & CLASS_LINKED))
+               if (!link_class(to))
+                       return false;
+
+       if (!(from->state & CLASS_LINKED))
+               if (!link_class(from))
+                       return false;
+
+       return class_isanysubclass(from, to);
+}
+
+
+/* class_is_instance ***********************************************************
+
+   Return if the given Java object is an instance of the given class.
+
+   ARGUMENTS:
+       c ... class
+          h ... Java object
+
+   RETURN:
+       true .... is instance
+          false ... is not instance
+
+*******************************************************************************/
+
+bool class_is_instance(classinfo *c, java_handle_t *h)
+{
+       if (!(c->state & CLASS_LINKED))
+               if (!link_class(c))
+                       return false;
+
+       return builtin_instanceof(h, c);
+}
+
+
 /* class_get_componenttype *****************************************************
 
    Return the component class of the given class.  If the given class
@@ -1619,7 +1568,7 @@ classinfo *class_get_componenttype(classinfo *c)
        if (ad->arraytype == ARRAYTYPE_OBJECT)
                component = ad->componentvftbl->clazz;
        else
-               component = primitive_class_get_by_type(ad->arraytype);
+               component = Primitive_get_class_by_type(ad->arraytype);
                
        return component;
 }
@@ -1713,6 +1662,201 @@ 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 a java.lang.reflect.Constructor object.
+
+                       rc = java_lang_reflect_Constructor_create(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 a java.lang.reflect.Field object.
+
+                       h = java_lang_reflect_Field_create(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 java.lang.reflect.Method object.
+
+                       h = java_lang_reflect_Method_create(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,
@@ -1791,6 +1935,40 @@ 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 a java.lang.reflect.Constructor object.
+
+       rc = java_lang_reflect_Constructor_create(m);
+
+       return rc;
+}
+#endif
+
+
 /* class_get_enclosingmethod ***************************************************
 
    Return the enclosing method for the given class.
@@ -1803,7 +1981,7 @@ classinfo *class_get_enclosingclass(classinfo *c)
 
 *******************************************************************************/
 
-methodinfo *class_get_enclosingmethod(classinfo *c)
+methodinfo *class_get_enclosingmethod_raw(classinfo *c)
 {
        constant_nameandtype *cn;
        classinfo            *ec;
@@ -1835,6 +2013,39 @@ methodinfo *class_get_enclosingmethod(classinfo *c)
 }
 
 
+/**
+ * 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 a java.lang.reflect.Method object.
+
+       rm = java_lang_reflect_Method_create(m);
+
+       return rm;
+}
+#endif
+
+
 /* class_get_interfaces ********************************************************
 
    Return an array of interfaces of the given class.
@@ -2115,7 +2326,7 @@ void class_classref_or_classinfo_println(classref_or_classinfo c)
 void class_showconstantpool (classinfo *c) 
 {
        u4 i;
-       voidptr e;
+       void* e;
 
        printf ("---- dump of constant pool ----\n");