1 /* src/vm/jit/verify/typeinfo.c - type system used by the type checker
3 Copyright (C) 1996-2005, 2006, 2007 R. Grafl, A. Krall, C. Kruegel,
4 C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
5 E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
6 J. Wenninger, Institut f. Computersprachen - TU Wien
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., 51 Franklin Street, Fifth Floor, Boston, MA
25 $Id: typeinfo.c 7483 2007-03-08 13:17:40Z michi $
35 #include "mm/memory.h"
36 #include "toolbox/logging.h"
38 #include "vm/exceptions.h"
40 #include "vm/jit/jit.h"
41 #include "vm/jit/verify/typeinfo.h"
43 #include "vmcore/class.h"
44 #include "vmcore/descriptor.h"
45 #include "vmcore/loader.h"
46 #include "vm/resolve.h"
49 /* check if a linked class is an array class. Only use for linked classes! */
50 #define CLASSINFO_IS_ARRAY(clsinfo) ((clsinfo)->vftbl->arraydesc != NULL)
52 /* check if a linked class implements the interface with the given index */
53 #define CLASSINFO_IMPLEMENTS_INTERFACE(cls,index) \
54 ( ((index) < (cls)->vftbl->interfacetablelength) \
55 && ( (cls)->vftbl->interfacetable[-(index)] != NULL ) )
57 /******************************************************************************/
59 /******************************************************************************/
62 #define TYPEINFO_ASSERT(cond) assert(cond)
64 #define TYPEINFO_ASSERT(cond)
67 /**********************************************************************/
68 /* TYPEVECTOR FUNCTIONS */
69 /**********************************************************************/
71 #if defined(ENABLE_VERIFIER)
73 /* typevector_copy *************************************************************
75 Return a copy of the given typevector.
78 src..............typevector set to copy, must be != NULL
79 size.............number of elements per typevector
82 a pointer to the new typevector set
84 *******************************************************************************/
87 typevector_copy(varinfo *src, int size)
93 dst = DNEW_TYPEVECTOR(size);
94 memcpy(dst,src,TYPEVECTOR_SIZE(size));
99 /* typevector_copy_inplace *****************************************************
101 Copy a typevector to a given destination.
104 src..............typevector to copy, must be != NULL
105 dst..............destination to write the copy to
106 size.............number of elements per typevector
108 *******************************************************************************/
111 typevector_copy_inplace(varinfo *src,varinfo *dst,int size)
113 memcpy(dst,src,TYPEVECTOR_SIZE(size));
116 /* typevector_checktype ********************************************************
118 Check if the typevector contains a given type at a given index.
121 vec..............typevector set, must be != NULL
122 index............index of component to check
123 type.............TYPE_* constant to check against
126 true if the typevector contains TYPE at INDEX,
129 *******************************************************************************/
132 typevector_checktype(varinfo *vec,int index,int type)
134 TYPEINFO_ASSERT(vec);
136 return vec[index].type == type;
139 /* typevector_checkreference ***************************************************
141 Check if the typevector contains a reference at a given index.
144 vec..............typevector, must be != NULL
145 index............index of component to check
148 true if the typevector contains a reference at INDEX,
151 *******************************************************************************/
154 typevector_checkreference(varinfo *vec, int index)
156 TYPEINFO_ASSERT(vec);
157 return TYPEDESC_IS_REFERENCE(vec[index]);
160 /* typevectorset_checkretaddr **************************************************
162 Check if the typevectors contains a returnAddress at a given index.
165 vec..............typevector, must be != NULL
166 index............index of component to check
169 true if the typevector contains a returnAddress at INDEX,
172 *******************************************************************************/
175 typevector_checkretaddr(varinfo *vec,int index)
177 TYPEINFO_ASSERT(vec);
178 return TYPEDESC_IS_RETURNADDRESS(vec[index]);
181 /* typevector_store ************************************************************
183 Store a type at a given index in the typevector.
186 vec..............typevector set, must be != NULL
187 index............index of component to set
188 type.............TYPE_* constant of type to set
189 info.............typeinfo of type to set, may be NULL,
192 *******************************************************************************/
195 typevector_store(varinfo *vec,int index,int type,typeinfo *info)
197 TYPEINFO_ASSERT(vec);
199 vec[index].type = type;
201 TYPEINFO_COPY(*info,vec[index].typeinfo);
204 /* typevector_store_retaddr ****************************************************
206 Store a returnAddress type at a given index in the typevector.
209 vec..............typevector set, must be != NULL
210 index............index of component to set
211 info.............typeinfo of the returnAddress.
213 *******************************************************************************/
216 typevector_store_retaddr(varinfo *vec,int index,typeinfo *info)
218 TYPEINFO_ASSERT(vec);
219 TYPEINFO_ASSERT(TYPEINFO_IS_PRIMITIVE(*info));
221 vec[index].type = TYPE_ADR;
222 TYPEINFO_INIT_RETURNADDRESS(vec[index].typeinfo,
223 TYPEINFO_RETURNADDRESS(*info));
226 /* typevector_init_object ******************************************************
228 Replace all uninitialized object types in the typevector set which were
229 created by the given instruction by initialized object types.
232 set..............typevector set
233 ins..............instruction which created the uninitialized object type
234 initclass........class of the initialized object type to set
235 size.............number of elements per typevector
238 true.............success
239 false............an exception has been thrown
241 XXX maybe we should do the lazy resolving before calling this function
243 *******************************************************************************/
246 typevector_init_object(varinfo *set,void *ins,
247 classref_or_classinfo initclass,
252 for (i=0; i<size; ++i) {
253 if (set[i].type == TYPE_ADR
254 && TYPEINFO_IS_NEWOBJECT(set[i].typeinfo)
255 && TYPEINFO_NEWOBJECT_INSTRUCTION(set[i].typeinfo) == ins)
257 if (!typeinfo_init_class(&(set[i].typeinfo),initclass))
264 /* typevector_merge ************************************************************
266 Merge a typevector with another one.
267 The given typevectors must have the same number of components.
270 m................method for exception messages
271 dst..............the first typevector
272 y................the second typevector
273 size.............number of elements per typevector
276 *dst.............the resulting typevector
279 typecheck_TRUE...dst has been modified
280 typecheck_FALSE..dst has not been modified
281 typecheck_FAIL...an exception has been thrown
283 *******************************************************************************/
286 typevector_merge(methodinfo *m,varinfo *dst,varinfo *y,int size)
288 bool changed = false;
294 if (a->type != TYPE_VOID && a->type != b->type) {
298 else if (a->type == TYPE_ADR) {
299 if (TYPEINFO_IS_PRIMITIVE(a->typeinfo)) {
300 /* 'a' is a returnAddress */
301 if (!TYPEINFO_IS_PRIMITIVE(b->typeinfo)
302 || (TYPEINFO_RETURNADDRESS(a->typeinfo)
303 != TYPEINFO_RETURNADDRESS(b->typeinfo)))
310 /* 'a' is a reference */
311 if (TYPEINFO_IS_PRIMITIVE(b->typeinfo)) {
316 /* two reference types are merged. There cannot be */
317 /* a merge error. In the worst case we get j.l.O. */
318 r = typeinfo_merge(m,&(a->typeinfo),&(b->typeinfo));
319 if (r == typecheck_FAIL)
331 /**********************************************************************/
332 /* READ-ONLY FUNCTIONS */
333 /* The following functions don't change typeinfo data. */
334 /**********************************************************************/
336 /* typeinfo_is_array ***********************************************************
338 Check whether a typeinfo describes an array type.
341 info.............the typeinfo, must be != NULL
344 true if INFO describes an array type.
346 *******************************************************************************/
349 typeinfo_is_array(typeinfo *info)
351 TYPEINFO_ASSERT(info);
352 return TYPEINFO_IS_ARRAY(*info);
355 /* typeinfo_is_primitive_array *************************************************
357 Check whether a typeinfo describes a primitive array type.
360 info.............the typeinfo, must be != NULL
363 true if INFO describes an array of a primitive type.
365 *******************************************************************************/
368 typeinfo_is_primitive_array(typeinfo *info,int arraytype)
370 TYPEINFO_ASSERT(info);
371 return TYPEINFO_IS_PRIMITIVE_ARRAY(*info,arraytype);
374 /* typeinfo_is_array_of_refs ***************************************************
376 Check whether a typeinfo describes an array of references type.
379 info.............the typeinfo, must be != NULL
382 true if INFO describes an array of a refrence type.
384 *******************************************************************************/
387 typeinfo_is_array_of_refs(typeinfo *info)
389 TYPEINFO_ASSERT(info);
390 return TYPEINFO_IS_ARRAY_OF_REFS(*info);
393 /* interface_extends_interface *************************************************
395 Check if a resolved interface extends a given resolved interface.
398 cls..............the interface, must be linked
399 interf...........the interface to check against
402 true.............CLS extends INTERF
403 false............CLS does not extend INTERF
405 *******************************************************************************/
408 interface_extends_interface(classinfo *cls,classinfo *interf)
412 TYPEINFO_ASSERT(cls);
413 TYPEINFO_ASSERT(interf);
414 TYPEINFO_ASSERT((interf->flags & ACC_INTERFACE) != 0);
415 TYPEINFO_ASSERT((cls->flags & ACC_INTERFACE) != 0);
416 TYPEINFO_ASSERT(cls->state & CLASS_LINKED);
418 /* first check direct superinterfaces */
419 for (i=0; i<cls->interfacescount; ++i) {
420 if (cls->interfaces[i].cls == interf)
424 /* check indirect superinterfaces */
425 for (i=0; i<cls->interfacescount; ++i) {
426 if (interface_extends_interface(cls->interfaces[i].cls,interf))
433 /* classinfo_implements_interface **********************************************
435 Check if a resolved class implements a given resolved interface.
438 cls..............the class
439 interf...........the interface
442 typecheck_TRUE...CLS implements INTERF
443 typecheck_FALSE..CLS does not implement INTERF
444 typecheck_FAIL...an exception has been thrown
446 *******************************************************************************/
448 static typecheck_result
449 classinfo_implements_interface(classinfo *cls,classinfo *interf)
451 TYPEINFO_ASSERT(cls);
452 TYPEINFO_ASSERT(interf);
453 TYPEINFO_ASSERT((interf->flags & ACC_INTERFACE) != 0);
455 if (!(cls->state & CLASS_LINKED))
456 if (!link_class(cls))
457 return typecheck_FAIL;
459 if (cls->flags & ACC_INTERFACE) {
460 /* cls is an interface */
462 return typecheck_TRUE;
464 /* check superinterfaces */
465 return interface_extends_interface(cls,interf);
468 TYPEINFO_ASSERT(cls->state & CLASS_LINKED);
469 return CLASSINFO_IMPLEMENTS_INTERFACE(cls,interf->index);
472 /* mergedlist_implements_interface *********************************************
474 Check if all the classes in a given merged list implement a given resolved
478 merged...........the list of merged class types
479 interf...........the interface to check against
482 typecheck_TRUE...all classes implement INTERF
483 typecheck_FALSE..there is at least one class that does not implement
485 typecheck_MAYBE..check cannot be performed now because of unresolved
487 typecheck_FAIL...an exception has been thrown
489 *******************************************************************************/
491 static typecheck_result
492 mergedlist_implements_interface(typeinfo_mergedlist *merged,
496 classref_or_classinfo *mlist;
499 TYPEINFO_ASSERT(interf);
500 TYPEINFO_ASSERT((interf->flags & ACC_INTERFACE) != 0);
502 /* Check if there is an non-empty mergedlist. */
504 return typecheck_FALSE;
506 /* If all classinfos in the (non-empty) merged array implement the
507 * interface return true, otherwise false.
509 mlist = merged->list;
512 if (IS_CLASSREF(*mlist)) {
513 return typecheck_MAYBE;
515 r = classinfo_implements_interface((mlist++)->cls,interf);
516 if (r != typecheck_TRUE)
519 return typecheck_TRUE;
522 /* merged_implements_interface *************************************************
524 Check if a possible merged type implements a given resolved interface
528 typeclass........(common) class of the (merged) type
529 merged...........the list of merged class types
530 interf...........the interface to check against
533 typecheck_TRUE...the type implement INTERF
534 typecheck_FALSE..the type does not implement INTERF
535 typecheck_MAYBE..check cannot be performed now because of unresolved
537 typecheck_FAIL...an exception has been thrown
539 *******************************************************************************/
541 static typecheck_result
542 merged_implements_interface(classinfo *typeclass,typeinfo_mergedlist *merged,
547 /* primitive types don't support interfaces. */
549 return typecheck_FALSE;
551 /* the null type can be cast to any interface type. */
552 if (typeclass == pseudo_class_Null)
553 return typecheck_TRUE;
555 /* check if typeclass implements the interface. */
556 r = classinfo_implements_interface(typeclass,interf);
557 if (r != typecheck_FALSE)
560 /* check the mergedlist */
562 return typecheck_FALSE;
563 return mergedlist_implements_interface(merged,interf);
566 /* merged_is_subclass **********************************************************
568 Check if a possible merged type is a subclass of a given class.
569 A merged type is a subclass of a class C if all types in the merged list
570 are subclasses of C. A sufficient condition for this is that the
571 common type of the merged type is a subclass of C.
574 typeclass........(common) class of the (merged) type
575 MUST be a loaded and linked class
576 merged...........the list of merged class types
577 cls..............the class to theck against
580 typecheck_TRUE...the type is a subclass of CLS
581 typecheck_FALSE..the type is not a subclass of CLS
582 typecheck_MAYBE..check cannot be performed now because of unresolved
584 typecheck_FAIL...an exception has been thrown
586 *******************************************************************************/
588 static typecheck_result
589 merged_is_subclass(classinfo *typeclass,typeinfo_mergedlist *merged,
593 classref_or_classinfo *mlist;
595 TYPEINFO_ASSERT(cls);
597 /* primitive types aren't subclasses of anything. */
599 return typecheck_FALSE;
601 /* the null type can be cast to any reference type. */
602 if (typeclass == pseudo_class_Null)
603 return typecheck_TRUE;
605 TYPEINFO_ASSERT(typeclass->state & CLASS_LOADED);
606 TYPEINFO_ASSERT(typeclass->state & CLASS_LINKED);
608 /* check if the common typeclass is a subclass of CLS. */
609 if (class_issubclass(typeclass,cls))
610 return typecheck_TRUE;
612 /* check the mergedlist */
614 return typecheck_FALSE;
615 /* If all classinfos in the (non-empty) merged list are subclasses
616 * of CLS, return true, otherwise false.
617 * If there is at least one unresolved type in the list,
618 * return typecheck_MAYBE.
620 mlist = merged->list;
623 if (IS_CLASSREF(*mlist)) {
624 return typecheck_MAYBE;
626 if (!(mlist->cls->state & CLASS_LINKED))
627 if (!link_class(mlist->cls))
628 return typecheck_FAIL;
629 if (!class_issubclass(mlist->cls,cls))
630 return typecheck_FALSE;
633 return typecheck_TRUE;
636 /* typeinfo_is_assignable_to_class *********************************************
638 Check if a type is assignable to a given class type.
641 value............the type of the value
642 dest.............the type of the destination
645 typecheck_TRUE...the type is assignable
646 typecheck_FALSE..the type is not assignable
647 typecheck_MAYBE..check cannot be performed now because of unresolved
649 typecheck_FAIL...an exception has been thrown
651 *******************************************************************************/
654 typeinfo_is_assignable_to_class(typeinfo *value,classref_or_classinfo dest)
656 classref_or_classinfo c;
660 TYPEINFO_ASSERT(value);
662 c = value->typeclass;
664 /* assignments of primitive values are not checked here. */
665 if (!c.any && !dest.any)
666 return typecheck_TRUE;
668 /* primitive and reference types are not assignment compatible. */
669 if (!c.any || !dest.any)
670 return typecheck_FALSE;
672 /* the null type can be assigned to any type */
673 if (TYPEINFO_IS_NULLTYPE(*value))
674 return typecheck_TRUE;
676 /* uninitialized objects are not assignable */
677 if (TYPEINFO_IS_NEWOBJECT(*value))
678 return typecheck_FALSE;
680 if (IS_CLASSREF(c)) {
681 /* The value type is an unresolved class reference. */
682 classname = c.ref->name;
685 classname = c.cls->name;
688 if (IS_CLASSREF(dest)) {
689 /* the destination type is an unresolved class reference */
690 /* In this case we cannot tell a lot about assignability. */
692 /* the common case of value and dest type having the same classname */
693 if (dest.ref->name == classname && !value->merged)
694 return typecheck_TRUE;
696 /* we cannot tell if value is assignable to dest, so we */
697 /* leave it up to the resolving code to check this */
698 return typecheck_MAYBE;
701 /* { we know that dest is a loaded class } */
703 if (IS_CLASSREF(c)) {
704 /* the value type is an unresolved class reference */
706 /* the common case of value and dest type having the same classname */
707 if (dest.cls->name == classname)
708 return typecheck_TRUE;
710 /* we cannot tell if value is assignable to dest, so we */
711 /* leave it up to the resolving code to check this */
712 return typecheck_MAYBE;
715 /* { we know that both c and dest are loaded classes } */
716 /* (c may still have a merged list containing unresolved classrefs!) */
718 TYPEINFO_ASSERT(!IS_CLASSREF(c));
719 TYPEINFO_ASSERT(!IS_CLASSREF(dest));
723 TYPEINFO_ASSERT(cls->state & CLASS_LOADED);
724 TYPEINFO_ASSERT(dest.cls->state & CLASS_LOADED);
726 /* maybe we need to link the classes */
727 if (!(cls->state & CLASS_LINKED))
728 if (!link_class(cls))
729 return typecheck_FAIL;
730 if (!(dest.cls->state & CLASS_LINKED))
731 if (!link_class(dest.cls))
732 return typecheck_FAIL;
734 /* { we know that both c and dest are linked classes } */
735 TYPEINFO_ASSERT(cls->state & CLASS_LINKED);
736 TYPEINFO_ASSERT(dest.cls->state & CLASS_LINKED);
738 if (dest.cls->flags & ACC_INTERFACE) {
739 /* We are assigning to an interface type. */
740 return merged_implements_interface(cls,value->merged,dest.cls);
743 if (CLASSINFO_IS_ARRAY(dest.cls)) {
744 arraydescriptor *arraydesc = dest.cls->vftbl->arraydesc;
745 int dimension = arraydesc->dimension;
746 classinfo *elementclass = (arraydesc->elementvftbl)
747 ? arraydesc->elementvftbl->class : NULL;
749 /* We are assigning to an array type. */
750 if (!TYPEINFO_IS_ARRAY(*value))
751 return typecheck_FALSE;
753 /* {Both value and dest.cls are array types.} */
755 /* value must have at least the dimension of dest.cls. */
756 if (value->dimension < dimension)
757 return typecheck_FALSE;
759 if (value->dimension > dimension) {
760 /* value has higher dimension so we need to check
761 * if its component array can be assigned to the
762 * element type of dest.cls */
764 if (!elementclass) return typecheck_FALSE;
766 if (elementclass->flags & ACC_INTERFACE) {
767 /* We are assigning to an interface type. */
768 return classinfo_implements_interface(pseudo_class_Arraystub,
772 /* We are assigning to a class type. */
773 return class_issubclass(pseudo_class_Arraystub,elementclass);
776 /* {value and dest.cls have the same dimension} */
778 if (value->elementtype != arraydesc->elementtype)
779 return typecheck_FALSE;
781 if (value->elementclass.any) {
782 /* We are assigning an array of objects so we have to
783 * check if the elements are assignable.
786 if (elementclass->flags & ACC_INTERFACE) {
787 /* We are assigning to an interface type. */
789 return merged_implements_interface(value->elementclass.cls,
794 /* We are assigning to a class type. */
795 return merged_is_subclass(value->elementclass.cls,value->merged,elementclass);
798 return typecheck_TRUE;
801 /* {dest.cls is not an array} */
802 /* {dest.cls is a loaded class} */
804 /* If there are any unresolved references in the merged list, we cannot */
805 /* tell if the assignment will be ok. */
806 /* This can only happen when cls is java.lang.Object */
807 if (cls == class_java_lang_Object && value->merged) {
808 classref_or_classinfo *mlist = value->merged->list;
809 int i = value->merged->count;
811 if (IS_CLASSREF(*mlist++))
812 return typecheck_MAYBE;
815 /* We are assigning to a class type */
816 if (cls->flags & ACC_INTERFACE)
817 cls = class_java_lang_Object;
819 return merged_is_subclass(cls,value->merged,dest.cls);
822 /* typeinfo_is_assignable ******************************************************
824 Check if a type is assignable to a given type.
827 value............the type of the value
828 dest.............the type of the destination, must not be a merged type
831 typecheck_TRUE...the type is assignable
832 typecheck_FALSE..the type is not assignable
833 typecheck_MAYBE..check cannot be performed now because of unresolved
835 typecheck_FAIL...an exception has been thrown
837 *******************************************************************************/
840 typeinfo_is_assignable(typeinfo *value,typeinfo *dest)
842 TYPEINFO_ASSERT(value);
843 TYPEINFO_ASSERT(dest);
844 TYPEINFO_ASSERT(dest->merged == NULL);
846 return typeinfo_is_assignable_to_class(value,dest->typeclass);
849 /**********************************************************************/
850 /* INITIALIZATION FUNCTIONS */
851 /* The following functions fill in uninitialized typeinfo structures. */
852 /**********************************************************************/
854 /* typeinfo_init_classinfo *****************************************************
856 Initialize a typeinfo to a resolved class.
859 c................the class
862 *info............is initialized
865 true.............success
866 false............an exception has been thrown
868 *******************************************************************************/
871 typeinfo_init_classinfo(typeinfo *info, classinfo *c)
873 if ((info->typeclass.cls = c)->vftbl->arraydesc) {
874 if (c->vftbl->arraydesc->elementvftbl)
875 info->elementclass.cls = c->vftbl->arraydesc->elementvftbl->class;
877 info->elementclass.any = NULL;
878 info->dimension = c->vftbl->arraydesc->dimension;
879 info->elementtype = c->vftbl->arraydesc->elementtype;
882 info->elementclass.any = NULL;
884 info->elementtype = 0;
889 /* typeinfo_init_class *********************************************************
891 Initialize a typeinfo to a possibly unresolved class type.
894 c................the class type
897 *info............is initialized
900 true.............success
901 false............an exception has been thrown
903 *******************************************************************************/
906 typeinfo_init_class(typeinfo *info,classref_or_classinfo c)
912 TYPEINFO_ASSERT(c.any);
913 TYPEINFO_ASSERT(info);
915 /* if necessary, try to resolve lazily */
916 if (!resolve_classref_or_classinfo(NULL /* XXX should know method */,
917 c,resolveLazy,false,true,&cls))
923 typeinfo_init_classinfo(info,cls);
927 /* {the type could no be resolved lazily} */
929 info->typeclass.ref = c.ref;
930 info->elementclass.any = NULL;
934 /* handle array type references */
935 utf_ptr = c.ref->name->text;
936 len = c.ref->name->blength;
937 if (*utf_ptr == '[') {
938 /* count dimensions */
939 while (*utf_ptr == '[') {
944 if (*utf_ptr == 'L') {
947 info->elementtype = ARRAYTYPE_OBJECT;
948 info->elementclass.ref = class_get_classref(c.ref->referer,utf_new(utf_ptr,len));
951 /* an array with primitive element type */
952 /* should have been resolved above */
953 TYPEINFO_ASSERT(false);
959 /* typeinfo_init_from_typedesc *************************************************
961 Initialize a typeinfo from a typedesc.
964 desc.............the typedesc
967 *type............set to the TYPE_* constant of DESC (if type != NULL)
968 *info............receives the typeinfo (if info != NULL)
971 true.............success
972 false............an exception has been thrown
974 *******************************************************************************/
977 typeinfo_init_from_typedesc(typedesc *desc,u1 *type,typeinfo *info)
979 TYPEINFO_ASSERT(desc);
981 #ifdef TYPEINFO_VERBOSE
982 fprintf(stderr,"typeinfo_init_from_typedesc(");
983 descriptor_debug_print_typedesc(stderr,desc);
984 fprintf(stderr,")\n");
991 if (desc->type == TYPE_ADR) {
992 TYPEINFO_ASSERT(desc->classref);
993 if (!typeinfo_init_class(info,CLASSREF_OR_CLASSINFO(desc->classref)))
997 TYPEINFO_INIT_PRIMITIVE(*info);
1003 /* typeinfos_init_from_methoddesc **********************************************
1005 Initialize an array of typeinfos and u1 TYPE_* values from a methoddesc.
1008 desc.............the methoddesc
1009 buflen...........number of parameters the buffer can hold
1010 twoword..........if true, use two parameter slots for two-word types
1013 *typebuf.........receives a TYPE_* constant for each parameter
1014 typebuf must be != NULL
1015 *infobuf.........receives a typeinfo for each parameter
1016 infobuf must be != NULL
1017 *returntype......receives a TYPE_* constant for the return type
1018 returntype may be NULL
1019 *returntypeinfo..receives a typeinfo for the return type
1020 returntypeinfo may be NULL
1023 true.............success
1024 false............an exception has been thrown
1027 If (according to BUFLEN) the buffers are to small to hold the
1028 parameter types, an internal error is thrown. This must be
1029 avoided by checking the number of parameters and allocating enough
1030 space before calling this function.
1032 *******************************************************************************/
1035 typeinfos_init_from_methoddesc(methoddesc *desc,u1 *typebuf,typeinfo *infobuf,
1036 int buflen,bool twoword,
1037 u1 *returntype,typeinfo *returntypeinfo)
1042 TYPEINFO_ASSERT(desc);
1043 TYPEINFO_ASSERT(typebuf);
1044 TYPEINFO_ASSERT(infobuf);
1046 #ifdef TYPEINFO_VERBOSE
1047 fprintf(stderr,"typeinfos_init_from_methoddesc(");
1048 descriptor_debug_print_methoddesc(stderr,desc);
1049 fprintf(stderr,")\n");
1052 /* check arguments */
1053 for (i=0; i<desc->paramcount; ++i) {
1054 if (++args > buflen) {
1055 exceptions_throw_internalerror("Buffer too small for method arguments.");
1059 if (!typeinfo_init_from_typedesc(desc->paramtypes + i,typebuf++,infobuf++))
1062 if (twoword && (typebuf[-1] == TYPE_LNG || typebuf[-1] == TYPE_DBL)) {
1063 if (++args > buflen) {
1064 exceptions_throw_internalerror("Buffer too small for method arguments.");
1068 *typebuf++ = TYPE_VOID;
1069 TYPEINFO_INIT_PRIMITIVE(*infobuf);
1074 /* check returntype */
1076 if (!typeinfo_init_from_typedesc(&(desc->returntype),returntype,returntypeinfo))
1083 /* typedescriptor_init_from_typedesc *******************************************
1085 Initialize a typedescriptor from a typedesc.
1088 desc.............the typedesc
1091 *td..............receives the typedescriptor
1095 true.............success
1096 false............an exception has been thrown
1098 *******************************************************************************/
1101 typedescriptor_init_from_typedesc(typedescriptor *td,
1104 TYPEINFO_ASSERT(td);
1105 TYPEINFO_ASSERT(desc);
1107 td->type = desc->type;
1108 if (td->type == TYPE_ADR) {
1109 if (!typeinfo_init_class(&(td->typeinfo),CLASSREF_OR_CLASSINFO(desc->classref)))
1113 TYPEINFO_INIT_PRIMITIVE(td->typeinfo);
1118 /* typeinfo_init_varinfo_from_typedesc *****************************************
1120 Initialize a varinfo from a typedesc.
1123 desc.............the typedesc
1126 *var.............receives the type
1130 true.............success
1131 false............an exception has been thrown
1133 *******************************************************************************/
1136 typeinfo_init_varinfo_from_typedesc(varinfo *var,
1139 TYPEINFO_ASSERT(var);
1140 TYPEINFO_ASSERT(desc);
1142 var->type = desc->type;
1143 if (var->type == TYPE_ADR) {
1144 if (!typeinfo_init_class(&(var->typeinfo),CLASSREF_OR_CLASSINFO(desc->classref)))
1148 TYPEINFO_INIT_PRIMITIVE(var->typeinfo);
1153 /* typeinfo_init_varinfos_from_methoddesc **************************************
1155 Initialize an array of varinfos from a methoddesc.
1158 desc.............the methoddesc
1159 buflen...........number of parameters the buffer can hold
1160 startindex.......the zero-based index of the first parameter to
1161 write to the array. In other words the number of
1162 parameters to skip at the beginning of the methoddesc.
1163 map..............map from parameter indices to varinfo indices
1164 (indexed like jitdata.local_map)
1167 *vars............array receiving the varinfos
1168 td[0] receives the type of the
1169 (startindex+1)th parameter of the method
1170 *returntype......receives the typedescriptor of the return type.
1171 returntype may be NULL
1174 true.............everything ok
1175 false............an exception has been thrown
1178 If (according to BUFLEN) the buffer is to small to hold the
1179 parameter types, an internal error is thrown. This must be
1180 avoided by checking the number of parameters and allocating enough
1181 space before calling this function.
1183 *******************************************************************************/
1186 typeinfo_init_varinfos_from_methoddesc(varinfo *vars,
1188 int buflen, int startindex,
1190 typedescriptor *returntype)
1197 /* skip arguments */
1198 for (i=0; i<startindex; ++i) {
1200 if (IS_2_WORD_TYPE(desc->paramtypes[i].type))
1204 /* check arguments */
1205 for (i=startindex; i<desc->paramcount; ++i) {
1206 type = desc->paramtypes[i].type;
1207 index = map[5*slot + type];
1210 if (IS_2_WORD_TYPE(type))
1213 if (index == UNUSED)
1216 if (index >= buflen) {
1217 exceptions_throw_internalerror("Buffer too small for method arguments.");
1221 if (!typeinfo_init_varinfo_from_typedesc(vars + index, desc->paramtypes + i))
1225 /* check returntype */
1227 if (!typedescriptor_init_from_typedesc(returntype,&(desc->returntype)))
1234 /* typedescriptors_init_from_methoddesc ****************************************
1236 Initialize an array of typedescriptors from a methoddesc.
1239 desc.............the methoddesc
1240 buflen...........number of parameters the buffer can hold
1241 twoword..........if true, use two parameter slots for two-word types
1242 startindex.......the zero-based index of the first parameter to
1243 write to the array. In other words the number of
1244 parameters to skip at the beginning of the methoddesc.
1247 *td..............array receiving the typedescriptors.
1248 td[0] receives the typedescriptor of the
1249 (startindex+1)th parameter of the method
1250 *returntype......receives the typedescriptor of the return type.
1251 returntype may be NULL
1254 >= 0.............number of typedescriptors filled in TD
1255 -1...............an exception has been thrown
1258 If (according to BUFLEN) the buffer is to small to hold the
1259 parameter types, an internal error is thrown. This must be
1260 avoided by checking the number of parameters and allocating enough
1261 space before calling this function.
1263 *******************************************************************************/
1266 typedescriptors_init_from_methoddesc(typedescriptor *td,
1268 int buflen,bool twoword,int startindex,
1269 typedescriptor *returntype)
1274 /* check arguments */
1275 for (i=startindex; i<desc->paramcount; ++i) {
1276 if (++args > buflen) {
1277 exceptions_throw_internalerror("Buffer too small for method arguments.");
1281 if (!typedescriptor_init_from_typedesc(td,desc->paramtypes + i))
1285 if (twoword && (td[-1].type == TYPE_LNG || td[-1].type == TYPE_DBL)) {
1286 if (++args > buflen) {
1287 exceptions_throw_internalerror("Buffer too small for method arguments.");
1291 td->type = TYPE_VOID;
1292 TYPEINFO_INIT_PRIMITIVE(td->typeinfo);
1297 /* check returntype */
1299 if (!typedescriptor_init_from_typedesc(returntype,&(desc->returntype)))
1306 /* typeinfo_init_component *****************************************************
1308 Initialize a typeinfo with the component type of a given array type.
1311 srcarray.........the typeinfo of the array type
1314 *dst.............receives the typeinfo of the component type
1317 true.............success
1318 false............an exception has been thrown
1320 *******************************************************************************/
1323 typeinfo_init_component(typeinfo *srcarray,typeinfo *dst)
1325 typeinfo_mergedlist *merged;
1327 TYPEINFO_ASSERT(srcarray);
1328 TYPEINFO_ASSERT(dst);
1330 if (TYPEINFO_IS_NULLTYPE(*srcarray)) {
1331 TYPEINFO_INIT_NULLTYPE(*dst);
1335 if (!TYPEINFO_IS_ARRAY(*srcarray)) {
1336 /* XXX should we make that a verify error? */
1337 exceptions_throw_internalerror("Trying to access component of non-array");
1341 /* save the mergedlist (maybe dst == srcarray) */
1343 merged = srcarray->merged;
1345 if (IS_CLASSREF(srcarray->typeclass)) {
1346 constant_classref *comp;
1347 comp = class_get_classref_component_of(srcarray->typeclass.ref);
1350 if (!typeinfo_init_class(dst,CLASSREF_OR_CLASSINFO(comp)))
1354 TYPEINFO_INIT_PRIMITIVE(*dst);
1360 if (!(srcarray->typeclass.cls->state & CLASS_LINKED)) {
1361 if (!link_class(srcarray->typeclass.cls)) {
1366 TYPEINFO_ASSERT(srcarray->typeclass.cls->vftbl);
1367 TYPEINFO_ASSERT(srcarray->typeclass.cls->vftbl->arraydesc);
1369 comp = srcarray->typeclass.cls->vftbl->arraydesc->componentvftbl;
1371 typeinfo_init_classinfo(dst,comp->class);
1373 TYPEINFO_INIT_PRIMITIVE(*dst);
1376 dst->merged = merged; /* XXX should we do a deep copy? */
1380 /* typeinfo_clone **************************************************************
1382 Create a deep copy of a typeinfo struct.
1385 src..............the typeinfo to copy
1388 *dest............receives the copy
1391 If src == dest this function is a nop.
1393 *******************************************************************************/
1396 typeinfo_clone(typeinfo *src,typeinfo *dest)
1399 classref_or_classinfo *srclist,*destlist;
1407 count = src->merged->count;
1408 TYPEINFO_ALLOCMERGED(dest->merged,count);
1409 dest->merged->count = count;
1411 srclist = src->merged->list;
1412 destlist = dest->merged->list;
1414 *destlist++ = *srclist++;
1418 /**********************************************************************/
1419 /* MISCELLANEOUS FUNCTIONS */
1420 /**********************************************************************/
1422 /* typeinfo_free ***************************************************************
1424 Free memory referenced by the given typeinfo. The typeinfo itself is not
1428 info.............the typeinfo
1430 *******************************************************************************/
1433 typeinfo_free(typeinfo *info)
1435 TYPEINFO_FREEMERGED_IF_ANY(info->merged);
1436 info->merged = NULL;
1439 /**********************************************************************/
1440 /* MERGING FUNCTIONS */
1441 /* The following functions are used to merge the types represented by */
1442 /* two typeinfo structures into one typeinfo structure. */
1443 /**********************************************************************/
1447 typeinfo_merge_error(methodinfo *m,char *str,typeinfo *x,typeinfo *y) {
1448 #ifdef TYPEINFO_VERBOSE
1449 fprintf(stderr,"Error in typeinfo_merge: %s\n",str);
1450 fprintf(stderr,"Typeinfo x:\n");
1451 typeinfo_print(stderr,x,1);
1452 fprintf(stderr,"Typeinfo y:\n");
1453 typeinfo_print(stderr,y,1);
1457 exceptions_throw_verifyerror(m, str);
1460 /* Condition: clsx != clsy. */
1461 /* Returns: true if dest was changed (currently always true). */
1464 typeinfo_merge_two(typeinfo *dest,classref_or_classinfo clsx,classref_or_classinfo clsy)
1466 TYPEINFO_ASSERT(dest);
1467 TYPEINFO_FREEMERGED_IF_ANY(dest->merged);
1468 TYPEINFO_ALLOCMERGED(dest->merged,2);
1469 dest->merged->count = 2;
1471 TYPEINFO_ASSERT(clsx.any != clsy.any);
1473 if (clsx.any < clsy.any) {
1474 dest->merged->list[0] = clsx;
1475 dest->merged->list[1] = clsy;
1478 dest->merged->list[0] = clsy;
1479 dest->merged->list[1] = clsx;
1485 /* Returns: true if dest was changed. */
1488 typeinfo_merge_add(typeinfo *dest,typeinfo_mergedlist *m,classref_or_classinfo cls)
1491 typeinfo_mergedlist *newmerged;
1492 classref_or_classinfo *mlist,*newlist;
1497 /* Check if cls is already in the mergedlist m. */
1499 if ((mlist++)->any == cls.any) { /* XXX check equal classrefs? */
1500 /* cls is in the list, so m is the resulting mergedlist */
1501 if (dest->merged == m)
1504 /* We have to copy the mergedlist */
1505 TYPEINFO_FREEMERGED_IF_ANY(dest->merged);
1507 TYPEINFO_ALLOCMERGED(dest->merged,count);
1508 dest->merged->count = count;
1509 newlist = dest->merged->list;
1512 *newlist++ = *mlist++;
1518 /* Add cls to the mergedlist. */
1520 TYPEINFO_ALLOCMERGED(newmerged,count+1);
1521 newmerged->count = count+1;
1522 newlist = newmerged->list;
1525 if (mlist->any > cls.any)
1527 *newlist++ = *mlist++;
1532 *newlist++ = *mlist++;
1535 /* Put the new mergedlist into dest. */
1536 TYPEINFO_FREEMERGED_IF_ANY(dest->merged);
1537 dest->merged = newmerged;
1542 /* Returns: true if dest was changed. */
1545 typeinfo_merge_mergedlists(typeinfo *dest,typeinfo_mergedlist *x,
1546 typeinfo_mergedlist *y)
1550 typeinfo_mergedlist *temp,*result;
1551 classref_or_classinfo *clsx,*clsy,*newlist;
1553 /* count the elements that will be in the resulting list */
1554 /* (Both lists are sorted, equal elements are counted only once.) */
1559 while (countx && county) {
1560 if (clsx->any == clsy->any) {
1566 else if (clsx->any < clsy->any) {
1576 count += countx + county;
1578 /* {The new mergedlist will have count entries.} */
1580 if ((x->count != count) && (y->count == count)) {
1581 temp = x; x = y; y = temp;
1583 /* {If one of x,y is already the result it is x.} */
1584 if (x->count == count) {
1585 /* x->merged is equal to the result */
1586 if (x == dest->merged)
1589 if (!dest->merged || dest->merged->count != count) {
1590 TYPEINFO_FREEMERGED_IF_ANY(dest->merged);
1591 TYPEINFO_ALLOCMERGED(dest->merged,count);
1592 dest->merged->count = count;
1595 newlist = dest->merged->list;
1598 *newlist++ = *clsx++;
1603 /* {We have to merge two lists.} */
1605 /* allocate the result list */
1606 TYPEINFO_ALLOCMERGED(result,count);
1607 result->count = count;
1608 newlist = result->list;
1610 /* merge the sorted lists */
1615 while (countx && county) {
1616 if (clsx->any == clsy->any) {
1617 *newlist++ = *clsx++;
1622 else if (clsx->any < clsy->any) {
1623 *newlist++ = *clsx++;
1627 *newlist++ = *clsy++;
1632 *newlist++ = *clsx++;
1634 *newlist++ = *clsy++;
1636 /* replace the list in dest with the result list */
1637 TYPEINFO_FREEMERGED_IF_ANY(dest->merged);
1638 dest->merged = result;
1643 /* typeinfo_merge_nonarrays ****************************************************
1645 Merge two non-array types.
1648 x................the first type
1649 y................the second type
1650 mergedx..........merged list of the first type, may be NULL
1651 mergedy..........merged list of the descond type, may be NULL
1654 *dest............receives the resulting merged list
1655 *result..........receives the resulting type
1658 typecheck_TRUE...*dest has been modified
1659 typecheck_FALSE..*dest has not been modified
1660 typecheck_FAIL...an exception has been thrown
1663 RESULT is an extra parameter so it can point to dest->typeclass or to
1666 *******************************************************************************/
1668 static typecheck_result
1669 typeinfo_merge_nonarrays(typeinfo *dest,
1670 classref_or_classinfo *result,
1671 classref_or_classinfo x,classref_or_classinfo y,
1672 typeinfo_mergedlist *mergedx,
1673 typeinfo_mergedlist *mergedy)
1675 classref_or_classinfo t;
1676 classinfo *tcls,*common;
1677 typeinfo_mergedlist *tmerged;
1683 TYPEINFO_ASSERT(dest && result && x.any && y.any);
1684 TYPEINFO_ASSERT(x.cls != pseudo_class_Null);
1685 TYPEINFO_ASSERT(y.cls != pseudo_class_Null);
1686 TYPEINFO_ASSERT(x.cls != pseudo_class_New);
1687 TYPEINFO_ASSERT(y.cls != pseudo_class_New);
1689 /*--------------------------------------------------*/
1691 /*--------------------------------------------------*/
1693 /* Common case 1: x and y are the same class or class reference */
1694 /* (This case is very simple unless *both* x and y really represent
1695 * merges of subclasses of clsx==clsy.)
1697 if ( (x.any == y.any) && (!mergedx || !mergedy) ) {
1699 /* DEBUG */ /* log_text("return simple x"); */
1700 changed = (dest->merged != NULL);
1701 TYPEINFO_FREEMERGED_IF_ANY(dest->merged);
1702 dest->merged = NULL;
1704 /* DEBUG */ /* log_text("returning"); */
1708 xname = (IS_CLASSREF(x)) ? x.ref->name : x.cls->name;
1709 yname = (IS_CLASSREF(y)) ? y.ref->name : y.cls->name;
1711 /* Common case 2: xname == yname, at least one unresolved */
1712 if ((IS_CLASSREF(x) || IS_CLASSREF(y)) && (xname == yname))
1714 /* use the loaded one if any */
1715 if (!IS_CLASSREF(y))
1717 goto return_simple_x;
1720 /*--------------------------------------------------*/
1721 /* non-trivial cases */
1722 /*--------------------------------------------------*/
1724 #ifdef TYPEINFO_VERBOSE
1727 fprintf(stderr,"merge_nonarrays:\n");
1728 fprintf(stderr," ");if(IS_CLASSREF(x))fprintf(stderr,"<ref>");utf_fprint_printable_ascii(stderr,xname);fprintf(stderr,"\n");
1729 fprintf(stderr," ");if(IS_CLASSREF(y))fprintf(stderr,"<ref>");utf_fprint_printable_ascii(stderr,yname);fprintf(stderr,"\n");
1731 typeinfo_init_class(&dbgx,x);
1732 dbgx.merged = mergedx;
1733 typeinfo_init_class(&dbgy,y);
1734 dbgy.merged = mergedy;
1735 typeinfo_print(stderr,&dbgx,4);
1736 fprintf(stderr," with:\n");
1737 typeinfo_print(stderr,&dbgy,4);
1741 TYPEINFO_ASSERT(IS_CLASSREF(x) || (x.cls->state & CLASS_LOADED));
1742 TYPEINFO_ASSERT(IS_CLASSREF(y) || (y.cls->state & CLASS_LOADED));
1744 /* If y is unresolved or an interface, swap x and y. */
1745 if (IS_CLASSREF(y) || (!IS_CLASSREF(x) && y.cls->flags & ACC_INTERFACE))
1747 t = x; x = y; y = t;
1748 tmerged = mergedx; mergedx = mergedy; mergedy = tmerged;
1751 /* {We know: If only one of x,y is unresolved it is x,} */
1752 /* { If both x,y are resolved and only one of x,y is an interface it is x.} */
1754 if (IS_CLASSREF(x)) {
1755 /* {We know: x and y have different class names} */
1757 /* Check if we are merging an unresolved type with java.lang.Object */
1758 if (y.cls == class_java_lang_Object && !mergedy) {
1760 goto return_simple_x;
1763 common = class_java_lang_Object;
1764 goto merge_with_simple_x;
1767 /* {We know: both x and y are resolved} */
1768 /* {We know: If only one of x,y is an interface it is x.} */
1770 TYPEINFO_ASSERT(!IS_CLASSREF(x) && !IS_CLASSREF(y));
1771 TYPEINFO_ASSERT(x.cls->state & CLASS_LOADED);
1772 TYPEINFO_ASSERT(y.cls->state & CLASS_LOADED);
1774 /* Handle merging of interfaces: */
1775 if (x.cls->flags & ACC_INTERFACE) {
1776 /* {x.cls is an interface and mergedx == NULL.} */
1778 if (y.cls->flags & ACC_INTERFACE) {
1779 /* We are merging two interfaces. */
1780 /* {mergedy == NULL} */
1782 /* {We know that x.cls!=y.cls (see common case at beginning.)} */
1783 result->cls = class_java_lang_Object;
1784 return typeinfo_merge_two(dest,x,y);
1787 /* {We know: x is an interface, y is a class.} */
1789 /* Check if we are merging an interface with java.lang.Object */
1790 if (y.cls == class_java_lang_Object && !mergedy) {
1792 goto return_simple_x;
1795 /* If the type y implements x then the result of the merge
1796 * is x regardless of mergedy.
1799 /* we may have to link the classes */
1800 if (!(x.cls->state & CLASS_LINKED))
1801 if (!link_class(x.cls))
1802 return typecheck_FAIL;
1803 if (!(y.cls->state & CLASS_LINKED))
1804 if (!link_class(y.cls))
1805 return typecheck_FAIL;
1807 TYPEINFO_ASSERT(x.cls->state & CLASS_LINKED);
1808 TYPEINFO_ASSERT(y.cls->state & CLASS_LINKED);
1810 if (CLASSINFO_IMPLEMENTS_INTERFACE(y.cls,x.cls->index))
1812 /* y implements x, so the result of the merge is x. */
1813 goto return_simple_x;
1816 r = mergedlist_implements_interface(mergedy,x.cls);
1817 if (r == typecheck_FAIL)
1819 if (r == typecheck_TRUE)
1821 /* y implements x, so the result of the merge is x. */
1822 goto return_simple_x;
1825 /* {We know: x is an interface, the type y a class or a merge
1826 * of subclasses and is not guaranteed to implement x.} */
1828 common = class_java_lang_Object;
1829 goto merge_with_simple_x;
1832 /* {We know: x and y are classes (not interfaces).} */
1834 /* we may have to link the classes */
1835 if (!(x.cls->state & CLASS_LINKED))
1836 if (!link_class(x.cls))
1837 return typecheck_FAIL;
1838 if (!(y.cls->state & CLASS_LINKED))
1839 if (!link_class(y.cls))
1840 return typecheck_FAIL;
1842 TYPEINFO_ASSERT(x.cls->state & CLASS_LINKED);
1843 TYPEINFO_ASSERT(y.cls->state & CLASS_LINKED);
1845 /* If *x is deeper in the inheritance hierarchy swap x and y. */
1846 if (x.cls->index > y.cls->index) {
1847 t = x; x = y; y = t;
1848 tmerged = mergedx; mergedx = mergedy; mergedy = tmerged;
1851 /* {We know: y is at least as deep in the hierarchy as x.} */
1853 /* Find nearest common anchestor for the classes. */
1856 while (tcls->index > common->index)
1857 tcls = tcls->super.cls;
1858 while (common != tcls) {
1859 common = common->super.cls;
1860 tcls = tcls->super.cls;
1863 /* {common == nearest common anchestor of x and y.} */
1865 /* If x.cls==common and x is a whole class (not a merge of subclasses)
1866 * then the result of the merge is x.
1868 if (x.cls == common && !mergedx) {
1869 goto return_simple_x;
1873 result->cls = common;
1875 return typeinfo_merge_mergedlists(dest,mergedx,mergedy);
1877 return typeinfo_merge_add(dest,mergedx,y);
1880 merge_with_simple_x:
1881 result->cls = common;
1883 return typeinfo_merge_add(dest,mergedy,x);
1885 return typeinfo_merge_two(dest,x,y);
1888 /* typeinfo_merge **************************************************************
1893 m................method for exception messages
1894 dest.............the first type
1895 y................the second type
1898 *dest............receives the result of the merge
1901 typecheck_TRUE...*dest has been modified
1902 typecheck_FALSE..*dest has not been modified
1903 typecheck_FAIL...an exception has been thrown
1906 1) *dest must be a valid initialized typeinfo
1909 *******************************************************************************/
1912 typeinfo_merge(methodinfo *m,typeinfo *dest,typeinfo* y)
1916 classref_or_classinfo common;
1917 classref_or_classinfo elementclass;
1923 /*--------------------------------------------------*/
1925 /*--------------------------------------------------*/
1927 /* Merging something with itself is a nop */
1929 return typecheck_FALSE;
1931 /* Merging two returnAddress types is ok. */
1932 /* Merging two different returnAddresses never happens, as the verifier */
1933 /* keeps them separate in order to check all the possible return paths */
1934 /* from JSR subroutines. */
1935 if (!dest->typeclass.any && !y->typeclass.any) {
1936 TYPEINFO_ASSERT(TYPEINFO_RETURNADDRESS(*dest) == TYPEINFO_RETURNADDRESS(*y));
1937 return typecheck_FALSE;
1940 /* Primitive types cannot be merged with reference types */
1941 /* This must be checked before calls to typeinfo_merge. */
1942 TYPEINFO_ASSERT(dest->typeclass.any && y->typeclass.any);
1944 /* handle uninitialized object types */
1945 if (TYPEINFO_IS_NEWOBJECT(*dest) || TYPEINFO_IS_NEWOBJECT(*y)) {
1946 if (!TYPEINFO_IS_NEWOBJECT(*dest) || !TYPEINFO_IS_NEWOBJECT(*y)) {
1947 typeinfo_merge_error(m,"Trying to merge uninitialized object type.",dest,y);
1948 return typecheck_FAIL;
1950 if (TYPEINFO_NEWOBJECT_INSTRUCTION(*dest) != TYPEINFO_NEWOBJECT_INSTRUCTION(*y)) {
1951 typeinfo_merge_error(m,"Trying to merge different uninitialized objects.",dest,y);
1952 return typecheck_FAIL;
1954 /* the same uninitialized object -- no change */
1955 return typecheck_FALSE;
1958 /*--------------------------------------------------*/
1960 /*--------------------------------------------------*/
1962 /* Common case: dest and y are the same class or class reference */
1963 /* (This case is very simple unless *both* dest and y really represent
1964 * merges of subclasses of class dest==class y.)
1966 if ((dest->typeclass.any == y->typeclass.any) && (!dest->merged || !y->merged)) {
1968 changed = (dest->merged != NULL);
1969 TYPEINFO_FREEMERGED_IF_ANY(dest->merged);
1970 dest->merged = NULL;
1974 /* Handle null types: */
1975 if (TYPEINFO_IS_NULLTYPE(*y)) {
1976 return typecheck_FALSE;
1978 if (TYPEINFO_IS_NULLTYPE(*dest)) {
1979 TYPEINFO_FREEMERGED_IF_ANY(dest->merged);
1980 TYPEINFO_CLONE(*y,*dest);
1981 return typecheck_TRUE;
1984 /* Common case: two types with the same name, at least one unresolved */
1985 if (IS_CLASSREF(dest->typeclass)) {
1986 if (IS_CLASSREF(y->typeclass)) {
1987 if (dest->typeclass.ref->name == y->typeclass.ref->name)
1991 /* XXX should we take y instead of dest here? */
1992 if (dest->typeclass.ref->name == y->typeclass.cls->name)
1997 if (IS_CLASSREF(y->typeclass)
1998 && (dest->typeclass.cls->name == y->typeclass.ref->name))
2004 /*--------------------------------------------------*/
2005 /* non-trivial cases */
2006 /*--------------------------------------------------*/
2008 #ifdef TYPEINFO_VERBOSE
2009 fprintf(stderr,"merge:\n");
2010 typeinfo_print(stderr,dest,4);
2011 typeinfo_print(stderr,y,4);
2014 /* This function uses x internally, so x and y can be swapped
2015 * without changing dest. */
2019 /* Handle merging of arrays: */
2020 if (TYPEINFO_IS_ARRAY(*x) && TYPEINFO_IS_ARRAY(*y)) {
2022 /* Make x the one with lesser dimension */
2023 if (x->dimension > y->dimension) {
2024 tmp = x; x = y; y = tmp;
2027 /* If one array (y) has higher dimension than the other,
2028 * interpret it as an array (same dim. as x) of Arraystubs. */
2029 if (x->dimension < y->dimension) {
2030 dimension = x->dimension;
2031 elementtype = ARRAYTYPE_OBJECT;
2032 elementclass.cls = pseudo_class_Arraystub;
2035 dimension = y->dimension;
2036 elementtype = y->elementtype;
2037 elementclass = y->elementclass;
2040 /* {The arrays are of the same dimension.} */
2042 if (x->elementtype != elementtype) {
2043 /* Different element types are merged, so the resulting array
2044 * type has one accessible dimension less. */
2045 if (--dimension == 0) {
2046 common.cls = pseudo_class_Arraystub;
2048 elementclass.any = NULL;
2051 common.cls = class_multiarray_of(dimension,pseudo_class_Arraystub,true);
2053 exceptions_throw_internalerror("XXX Coult not create array class");
2054 return typecheck_FAIL;
2057 elementtype = ARRAYTYPE_OBJECT;
2058 elementclass.cls = pseudo_class_Arraystub;
2062 /* {The arrays have the same dimension and elementtype.} */
2064 if (elementtype == ARRAYTYPE_OBJECT) {
2065 /* The elements are references, so their respective
2066 * types must be merged.
2068 r = typeinfo_merge_nonarrays(dest,
2072 x->merged,y->merged);
2073 TYPEINFO_ASSERT(r != typecheck_MAYBE);
2074 if (r == typecheck_FAIL)
2078 /* DEBUG */ /* log_text("finding resulting array class: "); */
2079 if (IS_CLASSREF(elementclass))
2080 common.ref = class_get_classref_multiarray_of(dimension,elementclass.ref);
2082 common.cls = class_multiarray_of(dimension,elementclass.cls,true);
2084 exceptions_throw_internalerror("XXX Coult not create array class");
2085 return typecheck_FAIL;
2088 /* DEBUG */ /* utf_display_printable_ascii(common->name); printf("\n"); */
2091 common.any = y->typeclass.any;
2096 /* {We know that at least one of x or y is no array, so the
2097 * result cannot be an array.} */
2099 r = typeinfo_merge_nonarrays(dest,
2101 x->typeclass,y->typeclass,
2102 x->merged,y->merged);
2103 TYPEINFO_ASSERT(r != typecheck_MAYBE);
2104 if (r == typecheck_FAIL)
2110 elementclass.any = NULL;
2113 /* Put the new values into dest if neccessary. */
2115 if (dest->typeclass.any != common.any) {
2116 dest->typeclass.any = common.any;
2119 if (dest->dimension != dimension) {
2120 dest->dimension = dimension;
2123 if (dest->elementtype != elementtype) {
2124 dest->elementtype = elementtype;
2127 if (dest->elementclass.any != elementclass.any) {
2128 dest->elementclass.any = elementclass.any;
2134 #endif /* ENABLE_VERIFER */
2137 /**********************************************************************/
2138 /* DEBUGGING HELPERS */
2139 /**********************************************************************/
2141 #ifdef TYPEINFO_DEBUG
2145 typeinfo_test_compare(classref_or_classinfo *a,classref_or_classinfo *b)
2147 if (a->any == b->any) return 0;
2148 if (a->any < b->any) return -1;
2153 typeinfo_test_parse(typeinfo *info,char *str)
2160 utf *desc = utf_new_char(str);
2162 num = typeinfo_count_method_args(desc,false);
2164 typebuf = DMNEW(u1,num);
2165 infobuf = DMNEW(typeinfo,num);
2167 typeinfo_init_from_method_args(desc,typebuf,infobuf,num,false,
2170 TYPEINFO_ALLOCMERGED(info->merged,num);
2171 info->merged->count = num;
2173 for (i=0; i<num; ++i) {
2174 if (typebuf[i] != TYPE_ADR) {
2175 log_text("non-reference type in mergedlist");
2179 info->merged->list[i].any = infobuf[i].typeclass.any;
2181 qsort(info->merged->list,num,sizeof(classref_or_classinfo),
2182 (int(*)(const void *,const void *))&typeinfo_test_compare);
2185 typeinfo_init_from_method_args(desc,NULL,NULL,0,false,
2191 #define TYPEINFO_TEST_BUFLEN 4000
2194 typeinfo_equal(typeinfo *x,typeinfo *y)
2198 if (x->typeclass.any != y->typeclass.any) return false;
2199 if (x->dimension != y->dimension) return false;
2201 if (x->elementclass.any != y->elementclass.any) return false;
2202 if (x->elementtype != y->elementtype) return false;
2205 if (TYPEINFO_IS_NEWOBJECT(*x))
2206 if (TYPEINFO_NEWOBJECT_INSTRUCTION(*x)
2207 != TYPEINFO_NEWOBJECT_INSTRUCTION(*y))
2210 if (x->merged || y->merged) {
2211 if (!(x->merged && y->merged)) return false;
2212 if (x->merged->count != y->merged->count) return false;
2213 for (i=0; i<x->merged->count; ++i)
2214 if (x->merged->list[i].any != y->merged->list[i].any)
2221 typeinfo_testmerge(typeinfo *a,typeinfo *b,typeinfo *result,int *failed)
2224 bool changed,changed_should_be;
2227 TYPEINFO_CLONE(*a,dest);
2230 typeinfo_print_short(stdout,&dest);
2232 typeinfo_print_short(stdout,b);
2235 r = typeinfo_merge(NULL,&dest,b);
2236 if (r == typecheck_FAIL) {
2237 printf("EXCEPTION\n");
2240 changed = (r) ? 1 : 0;
2241 changed_should_be = (!typeinfo_equal(&dest,a)) ? 1 : 0;
2243 printf(" %s\n",(changed) ? "changed" : "=");
2245 if (typeinfo_equal(&dest,result)) {
2247 typeinfo_print_short(stdout,&dest);
2249 if (changed != changed_should_be) {
2250 printf("WRONG RETURN VALUE!\n");
2256 typeinfo_print_short(stdout,&dest);
2258 printf("SHOULD BE ");
2259 typeinfo_print_short(stdout,result);
2267 typeinfo_inc_dimension(typeinfo *info)
2269 if (info->dimension++ == 0) {
2270 info->elementtype = ARRAYTYPE_OBJECT;
2271 info->elementclass = info->typeclass;
2273 info->typeclass = class_array_of(info->typeclass,true);
2277 #define TYPEINFO_TEST_MAXDIM 10
2280 typeinfo_testrun(char *filename)
2282 char buf[TYPEINFO_TEST_BUFLEN];
2283 char bufa[TYPEINFO_TEST_BUFLEN];
2284 char bufb[TYPEINFO_TEST_BUFLEN];
2285 char bufc[TYPEINFO_TEST_BUFLEN];
2289 FILE *file = fopen(filename,"rt");
2293 log_text("could not open typeinfo test file");
2297 while (fgets(buf,TYPEINFO_TEST_BUFLEN,file)) {
2298 if (buf[0] == '#' || !strlen(buf))
2301 res = sscanf(buf,"%s\t%s\t%s\n",bufa,bufb,bufc);
2302 if (res != 3 || !strlen(bufa) || !strlen(bufb) || !strlen(bufc)) {
2303 log_text("Invalid line in typeinfo test file (none of empty, comment or test)");
2308 typeinfo_test_parse(&a,bufa);
2309 typeinfo_test_parse(&b,bufb);
2310 typeinfo_test_parse(&c,bufc);
2315 typeinfo_testmerge(&a,&b,&c,&failed); /* check result */
2316 typeinfo_testmerge(&b,&a,&c,&failed); /* check commutativity */
2318 if (TYPEINFO_IS_NULLTYPE(a)) break;
2319 if (TYPEINFO_IS_NULLTYPE(b)) break;
2320 if (TYPEINFO_IS_NULLTYPE(c)) break;
2322 maxdim = a.dimension;
2323 if (b.dimension > maxdim) maxdim = b.dimension;
2324 if (c.dimension > maxdim) maxdim = c.dimension;
2327 if (maxdim < TYPEINFO_TEST_MAXDIM) {
2328 typeinfo_inc_dimension(&a);
2329 typeinfo_inc_dimension(&b);
2330 typeinfo_inc_dimension(&c);
2332 } while (maxdim < TYPEINFO_TEST_MAXDIM);
2339 fprintf(stderr,"Failed typeinfo_merge tests: %d\n",failed);
2340 log_text("Failed test");
2348 log_text("Running typeinfo test file...");
2349 typeinfo_testrun("typeinfo.tst");
2350 log_text("Finished typeinfo test file.");
2355 typeinfo_init_from_fielddescriptor(typeinfo *info,char *desc)
2357 typeinfo_init_from_descriptor(info,desc,desc+strlen(desc));
2361 #define TYPEINFO_MAXINDENT 80
2364 typeinfo_print_class(FILE *file,classref_or_classinfo c)
2366 /*fprintf(file,"<class %p>",c.any);*/
2369 fprintf(file,"<null>");
2372 if (IS_CLASSREF(c)) {
2373 fprintf(file,"<ref>");
2374 utf_fprint_printable_ascii(file,c.ref->name);
2377 utf_fprint_printable_ascii(file,c.cls->name);
2383 typeinfo_print(FILE *file,typeinfo *info,int indent)
2386 char ind[TYPEINFO_MAXINDENT + 1];
2390 if (indent > TYPEINFO_MAXINDENT) indent = TYPEINFO_MAXINDENT;
2392 for (i=0; i<indent; ++i)
2396 if (TYPEINFO_IS_PRIMITIVE(*info)) {
2397 bptr = (basicblock*) TYPEINFO_RETURNADDRESS(*info);
2399 fprintf(file,"%sreturnAddress (L%03d)\n",ind,bptr->nr);
2401 fprintf(file,"%sprimitive\n",ind);
2405 if (TYPEINFO_IS_NULLTYPE(*info)) {
2406 fprintf(file,"%snull\n",ind);
2410 if (TYPEINFO_IS_NEWOBJECT(*info)) {
2411 ins = (instruction *) TYPEINFO_NEWOBJECT_INSTRUCTION(*info);
2413 fprintf(file,"%sNEW(%p):",ind,(void*)ins);
2414 typeinfo_print_class(file,ins[-1].sx.val.c);
2418 fprintf(file,"%sNEW(this)",ind);
2423 fprintf(file,"%sClass: ",ind);
2424 typeinfo_print_class(file,info->typeclass);
2427 if (TYPEINFO_IS_ARRAY(*info)) {
2428 fprintf(file,"%sDimension: %d",ind,(int)info->dimension);
2429 fprintf(file,"\n%sElements: ",ind);
2430 switch (info->elementtype) {
2431 case ARRAYTYPE_INT : fprintf(file,"int\n"); break;
2432 case ARRAYTYPE_LONG : fprintf(file,"long\n"); break;
2433 case ARRAYTYPE_FLOAT : fprintf(file,"float\n"); break;
2434 case ARRAYTYPE_DOUBLE : fprintf(file,"double\n"); break;
2435 case ARRAYTYPE_BYTE : fprintf(file,"byte\n"); break;
2436 case ARRAYTYPE_CHAR : fprintf(file,"char\n"); break;
2437 case ARRAYTYPE_SHORT : fprintf(file,"short\n"); break;
2438 case ARRAYTYPE_BOOLEAN : fprintf(file,"boolean\n"); break;
2440 case ARRAYTYPE_OBJECT:
2441 typeinfo_print_class(file,info->elementclass);
2446 fprintf(file,"INVALID ARRAYTYPE!\n");
2451 fprintf(file,"%sMerged: ",ind);
2452 for (i=0; i<info->merged->count; ++i) {
2453 if (i) fprintf(file,", ");
2454 typeinfo_print_class(file,info->merged->list[i]);
2461 typeinfo_print_short(FILE *file,typeinfo *info)
2467 /*fprintf(file,"<typeinfo %p>",info);*/
2470 fprintf(file,"(typeinfo*)NULL");
2474 if (TYPEINFO_IS_PRIMITIVE(*info)) {
2475 bptr = (basicblock*) TYPEINFO_RETURNADDRESS(*info);
2477 fprintf(file,"ret(L%03d)",bptr->nr);
2479 fprintf(file,"primitive");
2483 if (TYPEINFO_IS_NULLTYPE(*info)) {
2484 fprintf(file,"null");
2488 if (TYPEINFO_IS_NEWOBJECT(*info)) {
2489 ins = (instruction *) TYPEINFO_NEWOBJECT_INSTRUCTION(*info);
2491 /*fprintf(file,"<ins %p>",ins);*/
2492 fprintf(file,"NEW(%p):",(void*)ins);
2493 typeinfo_print_class(file,ins[-1].sx.val.c);
2496 fprintf(file,"NEW(this)");
2500 typeinfo_print_class(file,info->typeclass);
2504 for (i=0; i<info->merged->count; ++i) {
2505 if (i) fprintf(file,",");
2506 typeinfo_print_class(file,info->merged->list[i]);
2513 typeinfo_print_type(FILE *file,int type,typeinfo *info)
2516 case TYPE_VOID: fprintf(file,"V"); break;
2517 case TYPE_INT: fprintf(file,"I"); break;
2518 case TYPE_FLT: fprintf(file,"F"); break;
2519 case TYPE_DBL: fprintf(file,"D"); break;
2520 case TYPE_LNG: fprintf(file,"J"); break;
2521 case TYPE_RET: fprintf(file,"R:"); /* FALLTHROUGH! */
2523 typeinfo_print_short(file,info);
2532 typedescriptor_print(FILE *file,typedescriptor *td)
2534 typeinfo_print_type(file,td->type,&(td->typeinfo));
2538 typevector_print(FILE *file,varinfo *vec,int size)
2542 for (i=0; i<size; ++i) {
2543 fprintf(file," %d=",i);
2544 typeinfo_print_type(file, vec[i].type, &(vec[i].typeinfo));
2548 #endif /* TYPEINFO_DEBUG */
2552 * These are local overrides for various environment variables in Emacs.
2553 * Please do not remove this and leave it at the end of the file, where
2554 * Emacs will automagically detect them.
2555 * ---------------------------------------------------------------------
2558 * indent-tabs-mode: t
2562 * vim:noexpandtab:sw=4:ts=4: