X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=src%2Fvm%2Flinker.c;h=db8ae3f53de067e5b2e0e71978c9107b02869d14;hb=da49fa899f1ba447e4ee376a87729e43fde8754c;hp=f660e9091143f9daf2d131de40f473620ae089ee;hpb=1626e9b23654a8529794448b7962ec89253c1102;p=cacao.git diff --git a/src/vm/linker.c b/src/vm/linker.c index f660e9091..db8ae3f53 100644 --- a/src/vm/linker.c +++ b/src/vm/linker.c @@ -32,19 +32,27 @@ Edwin Steiner Christian Thalinger - $Id: linker.c 2190 2005-04-02 10:07:44Z edwin $ + $Id: linker.c 3685 2005-11-16 13:28:59Z twisti $ */ +#include + +#include "config.h" +#include "vm/types.h" + #include "mm/memory.h" #include "native/native.h" #include "vm/builtin.h" #include "vm/class.h" +#include "vm/classcache.h" #include "vm/exceptions.h" #include "vm/loader.h" #include "vm/options.h" +#include "vm/resolve.h" #include "vm/statistics.h" +#include "vm/stringlocal.h" #include "vm/jit/codegen.inc.h" @@ -62,7 +70,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). *******************************************************************************/ @@ -149,10 +157,60 @@ bool linker_init(void) return false; + /* load some other important classes */ + + if (!link_class(class_java_lang_Class)) + return false; + + if (!link_class(class_java_lang_ClassLoader)) + return false; + + if (!link_class(class_java_lang_SecurityManager)) + return false; + + 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 */ + + if (!link_class(class_java_lang_StackTraceElement)) + return false; + + if (!link_class(class_java_lang_reflect_Constructor)) + return false; + + if (!link_class(class_java_lang_reflect_Field)) + return false; + + if (!link_class(class_java_lang_reflect_Method)) + return false; + + if (!link_class(class_java_security_PrivilegedAction)) + return false; + + if (!link_class(class_java_util_Vector)) + return false; + + if (!link_class(arrayclass_java_lang_Object)) + return false; + + /* create pseudo classes used by the typechecker */ /* pseudo class for Arraystubs (extends java.lang.Object) */ + 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; @@ -160,23 +218,39 @@ bool linker_init(void) pseudo_class_Arraystub->interfaces[0].cls = class_java_lang_Cloneable; pseudo_class_Arraystub->interfaces[1].cls = class_java_io_Serializable; - if (!link_class(pseudo_class_Arraystub)) + if (!classcache_store_unique(pseudo_class_Arraystub)) { + log_text("could not cache pseudo_class_Arraystub"); + assert(0); + } + + 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->super.cls = class_java_lang_Object; + + if (!classcache_store_unique(pseudo_class_Null)) { + log_text("could not cache pseudo_class_Null"); + assert(0); + } 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->super.cls = class_java_lang_Object; + if (!classcache_store_unique(pseudo_class_New)) { + log_text("could not cache pseudo_class_New"); + assert(0); + } /* create classes representing primitive types */ @@ -202,39 +276,61 @@ bool linker_init(void) static bool link_primitivetype_table(void) { classinfo *c; - s4 i; + utf *u; + s4 i; for (i = 0; i < PRIMITIVETYPE_COUNT; i++) { /* skip dummies */ + if (!primitivetype_table[i].name) continue; /* create primitive class */ - c = class_new_intern(utf_new_char(primitivetype_table[i].name)); + + c = class_create_classinfo(utf_new_char(primitivetype_table[i].name)); + + c->flags = ACC_PUBLIC | ACC_FINAL | ACC_ABSTRACT; c->classUsed = NOTUSED; /* not used initially CO-RT */ c->impldBy = NULL; /* prevent loader from loading primitive class */ + c->loaded = true; + + /* INFO: don't put primitive classes into the classcache */ + if (!link_class(c)) return false; primitivetype_table[i].class_primitive = c; /* create class for wrapping the primitive type */ - c = class_new_intern(utf_new_char(primitivetype_table[i].wrapname)); + + u = utf_new_char(primitivetype_table[i].wrapname); + + if (!(c = load_class_bootstrap(u))) + 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 */ + if (primitivetype_table[i].arrayname) { - c = class_new_intern(utf_new_char(primitivetype_table[i].arrayname)); + u = utf_new_char(primitivetype_table[i].arrayname); + c = class_create_classinfo(u); + c = load_newly_created_array(c, NULL); + if (c == NULL) + return false; + primitivetype_table[i].arrayclass = c; - c->loaded = true; + + assert(c->loaded); if (!c->linked) if (!link_class(c)) return false; + primitivetype_table[i].arrayvftbl = c->vftbl; } } @@ -254,6 +350,11 @@ classinfo *link_class(classinfo *c) { classinfo *r; + if (!c) { + *exceptionptr = new_nullpointerexception(); + return NULL; + } + #if defined(USE_THREADS) /* enter a monitor on the class */ @@ -280,9 +381,11 @@ classinfo *link_class(classinfo *c) #endif /* call the internal function */ + r = link_class_intern(c); /* if return value is NULL, we had a problem and the class is not linked */ + if (!r) c->linked = false; @@ -322,10 +425,11 @@ static classinfo *link_class_intern(classinfo *c) s4 vftbllength; /* vftbllength of current class */ s4 interfacetablelength; /* interface table length */ vftbl_t *v; /* vftbl of current class */ - s4 i; /* interface/method/field counter */ + s4 i,j; /* interface/method/field counter */ arraydescriptor *arraydesc; /* descriptor for array classes */ /* maybe the class is already linked */ + if (c->linked) return c; @@ -333,11 +437,23 @@ static classinfo *link_class_intern(classinfo *c) log_message_class("Linking class: ", c); /* the class must be loaded */ + if (!c->loaded) throw_cacao_exception_exit(string_java_lang_InternalError, "Trying to link unloaded class"); + /* 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 */ + c->linked = true; arraydesc = NULL; @@ -345,8 +461,14 @@ static classinfo *link_class_intern(classinfo *c) /* check interfaces */ for (i = 0; i < c->interfacescount; i++) { - tc = c->interfaces[i].cls; + /* resolve this super interface */ + if (!resolve_classref_or_classinfo(NULL, c->interfaces[i], resolveEager, + true, false, &tc)) + return NULL; + + c->interfaces[i].cls = tc; + /* detect circularity */ if (tc == c) { @@ -356,9 +478,7 @@ static classinfo *link_class_intern(classinfo *c) return NULL; } - if (!tc->loaded) - if (!load_class_from_classloader(tc, c->classloader)) - return NULL; + assert(tc->loaded); if (!(tc->flags & ACC_INTERFACE)) { *exceptionptr = @@ -374,11 +494,11 @@ static classinfo *link_class_intern(classinfo *c) /* check super class */ - super = c->super.cls; + super = NULL; - if (super == NULL) { /* class java.lang.Object */ + if (c->super.any == NULL) { /* class java.lang.Object */ c->index = 0; - c->classUsed = USED; /* Object class is always used CO-RT*/ + c->classUsed = USED; /* Object class is always used CO-RT*/ c->impldBy = NULL; c->instancesize = sizeof(java_objectheader); @@ -387,7 +507,15 @@ static classinfo *link_class_intern(classinfo *c) c->finalizer = NULL; } else { + /* resolve super class */ + + if (!resolve_classref_or_classinfo(NULL, c->super, resolveEager, true, false, + &super)) + return NULL; + c->super.cls = super; + /* detect circularity */ + if (super == c) { *exceptionptr = new_exception_utfmessage(string_java_lang_ClassCircularityError, @@ -395,16 +523,16 @@ static classinfo *link_class_intern(classinfo *c) return NULL; } - if (!super->loaded) - if (!load_class_from_classloader(super, c->classloader)) - return NULL; + assert(super->loaded); if (super->flags & ACC_INTERFACE) { /* java.lang.IncompatibleClassChangeError: class a has interface java.lang.Cloneable as super class */ - panic("Interface specified as super class"); + log_text("Interface specified as super class"); + assert(0); } /* Don't allow extending final classes */ + if (super->flags & ACC_FINAL) { *exceptionptr = new_exception_message(string_java_lang_VerifyError, @@ -417,6 +545,7 @@ static classinfo *link_class_intern(classinfo *c) return NULL; /* handle array classes */ + if (c->name->text[0] == '[') if (!(arraydesc = link_array(c))) return NULL; @@ -609,24 +738,11 @@ static classinfo *link_class_intern(classinfo *c) /* Methods in ABSTRACT classes from interfaces maybe already have a */ /* stubroutine. */ - if (!m->stubroutine) { - if (!(m->flags & ACC_NATIVE)) { - m->stubroutine = createcompilerstub(m); - - } else { - functionptr f = native_findfunction(c->name, - m->name, - m->descriptor, - (m->flags & ACC_STATIC)); -#if defined(STATIC_CLASSPATH) - if (f) -#endif - m->stubroutine = createnativestub(f, m); - } - } + if (!m->stubroutine) + m->stubroutine = createcompilerstub(m); if (!(m->flags & ACC_STATIC)) - v->table[m->vftblindex] = m->stubroutine; + v->table[m->vftblindex] = (methodptr) (ptrint) m->stubroutine; } /* compute instance size and offset of each field */ @@ -675,6 +791,22 @@ static classinfo *link_class_intern(classinfo *c) c->finalizer = fi; } + /* resolve exception class references */ + + for (i = 0; i < c->methodscount; i++) { + methodinfo *m = &(c->methods[i]); + + for (j = 0; j < m->exceptiontablelength; j++) { + if (!m->exceptiontable[j].catchtype.any) + continue; + if (!resolve_classref_or_classinfo(NULL, + m->exceptiontable[j].catchtype, + resolveEager, true, false, + &(m->exceptiontable[j].catchtype.cls))) + return NULL; + } + } + /* final tasks */ linker_compute_subclasses(c); @@ -700,33 +832,36 @@ static classinfo *link_class_intern(classinfo *c) static arraydescriptor *link_array(classinfo *c) { - classinfo *comp = NULL; - s4 namelen = c->name->blength; + classinfo *comp; + s4 namelen; arraydescriptor *desc; - vftbl_t *compvftbl; + vftbl_t *compvftbl; + utf *u; + + comp = NULL; + namelen = c->name->blength; /* Check the component type */ + switch (c->name->text[1]) { case '[': /* c is an array of arrays. */ - comp = class_new(utf_new_intern(c->name->text + 1, namelen - 1)); - if (!comp) - panic("Could not find component array class."); + 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. */ - comp = class_new(utf_new_intern(c->name->text + 2, namelen - 3)); - if (!comp) - panic("Could not find component class."); + 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) { - if (!comp->loaded) - if (!load_class_from_classloader(comp, c->classloader)) - return NULL; if (!link_class(comp)) return NULL; @@ -742,14 +877,22 @@ static arraydescriptor *link_array(classinfo *c) desc->dataoffset = OFFSET(java_objectarray, data); compvftbl = comp->vftbl; - if (!compvftbl) - panic("Component class has no vftbl"); + + if (!compvftbl) { + log_text("Component class has no vftbl"); + assert(0); + } + desc->componentvftbl = compvftbl; if (compvftbl->arraydesc) { desc->elementvftbl = compvftbl->arraydesc->elementvftbl; - if (compvftbl->arraydesc->dimension >= 255) - panic("Creating array of dimension >255"); + + if (compvftbl->arraydesc->dimension >= 255) { + log_text("Creating array of dimension >255"); + assert(0); + } + desc->dimension = compvftbl->arraydesc->dimension + 1; desc->elementtype = compvftbl->arraydesc->elementtype; @@ -811,7 +954,8 @@ static arraydescriptor *link_array(classinfo *c) break; default: - panic("Invalid array class name"); + *exceptionptr = new_noclassdeffounderror(c->name); + return NULL; } desc->componentvftbl = NULL; @@ -852,14 +996,9 @@ static void linker_compute_subclasses(classinfo *c) classvalue = 0; - /* this is the java.lang.Object special case */ - - if (!class_java_lang_Object) { - linker_compute_class_values(c); + /* compute class values */ - } else { - linker_compute_class_values(class_java_lang_Object); - } + linker_compute_class_values(class_java_lang_Object); #if defined(USE_THREADS) #if defined(NATIVE_THREADS) @@ -908,8 +1047,10 @@ static void linker_addinterface(classinfo *c, classinfo *ic) s4 i = ic->index; vftbl_t *v = c->vftbl; - if (i >= v->interfacetablelength) - panic ("Inernal error: interfacetable overflow"); + if (i >= v->interfacetablelength) { + log_text("Inernal error: interfacetable overflow"); + assert(0); + } if (v->interfacetable[-i]) return; @@ -981,43 +1122,6 @@ static s4 class_highestinterface(classinfo *c) } -/***************** Function: print_arraydescriptor **************************** - - Debug helper for displaying an arraydescriptor - -*******************************************************************************/ - -void print_arraydescriptor(FILE *file, arraydescriptor *desc) -{ - if (!desc) { - fprintf(file, ""); - return; - } - - fprintf(file, "{"); - if (desc->componentvftbl) { - if (desc->componentvftbl->class) - utf_fprint(file, desc->componentvftbl->class->name); - else - fprintf(file, ""); - } - else - fprintf(file, "0"); - - fprintf(file, ","); - if (desc->elementvftbl) { - if (desc->elementvftbl->class) - utf_fprint(file, desc->elementvftbl->class->name); - else - fprintf(file, ""); - } - else - fprintf(file, "0"); - fprintf(file, ",%d,%d,%d,%d}", desc->arraytype, desc->dimension, - desc->dataoffset, desc->componentsize); -} - - /* * These are local overrides for various environment variables in Emacs. * Please do not remove this and leave it at the end of the file, where