* src/vm/linker.c (link_class_intern): Comment reformatted.
[cacao.git] / src / vm / linker.c
index b70543204dc89d85872928cce62de6934b0c9b6e..9ea19e707875d3b361b904d61e6cbc11ae53c443 100644 (file)
@@ -1,9 +1,9 @@
 /* src/vm/linker.c - class linker functions
 
-   Copyright (C) 1996-2005 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 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
 
    This file is part of CACAO.
 
 
    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
-   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
-   02111-1307, USA.
+   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+   02110-1301, USA.
 
-   Contact: cacao@complang.tuwien.ac.at
+   Contact: cacao@cacaojvm.org
 
    Authors: Reinhard Grafl
 
             Edwin Steiner
             Christian Thalinger
 
-   $Id: linker.c 2728 2005-06-17 08:12:26Z twisti $
+   $Id: linker.c 4528 2006-02-20 23:31:39Z twisti $
 
 */
 
 
+#include "config.h"
+
 #include <assert.h>
 
+#include "vm/types.h"
+
 #include "mm/memory.h"
 #include "native/native.h"
 #include "vm/builtin.h"
@@ -50,7 +54,7 @@
 #include "vm/resolve.h"
 #include "vm/statistics.h"
 #include "vm/stringlocal.h"
-#include "vm/jit/codegen.inc.h"
+#include "vm/access.h"
 
 
 /* global variables ***********************************************************/
@@ -67,7 +71,7 @@ static s4 classvalue;
    primitive class.
  
    CAUTION: Don't change the order of the types. This table is indexed
-   by the ARRAYTYPE_ constants (expcept ARRAYTYPE_OBJECT).
+   by the ARRAYTYPE_ constants (except ARRAYTYPE_OBJECT).
 
 *******************************************************************************/
 
@@ -109,6 +113,19 @@ bool linker_init(void)
 
        interfaceindex = 0;
 
+       /* link java.lang.Class as first class of the system, because we
+       need it's vftbl for all other classes so we can use a class as
+       object */
+
+       if (!link_class(class_java_lang_Class))
+               return false;
+
+       /* now set the header.vftbl of all classes which were created
+       before java.lang.Class was linked */
+
+       class_postset_header_vftbl();
+
+
        /* link important system classes */
 
        if (!link_class(class_java_lang_Object))
@@ -156,9 +173,6 @@ bool linker_init(void)
 
        /* load some other important classes */
 
-       if (!link_class(class_java_lang_Class))
-               return false;
-
        if (!link_class(class_java_lang_ClassLoader))
                return false;
 
@@ -168,9 +182,15 @@ bool linker_init(void)
        if (!link_class(class_java_lang_System))
                return false;
 
+       if (!link_class(class_java_lang_Thread))
+               return false;
+
        if (!link_class(class_java_lang_ThreadGroup))
                return false;
 
+       if (!link_class(class_java_lang_VMThread))
+               return false;
+
 
        /* some classes which may be used more often */
 
@@ -200,28 +220,28 @@ bool linker_init(void)
 
     /* pseudo class for Arraystubs (extends java.lang.Object) */
     
-    pseudo_class_Arraystub =
+       pseudo_class_Arraystub =
                class_create_classinfo(utf_new_char("$ARRAYSTUB$"));
-       pseudo_class_Arraystub->loaded = true;
-    pseudo_class_Arraystub->super.cls = class_java_lang_Object;
-    pseudo_class_Arraystub->interfacescount = 2;
-    pseudo_class_Arraystub->interfaces = MNEW(classref_or_classinfo, 2);
-    pseudo_class_Arraystub->interfaces[0].cls = class_java_lang_Cloneable;
-    pseudo_class_Arraystub->interfaces[1].cls = class_java_io_Serializable;
+       pseudo_class_Arraystub->state |= CLASS_LOADED;
+       pseudo_class_Arraystub->super.cls = class_java_lang_Object;
+       pseudo_class_Arraystub->interfacescount = 2;
+       pseudo_class_Arraystub->interfaces = MNEW(classref_or_classinfo, 2);
+       pseudo_class_Arraystub->interfaces[0].cls = class_java_lang_Cloneable;
+       pseudo_class_Arraystub->interfaces[1].cls = class_java_io_Serializable;
 
        if (!classcache_store_unique(pseudo_class_Arraystub)) {
                log_text("could not cache pseudo_class_Arraystub");
                assert(0);
        }
 
-    if (!link_class(pseudo_class_Arraystub))
+       if (!link_class(pseudo_class_Arraystub))
                return false;
 
-    /* pseudo class representing the null type */
-    
+       /* pseudo class representing the null type */
+
        pseudo_class_Null = class_create_classinfo(utf_new_char("$NULL$"));
-       pseudo_class_Null->loaded = true;
-    pseudo_class_Null->super.cls = class_java_lang_Object;
+       pseudo_class_Null->state |= CLASS_LOADED;
+       pseudo_class_Null->super.cls = class_java_lang_Object;
 
        if (!classcache_store_unique(pseudo_class_Null)) {
                log_text("could not cache pseudo_class_Null");
@@ -231,11 +251,11 @@ bool linker_init(void)
        if (!link_class(pseudo_class_Null))
                return false;
 
-    /* pseudo class representing new uninitialized objects */
+       /* pseudo class representing new uninitialized objects */
     
        pseudo_class_New = class_create_classinfo(utf_new_char("$NEW$"));
-       pseudo_class_New->loaded = true;
-       pseudo_class_New->linked = true; /* XXX is this allright? */
+       pseudo_class_New->state |= CLASS_LOADED;
+       pseudo_class_New->state |= CLASS_LINKED; /* XXX is this allright? */
        pseudo_class_New->super.cls = class_java_lang_Object;
 
        if (!classcache_store_unique(pseudo_class_New)) {
@@ -279,16 +299,15 @@ static bool link_primitivetype_table(void)
                /* create primitive class */
 
                c = class_create_classinfo(utf_new_char(primitivetype_table[i].name));
-               c->classUsed = NOTUSED; /* not used initially CO-RT */
-               c->impldBy = NULL;
+
+               c->flags = ACC_PUBLIC | ACC_FINAL | ACC_ABSTRACT;
                
                /* prevent loader from loading primitive class */
 
-               c->loaded = true;
-               if (!classcache_store_unique(c)) {
-                       log_text("Could not cache primitive class");
-                       return false;
-               }
+               c->state |= CLASS_LOADED;
+
+               /* INFO: don't put primitive classes into the classcache */
+
                if (!link_class(c))
                        return false;
 
@@ -302,8 +321,6 @@ static bool link_primitivetype_table(void)
                        return false;
 
                primitivetype_table[i].class_wrap = c;
-               primitivetype_table[i].class_wrap->classUsed = NOTUSED; /* not used initially CO-RT */
-               primitivetype_table[i].class_wrap->impldBy = NULL;
 
                /* create the primitive array class */
 
@@ -316,8 +333,9 @@ static bool link_primitivetype_table(void)
 
                        primitivetype_table[i].arrayclass = c;
 
-                       assert(c->loaded);
-                       if (!c->linked)
+                       assert(c->state & CLASS_LOADED);
+
+                       if (!(c->state & CLASS_LINKED))
                                if (!link_class(c))
                                        return false;
 
@@ -341,7 +359,7 @@ classinfo *link_class(classinfo *c)
        classinfo *r;
 
        if (!c) {
-               *exceptionptr = new_nullpointerexception();
+               exceptions_throw_nullpointerexception();
                return NULL;
        }
 
@@ -352,7 +370,8 @@ classinfo *link_class(classinfo *c)
 #endif
 
        /* maybe the class is already linked */
-       if (c->linked) {
+
+       if (c->state & CLASS_LINKED) {
 #if defined(USE_THREADS)
                builtin_monitorexit((java_objectheader *) c);
 #endif
@@ -360,7 +379,7 @@ classinfo *link_class(classinfo *c)
                return c;
        }
 
-#if defined(STATISTICS)
+#if defined(ENABLE_STATISTICS)
        /* measure time */
 
        if (getcompilingtime)
@@ -377,9 +396,9 @@ classinfo *link_class(classinfo *c)
        /* if return value is NULL, we had a problem and the class is not linked */
 
        if (!r)
-               c->linked = false;
+               c->state &= ~CLASS_LINKING;
 
-#if defined(STATISTICS)
+#if defined(ENABLE_STATISTICS)
        /* measure time */
 
        if (getloadingtime)
@@ -418,9 +437,9 @@ static classinfo *link_class_intern(classinfo *c)
        s4 i,j;                       /* interface/method/field counter           */
        arraydescriptor *arraydesc;   /* descriptor for array classes             */
 
-       /* maybe the class is already linked */
+       /* the class is already linked */
 
-       if (c->linked)
+       if (c->state & CLASS_LINKED)
                return c;
 
        if (linkverbose)
@@ -428,13 +447,22 @@ static classinfo *link_class_intern(classinfo *c)
 
        /* the class must be loaded */
 
-       if (!c->loaded)
-               throw_cacao_exception_exit(string_java_lang_InternalError,
-                                                                  "Trying to link unloaded class");
+       /* XXX should this be a specific exception? */
+       assert(c->state & CLASS_LOADED);
+
+       /* cache the self-reference of this class                          */
+       /* we do this for cases where the defining loader of the class     */
+       /* has not yet been recorded as an initiating loader for the class */
+       /* this is needed so subsequent code can assume that self-refs     */
+       /* will always resolve lazily                                      */
+       /* No need to do it for the bootloader - it is always registered   */
+       /* as initiating loader for the classes it loads.                  */
+       if (c->classloader)
+               classcache_store(c->classloader,c,false);
 
-       /* ok, this class is somewhat linked */
+       /* this class is currently linking */
 
-       c->linked = true;
+       c->state |= CLASS_LINKING;
 
        arraydesc = NULL;
 
@@ -444,7 +472,7 @@ static classinfo *link_class_intern(classinfo *c)
                /* resolve this super interface */
 
                if (!resolve_classref_or_classinfo(NULL, c->interfaces[i], resolveEager,
-                                                                                  false, &tc))
+                                                                                  true, false, &tc))
                        return NULL;
 
                c->interfaces[i].cls = tc;
@@ -458,7 +486,7 @@ static classinfo *link_class_intern(classinfo *c)
                        return NULL;
                }
 
