X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=src%2Fvm%2Flinker.c;h=db8ae3f53de067e5b2e0e71978c9107b02869d14;hb=a1e3527fd4da513cdd0d90d08cad17afda860070;hp=4ff12a5ac238ac2e9e95e413b1309f8f8cb05adb;hpb=42374a314b2eec905f59f4d0a28f90d4e7d173b2;p=cacao.git diff --git a/src/vm/linker.c b/src/vm/linker.c index 4ff12a5ac..db8ae3f53 100644 --- a/src/vm/linker.c +++ b/src/vm/linker.c @@ -32,19 +32,27 @@ Edwin Steiner Christian Thalinger - $Id: linker.c 2169 2005-03-31 15:50:57Z twisti $ + $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). *******************************************************************************/ @@ -71,10 +79,12 @@ primitivetypeinfo primitivetype_table[PRIMITIVETYPE_COUNT] = { { NULL, NULL, "java/lang/Long", 'J', "long" , "[J", NULL, NULL }, { NULL, NULL, "java/lang/Float", 'F', "float" , "[F", NULL, NULL }, { NULL, NULL, "java/lang/Double", 'D', "double" , "[D", NULL, NULL }, + { NULL, NULL, NULL, 0 , NULL , NULL, NULL, NULL }, { NULL, NULL, "java/lang/Byte", 'B', "byte" , "[B", NULL, NULL }, { NULL, NULL, "java/lang/Character", 'C', "char" , "[C", NULL, NULL }, { NULL, NULL, "java/lang/Short", 'S', "short" , "[S", NULL, NULL }, { NULL, NULL, "java/lang/Boolean", 'Z', "boolean" , "[Z", NULL, NULL }, + { NULL, NULL, NULL, 0 , NULL , NULL, NULL, NULL }, { NULL, NULL, "java/lang/Void", 'V', "void" , NULL, NULL, NULL } }; @@ -147,34 +157,100 @@ 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 = class_java_lang_Object; + pseudo_class_Arraystub->super.cls = class_java_lang_Object; pseudo_class_Arraystub->interfacescount = 2; - pseudo_class_Arraystub->interfaces = MNEW(classinfo*, 2); - pseudo_class_Arraystub->interfaces[0] = class_java_lang_Cloneable; - pseudo_class_Arraystub->interfaces[1] = class_java_io_Serializable; + 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 (!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 = 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; - pseudo_class_New->super = class_java_lang_Object; + 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 */ @@ -200,35 +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; } } @@ -248,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 */ @@ -274,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; @@ -316,22 +425,35 @@ 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; + if (linkverbose) + 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"); - if (linkverbose) - log_message_class("Linking class: ", c); + /* 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; @@ -339,8 +461,14 @@ static classinfo *link_class_intern(classinfo *c) /* check interfaces */ for (i = 0; i < c->interfacescount; i++) { - tc = c->interfaces[i]; + /* 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) { @@ -350,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 = @@ -368,11 +494,11 @@ static classinfo *link_class_intern(classinfo *c) /* check super class */ - super = c->super; + 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); @@ -381,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, @@ -389,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, @@ -411,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; @@ -456,7 +591,7 @@ static classinfo *link_class_intern(classinfo *c) } } - tc = tc->super; + tc = tc->super.cls; } notfoundvftblindex: @@ -479,7 +614,7 @@ static classinfo *link_class_intern(classinfo *c) abstractmethodscount = 0; for (i = 0; i < c->interfacescount; i++) { - ic = c->interfaces[i]; + ic = c->interfaces[i].cls; for (j = 0; j < ic->methodscount; j++) { im = &(ic->methods[j]); @@ -497,7 +632,7 @@ static classinfo *link_class_intern(classinfo *c) goto noabstractmethod; } - tc = tc->super; + tc = tc->super.cls; } abstractmethodscount++; @@ -516,7 +651,7 @@ static classinfo *link_class_intern(classinfo *c) c->methodscount + abstractmethodscount); for (i = 0; i < c->interfacescount; i++) { - ic = c->interfaces[i]; + ic = c->interfaces[i].cls; for (j = 0; j < ic->methodscount; j++) { im = &(ic->methods[j]); @@ -534,7 +669,7 @@ static classinfo *link_class_intern(classinfo *c) goto noabstractmethod2; } - tc = tc->super; + tc = tc->super.cls; } am = &(c->methods[c->methodscount]); @@ -565,11 +700,11 @@ static classinfo *link_class_intern(classinfo *c) tc = c; while (tc) { for (i = 0; i < tc->interfacescount; i++) { - s4 h = class_highestinterface(tc->interfaces[i]) + 1; + s4 h = class_highestinterface(tc->interfaces[i].cls) + 1; if (h > interfacetablelength) interfacetablelength = h; } - tc = tc->super; + tc = tc->super.cls; } /* allocate virtual function table */ @@ -603,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 */ @@ -653,9 +775,9 @@ static classinfo *link_class_intern(classinfo *c) /* add interfaces */ - for (tc = c; tc != NULL; tc = tc->super) + for (tc = c; tc != NULL; tc = tc->super.cls) for (i = 0; i < tc->interfacescount; i++) - linker_addinterface(c, tc->interfaces[i]); + linker_addinterface(c, tc->interfaces[i].cls); /* add finalizer method (not for java.lang.Object) */ @@ -669,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); @@ -694,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; @@ -736,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; @@ -805,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; @@ -839,21 +989,16 @@ static void linker_compute_subclasses(classinfo *c) c->sub = 0; } - if (!(c->flags & ACC_INTERFACE) && (c->super != NULL)) { - c->nextsub = c->super->sub; - c->super->sub = c; + if (!(c->flags & ACC_INTERFACE) && (c->super.any != NULL)) { + c->nextsub = c->super.cls->sub; + c->super.cls->sub = 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) @@ -902,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; @@ -935,7 +1082,7 @@ static void linker_addinterface(classinfo *c, classinfo *ic) goto foundmethod; } } - sc = sc->super; + sc = sc->super.cls; } foundmethod: ; @@ -943,7 +1090,7 @@ static void linker_addinterface(classinfo *c, classinfo *ic) } for (j = 0; j < ic->interfacescount; j++) - linker_addinterface(c, ic->interfaces[j]); + linker_addinterface(c, ic->interfaces[j].cls); } @@ -965,7 +1112,7 @@ static s4 class_highestinterface(classinfo *c) h = c->index; for (i = 0; i < c->interfacescount; i++) { - h2 = class_highestinterface(c->interfaces[i]); + h2 = class_highestinterface(c->interfaces[i].cls); if (h2 > h) h = h2;