X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=typeinfo.c;h=9c244dd89402992ef811760d2b53482e7ad80f4a;hb=6edb6adb2951660c63c3a7186ebc9895328cef28;hp=eb1559d4c4dfa9d65310e6bc6ad41f108a8592f2;hpb=f4dff436f4e65d9f84854a415049a6b4721cb9eb;p=cacao.git diff --git a/typeinfo.c b/typeinfo.c index eb1559d4c..9c244dd89 100644 --- a/typeinfo.c +++ b/typeinfo.c @@ -26,7 +26,7 @@ Authors: Edwin Steiner - $Id: typeinfo.c 719 2003-12-08 14:26:05Z edwin $ + $Id: typeinfo.c 1191 2004-06-19 12:46:00Z twisti $ */ @@ -36,14 +36,292 @@ #include "typeinfo.h" #include "tables.h" #include "loader.h" -#include "toolbox/loging.h" +#include "toolbox/logging.h" #include "toolbox/memory.h" +#include "jit/jit.h" /* XXX move typeinfo.* into jit/ */ #define CLASS_IMPLEMENTS_INTERFACE(cls,index) \ ( ((index) < (cls)->vftbl->interfacetablelength) \ && (VFTBLINTERFACETABLE((cls)->vftbl,(index)) != NULL) ) +/**********************************************************************/ +/* TYPEVECTOR FUNCTIONS */ +/**********************************************************************/ + +typevector * +typevectorset_copy(typevector *src,int k,int size) +{ + typevector *dst = DNEW_TYPEVECTOR(size); + + memcpy(dst,src,TYPEVECTOR_SIZE(size)); + dst->k = k; + if (src->alt) + dst->alt = typevectorset_copy(src->alt,k+1,size); + return dst; +} + +bool +typevectorset_checktype(typevector *vec,int index,int type) +{ + do { + if (vec->td[index].type != type) + return false; + } while ((vec = vec->alt) != NULL); + return true; +} + +bool +typevectorset_checkreference(typevector *vec,int index) +{ + do { + if (!TYPEDESC_IS_REFERENCE(vec->td[index])) + return false; + } while ((vec = vec->alt) != NULL); + return true; +} + +bool +typevectorset_checkretaddr(typevector *vec,int index) +{ + do { + if (!TYPEDESC_IS_RETURNADDRESS(vec->td[index])) + return false; + } while ((vec = vec->alt) != NULL); + return true; +} + +int +typevectorset_copymergedtype(typevector *vec,int index,typeinfo *dst) +{ + int type; + typedescriptor *td; + + td = vec->td + index; + type = td->type; + TYPEINFO_COPY(td->info,*dst); + + if (vec->alt) { + int primitive; + + primitive = TYPEINFO_IS_PRIMITIVE(*dst) ? 1 : 0; + + while ((vec = vec->alt) != NULL) { + td = vec->td + index; + if (type != td->type) + return TYPE_VOID; + + if (type == TYPE_ADDRESS) { + if ((TYPEINFO_IS_PRIMITIVE(td->info) ? 1 : 0) != primitive) + return TYPE_VOID; + typeinfo_merge(dst,&(td->info)); + } + } + } + return type; +} + +int +typevectorset_mergedtype(typevector *vec,int index,typeinfo *temp,typeinfo **result) +{ + if (vec->alt) { + *result = temp; + return typevectorset_copymergedtype(vec,index,temp); + } + + *result = &(vec->td[index].info); + return vec->td[index].type; +} + +typeinfo * +typevectorset_mergedtypeinfo(typevector *vec,int index,typeinfo *temp) +{ + typeinfo *result; + int type = typevectorset_mergedtype(vec,index,temp,&result); + return (type == TYPE_ADDRESS) ? result : NULL; +} + +void +typevectorset_store(typevector *vec,int index,int type,typeinfo *info) +{ + do { + vec->td[index].type = type; + if (info) + TYPEINFO_COPY(*info,vec->td[index].info); + if (index > 0 && IS_2_WORD_TYPE(vec->td[index-1].type)) + vec->td[index-1].type = TYPE_VOID; + } while ((vec = vec->alt) != NULL); +} + +void +typevectorset_store_retaddr(typevector *vec,int index,typeinfo *info) +{ + typeinfo_retaddr_set *adr; + + adr = (typeinfo_retaddr_set*) TYPEINFO_RETURNADDRESS(*info); + do { + vec->td[index].type = TYPE_ADDRESS; + TYPEINFO_INIT_RETURNADDRESS(vec->td[index].info,adr->addr); + if (index > 0 && IS_2_WORD_TYPE(vec->td[index-1].type)) + vec->td[index-1].type = TYPE_VOID; + adr = adr->alt; + } while ((vec = vec->alt) != NULL); +} + +void +typevectorset_store_twoword(typevector *vec,int index,int type) +{ + do { + vec->td[index].type = type; + vec->td[index+1].type = TYPE_VOID; + if (index > 0 && IS_2_WORD_TYPE(vec->td[index-1].type)) + vec->td[index-1].type = TYPE_VOID; + } while ((vec = vec->alt) != NULL); +} + +void +typevectorset_init_object(typevector *set,void *ins,classinfo *initclass, + int size) +{ + int i; + + for (;set; set=set->alt) { + for (i=0; itd[i].type == TYPE_ADR + && TYPEINFO_IS_NEWOBJECT(set->td[i].info) + && TYPEINFO_NEWOBJECT_INSTRUCTION(set->td[i].info) == ins) + { + TYPEINFO_INIT_CLASSINFO(set->td[i].info,initclass); + } + } + } +} + +bool +typevector_merge(typevector *dst,typevector *y,int size) +{ + bool changed = false; + + typedescriptor *a = dst->td; + typedescriptor *b = y->td; + while (size--) { + if (a->type != TYPE_VOID && a->type != b->type) { + a->type = TYPE_VOID; + changed = true; + } + else if (a->type == TYPE_ADDRESS) { + if (TYPEINFO_IS_PRIMITIVE(a->info)) { + /* 'a' is a returnAddress */ + if (!TYPEINFO_IS_PRIMITIVE(b->info) + || (TYPEINFO_RETURNADDRESS(a->info) + != TYPEINFO_RETURNADDRESS(b->info))) + { + a->type = TYPE_VOID; + changed = true; + } + } + else { + /* 'a' is a reference */ + if (TYPEINFO_IS_PRIMITIVE(b->info)) { + a->type = TYPE_VOID; + changed = true; + } + else { + changed |= typeinfo_merge(&(a->info),&(b->info)); + } + } + } + a++; + b++; + } + return changed; +} + +bool typevector_separable_from(typevector *a,typevector *b,int size) +{ + typedescriptor *tda = a->td; + typedescriptor *tdb = b->td; + for (;size--; tda++,tdb++) { + if (TYPEDESC_IS_RETURNADDRESS(*tda) + && TYPEDESC_IS_RETURNADDRESS(*tdb) + && TYPEINFO_RETURNADDRESS(tda->info) + != TYPEINFO_RETURNADDRESS(tdb->info)) + return true; + } + return false; +} + +void +typevectorset_add(typevector *dst,typevector *v,int size) +{ + while (dst->alt) + dst = dst->alt; + dst->alt = DNEW_TYPEVECTOR(size); + memcpy(dst->alt,v,TYPEVECTOR_SIZE(size)); + dst->alt->alt = NULL; + dst->alt->k = dst->k + 1; +} + +typevector * +typevectorset_select(typevector **set,int retindex,void *retaddr) +{ + typevector *selected; + + if (!*set) return NULL; + + if (TYPEINFO_RETURNADDRESS((*set)->td[retindex].info) == retaddr) { + selected = *set; + *set = selected->alt; + selected->alt = typevectorset_select(set,retindex,retaddr); + } + else { + selected = typevectorset_select(&((*set)->alt),retindex,retaddr); + } + return selected; +} + +bool +typevectorset_separable_with(typevector *set,typevector *add,int size) +{ + int i; + typevector *v; + void *addr; + bool separable; + + for (i=0; itd[i])) + continue; + addr = TYPEINFO_RETURNADDRESS(add->td[i].info); + + v = set; + separable = false; + do { + if (!TYPEDESC_IS_RETURNADDRESS(v->td[i])) + goto next_index; + if (TYPEINFO_RETURNADDRESS(v->td[i].info) != addr) + separable = true; + v = v->alt; + if (!v && separable) return true; + } while (v); + next_index: + ; + } + return false; +} + +bool +typevectorset_collapse(typevector *dst,int size) +{ + bool changed = false; + + while (dst->alt) { + typevector_merge(dst,dst->alt,size); + dst->alt = dst->alt->alt; + changed = true; + } + return changed; +} + /**********************************************************************/ /* READ-ONLY FUNCTIONS */ /* The following functions don't change typeinfo data. */ @@ -88,11 +366,18 @@ interface_extends_interface(classinfo *cls,classinfo *interf) return false; } -/* XXX If really a performance issue, this could become a macro. */ static bool classinfo_implements_interface(classinfo *cls,classinfo *interf) { + if (!cls->loaded) + if (!class_load(cls)) + return false; + + if (!cls->linked) + if (!class_link(cls)) + return false; + if (cls->flags & ACC_INTERFACE) { /* cls is an interface */ if (cls == interf) @@ -150,24 +435,42 @@ merged_implements_interface(classinfo *typeclass,typeinfo_mergedlist *merged, bool typeinfo_is_assignable(typeinfo *value,typeinfo *dest) { - classinfo *cls; - - cls = value->typeclass; - /* DEBUG CHECK: dest must not have a merged list. */ #ifdef TYPEINFO_DEBUG if (dest->merged) panic("Internal error: typeinfo_is_assignable on merged destination."); #endif - + + return typeinfo_is_assignable_to_classinfo(value,dest->typeclass); +} + +bool +typeinfo_is_assignable_to_classinfo(typeinfo *value,classinfo *dest) +{ + classinfo *cls; + + cls = value->typeclass; + /* assignments of primitive values are not checked here. */ - if (!cls && !dest->typeclass) + if (!cls && !dest) return true; /* primitive and reference types are not assignment compatible. */ - if (!cls || !dest->typeclass) + if (!cls || !dest) return false; + /* maybe we need to load and link the class */ + if (!cls->loaded) + class_load(cls); + + if (!cls->linked) + class_link(cls); + +#ifdef TYPEINFO_DEBUG + if (!dest->linked) + panic("Internal error: typeinfo_is_assignable_to_classinfo: unlinked class."); +#endif + /* the null type can be assigned to any type */ if (TYPEINFO_IS_NULLTYPE(*value)) return true; @@ -176,13 +479,17 @@ typeinfo_is_assignable(typeinfo *value,typeinfo *dest) if (TYPEINFO_IS_NEWOBJECT(*value)) return false; - if (dest->typeclass->flags & ACC_INTERFACE) { + if (dest->flags & ACC_INTERFACE) { /* We are assigning to an interface type. */ - return merged_implements_interface(cls,value->merged, - dest->typeclass); + return merged_implements_interface(cls,value->merged,dest); } - if (TYPEINFO_IS_ARRAY(*dest)) { + if (CLASS_IS_ARRAY(dest)) { + arraydescriptor *arraydesc = dest->vftbl->arraydesc; + int dimension = arraydesc->dimension; + classinfo *elementclass = (arraydesc->elementvftbl) + ? arraydesc->elementvftbl->class : NULL; + /* We are assigning to an array type. */ if (!TYPEINFO_IS_ARRAY(*value)) return false; @@ -190,27 +497,29 @@ typeinfo_is_assignable(typeinfo *value,typeinfo *dest) /* {Both value and dest are array types.} */ /* value must have at least the dimension of dest. */ - if (value->dimension < dest->dimension) + if (value->dimension < dimension) return false; - if (value->dimension > dest->dimension) { + if (value->dimension > dimension) { /* value has higher dimension so we need to check * if its component array can be assigned to the * element type of dest */ + + if (!elementclass) return false; - if (dest->elementclass->flags & ACC_INTERFACE) { + if (elementclass->flags & ACC_INTERFACE) { /* We are assigning to an interface type. */ return classinfo_implements_interface(pseudo_class_Arraystub, - dest->elementclass); + elementclass); } /* We are assigning to a class type. */ - return class_issubclass(pseudo_class_Arraystub,dest->elementclass); + return class_issubclass(pseudo_class_Arraystub,elementclass); } /* {value and dest have the same dimension} */ - if (value->elementtype != dest->elementtype) + if (value->elementtype != arraydesc->elementtype) return false; if (value->elementclass) { @@ -218,16 +527,16 @@ typeinfo_is_assignable(typeinfo *value,typeinfo *dest) * check if the elements are assignable. */ - if (dest->elementclass->flags & ACC_INTERFACE) { + if (elementclass->flags & ACC_INTERFACE) { /* We are assigning to an interface type. */ return merged_implements_interface(value->elementclass, value->merged, - dest->elementclass); + elementclass); } /* We are assigning to a class type. */ - return class_issubclass(value->elementclass,dest->elementclass); + return class_issubclass(value->elementclass,elementclass); } return true; @@ -239,7 +548,7 @@ typeinfo_is_assignable(typeinfo *value,typeinfo *dest) if (cls->flags & ACC_INTERFACE) cls = class_java_lang_Object; - return class_issubclass(cls,dest->typeclass); + return class_issubclass(cls,dest); } /**********************************************************************/ @@ -253,103 +562,48 @@ typeinfo_init_from_descriptor(typeinfo *info,char *utf_ptr,char *end_ptr) classinfo *cls; char *end; - /* XXX simplify */ - cls = class_from_descriptor(utf_ptr,end_ptr,&end,CLASSLOAD_NEW); - - if (!cls) - panic("Invalid descriptor."); - - switch (*utf_ptr) { - case 'L': - case '[': - /* a class, interface or array descriptor */ - TYPEINFO_INIT_CLASSINFO(*info,cls); - break; - default: - /* a primitive type */ - TYPEINFO_INIT_PRIMITIVE(*info); - } - - /* exceeding characters */ - if (end!=end_ptr) panic ("descriptor has exceeding chars"); + cls = class_from_descriptor(utf_ptr,end_ptr,&end, + CLASSLOAD_NULLPRIMITIVE + | CLASSLOAD_NEW + | CLASSLOAD_NOVOID + | CLASSLOAD_CHECKEND); + + if (cls) { + if (!cls->loaded) + class_load(cls); + + if (!cls->linked) + class_link(cls); + + /* a class, interface or array descriptor */ + TYPEINFO_INIT_CLASSINFO(*info,cls); + } else { + /* a primitive type */ + TYPEINFO_INIT_PRIMITIVE(*info); + } } -/* XXX delete or use SKIP_FIELDDESCRIPTOR_SAFE */ int typeinfo_count_method_args(utf *d,bool twoword) { int args = 0; char *utf_ptr = d->text; char *end_pos = utf_end(d); - char c,ch; + char c; /* method descriptor must start with parenthesis */ if (*utf_ptr++ != '(') panic ("Missing '(' in method descriptor"); + /* check arguments */ - while ((c = *utf_ptr++) != ')') { - switch (c) { - case 'B': - case 'C': - case 'I': - case 'S': - case 'Z': - case 'F': - /* primitive one-word type */ - args++; - break; - - case 'J': - case 'D': - /* primitive two-word type */ - args++; - if (twoword) args++; - break; - - case 'L': - /* skip classname */ - while ( *utf_ptr++ != ';' ) - if (utf_ptr>=end_pos) - panic ("Missing ';' in objecttype-descriptor"); - - args++; - break; - - case '[' : - /* array type */ - while ((ch = *utf_ptr++)=='[') - /* skip */ ; - - /* component type of array */ - switch (ch) { - case 'B': - case 'C': - case 'I': - case 'S': - case 'Z': - case 'J': - case 'F': - case 'D': - /* primitive type */ - break; - - case 'L': - /* skip classname */ - while ( *utf_ptr++ != ';' ) - if (utf_ptr>=end_pos) - panic ("Missing ';' in objecttype-descriptor"); - break; - - default: - panic ("Ill formed methodtype-descriptor"); - } - - args++; - break; - - default: - panic ("Ill formed methodtype-descriptor"); - } + while ((c = *utf_ptr) != ')') { + class_from_descriptor(utf_ptr,end_pos,&utf_ptr, + CLASSLOAD_SKIP | CLASSLOAD_NOVOID + | CLASSLOAD_NULLPRIMITIVE); + args++; + if (twoword && (c == 'J' || c == 'D')) + /* primitive two-word type */ + args++; } return args; @@ -362,124 +616,138 @@ typeinfo_init_from_method_args(utf *desc,u1 *typebuf,typeinfo *infobuf, { char *utf_ptr = desc->text; /* current position in utf text */ char *end_pos = utf_end(desc); /* points behind utf string */ - char c; int args = 0; classinfo *cls; /* method descriptor must start with parenthesis */ - if (*utf_ptr++ != '(') panic ("Missing '(' in method descriptor"); + if (utf_ptr == end_pos || *utf_ptr++ != '(') panic ("Missing '(' in method descriptor"); /* check arguments */ - while ((c = *utf_ptr) != ')') { - /* XXX simplify */ - cls = class_from_descriptor(utf_ptr,end_pos,&utf_ptr,CLASSLOAD_NEW); - if (!cls) - panic("Invalid method descriptor."); - - switch (c) { - case 'B': - case 'C': - case 'I': - case 'S': - case 'Z': - case 'F': - /* primitive one-word type */ - if (++args > buflen) - panic("Buffer too small for method arguments."); - if (typebuf) - *typebuf++ = (c == 'F') ? TYPE_FLOAT : TYPE_INT; /* XXX TYPE_FLT? */ - TYPEINFO_INIT_PRIMITIVE(*infobuf); - infobuf++; - break; - - case 'J': - case 'D': - /* primitive two-word type */ - if (++args > buflen) - panic("Buffer too small for method arguments."); - if (typebuf) - *typebuf++ = (c == 'J') ? TYPE_LONG : TYPE_DOUBLE; /* XXX TYPE_DBL? */ - TYPEINFO_INIT_PRIMITIVE(*infobuf); - infobuf++; - if (twoword) { - if (++args > buflen) - panic("Buffer too small for method arguments."); - if (typebuf) - *typebuf++ = TYPE_VOID; - TYPEINFO_INIT_PRIMITIVE(*infobuf); - infobuf++; - } - break; - - case 'L': - case '[' : - /* reference type */ - - if (++args > buflen) - panic("Buffer too small for method arguments."); - if (typebuf) - *typebuf++ = TYPE_ADDRESS; - - TYPEINFO_INIT_CLASSINFO(*infobuf,cls); - infobuf++; - break; - - default: - panic ("Ill formed methodtype-descriptor (type)"); - } + while (utf_ptr != end_pos && *utf_ptr != ')') { + if (++args > buflen) + panic("Buffer too small for method arguments."); + + *typebuf++ = type_from_descriptor(&cls,utf_ptr,end_pos,&utf_ptr, + CLASSLOAD_NEW + | CLASSLOAD_NULLPRIMITIVE + | CLASSLOAD_NOVOID); + + if (cls) { + if (!cls->loaded) + class_load(cls); + + if (!cls->linked) + class_link(cls); + + TYPEINFO_INIT_CLASSINFO(*infobuf, cls); + + } else { + TYPEINFO_INIT_PRIMITIVE(*infobuf); + } + infobuf++; + + if (twoword && (typebuf[-1] == TYPE_LONG || typebuf[-1] == TYPE_DOUBLE)) { + if (++args > buflen) + panic("Buffer too small for method arguments."); + *typebuf++ = TYPE_VOID; + TYPEINFO_INIT_PRIMITIVE(*infobuf); + infobuf++; + } } utf_ptr++; /* skip ')' */ /* check returntype */ if (returntype) { - switch (*utf_ptr) { - case 'B': - case 'C': - case 'I': - case 'S': - case 'Z': - *returntype = TYPE_INT; - goto primitive_tail; - - case 'J': - *returntype = TYPE_LONG; - goto primitive_tail; - - case 'F': - *returntype = TYPE_FLOAT; - goto primitive_tail; - - case 'D': - *returntype = TYPE_DOUBLE; - goto primitive_tail; - - case 'V': - *returntype = TYPE_VOID; - primitive_tail: - if ((utf_ptr+1) != end_pos) - panic ("Method-descriptor has exceeding chars"); - if (returntypeinfo) { - TYPEINFO_INIT_PRIMITIVE(*returntypeinfo); - } - break; + *returntype = type_from_descriptor(&cls,utf_ptr,end_pos,&utf_ptr, + CLASSLOAD_NULLPRIMITIVE + | CLASSLOAD_NEW + | CLASSLOAD_CHECKEND); + + if (returntypeinfo) { + if (cls) { + if (!cls->loaded) + class_load(cls); + + if (!cls->linked) + class_link(cls); + + TYPEINFO_INIT_CLASSINFO(*returntypeinfo, cls); + + } else { + TYPEINFO_INIT_PRIMITIVE(*returntypeinfo); + } + } + } +} - case 'L': - case '[': - *returntype = TYPE_ADDRESS; - cls = class_from_descriptor(utf_ptr,end_pos,&utf_ptr,CLASSLOAD_NEW); - if (!cls) - panic("Invalid return type"); - if (utf_ptr != end_pos) - panic ("Method-descriptor has exceeding chars"); - if (returntypeinfo) { - TYPEINFO_INIT_CLASSINFO(*returntypeinfo,cls); - } - break; +int +typedescriptors_init_from_method_args(typedescriptor *td, + utf *desc, + int buflen,bool twoword, + typedescriptor *returntype) +{ + char *utf_ptr = desc->text; /* current position in utf text */ + char *end_pos = utf_end(desc); /* points behind utf string */ + int args = 0; + classinfo *cls; - default: - panic ("Ill formed methodtype-descriptor (returntype)"); - } + /* method descriptor must start with parenthesis */ + if (utf_ptr == end_pos || *utf_ptr++ != '(') panic ("Missing '(' in method descriptor"); + + /* check arguments */ + while (utf_ptr != end_pos && *utf_ptr != ')') { + if (++args > buflen) + panic("Buffer too small for method arguments."); + + td->type = type_from_descriptor(&cls,utf_ptr,end_pos,&utf_ptr, + CLASSLOAD_NEW + | CLASSLOAD_NULLPRIMITIVE + | CLASSLOAD_NOVOID); + + if (cls) { + if (!cls->loaded) + class_load(cls); + + if (!cls->linked) + class_link(cls); + + TYPEINFO_INIT_CLASSINFO(td->info, cls); + + } else { + TYPEINFO_INIT_PRIMITIVE(td->info); + } + td++; + + if (twoword && (td[-1].type == TYPE_LONG || td[-1].type == TYPE_DOUBLE)) { + if (++args > buflen) + panic("Buffer too small for method arguments."); + td->type = TYPE_VOID; + TYPEINFO_INIT_PRIMITIVE(td->info); + td++; + } } + utf_ptr++; /* skip ')' */ + + /* check returntype */ + if (returntype) { + returntype->type = type_from_descriptor(&cls,utf_ptr,end_pos,&utf_ptr, + CLASSLOAD_NULLPRIMITIVE + | CLASSLOAD_NEW + | CLASSLOAD_CHECKEND); + if (cls) { + if (!cls->loaded) + class_load(cls); + + if (!cls->linked) + class_link(cls); + + TYPEINFO_INIT_CLASSINFO(returntype->info,cls); + + } else { + TYPEINFO_INIT_PRIMITIVE(returntype->info); + } + } + return args; } void @@ -492,7 +760,6 @@ typeinfo_init_component(typeinfo *srcarray,typeinfo *dst) return; } - /* XXX find component class */ if (!TYPEINFO_IS_ARRAY(*srcarray)) panic("Trying to access component of non-array"); @@ -503,20 +770,6 @@ typeinfo_init_component(typeinfo *srcarray,typeinfo *dst) else { TYPEINFO_INIT_PRIMITIVE(*dst); } - - /* XXX assign directly ? */ -#if 0 - if ((dst->dimension = srcarray->dimension - 1) == 0) { - dst->typeclass = srcarray->elementclass; - dst->elementtype = 0; - dst->elementclass = NULL; - } - else { - dst->typeclass = srcarray->typeclass; - dst->elementtype = srcarray->elementtype; - dst->elementclass = srcarray->elementclass; - } -#endif dst->merged = srcarray->merged; } @@ -537,7 +790,6 @@ typeinfo_clone(typeinfo *src,typeinfo *dest) TYPEINFO_ALLOCMERGED(dest->merged,count); dest->merged->count = count; - /* XXX use memcpy? */ srclist = src->merged->list; destlist = dest->merged->list; while (count--) @@ -772,7 +1024,7 @@ typeinfo_merge_nonarrays(typeinfo *dest, typeinfo_mergedlist *tmerged; bool changed; - /* XXX remove */ + /* DEBUG */ /* #ifdef TYPEINFO_DEBUG typeinfo dbgx,dbgy; @@ -787,19 +1039,36 @@ typeinfo_merge_nonarrays(typeinfo *dest, #endif */ + /* check clsx */ + if (!clsx->loaded) + if (!class_load(clsx)) + return false; + + if (!clsx->linked) + if (!class_link(clsx)) + return false; + + /* check clsy */ + if (!clsy->loaded) + if (!class_load(clsy)) + return false; + + if (!clsy->linked) + if (!class_link(clsy)) + return false; + /* Common case: clsx == clsy */ /* (This case is very simple unless *both* x and y really represent * merges of subclasses of clsx==clsy.) */ - /* XXX count this case for statistics */ if ((clsx == clsy) && (!mergedx || !mergedy)) { return_simple_x: - /* XXX remove */ /* log_text("return simple x"); */ + /* DEBUG */ /* log_text("return simple x"); */ changed = (dest->merged != NULL); TYPEINFO_FREEMERGED_IF_ANY(dest->merged); dest->merged = NULL; *result = clsx; - /* XXX remove */ /* log_text("returning"); */ + /* DEBUG */ /* log_text("returning"); */ return changed; } @@ -817,7 +1086,6 @@ typeinfo_merge_nonarrays(typeinfo *dest, if (clsy->flags & ACC_INTERFACE) { /* We are merging two interfaces. */ /* {mergedy == NULL} */ - /* XXX: should we optimize direct superinterfaces? */ /* {We know that clsx!=clsy (see common case at beginning.)} */ *result = class_java_lang_Object; @@ -851,7 +1119,7 @@ typeinfo_merge_nonarrays(typeinfo *dest, * by y, too, so we have to add clsx to the mergedlist. */ - /* XXX if x has no superinterfaces we could return a simple java.lang.Object */ + /* if x has no superinterfaces we could return a simple java.lang.Object */ common = class_java_lang_Object; goto merge_with_simple_x; @@ -916,7 +1184,7 @@ typeinfo_merge(typeinfo *dest,typeinfo* y) int elementtype; bool changed; - /* XXX remove */ + /* DEBUG */ /* #ifdef TYPEINFO_DEBUG typeinfo_print(stdout,dest,4); @@ -929,10 +1197,16 @@ typeinfo_merge(typeinfo *dest,typeinfo* y) return false; /* Merging two returnAddress types is ok. */ - if (!dest->typeclass && !y->typeclass) + if (!dest->typeclass && !y->typeclass) { +#ifdef TYPEINFO_DEBUG + if (TYPEINFO_RETURNADDRESS(*dest) != TYPEINFO_RETURNADDRESS(*y)) + panic("Internal error: typeinfo_merge merges different returnAddresses"); +#endif return false; + } /* Primitive types cannot be merged with reference types */ + /* XXX only check this in debug mode? */ if (!dest->typeclass || !y->typeclass) typeinfo_merge_error("Trying to merge primitive types.",dest,y); @@ -953,22 +1227,21 @@ typeinfo_merge(typeinfo *dest,typeinfo* y) return false; } - /* XXX remove */ /* log_text("Testing common case"); */ + /* DEBUG */ /* log_text("Testing common case"); */ /* Common case: class dest == class y */ /* (This case is very simple unless *both* dest and y really represent * merges of subclasses of class dest==class y.) */ - /* XXX count this case for statistics */ if ((dest->typeclass == y->typeclass) && (!dest->merged || !y->merged)) { changed = (dest->merged != NULL); - TYPEINFO_FREEMERGED_IF_ANY(dest->merged); /* XXX unify if? */ + TYPEINFO_FREEMERGED_IF_ANY(dest->merged); /* unify if? */ dest->merged = NULL; - /* XXX remove */ /* log_text("common case handled"); */ + /* DEBUG */ /* log_text("common case handled"); */ return changed; } - /* XXX remove */ /* log_text("Handling null types"); */ + /* DEBUG */ /* log_text("Handling null types"); */ /* Handle null types: */ if (TYPEINFO_IS_NULLTYPE(*y)) { @@ -988,7 +1261,7 @@ typeinfo_merge(typeinfo *dest,typeinfo* y) /* Handle merging of arrays: */ if (TYPEINFO_IS_ARRAY(*x) && TYPEINFO_IS_ARRAY(*y)) { - /* XXX remove */ /* log_text("Handling arrays"); */ + /* DEBUG */ /* log_text("Handling arrays"); */ /* Make x the one with lesser dimension */ if (x->dimension > y->dimension) { @@ -1037,10 +1310,9 @@ typeinfo_merge(typeinfo *dest,typeinfo* y) elementclass, x->merged,y->merged); - /* XXX otimize this? */ - /* XXX remove */ /* log_text("finding resulting array class: "); */ + /* DEBUG */ /* log_text("finding resulting array class: "); */ common = class_multiarray_of(dimension,elementclass); - /* XXX remove */ /* utf_display(common->name); printf("\n"); */ + /* DEBUG */ /* utf_display(common->name); printf("\n"); */ } } } @@ -1077,7 +1349,7 @@ typeinfo_merge(typeinfo *dest,typeinfo* y) changed = true; } - /* XXX remove */ /* log_text("returning from merge"); */ + /* DEBUG */ /* log_text("returning from merge"); */ return changed; } @@ -1229,6 +1501,7 @@ typeinfo_testrun(char *filename) int maxdim; int failed = 0; FILE *file = fopen(filename,"rt"); + int res; if (!file) panic("could not open typeinfo test file"); @@ -1237,7 +1510,7 @@ typeinfo_testrun(char *filename) if (buf[0] == '#' || !strlen(buf)) continue; - int res = sscanf(buf,"%s\t%s\t%s\n",bufa,bufb,bufc); + res = sscanf(buf,"%s\t%s\t%s\n",bufa,bufb,bufc); if (res != 3 || !strlen(bufa) || !strlen(bufb) || !strlen(bufc)) panic("Invalid line in typeinfo test file (none of empty, comment or test)"); @@ -1294,6 +1567,7 @@ typeinfo_print(FILE *file,typeinfo *info,int indent) int i; char ind[TYPEINFO_MAXINDENT + 1]; instruction *ins; + basicblock *bptr; if (indent > TYPEINFO_MAXINDENT) indent = TYPEINFO_MAXINDENT; @@ -1302,7 +1576,11 @@ typeinfo_print(FILE *file,typeinfo *info,int indent) ind[i] = (char) 0; if (TYPEINFO_IS_PRIMITIVE(*info)) { - fprintf(file,"%sprimitive\n",ind); + bptr = (basicblock*) TYPEINFO_RETURNADDRESS(*info); + if (bptr) + fprintf(file,"%sreturnAddress (L%03d)\n",ind,bptr->debug_nr); + else + fprintf(file,"%sprimitive\n",ind); return; } @@ -1367,9 +1645,14 @@ typeinfo_print_short(FILE *file,typeinfo *info) { int i; instruction *ins; + basicblock *bptr; if (TYPEINFO_IS_PRIMITIVE(*info)) { - fprintf(file,"primitive"); + bptr = (basicblock*) TYPEINFO_RETURNADDRESS(*info); + if (bptr) + fprintf(file,"ret(L%03d)",bptr->debug_nr); + else + fprintf(file,"primitive"); return; } @@ -1411,11 +1694,7 @@ typeinfo_print_type(FILE *file,int type,typeinfo *info) case TYPE_DOUBLE: fprintf(file,"D"); break; case TYPE_LONG: fprintf(file,"J"); break; case TYPE_ADDRESS: - if (TYPEINFO_IS_PRIMITIVE(*info)) - fprintf(file,"R"); /* returnAddress */ - else { - typeinfo_print_short(file,info); - } + typeinfo_print_short(file,info); break; default: @@ -1423,6 +1702,68 @@ typeinfo_print_type(FILE *file,int type,typeinfo *info) } } +void +typeinfo_print_stacktype(FILE *file,int type,typeinfo *info) +{ + if (type == TYPE_ADDRESS && TYPEINFO_IS_PRIMITIVE(*info)) { + typeinfo_retaddr_set *set = (typeinfo_retaddr_set*) + TYPEINFO_RETURNADDRESS(*info); + fprintf(file,"ret(L%03d",((basicblock*)(set->addr))->debug_nr); + set = set->alt; + while (set) { + fprintf(file,"|L%03d",((basicblock*)(set->addr))->debug_nr); + set = set->alt; + } + fprintf(file,")"); + } + else + typeinfo_print_type(file,type,info); +} + +void +typedescriptor_print(FILE *file,typedescriptor *td) +{ + typeinfo_print_type(file,td->type,&(td->info)); +} + +void +typevector_print(FILE *file,typevector *vec,int size) +{ + int i; + + fprintf(file,"[%d]",vec->k); + for (i=0; ik); + vec = set->alt; + while (vec) { + fprintf(file,"|%d",vec->k); + vec = vec->alt; + } + fprintf(file,"]"); + + for (i=0; itd + i); + vec = vec->alt; + } + } +} + #endif /* TYPEINFO_DEBUG */