-               assert(tc->loaded);
+               assert(tc->state & CLASS_LOADED);
 
                if (!(tc->flags & ACC_INTERFACE)) {
                        *exceptionptr =
@@ -467,7 +495,7 @@ static classinfo *link_class_intern(classinfo *c)
                        return NULL;
                }
 
-               if (!tc->linked)
+               if (!(tc->state & CLASS_LINKED))
                        if (!link_class(tc))
                                return NULL;
        }
@@ -478,8 +506,6 @@ static classinfo *link_class_intern(classinfo *c)
 
        if (c->super.any == NULL) {                     /* class java.lang.Object */
                c->index = 0;
-        c->classUsed = USED;              /* Object class is always used CO-RT*/
-               c->impldBy = NULL;
                c->instancesize = sizeof(java_objectheader);
                
                vftbllength = supervftbllength = 0;
@@ -489,7 +515,7 @@ static classinfo *link_class_intern(classinfo *c)
        } else {
                /* resolve super class */
 
-               if (!resolve_classref_or_classinfo(NULL, c->super, resolveEager, false,
+               if (!resolve_classref_or_classinfo(NULL, c->super, resolveEager, true, false,
                                                                                   &super))
                        return NULL;
                c->super.cls = super;
@@ -503,7 +529,7 @@ static classinfo *link_class_intern(classinfo *c)
                        return NULL;
                }
 
-               assert(super->loaded);
+               assert(super->state & CLASS_LOADED);
 
                if (super->flags & ACC_INTERFACE) {
                        /* java.lang.IncompatibleClassChangeError: class a has interface java.lang.Cloneable as super class */
@@ -520,7 +546,7 @@ static classinfo *link_class_intern(classinfo *c)
                        return NULL;
                }
                
-               if (!super->linked)
+               if (!(super->state & CLASS_LINKED))
                        if (!link_class(super))
                                return NULL;
 
@@ -559,6 +585,15 @@ static classinfo *link_class_intern(classinfo *c)
                                                if (tc->methods[j].flags & ACC_PRIVATE)
                                                        goto notfoundvftblindex;
 
+                                               /* package-private methods in other packages */
+                                               /* must not be overridden                    */
+                                               /* (see Java Language Specification 8.4.8.1) */
+                                               if ( !(tc->methods[j].flags & (ACC_PUBLIC | ACC_PROTECTED)) 
+                                                        && !SAME_PACKAGE(c,tc) ) 
+                                               {
+                                                   goto notfoundvftblindex;
+                                               }
+
                                                if (tc->methods[j].flags & ACC_FINAL) {
                                                        /* class a overrides final method . */
                                                        *exceptionptr =
@@ -668,7 +703,7 @@ static classinfo *link_class_intern(classinfo *c)
        }
 
 
-#if defined(STATISTICS)
+#if defined(ENABLE_STATISTICS)
        if (opt_stat)
                count_vftbl_len +=
                        sizeof(vftbl_t) + (sizeof(methodptr) * (vftbllength - 1));
@@ -694,7 +729,7 @@ static classinfo *link_class_intern(classinfo *c)
                                                          sizeof(methodptr*) * (interfacetablelength - (interfacetablelength > 0)));
        v = (vftbl_t *) (((methodptr *) v) +
                                         (interfacetablelength - 1) * (interfacetablelength > 1));
-       c->header.vftbl = c->vftbl = v;
+       c->vftbl = v;
        v->class = c;
        v->vftbllength = vftbllength;
        v->interfacetablelength = interfacetablelength;
@@ -715,23 +750,20 @@ static classinfo *link_class_intern(classinfo *c)
        for (i = 0; i < c->methodscount; i++) {
                methodinfo *m = &(c->methods[i]);
 
-               /* Methods in ABSTRACT classes from interfaces maybe already have a   */
-               /* stubroutine.                                                       */
+               /* Methods in ABSTRACT classes from interfaces maybe already
+                  have a stubroutine. */
 
                if (!m->stubroutine) {
-                       if (!(m->flags & ACC_NATIVE)) {
+#if defined(ENABLE_JIT)
+# if defined(ENABLE_INTRP)
+                       if (opt_intrp)
+                               m->stubroutine = intrp_createcompilerstub(m);
+                       else
+#endif
                                m->stubroutine = createcompilerstub(m);
-
-                       } else {
-                               functionptr f = NULL;
-
-#if defined(STATIC_CLASSPATH)
-                               f = native_findfunction(c->name, m->name, m->descriptor,
-                                                                               (m->flags & ACC_STATIC));
-                               if (f)
+#else
+                       m->stubroutine = intrp_createcompilerstub(m);
 #endif
-                                       m->stubroutine = codegen_createnativestub(f, m);
-                       }
                }
 
                if (!(m->flags & ACC_STATIC))
@@ -745,7 +777,7 @@ static classinfo *link_class_intern(classinfo *c)
                fieldinfo *f = &(c->fields[i]);
                
                if (!(f->flags & ACC_STATIC)) {
-                       dsize = desc_typesize(f->descriptor);
+                       dsize = descriptor_typesize(f->parseddesc);
                        c->instancesize = ALIGN(c->instancesize, dsize);
                        f->offset = c->instancesize;
                        c->instancesize += dsize;
@@ -756,7 +788,7 @@ static classinfo *link_class_intern(classinfo *c)
        
        v->interfacevftbllength = MNEW(s4, interfacetablelength);
 
-#if defined(STATISTICS)
+#if defined(ENABLE_STATISTICS)
        if (opt_stat)
                count_vftbl_len += (4 + sizeof(s4)) * v->interfacetablelength;
 #endif
@@ -794,22 +826,20 @@ static classinfo *link_class_intern(classinfo *c)
                                continue;
                        if (!resolve_classref_or_classinfo(NULL,
                                                                                           m->exceptiontable[j].catchtype,
-                                                                                          resolveEager, false,
+                                                                                          resolveEager, true, false,
                                                                                           &(m->exceptiontable[j].catchtype.cls)))
                                return NULL;
                }
-
-               for (j = 0; j < m->thrownexceptionscount; j++)
-                       if (!resolve_classref_or_classinfo(NULL, m->thrownexceptions[j],
-                                                                                          resolveEager, false,
-                                                                                          &(m->thrownexceptions[j].cls)))
-                               return NULL;
        }
        
        /* final tasks */
 
        linker_compute_subclasses(c);
 
+       /* revert the linking state and class is linked */
+
+       c->state = (c->state & ~CLASS_LINKING) | CLASS_LINKED;
+
        if (linkverbose)
                log_message_class("Linking done class: ", c);
 
@@ -845,28 +875,29 @@ static arraydescriptor *link_array(classinfo *c)
        switch (c->name->text[1]) {
        case '[':
                /* c is an array of arrays. */
-               u = utf_new_intern(c->name->text + 1, namelen - 1);
+               u = utf_new(c->name->text + 1, namelen - 1);
                if (!(comp = load_class_from_classloader(u, c->classloader)))
                        return NULL;
                break;
 
        case 'L':
                /* c is an array of objects. */
-               u = utf_new_intern(c->name->text + 2, namelen - 3);
+               u = utf_new(c->name->text + 2, namelen - 3);
                if (!(comp = load_class_from_classloader(u, c->classloader)))
                        return NULL;
                break;
        }
 
        /* If the component type has not been linked, link it now */
-       assert(!comp || comp->loaded);
-       if (comp && !comp->linked) {
 
+       assert(!comp || (comp->state & CLASS_LOADED));
+
+       if (comp && !(comp->state & CLASS_LINKED))
                if (!link_class(comp))
                        return NULL;
-       }
 
        /* Allocate the arraydescriptor */
+
        desc = NEW(arraydescriptor);
 
        if (comp) {
@@ -953,8 +984,8 @@ static arraydescriptor *link_array(classinfo *c)
                        break;
 
                default:
-                       log_text("Invalid array class name");
-                       assert(0);
+                       *exceptionptr = new_noclassdeffounderror(c->name);
+                       return NULL;
                }
                
                desc->componentvftbl = NULL;
@@ -1063,7 +1094,7 @@ static void linker_addinterface(classinfo *c, classinfo *ic)
                v->interfacevftbllength[i] = ic->methodscount;
                v->interfacetable[-i] = MNEW(methodptr, ic->methodscount);
 
-#if defined(STATISTICS)
+#if defined(ENABLE_STATISTICS)
                if (opt_stat)
                        count_vftbl_len += sizeof(methodptr) *
                                (ic->methodscount + (ic->methodscount == 0));
@@ -1132,4 +1163,5 @@ static s4 class_highestinterface(classinfo *c)
  * c-basic-offset: 4
  * tab-width: 4
  * End:
+ * vim:noexpandtab:sw=4:ts=4:
  */