Removed return value from descriptor_params_from_paramtypes.
[cacao.git] / src / vm / loader.cpp
index 81ab0ad8594bd06ec0cd27cb3a0c5f6401db6209..0dc53d0c0330602339dbad0aae5934ce9589e5a0 100644 (file)
@@ -1,7 +1,8 @@
 /* src/vm/loader.cpp - class loader functions
 
-   Copyright (C) 1996-2005, 2006, 2007, 2008
+   Copyright (C) 1996-2011
    CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
+   Copyright (C) 2009 Theobroma Systems Ltd.
 
    This file is part of CACAO.
 
 #include "vm/types.h"
 
 #include "mm/dumpmemory.hpp"
-#include "mm/memory.h"
+#include "mm/memory.hpp"
 
 #include "native/llni.h"
 
 #include "threads/mutex.hpp"
 
 #include "toolbox/hashtable.h"
-#include "toolbox/logging.h"
+#include "toolbox/list.hpp"
+#include "toolbox/logging.hpp"
 
 #include "vm/jit/builtin.hpp"
 #include "vm/classcache.hpp"
@@ -47,6 +49,8 @@
 #include "vm/field.hpp"
 #include "vm/global.h"
 #include "vm/globals.hpp"
+#include "vm/hook.hpp"
+#include "vm/javaobjects.hpp"
 #include "vm/linker.hpp"
 #include "vm/loader.hpp"
 #include "vm/method.hpp"
@@ -61,7 +65,7 @@
 
 
 #if defined(ENABLE_JAVASE)
-# include "vm/annotation.h"
+# include "vm/annotation.hpp"
 # include "vm/stackmap.h"
 #endif
 
 
 #include "vm/jit/stubs.hpp"
 
-#if defined(ENABLE_JVMTI)
-# include "native/jvmti/cacaodbg.h"
-#endif
-
 
 /* global variables ***********************************************************/
 
@@ -100,9 +100,12 @@ void loader_preinit(void)
        TRACESUBSYSTEMINITIALIZATION("loader_preinit");
 
 #if defined(ENABLE_THREADS)
+       // Get current list of classpath entries.
+       SuckClasspath& suckclasspath = VM::get_current()->get_suckclasspath();
+
        /* Initialize the monitor pointer for zip/jar file locking. */
 
-       for (List<list_classpath_entry*>::iterator it = list_classpath_entries->begin(); it != list_classpath_entries->end(); it++) {
+       for (SuckClasspath::iterator it = suckclasspath.begin(); it != suckclasspath.end(); it++) {
                list_classpath_entry* lce = *it;
 
                if (lce->type == CLASSPATH_ARCHIVE)
@@ -226,8 +229,10 @@ void loader_init(void)
        class_java_util_Vector                 = load_class_bootstrap(utf_java_util_Vector);
 
 # if defined(WITH_JAVA_RUNTIME_LIBRARY_OPENJDK)
-       class_sun_misc_Signal                  = load_class_bootstrap(utf_new_char("sun/misc/Signal"));
-       class_sun_reflect_MagicAccessorImpl    = load_class_bootstrap(utf_new_char("sun/reflect/MagicAccessorImpl"));
+       class_sun_misc_Signal                     = load_class_bootstrap(utf_new_char("sun/misc/Signal"));
+       class_sun_reflect_MagicAccessorImpl       = load_class_bootstrap(utf_new_char("sun/reflect/MagicAccessorImpl"));
+       class_sun_reflect_MethodAccessorImpl      = load_class_bootstrap(utf_new_char("sun/reflect/MethodAccessorImpl"));
+       class_sun_reflect_ConstructorAccessorImpl = load_class_bootstrap(utf_new_char("sun/reflect/ConstructorAccessorImpl"));
 # endif
 
        arrayclass_java_lang_Object =
@@ -398,7 +403,10 @@ void loader_load_all_classes(void)
        utf                     *u;
 #endif
 
-       for (List<list_classpath_entry*>::iterator it = list_classpath_entries->begin(); it != list_classpath_entries->end(); it++) {
+       // Get current list of classpath entries.
+       SuckClasspath& suckclasspath = VM::get_current()->get_suckclasspath();
+
+       for (SuckClasspath::iterator it = suckclasspath.begin(); it != suckclasspath.end(); it++) {
                list_classpath_entry* lce = *it;
 
 #if defined(ENABLE_ZLIB)
@@ -484,58 +492,51 @@ bool loader_skip_attribute_body(classbuffer *cb)
 
 *******************************************************************************/
 
+/* The following structures are used to save information which cannot be 
+   processed during the first pass. After the complete constantpool has 
+   been traversed the references can be resolved (only in specific order). */
+
+/* CONSTANT_Class entries */
+typedef struct forward_class {
+       u2 thisindex;
+       u2 name_index;
+} forward_class;
+
+/* CONSTANT_String */
+typedef struct forward_string {
+       u2 thisindex;
+       u2 string_index;
+} forward_string;
+
+/* CONSTANT_NameAndType */
+typedef struct forward_nameandtype {
+       u2 thisindex;
+       u2 name_index;
+       u2 sig_index;
+} forward_nameandtype;
+
+/* CONSTANT_Fieldref, CONSTANT_Methodref or CONSTANT_InterfaceMethodref */
+typedef struct forward_fieldmethint {
+       u2 thisindex;
+       u1 tag;
+       u2 class_index;
+       u2 nameandtype_index;
+} forward_fieldmethint;
+
 static bool load_constantpool(classbuffer *cb, descriptor_pool *descpool)
 {
-
-       /* The following structures are used to save information which cannot be 
-          processed during the first pass. After the complete constantpool has 
-          been traversed the references can be resolved. 
-          (only in specific order)                                                */
-       
-       /* CONSTANT_Class entries */
-       typedef struct forward_class {
-               struct forward_class *next;
-               u2 thisindex;
-               u2 name_index;
-       } forward_class;
-
-       /* CONSTANT_String */
-       typedef struct forward_string {
-               struct forward_string *next;
-               u2 thisindex;
-               u2 string_index;
-       } forward_string;
-
-       /* CONSTANT_NameAndType */
-       typedef struct forward_nameandtype {
-               struct forward_nameandtype *next;
-               u2 thisindex;
-               u2 name_index;
-               u2 sig_index;
-       } forward_nameandtype;
-
-       /* CONSTANT_Fieldref, CONSTANT_Methodref or CONSTANT_InterfaceMethodref */
-       typedef struct forward_fieldmethint {
-               struct forward_fieldmethint *next;
-               u2 thisindex;
-               u1 tag;
-               u2 class_index;
-               u2 nameandtype_index;
-       } forward_fieldmethint;
-
-
        classinfo *c;
        u4 idx;
 
-       forward_class *forward_classes = NULL;
-       forward_string *forward_strings = NULL;
-       forward_nameandtype *forward_nameandtypes = NULL;
-       forward_fieldmethint *forward_fieldmethints = NULL;
+       DumpList<forward_class>        forward_classes;
+       DumpList<forward_string>       forward_strings;
+       DumpList<forward_nameandtype>  forward_nameandtypes;
+       DumpList<forward_fieldmethint> forward_fieldmethints;
 
-       forward_class *nfc;
-       forward_string *nfs;
-       forward_nameandtype *nfn;
-       forward_fieldmethint *nff;
+       forward_class nfc;
+       forward_string nfs;
+       forward_nameandtype nfn;
+       forward_fieldmethint nff;
 
        u4 cpcount;
        u1 *cptags;
@@ -569,11 +570,11 @@ static bool load_constantpool(classbuffer *cb, descriptor_pool *descpool)
                cpinfos[idx] = NULL;
        }
 
-                       
+
        /******* first pass *******/
        /* entries which cannot be resolved now are written into 
           temporary structures and traversed again later        */
-                  
+
        idx = 1;
        while (idx < cpcount) {
                u4 t;
@@ -586,88 +587,73 @@ static bool load_constantpool(classbuffer *cb, descriptor_pool *descpool)
 
                switch (t) {
                case CONSTANT_Class:
-#warning Use list.
-                       nfc = (forward_class*) DumpMemory::allocate(sizeof(forward_class));
+                       nfc.thisindex = idx;
 
-                       nfc->next = forward_classes;
-                       forward_classes = nfc;
-
-                       nfc->thisindex = idx;
                        /* reference to CONSTANT_NameAndType */
                        if (!suck_check_classbuffer_size(cb, 2))
                                return false;
 
-                       nfc->name_index = suck_u2(cb);
+                       nfc.name_index = suck_u2(cb);
+
+                       forward_classes.push_front(nfc);
 
                        idx++;
                        break;
-                       
+
                case CONSTANT_String:
-#warning Use list.
-                       nfs = (forward_string*) DumpMemory::allocate(sizeof(forward_string));
-                               
-                       nfs->next = forward_strings;
-                       forward_strings = nfs;
-                               
-                       nfs->thisindex = idx;
+                       nfs.thisindex = idx;
 
                        /* reference to CONSTANT_Utf8_info with string characters */
                        if (!suck_check_classbuffer_size(cb, 2))
                                return false;
 
-                       nfs->string_index = suck_u2(cb);
-                               
+                       nfs.string_index = suck_u2(cb);
+
+                       forward_strings.push_front(nfs);
+
                        idx++;
                        break;
 
                case CONSTANT_NameAndType:
-#warning Use list.
-                       nfn = (forward_nameandtype*) DumpMemory::allocate(sizeof(forward_nameandtype));
-                               
-                       nfn->next = forward_nameandtypes;
-                       forward_nameandtypes = nfn;
-                               
-                       nfn->thisindex = idx;
+                       nfn.thisindex = idx;
 
                        if (!suck_check_classbuffer_size(cb, 2 + 2))
                                return false;
 
                        /* reference to CONSTANT_Utf8_info containing simple name */
-                       nfn->name_index = suck_u2(cb);
+                       nfn.name_index = suck_u2(cb);
 
                        /* reference to CONSTANT_Utf8_info containing field or method
                           descriptor */
-                       nfn->sig_index = suck_u2(cb);
-                               
+                       nfn.sig_index = suck_u2(cb);
+
+                       forward_nameandtypes.push_front(nfn);
+
                        idx++;
                        break;
 
                case CONSTANT_Fieldref:
                case CONSTANT_Methodref:
                case CONSTANT_InterfaceMethodref:
-#warning Use list.
-                       nff = (forward_fieldmethint*) DumpMemory::allocate(sizeof(forward_fieldmethint));
-                       
-                       nff->next = forward_fieldmethints;
-                       forward_fieldmethints = nff;
-
-                       nff->thisindex = idx;
+                       nff.thisindex = idx;
                        /* constant type */
-                       nff->tag = t;
+                       nff.tag = t;
 
                        if (!suck_check_classbuffer_size(cb, 2 + 2))
                                return false;
 
                        /* class or interface type that contains the declaration of the
                           field or method */
-                       nff->class_index = suck_u2(cb);
+                       nff.class_index = suck_u2(cb);
 
                        /* name and descriptor of the field or method */
-                       nff->nameandtype_index = suck_u2(cb);
+                       nff.nameandtype_index = suck_u2(cb);
+
+                       forward_fieldmethints.push_front(nff);
 
                        idx++;
                        break;
-                               
+
                case CONSTANT_Integer: {
                        constant_integer *ci = NEW(constant_integer);
 
@@ -790,8 +776,10 @@ static bool load_constantpool(classbuffer *cb, descriptor_pool *descpool)
 
        /* resolve entries in temporary structures */
 
-       while (forward_classes) {
-               utf *name = (utf*) class_getconstant(c, forward_classes->name_index, CONSTANT_Utf8);
+       for (DumpList<forward_class>::iterator it = forward_classes.begin();
+                       it != forward_classes.end(); ++it) {
+
+               utf *name = (utf*) class_getconstant(c, it->name_index, CONSTANT_Utf8);
                if (!name)
                        return false;
 
@@ -807,30 +795,28 @@ static bool load_constantpool(classbuffer *cb, descriptor_pool *descpool)
                if (!descriptor_pool_add_class(descpool, name))
                        return false;
 
-               cptags[forward_classes->thisindex] = CONSTANT_Class;
+               cptags[it->thisindex] = CONSTANT_Class;
 
                /* the classref is created later */
-               cpinfos[forward_classes->thisindex] = name;
-
-               nfc = forward_classes;
-               forward_classes = forward_classes->next;
+               cpinfos[it->thisindex] = name;
        }
 
-       while (forward_strings) {
-               utf *text = (utf*) class_getconstant(c, forward_strings->string_index, CONSTANT_Utf8);
+       for (DumpList<forward_string>::iterator it = forward_strings.begin();
+                       it != forward_strings.end(); ++it) {
+
+               utf *text = (utf*) class_getconstant(c, it->string_index, CONSTANT_Utf8);
 
                if (!text)
                        return false;
 
                /* resolve utf-string */
-               cptags[forward_strings->thisindex] = CONSTANT_String;
-               cpinfos[forward_strings->thisindex] = text;
-               
-               nfs = forward_strings;
-               forward_strings = forward_strings->next;
+               cptags[it->thisindex] = CONSTANT_String;
+               cpinfos[it->thisindex] = text;
        }
 
-       while (forward_nameandtypes) {
+       for (DumpList<forward_nameandtype>::iterator it = forward_nameandtypes.begin();
+                       it != forward_nameandtypes.end(); ++it) {
+
                constant_nameandtype *cn = NEW(constant_nameandtype);   
 
 #if defined(ENABLE_STATISTICS)
@@ -840,13 +826,13 @@ static bool load_constantpool(classbuffer *cb, descriptor_pool *descpool)
 
                /* resolve simple name and descriptor */
                cn->name = (utf*) class_getconstant(c,
-                                                                                       forward_nameandtypes->name_index,
+                                                                                       it->name_index,
                                                                                        CONSTANT_Utf8);
                if (!cn->name)
                        return false;
 
                cn->descriptor = (utf*) class_getconstant(c,
-                                                                                                 forward_nameandtypes->sig_index,
+                                                                                                 it->sig_index,
                                                                                                  CONSTANT_Utf8);
                if (!cn->descriptor)
                        return false;
@@ -870,14 +856,13 @@ static bool load_constantpool(classbuffer *cb, descriptor_pool *descpool)
                }
 #endif /* ENABLE_VERIFIER */
 
-               cptags[forward_nameandtypes->thisindex] = CONSTANT_NameAndType;
-               cpinfos[forward_nameandtypes->thisindex] = cn;
-
-               nfn = forward_nameandtypes;
-               forward_nameandtypes = forward_nameandtypes->next;
+               cptags[it->thisindex] = CONSTANT_NameAndType;
+               cpinfos[it->thisindex] = cn;
        }
 
-       while (forward_fieldmethints) {
+       for (DumpList<forward_fieldmethint>::iterator it = forward_fieldmethints.begin();
+                       it != forward_fieldmethints.end(); ++it) {
+
                constant_nameandtype *nat;
                constant_FMIref *fmi = NEW(constant_FMIref);
 
@@ -888,7 +873,7 @@ static bool load_constantpool(classbuffer *cb, descriptor_pool *descpool)
                /* resolve simple name and descriptor */
 
                nat = (constant_nameandtype*) class_getconstant(c,
-                                                                                                               forward_fieldmethints->nameandtype_index,
+                                                                                                               it->nameandtype_index,
                                                                                                                CONSTANT_NameAndType);
 
                if (!nat)
@@ -901,15 +886,12 @@ static bool load_constantpool(classbuffer *cb, descriptor_pool *descpool)
 
                /* the classref is created later */
 
-               fmi->p.index = forward_fieldmethints->class_index;
+               fmi->p.index = it->class_index;
                fmi->name = nat->name;
                fmi->descriptor = nat->descriptor;
 
-               cptags[forward_fieldmethints->thisindex] = forward_fieldmethints->tag;
-               cpinfos[forward_fieldmethints->thisindex] = fmi;
-       
-               nff = forward_fieldmethints;
-               forward_fieldmethints = forward_fieldmethints->next;
+               cptags[it->thisindex] = it->tag;
+               cpinfos[it->thisindex] = fmi;
        }
 
        /* everything was ok */
@@ -985,37 +967,22 @@ bool loader_load_attribute_signature(classbuffer *cb, utf **signature)
 
 *******************************************************************************/
 
+#if defined(ENABLE_JAVASE)
 classinfo *load_class_from_sysloader(utf *name)
 {
-       methodinfo    *m;
-       java_handle_t *clo;
        classloader_t *cl;
        classinfo     *c;
 
-       assert(class_java_lang_Object);
-       assert(class_java_lang_ClassLoader);
-       assert(class_java_lang_ClassLoader->state & CLASS_LINKED);
-       
-       m = class_resolveclassmethod(class_java_lang_ClassLoader,
-                                                                utf_getSystemClassLoader,
-                                                                utf_void__java_lang_ClassLoader,
-                                                                class_java_lang_Object,
-                                                                false);
+       cl = java_lang_ClassLoader::invoke_getSystemClassLoader();
 
-       if (!m)
-               return false;
-
-       clo = vm_call_method(m, NULL);
-
-       if (!clo)
+       if (cl == NULL)
                return false;
 
-       cl = loader_hashtable_classloader_add(clo);
-
        c = load_class_from_classloader(name, cl);
 
        return c;
 }
+#endif /* defined(ENABLE_JAVASE) */
 
 
 /* load_class_from_classloader *************************************************
@@ -1182,6 +1149,18 @@ classinfo *load_class_from_classloader(utf *name, classloader_t *cl)
 
                        c = tmpc;
                }
+               else {
+                       // Expected behavior for the classloader is to throw an exception
+                       // and never return NULL. If the classloader shows a different
+                       // behavior, we are correcting it here (see PR126).
+                       if (exceptions_get_exception() == NULL) {
+#if !defined(NDEBUG)
+                               if (opt_PrintWarnings)
+                                       log_message_utf("load_class_from_classloader: Correcting faulty classloader behavior (PR126) for ", name);
+#endif
+                               exceptions_throw_classnotfoundexception(name);
+                       }
+               }
 
                RT_TIMING_GET_TIME(time_cache);
 
@@ -1197,12 +1176,6 @@ classinfo *load_class_from_classloader(utf *name, classloader_t *cl)
                        printf("]\n");
                }
 
-#if defined(ENABLE_JVMTI)
-               /* fire Class Load JVMTI event */
-               if (jvmti) jvmti_ClassLoadPrepare(false, c);
-#endif
-
-
                return c;
        } 
 
@@ -1620,7 +1593,6 @@ static bool load_class_from_classbuffer_intern(classbuffer *cb)
        /* allocate space for the parsed descriptors */
 
        descriptor_pool_alloc_parsed_descriptors(descpool);
-       c->parseddescs = (u1*) descriptor_pool_get_parsed_descriptors(descpool, &(c->parseddescsize));
 
 #if defined(ENABLE_STATISTICS)
        if (opt_stat) {
@@ -1992,18 +1964,14 @@ classinfo *load_class_from_classbuffer(classbuffer *cb)
 
        c->state = (c->state & ~CLASS_LOADING) | CLASS_LOADED;
 
-#if defined(ENABLE_JVMTI)
-       /* fire Class Prepare JVMTI event */
-
-       if (jvmti)
-               jvmti_ClassLoadPrepare(true, c);
-#endif
-
 #if !defined(NDEBUG)
        if (loadverbose)
                log_message_class("Loading done class: ", c);
 #endif
 
+       // Hook point just after a class was loaded.
+       Hook::class_loaded(c);
+
        return c;
 }
 
@@ -2169,8 +2137,7 @@ classinfo *load_newly_created_array(classinfo *c, classloader_t *loader)
 
        /* parse the descriptor to get the register allocation */
 
-       if (!descriptor_params_from_paramtypes(clonedesc, clone->flags))
-               return false;
+       descriptor_params_from_paramtypes(clonedesc, clone->flags);
 
        clone->code = NativeStub::generate(clone, BUILTIN_clone);
 
@@ -2179,8 +2146,6 @@ classinfo *load_newly_created_array(classinfo *c, classloader_t *loader)
        /* array classes are not loaded from class files */
 
        c->state          |= CLASS_LOADED;
-       c->parseddescs    = (u1 *) clonedesc;
-       c->parseddescsize = sizeof(methodinfo);
        c->classrefs      = classrefs;
        c->classrefcount  = 1;