1 /* typeinfo.c - type system used by the type checker
3 Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003
4 R. Grafl, A. Krall, C. Kruegel, C. Oates, R. Obermaisser,
5 M. Probst, S. Ring, E. Steiner, C. Thalinger, D. Thuernbeck,
6 P. Tomsich, J. Wenninger
8 This file is part of CACAO.
10 This program is free software; you can redistribute it and/or
11 modify it under the terms of the GNU General Public License as
12 published by the Free Software Foundation; either version 2, or (at
13 your option) any later version.
15 This program is distributed in the hope that it will be useful, but
16 WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 General Public License for more details.
20 You should have received a copy of the GNU General Public License
21 along with this program; if not, write to the Free Software
22 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
25 Contact: cacao@complang.tuwien.ac.at
27 Authors: Edwin Steiner
29 $Id: typeinfo.c 1296 2004-07-10 17:02:15Z stefan $
39 #include "toolbox/logging.h"
40 #include "toolbox/memory.h"
41 #include "jit/jit.h" /* XXX move typeinfo.* into jit/ */
44 #define CLASS_IMPLEMENTS_INTERFACE(cls,index) \
45 ( ((index) < (cls)->vftbl->interfacetablelength) \
46 && (VFTBLINTERFACETABLE((cls)->vftbl,(index)) != NULL) )
48 /**********************************************************************/
49 /* TYPEVECTOR FUNCTIONS */
50 /**********************************************************************/
53 typevectorset_copy(typevector *src,int k,int size)
55 typevector *dst = DNEW_TYPEVECTOR(size);
57 memcpy(dst,src,TYPEVECTOR_SIZE(size));
60 dst->alt = typevectorset_copy(src->alt,k+1,size);
65 typevectorset_checktype(typevector *vec,int index,int type)
68 if (vec->td[index].type != type)
70 } while ((vec = vec->alt) != NULL);
75 typevectorset_checkreference(typevector *vec,int index)
78 if (!TYPEDESC_IS_REFERENCE(vec->td[index]))
80 } while ((vec = vec->alt) != NULL);
85 typevectorset_checkretaddr(typevector *vec,int index)
88 if (!TYPEDESC_IS_RETURNADDRESS(vec->td[index]))
90 } while ((vec = vec->alt) != NULL);
95 typevectorset_copymergedtype(typevector *vec,int index,typeinfo *dst)
100 td = vec->td + index;
102 TYPEINFO_COPY(td->info,*dst);
107 primitive = TYPEINFO_IS_PRIMITIVE(*dst) ? 1 : 0;
109 while ((vec = vec->alt) != NULL) {
110 td = vec->td + index;
111 if (type != td->type)
114 if (type == TYPE_ADDRESS) {
115 if ((TYPEINFO_IS_PRIMITIVE(td->info) ? 1 : 0) != primitive)
117 typeinfo_merge(dst,&(td->info));
125 typevectorset_mergedtype(typevector *vec,int index,typeinfo *temp,typeinfo **result)
129 return typevectorset_copymergedtype(vec,index,temp);
132 *result = &(vec->td[index].info);
133 return vec->td[index].type;
137 typevectorset_mergedtypeinfo(typevector *vec,int index,typeinfo *temp)
140 int type = typevectorset_mergedtype(vec,index,temp,&result);
141 return (type == TYPE_ADDRESS) ? result : NULL;
145 typevectorset_store(typevector *vec,int index,int type,typeinfo *info)
148 vec->td[index].type = type;
150 TYPEINFO_COPY(*info,vec->td[index].info);
151 if (index > 0 && IS_2_WORD_TYPE(vec->td[index-1].type))
152 vec->td[index-1].type = TYPE_VOID;
153 } while ((vec = vec->alt) != NULL);
157 typevectorset_store_retaddr(typevector *vec,int index,typeinfo *info)
159 typeinfo_retaddr_set *adr;
161 adr = (typeinfo_retaddr_set*) TYPEINFO_RETURNADDRESS(*info);
163 vec->td[index].type = TYPE_ADDRESS;
164 TYPEINFO_INIT_RETURNADDRESS(vec->td[index].info,adr->addr);
165 if (index > 0 && IS_2_WORD_TYPE(vec->td[index-1].type))
166 vec->td[index-1].type = TYPE_VOID;
168 } while ((vec = vec->alt) != NULL);
172 typevectorset_store_twoword(typevector *vec,int index,int type)
175 vec->td[index].type = type;
176 vec->td[index+1].type = TYPE_VOID;
177 if (index > 0 && IS_2_WORD_TYPE(vec->td[index-1].type))
178 vec->td[index-1].type = TYPE_VOID;
179 } while ((vec = vec->alt) != NULL);
183 typevectorset_init_object(typevector *set,void *ins,classinfo *initclass,
188 for (;set; set=set->alt) {
189 for (i=0; i<size; ++i) {
190 if (set->td[i].type == TYPE_ADR
191 && TYPEINFO_IS_NEWOBJECT(set->td[i].info)
192 && TYPEINFO_NEWOBJECT_INSTRUCTION(set->td[i].info) == ins)
194 TYPEINFO_INIT_CLASSINFO(set->td[i].info,initclass);
201 typevector_merge(typevector *dst,typevector *y,int size)
203 bool changed = false;
205 typedescriptor *a = dst->td;
206 typedescriptor *b = y->td;
208 if (a->type != TYPE_VOID && a->type != b->type) {
212 else if (a->type == TYPE_ADDRESS) {
213 if (TYPEINFO_IS_PRIMITIVE(a->info)) {
214 /* 'a' is a returnAddress */
215 if (!TYPEINFO_IS_PRIMITIVE(b->info)
216 || (TYPEINFO_RETURNADDRESS(a->info)
217 != TYPEINFO_RETURNADDRESS(b->info)))
224 /* 'a' is a reference */
225 if (TYPEINFO_IS_PRIMITIVE(b->info)) {
230 changed |= typeinfo_merge(&(a->info),&(b->info));
240 bool typevector_separable_from(typevector *a,typevector *b,int size)
242 typedescriptor *tda = a->td;
243 typedescriptor *tdb = b->td;
244 for (;size--; tda++,tdb++) {
245 if (TYPEDESC_IS_RETURNADDRESS(*tda)
246 && TYPEDESC_IS_RETURNADDRESS(*tdb)
247 && TYPEINFO_RETURNADDRESS(tda->info)
248 != TYPEINFO_RETURNADDRESS(tdb->info))
255 typevectorset_add(typevector *dst,typevector *v,int size)
259 dst->alt = DNEW_TYPEVECTOR(size);
260 memcpy(dst->alt,v,TYPEVECTOR_SIZE(size));
261 dst->alt->alt = NULL;
262 dst->alt->k = dst->k + 1;
266 typevectorset_select(typevector **set,int retindex,void *retaddr)
268 typevector *selected;
270 if (!*set) return NULL;
272 if (TYPEINFO_RETURNADDRESS((*set)->td[retindex].info) == retaddr) {
274 *set = selected->alt;
275 selected->alt = typevectorset_select(set,retindex,retaddr);
278 selected = typevectorset_select(&((*set)->alt),retindex,retaddr);
284 typevectorset_separable_with(typevector *set,typevector *add,int size)
291 for (i=0; i<size; ++i) {
292 if (!TYPEDESC_IS_RETURNADDRESS(add->td[i]))
294 addr = TYPEINFO_RETURNADDRESS(add->td[i].info);
299 if (!TYPEDESC_IS_RETURNADDRESS(v->td[i]))
301 if (TYPEINFO_RETURNADDRESS(v->td[i].info) != addr)
304 if (!v && separable) return true;
313 typevectorset_collapse(typevector *dst,int size)
315 bool changed = false;
318 typevector_merge(dst,dst->alt,size);
319 dst->alt = dst->alt->alt;
325 /**********************************************************************/
326 /* READ-ONLY FUNCTIONS */
327 /* The following functions don't change typeinfo data. */
328 /**********************************************************************/
331 typeinfo_is_array(typeinfo *info)
333 return TYPEINFO_IS_ARRAY(*info);
337 typeinfo_is_primitive_array(typeinfo *info,int arraytype)
339 return TYPEINFO_IS_PRIMITIVE_ARRAY(*info,arraytype);
343 typeinfo_is_array_of_refs(typeinfo *info)
345 return TYPEINFO_IS_ARRAY_OF_REFS(*info);
350 interface_extends_interface(classinfo *cls,classinfo *interf)
354 /* first check direct superinterfaces */
355 for (i=0; i<cls->interfacescount; ++i) {
356 if (cls->interfaces[i] == interf)
360 /* check indirect superinterfaces */
361 for (i=0; i<cls->interfacescount; ++i) {
362 if (interface_extends_interface(cls->interfaces[i],interf))
371 classinfo_implements_interface(classinfo *cls,classinfo *interf)
374 if (!class_load(cls))
378 if (!class_link(cls))
381 if (cls->flags & ACC_INTERFACE) {
382 /* cls is an interface */
386 /* check superinterfaces */
387 return interface_extends_interface(cls,interf);
390 return CLASS_IMPLEMENTS_INTERFACE(cls,interf->index);
393 bool mergedlist_implements_interface(typeinfo_mergedlist *merged,
399 /* Check if there is an non-empty mergedlist. */
403 /* If all classinfos in the (non-empty) merged array implement the
404 * interface return true, otherwise false.
406 mlist = merged->list;
409 if (!classinfo_implements_interface(*mlist++,interf))
416 merged_implements_interface(classinfo *typeclass,typeinfo_mergedlist *merged,
419 /* primitive types don't support interfaces. */
423 /* the null type can be cast to any interface type. */
424 if (typeclass == pseudo_class_Null)
427 /* check if typeclass implements the interface. */
428 if (classinfo_implements_interface(typeclass,interf))
431 /* check the mergedlist */
432 return (merged && mergedlist_implements_interface(merged,interf));
436 typeinfo_is_assignable(typeinfo *value,typeinfo *dest)
438 /* DEBUG CHECK: dest must not have a merged list. */
439 #ifdef TYPEINFO_DEBUG
441 panic("Internal error: typeinfo_is_assignable on merged destination.");
444 return typeinfo_is_assignable_to_classinfo(value,dest->typeclass);
448 typeinfo_is_assignable_to_classinfo(typeinfo *value,classinfo *dest)
452 cls = value->typeclass;
454 /* assignments of primitive values are not checked here. */
458 /* primitive and reference types are not assignment compatible. */
462 /* maybe we need to load and link the class */
469 #ifdef TYPEINFO_DEBUG
471 panic("Internal error: typeinfo_is_assignable_to_classinfo: unlinked class.");
474 /* the null type can be assigned to any type */
475 if (TYPEINFO_IS_NULLTYPE(*value))
478 /* uninitialized objects are not assignable */
479 if (TYPEINFO_IS_NEWOBJECT(*value))
482 if (dest->flags & ACC_INTERFACE) {
483 /* We are assigning to an interface type. */
484 return merged_implements_interface(cls,value->merged,dest);
487 if (CLASS_IS_ARRAY(dest)) {
488 arraydescriptor *arraydesc = dest->vftbl->arraydesc;
489 int dimension = arraydesc->dimension;
490 classinfo *elementclass = (arraydesc->elementvftbl)
491 ? arraydesc->elementvftbl->class : NULL;
493 /* We are assigning to an array type. */
494 if (!TYPEINFO_IS_ARRAY(*value))
497 /* {Both value and dest are array types.} */
499 /* value must have at least the dimension of dest. */
500 if (value->dimension < dimension)
503 if (value->dimension > dimension) {
504 /* value has higher dimension so we need to check
505 * if its component array can be assigned to the
506 * element type of dest */
508 if (!elementclass) return false;
510 if (elementclass->flags & ACC_INTERFACE) {
511 /* We are assigning to an interface type. */
512 return classinfo_implements_interface(pseudo_class_Arraystub,
516 /* We are assigning to a class type. */
517 return class_issubclass(pseudo_class_Arraystub,elementclass);
520 /* {value and dest have the same dimension} */
522 if (value->elementtype != arraydesc->elementtype)
525 if (value->elementclass) {
526 /* We are assigning an array of objects so we have to
527 * check if the elements are assignable.
530 if (elementclass->flags & ACC_INTERFACE) {
531 /* We are assigning to an interface type. */
533 return merged_implements_interface(value->elementclass,
538 /* We are assigning to a class type. */
539 return class_issubclass(value->elementclass,elementclass);
545 /* {dest is not an array} */
547 /* We are assigning to a class type */
548 if (cls->flags & ACC_INTERFACE)
549 cls = class_java_lang_Object;
551 return class_issubclass(cls,dest);
554 /**********************************************************************/
555 /* INITIALIZATION FUNCTIONS */
556 /* The following functions fill in uninitialized typeinfo structures. */
557 /**********************************************************************/
560 typeinfo_init_from_descriptor(typeinfo *info,char *utf_ptr,char *end_ptr)
565 cls = class_from_descriptor(utf_ptr,end_ptr,&end,
566 CLASSLOAD_NULLPRIMITIVE
569 | CLASSLOAD_CHECKEND);
578 /* a class, interface or array descriptor */
579 TYPEINFO_INIT_CLASSINFO(*info,cls);
581 /* a primitive type */
582 TYPEINFO_INIT_PRIMITIVE(*info);
587 typeinfo_count_method_args(utf *d,bool twoword)
590 char *utf_ptr = d->text;
591 char *end_pos = utf_end(d);
594 /* method descriptor must start with parenthesis */
595 if (*utf_ptr++ != '(') panic ("Missing '(' in method descriptor");
598 /* check arguments */
599 while ((c = *utf_ptr) != ')') {
600 class_from_descriptor(utf_ptr,end_pos,&utf_ptr,
601 CLASSLOAD_SKIP | CLASSLOAD_NOVOID
602 | CLASSLOAD_NULLPRIMITIVE);
604 if (twoword && (c == 'J' || c == 'D'))
605 /* primitive two-word type */
613 typeinfo_init_from_method_args(utf *desc,u1 *typebuf,typeinfo *infobuf,
614 int buflen,bool twoword,
615 int *returntype,typeinfo *returntypeinfo)
617 char *utf_ptr = desc->text; /* current position in utf text */
618 char *end_pos = utf_end(desc); /* points behind utf string */
622 /* method descriptor must start with parenthesis */
623 if (utf_ptr == end_pos || *utf_ptr++ != '(') panic ("Missing '(' in method descriptor");
625 /* check arguments */
626 while (utf_ptr != end_pos && *utf_ptr != ')') {
628 panic("Buffer too small for method arguments.");
630 *typebuf++ = type_from_descriptor(&cls,utf_ptr,end_pos,&utf_ptr,
632 | CLASSLOAD_NULLPRIMITIVE
642 TYPEINFO_INIT_CLASSINFO(*infobuf, cls);
645 TYPEINFO_INIT_PRIMITIVE(*infobuf);
649 if (twoword && (typebuf[-1] == TYPE_LONG || typebuf[-1] == TYPE_DOUBLE)) {
651 panic("Buffer too small for method arguments.");
652 *typebuf++ = TYPE_VOID;
653 TYPEINFO_INIT_PRIMITIVE(*infobuf);
657 utf_ptr++; /* skip ')' */
659 /* check returntype */
661 *returntype = type_from_descriptor(&cls,utf_ptr,end_pos,&utf_ptr,
662 CLASSLOAD_NULLPRIMITIVE
664 | CLASSLOAD_CHECKEND);
666 if (returntypeinfo) {
674 TYPEINFO_INIT_CLASSINFO(*returntypeinfo, cls);
677 TYPEINFO_INIT_PRIMITIVE(*returntypeinfo);
684 typedescriptors_init_from_method_args(typedescriptor *td,
686 int buflen,bool twoword,
687 typedescriptor *returntype)
689 char *utf_ptr = desc->text; /* current position in utf text */
690 char *end_pos = utf_end(desc); /* points behind utf string */
694 /* method descriptor must start with parenthesis */
695 if (utf_ptr == end_pos || *utf_ptr++ != '(') panic ("Missing '(' in method descriptor");
697 /* check arguments */
698 while (utf_ptr != end_pos && *utf_ptr != ')') {
700 panic("Buffer too small for method arguments.");
702 td->type = type_from_descriptor(&cls,utf_ptr,end_pos,&utf_ptr,
704 | CLASSLOAD_NULLPRIMITIVE
714 TYPEINFO_INIT_CLASSINFO(td->info, cls);
717 TYPEINFO_INIT_PRIMITIVE(td->info);
721 if (twoword && (td[-1].type == TYPE_LONG || td[-1].type == TYPE_DOUBLE)) {
723 panic("Buffer too small for method arguments.");
724 td->type = TYPE_VOID;
725 TYPEINFO_INIT_PRIMITIVE(td->info);
729 utf_ptr++; /* skip ')' */
731 /* check returntype */
733 returntype->type = type_from_descriptor(&cls,utf_ptr,end_pos,&utf_ptr,
734 CLASSLOAD_NULLPRIMITIVE
736 | CLASSLOAD_CHECKEND);
744 TYPEINFO_INIT_CLASSINFO(returntype->info,cls);
747 TYPEINFO_INIT_PRIMITIVE(returntype->info);
754 typeinfo_init_component(typeinfo *srcarray,typeinfo *dst)
756 vftbl_t *comp = NULL;
758 if (TYPEINFO_IS_NULLTYPE(*srcarray)) {
759 TYPEINFO_INIT_NULLTYPE(*dst);
763 if (!TYPEINFO_IS_ARRAY(*srcarray))
764 panic("Trying to access component of non-array");
766 comp = srcarray->typeclass->vftbl->arraydesc->componentvftbl;
768 TYPEINFO_INIT_CLASSINFO(*dst,comp->class);
771 TYPEINFO_INIT_PRIMITIVE(*dst);
774 dst->merged = srcarray->merged;
778 typeinfo_clone(typeinfo *src,typeinfo *dest)
781 classinfo **srclist,**destlist;
789 count = src->merged->count;
790 TYPEINFO_ALLOCMERGED(dest->merged,count);
791 dest->merged->count = count;
793 srclist = src->merged->list;
794 destlist = dest->merged->list;
796 *destlist++ = *srclist++;
800 /**********************************************************************/
801 /* MISCELLANEOUS FUNCTIONS */
802 /**********************************************************************/
805 typeinfo_free(typeinfo *info)
807 TYPEINFO_FREEMERGED_IF_ANY(info->merged);
811 /**********************************************************************/
812 /* MERGING FUNCTIONS */
813 /* The following functions are used to merge the types represented by */
814 /* two typeinfo structures into one typeinfo structure. */
815 /**********************************************************************/
819 typeinfo_merge_error(char *str,typeinfo *x,typeinfo *y) {
820 #ifdef TYPEINFO_DEBUG
821 fprintf(stderr,"Error in typeinfo_merge: %s\n",str);
822 fprintf(stderr,"Typeinfo x:\n");
823 typeinfo_print(stderr,x,1);
824 fprintf(stderr,"Typeinfo y:\n");
825 typeinfo_print(stderr,y,1);
830 /* Condition: clsx != clsy. */
831 /* Returns: true if dest was changed (always true). */
834 typeinfo_merge_two(typeinfo *dest,classinfo *clsx,classinfo *clsy)
836 TYPEINFO_FREEMERGED_IF_ANY(dest->merged);
837 TYPEINFO_ALLOCMERGED(dest->merged,2);
838 dest->merged->count = 2;
840 #ifdef TYPEINFO_DEBUG
842 panic("Internal error: typeinfo_merge_two called with clsx==clsy.");
846 dest->merged->list[0] = clsx;
847 dest->merged->list[1] = clsy;
850 dest->merged->list[0] = clsy;
851 dest->merged->list[1] = clsx;
857 /* Returns: true if dest was changed. */
860 typeinfo_merge_add(typeinfo *dest,typeinfo_mergedlist *m,classinfo *cls)
863 typeinfo_mergedlist *newmerged;
864 classinfo **mlist,**newlist;
869 /* Check if cls is already in the mergedlist m. */
871 if (*mlist++ == cls) {
872 /* cls is in the list, so m is the resulting mergedlist */
873 if (dest->merged == m)
876 /* We have to copy the mergedlist */
877 TYPEINFO_FREEMERGED_IF_ANY(dest->merged);
879 TYPEINFO_ALLOCMERGED(dest->merged,count);
880 dest->merged->count = count;
881 newlist = dest->merged->list;
884 *newlist++ = *mlist++;
890 /* Add cls to the mergedlist. */
892 TYPEINFO_ALLOCMERGED(newmerged,count+1);
893 newmerged->count = count+1;
894 newlist = newmerged->list;
899 *newlist++ = *mlist++;
904 *newlist++ = *mlist++;
907 /* Put the new mergedlist into dest. */
908 TYPEINFO_FREEMERGED_IF_ANY(dest->merged);
909 dest->merged = newmerged;
914 /* Returns: true if dest was changed. */
917 typeinfo_merge_mergedlists(typeinfo *dest,typeinfo_mergedlist *x,
918 typeinfo_mergedlist *y)
922 typeinfo_mergedlist *temp,*result;
923 classinfo **clsx,**clsy,**newlist;
925 /* count the elements that will be in the resulting list */
926 /* (Both lists are sorted, equal elements are counted only once.) */
931 while (countx && county) {
932 if (*clsx == *clsy) {
938 else if (*clsx < *clsy) {
948 count += countx + county;
950 /* {The new mergedlist will have count entries.} */
952 if ((x->count != count) && (y->count == count)) {
953 temp = x; x = y; y = temp;
955 /* {If one of x,y is already the result it is x.} */
956 if (x->count == count) {
957 /* x->merged is equal to the result */
958 if (x == dest->merged)
961 if (!dest->merged || dest->merged->count != count) {
962 TYPEINFO_FREEMERGED_IF_ANY(dest->merged);
963 TYPEINFO_ALLOCMERGED(dest->merged,count);
964 dest->merged->count = count;
967 newlist = dest->merged->list;
970 *newlist++ = *clsx++;
975 /* {We have to merge two lists.} */
977 /* allocate the result list */
978 TYPEINFO_ALLOCMERGED(result,count);
979 result->count = count;
980 newlist = result->list;
982 /* merge the sorted lists */
987 while (countx && county) {
988 if (*clsx == *clsy) {
989 *newlist++ = *clsx++;
994 else if (*clsx < *clsy) {
995 *newlist++ = *clsx++;
999 *newlist++ = *clsy++;
1004 *newlist++ = *clsx++;
1006 *newlist++ = *clsy++;
1008 /* replace the list in dest with the result list */
1009 TYPEINFO_FREEMERGED_IF_ANY(dest->merged);
1010 dest->merged = result;
1017 typeinfo_merge_nonarrays(typeinfo *dest,
1019 classinfo *clsx,classinfo *clsy,
1020 typeinfo_mergedlist *mergedx,
1021 typeinfo_mergedlist *mergedy)
1023 classinfo *tcls,*common;
1024 typeinfo_mergedlist *tmerged;
1029 #ifdef TYPEINFO_DEBUG
1031 printf("typeinfo_merge_nonarrays:\n");
1032 TYPEINFO_INIT_CLASSINFO(dbgx,clsx);
1033 dbgx.merged = mergedx;
1034 TYPEINFO_INIT_CLASSINFO(dbgy,clsy);
1035 dbgy.merged = mergedy;
1036 typeinfo_print(stdout,&dbgx,4);
1038 typeinfo_print(stdout,&dbgy,4);
1044 if (!class_load(clsx))
1048 if (!class_link(clsx))
1053 if (!class_load(clsy))
1057 if (!class_link(clsy))
1060 /* Common case: clsx == clsy */
1061 /* (This case is very simple unless *both* x and y really represent
1062 * merges of subclasses of clsx==clsy.)
1064 if ((clsx == clsy) && (!mergedx || !mergedy)) {
1066 /* DEBUG */ /* log_text("return simple x"); */
1067 changed = (dest->merged != NULL);
1068 TYPEINFO_FREEMERGED_IF_ANY(dest->merged);
1069 dest->merged = NULL;
1071 /* DEBUG */ /* log_text("returning"); */
1075 /* If clsy is an interface, swap x and y. */
1076 if (clsy->flags & ACC_INTERFACE) {
1077 tcls = clsx; clsx = clsy; clsy = tcls;
1078 tmerged = mergedx; mergedx = mergedy; mergedy = tmerged;
1080 /* {We know: If only one of x,y is an interface it is x.} */
1082 /* Handle merging of interfaces: */
1083 if (clsx->flags & ACC_INTERFACE) {
1084 /* {clsx is an interface and mergedx == NULL.} */
1086 if (clsy->flags & ACC_INTERFACE) {
1087 /* We are merging two interfaces. */
1088 /* {mergedy == NULL} */
1090 /* {We know that clsx!=clsy (see common case at beginning.)} */
1091 *result = class_java_lang_Object;
1092 return typeinfo_merge_two(dest,clsx,clsy);
1095 /* {We know: x is an interface, clsy is a class.} */
1097 /* Check if we are merging an interface with java.lang.Object */
1098 if (clsy == class_java_lang_Object && !mergedy) {
1100 goto return_simple_x;
1104 /* If the type y implements clsx then the result of the merge
1105 * is clsx regardless of mergedy.
1108 if (CLASS_IMPLEMENTS_INTERFACE(clsy,clsx->index)
1109 || mergedlist_implements_interface(mergedy,clsx))
1111 /* y implements x, so the result of the merge is x. */
1112 goto return_simple_x;
1115 /* {We know: x is an interface, the type y a class or a merge
1116 * of subclasses and does not implement x.} */
1118 /* There may still be superinterfaces of x which are implemented
1119 * by y, too, so we have to add clsx to the mergedlist.
1122 /* if x has no superinterfaces we could return a simple java.lang.Object */
1124 common = class_java_lang_Object;
1125 goto merge_with_simple_x;
1128 /* {We know: x and y are classes (not interfaces).} */
1130 /* If *x is deeper in the inheritance hierarchy swap x and y. */
1131 if (clsx->index > clsy->index) {
1132 tcls = clsx; clsx = clsy; clsy = tcls;
1133 tmerged = mergedx; mergedx = mergedy; mergedy = tmerged;
1136 /* {We know: y is at least as deep in the hierarchy as x.} */
1138 /* Find nearest common anchestor for the classes. */
1141 while (tcls->index > common->index)
1143 while (common != tcls) {
1144 common = common->super;
1148 /* {common == nearest common anchestor of clsx and clsy.} */
1150 /* If clsx==common and x is a whole class (not a merge of subclasses)
1151 * then the result of the merge is clsx.
1153 if (clsx == common && !mergedx) {
1154 goto return_simple_x;
1160 return typeinfo_merge_mergedlists(dest,mergedx,mergedy);
1162 return typeinfo_merge_add(dest,mergedx,clsy);
1165 merge_with_simple_x:
1168 return typeinfo_merge_add(dest,mergedy,clsx);
1170 return typeinfo_merge_two(dest,clsx,clsy);
1173 /* Condition: *dest must be a valid initialized typeinfo. */
1174 /* Condition: dest != y. */
1175 /* Returns: true if dest was changed. */
1177 typeinfo_merge(typeinfo *dest,typeinfo* y)
1180 typeinfo *tmp; /* used for swapping */
1182 classinfo *elementclass;
1189 #ifdef TYPEINFO_DEBUG
1190 typeinfo_print(stdout,dest,4);
1191 typeinfo_print(stdout,y,4);
1195 /* Merging something with itself is a nop */
1199 /* Merging two returnAddress types is ok. */
1200 if (!dest->typeclass && !y->typeclass) {
1201 #ifdef TYPEINFO_DEBUG
1202 if (TYPEINFO_RETURNADDRESS(*dest) != TYPEINFO_RETURNADDRESS(*y))
1203 panic("Internal error: typeinfo_merge merges different returnAddresses");
1208 /* Primitive types cannot be merged with reference types */
1209 /* XXX only check this in debug mode? */
1210 if (!dest->typeclass || !y->typeclass)
1211 typeinfo_merge_error("Trying to merge primitive types.",dest,y);
1213 #ifdef TYPEINFO_DEBUG
1214 /* check that no unlinked classes are merged. */
1215 if (!dest->typeclass->linked || !y->typeclass->linked)
1216 typeinfo_merge_error("Trying to merge unlinked class(es).",dest,y);
1219 /* handle uninitialized object types */
1220 /* XXX is there a way we could put this after the common case? */
1221 if (TYPEINFO_IS_NEWOBJECT(*dest) || TYPEINFO_IS_NEWOBJECT(*y)) {
1222 if (!TYPEINFO_IS_NEWOBJECT(*dest) || !TYPEINFO_IS_NEWOBJECT(*y))
1223 typeinfo_merge_error("Trying to merge uninitialized object type.",dest,y);
1224 if (TYPEINFO_NEWOBJECT_INSTRUCTION(*dest)
1225 != TYPEINFO_NEWOBJECT_INSTRUCTION(*y))
1226 typeinfo_merge_error("Trying to merge different uninitialized objects.",dest,y);
1230 /* DEBUG */ /* log_text("Testing common case"); */
1232 /* Common case: class dest == class y */
1233 /* (This case is very simple unless *both* dest and y really represent
1234 * merges of subclasses of class dest==class y.)
1236 if ((dest->typeclass == y->typeclass) && (!dest->merged || !y->merged)) {
1237 changed = (dest->merged != NULL);
1238 TYPEINFO_FREEMERGED_IF_ANY(dest->merged); /* unify if? */
1239 dest->merged = NULL;
1240 /* DEBUG */ /* log_text("common case handled"); */
1244 /* DEBUG */ /* log_text("Handling null types"); */
1246 /* Handle null types: */
1247 if (TYPEINFO_IS_NULLTYPE(*y)) {
1250 if (TYPEINFO_IS_NULLTYPE(*dest)) {
1251 TYPEINFO_FREEMERGED_IF_ANY(dest->merged);
1252 TYPEINFO_CLONE(*y,*dest);
1256 /* This function uses x internally, so x and y can be swapped
1257 * without changing dest. */
1261 /* Handle merging of arrays: */
1262 if (TYPEINFO_IS_ARRAY(*x) && TYPEINFO_IS_ARRAY(*y)) {
1264 /* DEBUG */ /* log_text("Handling arrays"); */
1266 /* Make x the one with lesser dimension */
1267 if (x->dimension > y->dimension) {
1268 tmp = x; x = y; y = tmp;
1271 /* If one array (y) has higher dimension than the other,
1272 * interpret it as an array (same dim. as x) of Arraystubs. */
1273 if (x->dimension < y->dimension) {
1274 dimension = x->dimension;
1275 elementtype = ARRAYTYPE_OBJECT;
1276 elementclass = pseudo_class_Arraystub;
1279 dimension = y->dimension;
1280 elementtype = y->elementtype;
1281 elementclass = y->elementclass;
1284 /* {The arrays are of the same dimension.} */
1286 if (x->elementtype != elementtype) {
1287 /* Different element types are merged, so the resulting array
1288 * type has one accessible dimension less. */
1289 if (--dimension == 0) {
1290 common = pseudo_class_Arraystub;
1292 elementclass = NULL;
1295 common = class_multiarray_of(dimension,pseudo_class_Arraystub);
1296 elementtype = ARRAYTYPE_OBJECT;
1297 elementclass = pseudo_class_Arraystub;
1301 /* {The arrays have the same dimension and elementtype.} */
1303 if (elementtype == ARRAYTYPE_OBJECT) {
1304 /* The elements are references, so their respective
1305 * types must be merged.
1307 changed |= typeinfo_merge_nonarrays(dest,
1311 x->merged,y->merged);
1313 /* DEBUG */ /* log_text("finding resulting array class: "); */
1314 common = class_multiarray_of(dimension,elementclass);
1315 /* DEBUG */ /* utf_display(common->name); printf("\n"); */
1320 /* {We know that at least one of x or y is no array, so the
1321 * result cannot be an array.} */
1323 changed |= typeinfo_merge_nonarrays(dest,
1325 x->typeclass,y->typeclass,
1326 x->merged,y->merged);
1330 elementclass = NULL;
1333 /* Put the new values into dest if neccessary. */
1335 if (dest->typeclass != common) {
1336 dest->typeclass = common;
1339 if (dest->dimension != dimension) {
1340 dest->dimension = dimension;
1343 if (dest->elementtype != elementtype) {
1344 dest->elementtype = elementtype;
1347 if (dest->elementclass != elementclass) {
1348 dest->elementclass = elementclass;
1352 /* DEBUG */ /* log_text("returning from merge"); */
1358 /**********************************************************************/
1359 /* DEBUGGING HELPERS */
1360 /**********************************************************************/
1362 #ifdef TYPEINFO_DEBUG
1366 #include "jit/jit.h"
1368 extern instruction *instr;
1371 typeinfo_test_compare(classinfo **a,classinfo **b)
1373 if (*a == *b) return 0;
1374 if (*a < *b) return -1;
1379 typeinfo_test_parse(typeinfo *info,char *str)
1386 utf *desc = utf_new_char(str);
1388 num = typeinfo_count_method_args(desc,false);
1390 typebuf = DMNEW(u1,num);
1391 infobuf = DMNEW(typeinfo,num);
1393 typeinfo_init_from_method_args(desc,typebuf,infobuf,num,false,
1396 TYPEINFO_ALLOCMERGED(info->merged,num);
1397 info->merged->count = num;
1399 for (i=0; i<num; ++i) {
1400 if (typebuf[i] != TYPE_ADDRESS)
1401 panic("non-reference type in mergedlist");
1402 info->merged->list[i] = infobuf[i].typeclass;
1404 qsort(info->merged->list,num,sizeof(classinfo*),
1405 (int(*)(const void *,const void *))&typeinfo_test_compare);
1408 typeinfo_init_from_method_args(desc,NULL,NULL,0,false,
1413 #define TYPEINFO_TEST_BUFLEN 4000
1416 typeinfo_equal(typeinfo *x,typeinfo *y)
1420 if (x->typeclass != y->typeclass) return false;
1421 if (x->dimension != y->dimension) return false;
1423 if (x->elementclass != y->elementclass) return false;
1424 if (x->elementtype != y->elementtype) return false;
1427 if (TYPEINFO_IS_NEWOBJECT(*x))
1428 if (TYPEINFO_NEWOBJECT_INSTRUCTION(*x)
1429 != TYPEINFO_NEWOBJECT_INSTRUCTION(*y))
1432 if (x->merged || y->merged) {
1433 if (!(x->merged && y->merged)) return false;
1434 if (x->merged->count != y->merged->count) return false;
1435 for (i=0; i<x->merged->count; ++i)
1436 if (x->merged->list[i] != y->merged->list[i])
1443 typeinfo_testmerge(typeinfo *a,typeinfo *b,typeinfo *result,int *failed)
1446 bool changed,changed_should_be;
1448 TYPEINFO_CLONE(*a,dest);
1451 typeinfo_print_short(stdout,&dest);
1453 typeinfo_print_short(stdout,b);
1456 changed = (typeinfo_merge(&dest,b)) ? 1 : 0;
1457 changed_should_be = (!typeinfo_equal(&dest,a)) ? 1 : 0;
1459 printf(" %s\n",(changed) ? "changed" : "=");
1461 if (typeinfo_equal(&dest,result)) {
1463 typeinfo_print_short(stdout,&dest);
1465 if (changed != changed_should_be) {
1466 printf("WRONG RETURN VALUE!\n");
1472 typeinfo_print_short(stdout,&dest);
1474 printf("SHOULD BE ");
1475 typeinfo_print_short(stdout,result);
1482 typeinfo_inc_dimension(typeinfo *info)
1484 if (info->dimension++ == 0) {
1485 info->elementtype = ARRAYTYPE_OBJECT;
1486 info->elementclass = info->typeclass;
1488 info->typeclass = class_array_of(info->typeclass);
1491 #define TYPEINFO_TEST_MAXDIM 10
1494 typeinfo_testrun(char *filename)
1496 char buf[TYPEINFO_TEST_BUFLEN];
1497 char bufa[TYPEINFO_TEST_BUFLEN];
1498 char bufb[TYPEINFO_TEST_BUFLEN];
1499 char bufc[TYPEINFO_TEST_BUFLEN];
1503 FILE *file = fopen(filename,"rt");
1507 panic("could not open typeinfo test file");
1509 while (fgets(buf,TYPEINFO_TEST_BUFLEN,file)) {
1510 if (buf[0] == '#' || !strlen(buf))
1513 res = sscanf(buf,"%s\t%s\t%s\n",bufa,bufb,bufc);
1514 if (res != 3 || !strlen(bufa) || !strlen(bufb) || !strlen(bufc))
1515 panic("Invalid line in typeinfo test file (none of empty, comment or test)");
1517 typeinfo_test_parse(&a,bufa);
1518 typeinfo_test_parse(&b,bufb);
1519 typeinfo_test_parse(&c,bufc);
1521 typeinfo_testmerge(&a,&b,&c,&failed); /* check result */
1522 typeinfo_testmerge(&b,&a,&c,&failed); /* check commutativity */
1524 if (TYPEINFO_IS_NULLTYPE(a)) break;
1525 if (TYPEINFO_IS_NULLTYPE(b)) break;
1526 if (TYPEINFO_IS_NULLTYPE(c)) break;
1528 maxdim = a.dimension;
1529 if (b.dimension > maxdim) maxdim = b.dimension;
1530 if (c.dimension > maxdim) maxdim = c.dimension;
1532 if (maxdim < TYPEINFO_TEST_MAXDIM) {
1533 typeinfo_inc_dimension(&a);
1534 typeinfo_inc_dimension(&b);
1535 typeinfo_inc_dimension(&c);
1537 } while (maxdim < TYPEINFO_TEST_MAXDIM);
1543 fprintf(stderr,"Failed typeinfo_merge tests: %d\n",failed);
1544 panic("Failed test");
1551 log_text("Running typeinfo test file...");
1552 typeinfo_testrun("typeinfo.tst");
1553 log_text("Finished typeinfo test file.");
1557 typeinfo_init_from_fielddescriptor(typeinfo *info,char *desc)
1559 typeinfo_init_from_descriptor(info,desc,desc+strlen(desc));
1562 #define TYPEINFO_MAXINDENT 80
1565 typeinfo_print(FILE *file,typeinfo *info,int indent)
1568 char ind[TYPEINFO_MAXINDENT + 1];
1572 if (indent > TYPEINFO_MAXINDENT) indent = TYPEINFO_MAXINDENT;
1574 for (i=0; i<indent; ++i)
1578 if (TYPEINFO_IS_PRIMITIVE(*info)) {
1579 bptr = (basicblock*) TYPEINFO_RETURNADDRESS(*info);
1581 fprintf(file,"%sreturnAddress (L%03d)\n",ind,bptr->debug_nr);
1583 fprintf(file,"%sprimitive\n",ind);
1587 if (TYPEINFO_IS_NULLTYPE(*info)) {
1588 fprintf(file,"%snull\n",ind);
1592 if (TYPEINFO_IS_NEWOBJECT(*info)) {
1593 ins = (instruction *)TYPEINFO_NEWOBJECT_INSTRUCTION(*info);
1595 fprintf(file,"%sNEW(%d):",ind,ins-instr);
1596 utf_fprint(file,((classinfo *)ins[-1].val.a)->name);
1600 fprintf(file,"%sNEW(this)",ind);
1605 fprintf(file,"%sClass: ",ind);
1606 utf_fprint(file,info->typeclass->name);
1609 if (TYPEINFO_IS_ARRAY(*info)) {
1610 fprintf(file,"%sDimension: %d",ind,(int)info->dimension);
1611 fprintf(file,"\n%sElements: ",ind);
1612 switch (info->elementtype) {
1613 case ARRAYTYPE_INT : fprintf(file,"int\n"); break;
1614 case ARRAYTYPE_LONG : fprintf(file,"long\n"); break;
1615 case ARRAYTYPE_FLOAT : fprintf(file,"float\n"); break;
1616 case ARRAYTYPE_DOUBLE : fprintf(file,"double\n"); break;
1617 case ARRAYTYPE_BYTE : fprintf(file,"byte\n"); break;
1618 case ARRAYTYPE_CHAR : fprintf(file,"char\n"); break;
1619 case ARRAYTYPE_SHORT : fprintf(file,"short\n"); break;
1620 case ARRAYTYPE_BOOLEAN : fprintf(file,"boolean\n"); break;
1622 case ARRAYTYPE_OBJECT:
1623 fprintf(file,"reference: ");
1624 utf_fprint(file,info->elementclass->name);
1629 fprintf(file,"INVALID ARRAYTYPE!\n");
1634 fprintf(file,"%sMerged: ",ind);
1635 for (i=0; i<info->merged->count; ++i) {
1636 if (i) fprintf(file,", ");
1637 utf_fprint(file,info->merged->list[i]->name);
1644 typeinfo_print_short(FILE *file,typeinfo *info)
1650 if (TYPEINFO_IS_PRIMITIVE(*info)) {
1651 bptr = (basicblock*) TYPEINFO_RETURNADDRESS(*info);
1653 fprintf(file,"ret(L%03d)",bptr->debug_nr);
1655 fprintf(file,"primitive");
1659 if (TYPEINFO_IS_NULLTYPE(*info)) {
1660 fprintf(file,"null");
1664 if (TYPEINFO_IS_NEWOBJECT(*info)) {
1665 ins = (instruction *)TYPEINFO_NEWOBJECT_INSTRUCTION(*info);
1667 fprintf(file,"NEW(%d):",ins-instr);
1668 utf_fprint(file,((classinfo *)ins[-1].val.a)->name);
1671 fprintf(file,"NEW(this)");
1675 utf_fprint(file,info->typeclass->name);
1679 for (i=0; i<info->merged->count; ++i) {
1680 if (i) fprintf(file,",");
1681 utf_fprint(file,info->merged->list[i]->name);
1688 typeinfo_print_type(FILE *file,int type,typeinfo *info)
1691 case TYPE_VOID: fprintf(file,"V"); break;
1692 case TYPE_INT: fprintf(file,"I"); break;
1693 case TYPE_FLOAT: fprintf(file,"F"); break;
1694 case TYPE_DOUBLE: fprintf(file,"D"); break;
1695 case TYPE_LONG: fprintf(file,"J"); break;
1697 typeinfo_print_short(file,info);
1706 typeinfo_print_stacktype(FILE *file,int type,typeinfo *info)
1708 if (type == TYPE_ADDRESS && TYPEINFO_IS_PRIMITIVE(*info)) {
1709 typeinfo_retaddr_set *set = (typeinfo_retaddr_set*)
1710 TYPEINFO_RETURNADDRESS(*info);
1711 fprintf(file,"ret(L%03d",((basicblock*)(set->addr))->debug_nr);
1714 fprintf(file,"|L%03d",((basicblock*)(set->addr))->debug_nr);
1720 typeinfo_print_type(file,type,info);
1724 typedescriptor_print(FILE *file,typedescriptor *td)
1726 typeinfo_print_type(file,td->type,&(td->info));
1730 typevector_print(FILE *file,typevector *vec,int size)
1734 fprintf(file,"[%d]",vec->k);
1735 for (i=0; i<size; ++i) {
1736 fprintf(file," %d=",i);
1737 typedescriptor_print(file,vec->td + i);
1742 typevectorset_print(FILE *file,typevector *set,int size)
1747 fprintf(file,"[%d",set->k);
1750 fprintf(file,"|%d",vec->k);
1755 for (i=0; i<size; ++i) {
1756 fprintf(file," %d=",i);
1757 typedescriptor_print(file,set->td + i);
1761 typedescriptor_print(file,vec->td + i);
1767 #endif /* TYPEINFO_DEBUG */
1771 * These are local overrides for various environment variables in Emacs.
1772 * Please do not remove this and leave it at the end of the file, where
1773 * Emacs will automagically detect them.
1774 * ---------------------------------------------------------------------
1777 * indent-tabs-mode: t