1 /* src/vm/jit/verify/typeinfo.c - type system used by the type checker
3 Copyright (C) 1996-2005, 2006, 2007, 2008
4 CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
6 This file is part of CACAO.
8 This program is free software; you can redistribute it and/or
9 modify it under the terms of the GNU General Public License as
10 published by the Free Software Foundation; either version 2, or (at
11 your option) any later version.
13 This program is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
31 #include "mm/memory.h"
33 #include "toolbox/logging.h"
35 #include "vm/array.hpp"
36 #include "vm/class.hpp"
37 #include "vm/descriptor.h"
38 #include "vm/exceptions.hpp"
39 #include "vm/globals.hpp"
40 #include "vm/loader.hpp"
41 #include "vm/primitive.hpp"
42 #include "vm/resolve.hpp"
44 #include "vm/jit/jit.hpp"
45 #include "vm/jit/verify/typeinfo.hpp"
47 #if defined(__cplusplus)
51 /* check if a linked class is an array class. Only use for linked classes! */
52 #define CLASSINFO_IS_ARRAY(clsinfo) ((clsinfo)->vftbl->arraydesc != NULL)
54 /* check if a linked class implements the interface with the given index */
55 #define CLASSINFO_IMPLEMENTS_INTERFACE(cls,index) \
56 ( ((index) < (cls)->vftbl->interfacetablelength) \
57 && ( (cls)->vftbl->interfacetable[-(index)] != NULL ) )
59 /******************************************************************************/
61 /******************************************************************************/
64 #define TYPEINFO_ASSERT(cond) assert(cond)
66 #define TYPEINFO_ASSERT(cond)
69 /**********************************************************************/
70 /* TYPEVECTOR FUNCTIONS */
71 /**********************************************************************/
73 #if defined(ENABLE_VERIFIER)
75 /* typevector_copy *************************************************************
77 Return a copy of the given typevector.
80 src..............typevector set to copy, must be != NULL
81 size.............number of elements per typevector
84 a pointer to the new typevector set
86 *******************************************************************************/
89 typevector_copy(varinfo *src, int size)
95 dst = DNEW_TYPEVECTOR(size);
96 memcpy(dst,src,TYPEVECTOR_SIZE(size));
101 /* typevector_copy_inplace *****************************************************
103 Copy a typevector to a given destination.
106 src..............typevector to copy, must be != NULL
107 dst..............destination to write the copy to
108 size.............number of elements per typevector
110 *******************************************************************************/
113 typevector_copy_inplace(varinfo *src,varinfo *dst,int size)
115 memcpy(dst,src,TYPEVECTOR_SIZE(size));
118 /* typevector_checktype ********************************************************
120 Check if the typevector contains a given type at a given index.
123 vec..............typevector set, must be != NULL
124 index............index of component to check
125 type.............TYPE_* constant to check against
128 true if the typevector contains TYPE at INDEX,
131 *******************************************************************************/
134 typevector_checktype(varinfo *vec,int index,int type)
136 TYPEINFO_ASSERT(vec);
138 return vec[index].type == type;
141 /* typevector_checkreference ***************************************************
143 Check if the typevector contains a reference at a given index.
146 vec..............typevector, must be != NULL
147 index............index of component to check
150 true if the typevector contains a reference at INDEX,
153 *******************************************************************************/
156 typevector_checkreference(varinfo *vec, int index)
158 TYPEINFO_ASSERT(vec);
159 return TYPEDESC_IS_REFERENCE(vec[index]);
162 /* typevectorset_checkretaddr **************************************************
164 Check if the typevectors contains a returnAddress at a given index.
167 vec..............typevector, must be != NULL
168 index............index of component to check
171 true if the typevector contains a returnAddress at INDEX,
174 *******************************************************************************/
177 typevector_checkretaddr(varinfo *vec,int index)
179 TYPEINFO_ASSERT(vec);
180 return TYPEDESC_IS_RETURNADDRESS(vec[index]);
183 /* typevector_store ************************************************************
185 Store a type at a given index in the typevector.
188 vec..............typevector set, must be != NULL
189 index............index of component to set
190 type.............TYPE_* constant of type to set
191 info.............typeinfo of type to set, may be NULL,
194 *******************************************************************************/
197 typevector_store(varinfo *vec,int index,int type,typeinfo_t *info)
199 TYPEINFO_ASSERT(vec);
201 vec[index].type = type;
203 TYPEINFO_COPY(*info,vec[index].typeinfo);
206 /* typevector_store_retaddr ****************************************************
208 Store a returnAddress type at a given index in the typevector.
211 vec..............typevector set, must be != NULL
212 index............index of component to set
213 info.............typeinfo of the returnAddress.
215 *******************************************************************************/
218 typevector_store_retaddr(varinfo *vec,int index,typeinfo_t *info)
220 TYPEINFO_ASSERT(vec);
221 TYPEINFO_ASSERT(TYPEINFO_IS_PRIMITIVE(*info));
223 vec[index].type = TYPE_ADR;
224 TYPEINFO_INIT_RETURNADDRESS(vec[index].typeinfo,
225 TYPEINFO_RETURNADDRESS(*info));
228 /* typevector_init_object ******************************************************
230 Replace all uninitialized object types in the typevector set which were
231 created by the given instruction by initialized object types.
234 set..............typevector set
235 ins..............instruction which created the uninitialized object type
236 initclass........class of the initialized object type to set
237 size.............number of elements per typevector
240 true.............success
241 false............an exception has been thrown
243 XXX maybe we should do the lazy resolving before calling this function
245 *******************************************************************************/
248 typevector_init_object(varinfo *set,void *ins,
249 classref_or_classinfo initclass,
254 for (i=0; i<size; ++i) {
255 if (set[i].type == TYPE_ADR
256 && TYPEINFO_IS_NEWOBJECT(set[i].typeinfo)
257 && TYPEINFO_NEWOBJECT_INSTRUCTION(set[i].typeinfo) == ins)
259 if (!typeinfo_init_class(&(set[i].typeinfo),initclass))
266 /* typevector_merge ************************************************************
268 Merge a typevector with another one.
269 The given typevectors must have the same number of components.
272 m................method for exception messages
273 dst..............the first typevector
274 y................the second typevector
275 size.............number of elements per typevector
278 *dst.............the resulting typevector
281 typecheck_TRUE...dst has been modified
282 typecheck_FALSE..dst has not been modified
283 typecheck_FAIL...an exception has been thrown
285 *******************************************************************************/
288 typevector_merge(methodinfo *m,varinfo *dst,varinfo *y,int size)
290 bool changed = false;
296 if (a->type != TYPE_VOID && a->type != b->type) {
300 else if (a->type == TYPE_ADR) {
301 if (TYPEINFO_IS_PRIMITIVE(a->typeinfo)) {
302 /* 'a' is a returnAddress */
303 if (!TYPEINFO_IS_PRIMITIVE(b->typeinfo)
304 || (TYPEINFO_RETURNADDRESS(a->typeinfo)
305 != TYPEINFO_RETURNADDRESS(b->typeinfo)))
312 /* 'a' is a reference */
313 if (TYPEINFO_IS_PRIMITIVE(b->typeinfo)) {
318 /* two reference types are merged. There cannot be */
319 /* a merge error. In the worst case we get j.l.O. */
320 r = typeinfo_merge(m,&(a->typeinfo),&(b->typeinfo));
321 if (r == typecheck_FAIL)
330 return (typecheck_result) changed;
333 /**********************************************************************/
334 /* READ-ONLY FUNCTIONS */
335 /* The following functions don't change typeinfo data. */
336 /**********************************************************************/
338 /* typeinfo_is_array ***********************************************************
340 Check whether a typeinfo describes an array type.
343 info.............the typeinfo, must be != NULL
346 true if INFO describes an array type.
348 *******************************************************************************/
351 typeinfo_is_array(typeinfo_t *info)
353 TYPEINFO_ASSERT(info);
354 return TYPEINFO_IS_ARRAY(*info);
357 /* typeinfo_is_primitive_array *************************************************
359 Check whether a typeinfo describes a primitive array type.
362 info.............the typeinfo, must be != NULL
365 true if INFO describes an array of a primitive type.
367 *******************************************************************************/
370 typeinfo_is_primitive_array(typeinfo_t *info,int arraytype)
372 TYPEINFO_ASSERT(info);
373 return TYPEINFO_IS_PRIMITIVE_ARRAY(*info,arraytype);
376 /* typeinfo_is_array_of_refs ***************************************************
378 Check whether a typeinfo describes an array of references type.
381 info.............the typeinfo, must be != NULL
384 true if INFO describes an array of a refrence type.
386 *******************************************************************************/
389 typeinfo_is_array_of_refs(typeinfo_t *info)
391 TYPEINFO_ASSERT(info);
392 return TYPEINFO_IS_ARRAY_OF_REFS(*info);
395 /* interface_extends_interface *************************************************
397 Check if a resolved interface extends a given resolved interface.
400 cls..............the interface, must be linked
401 interf...........the interface to check against
404 true.............CLS extends INTERF
405 false............CLS does not extend INTERF
407 *******************************************************************************/
410 interface_extends_interface(classinfo *cls,classinfo *interf)
414 TYPEINFO_ASSERT(cls);
415 TYPEINFO_ASSERT(interf);
416 TYPEINFO_ASSERT((interf->flags & ACC_INTERFACE) != 0);
417 TYPEINFO_ASSERT((cls->flags & ACC_INTERFACE) != 0);
418 TYPEINFO_ASSERT(cls->state & CLASS_LINKED);
420 /* first check direct superinterfaces */
421 for (i=0; i<cls->interfacescount; ++i) {
422 if (cls->interfaces[i] == interf)
426 /* check indirect superinterfaces */
427 for (i=0; i<cls->interfacescount; ++i) {
428 if (interface_extends_interface(cls->interfaces[i],interf))
435 /* classinfo_implements_interface **********************************************
437 Check if a resolved class implements a given resolved interface.
440 cls..............the class
441 interf...........the interface
444 typecheck_TRUE...CLS implements INTERF
445 typecheck_FALSE..CLS does not implement INTERF
446 typecheck_FAIL...an exception has been thrown
448 *******************************************************************************/
450 static typecheck_result
451 classinfo_implements_interface(classinfo *cls,classinfo *interf)
453 TYPEINFO_ASSERT(cls);
454 TYPEINFO_ASSERT(interf);
455 TYPEINFO_ASSERT((interf->flags & ACC_INTERFACE) != 0);
457 if (!(cls->state & CLASS_LINKED))
458 if (!link_class(cls))
459 return typecheck_FAIL;
461 if (cls->flags & ACC_INTERFACE) {
462 /* cls is an interface */
464 return typecheck_TRUE;
466 /* check superinterfaces */
467 return (typecheck_result) interface_extends_interface(cls,interf);
470 TYPEINFO_ASSERT(cls->state & CLASS_LINKED);
471 return (typecheck_result) CLASSINFO_IMPLEMENTS_INTERFACE(cls,interf->index);
474 /* mergedlist_implements_interface *********************************************
476 Check if all the classes in a given merged list implement a given resolved
480 merged...........the list of merged class types
481 interf...........the interface to check against
484 typecheck_TRUE...all classes implement INTERF
485 typecheck_FALSE..there is at least one class that does not implement
487 typecheck_MAYBE..check cannot be performed now because of unresolved
489 typecheck_FAIL...an exception has been thrown
491 *******************************************************************************/
493 static typecheck_result
494 mergedlist_implements_interface(typeinfo_mergedlist_t *merged,
498 classref_or_classinfo *mlist;
501 TYPEINFO_ASSERT(interf);
502 TYPEINFO_ASSERT((interf->flags & ACC_INTERFACE) != 0);
504 /* Check if there is an non-empty mergedlist. */
506 return typecheck_FALSE;
508 /* If all classinfos in the (non-empty) merged array implement the
509 * interface return true, otherwise false.
511 mlist = merged->list;
514 if (IS_CLASSREF(*mlist)) {
515 return typecheck_MAYBE;
517 r = classinfo_implements_interface((mlist++)->cls,interf);
518 if (r != typecheck_TRUE)
521 return typecheck_TRUE;
524 /* merged_implements_interface *************************************************
526 Check if a possible merged type implements a given resolved interface
530 typeclass........(common) class of the (merged) type
531 merged...........the list of merged class types
532 interf...........the interface to check against
535 typecheck_TRUE...the type implement INTERF
536 typecheck_FALSE..the type does not implement INTERF
537 typecheck_MAYBE..check cannot be performed now because of unresolved
539 typecheck_FAIL...an exception has been thrown
541 *******************************************************************************/
543 static typecheck_result
544 merged_implements_interface(classinfo *typeclass,typeinfo_mergedlist_t *merged,
549 /* primitive types don't support interfaces. */
551 return typecheck_FALSE;
553 /* the null type can be cast to any interface type. */
554 if (typeclass == pseudo_class_Null)
555 return typecheck_TRUE;
557 /* check if typeclass implements the interface. */
558 r = classinfo_implements_interface(typeclass,interf);
559 if (r != typecheck_FALSE)
562 /* check the mergedlist */
564 return typecheck_FALSE;
565 return mergedlist_implements_interface(merged,interf);
568 /* merged_is_subclass **********************************************************
570 Check if a possible merged type is a subclass of a given class.
571 A merged type is a subclass of a class C if all types in the merged list
572 are subclasses of C. A sufficient condition for this is that the
573 common type of the merged type is a subclass of C.
576 typeclass........(common) class of the (merged) type
577 MUST be a loaded and linked class
578 merged...........the list of merged class types
579 cls..............the class to theck against
582 typecheck_TRUE...the type is a subclass of CLS
583 typecheck_FALSE..the type is not a subclass of CLS
584 typecheck_MAYBE..check cannot be performed now because of unresolved
586 typecheck_FAIL...an exception has been thrown
588 *******************************************************************************/
590 static typecheck_result
591 merged_is_subclass(classinfo *typeclass,typeinfo_mergedlist_t *merged,
595 classref_or_classinfo *mlist;
597 TYPEINFO_ASSERT(cls);
599 /* primitive types aren't subclasses of anything. */
601 return typecheck_FALSE;
603 /* the null type can be cast to any reference type. */
604 if (typeclass == pseudo_class_Null)
605 return typecheck_TRUE;
607 TYPEINFO_ASSERT(typeclass->state & CLASS_LOADED);
608 TYPEINFO_ASSERT(typeclass->state & CLASS_LINKED);
610 /* check if the common typeclass is a subclass of CLS. */
611 if (class_issubclass(typeclass,cls))
612 return typecheck_TRUE;
614 /* check the mergedlist */
616 return typecheck_FALSE;
617 /* If all classinfos in the (non-empty) merged list are subclasses
618 * of CLS, return true, otherwise false.
619 * If there is at least one unresolved type in the list,
620 * return typecheck_MAYBE.
622 mlist = merged->list;
625 if (IS_CLASSREF(*mlist)) {
626 return typecheck_MAYBE;
628 if (!(mlist->cls->state & CLASS_LINKED))
629 if (!link_class(mlist->cls))
630 return typecheck_FAIL;
631 if (!class_issubclass(mlist->cls,cls))
632 return typecheck_FALSE;
635 return typecheck_TRUE;
638 /* typeinfo_is_assignable_to_class *********************************************
640 Check if a type is assignable to a given class type.
643 value............the type of the value
644 dest.............the type of the destination
647 typecheck_TRUE...the type is assignable
648 typecheck_FALSE..the type is not assignable
649 typecheck_MAYBE..check cannot be performed now because of unresolved
651 typecheck_FAIL...an exception has been thrown
653 *******************************************************************************/
656 typeinfo_is_assignable_to_class(typeinfo_t *value,classref_or_classinfo dest)
658 classref_or_classinfo c;
662 TYPEINFO_ASSERT(value);
664 c = value->typeclass;
666 /* assignments of primitive values are not checked here. */
667 if (!c.any && !dest.any)
668 return typecheck_TRUE;
670 /* primitive and reference types are not assignment compatible. */
671 if (!c.any || !dest.any)
672 return typecheck_FALSE;
674 /* the null type can be assigned to any type */
675 if (TYPEINFO_IS_NULLTYPE(*value))
676 return typecheck_TRUE;
678 /* uninitialized objects are not assignable */
679 if (TYPEINFO_IS_NEWOBJECT(*value))
680 return typecheck_FALSE;
682 if (IS_CLASSREF(c)) {
683 /* The value type is an unresolved class reference. */
684 classname = c.ref->name;
687 classname = c.cls->name;
690 if (IS_CLASSREF(dest)) {
691 /* the destination type is an unresolved class reference */
692 /* In this case we cannot tell a lot about assignability. */
694 /* the common case of value and dest type having the same classname */
695 if (dest.ref->name == classname && !value->merged)
696 return typecheck_TRUE;
698 /* we cannot tell if value is assignable to dest, so we */
699 /* leave it up to the resolving code to check this */
700 return typecheck_MAYBE;
703 /* { we know that dest is a loaded class } */
705 if (IS_CLASSREF(c)) {
706 /* the value type is an unresolved class reference */
708 /* the common case of value and dest type having the same classname */
709 if (dest.cls->name == classname)
710 return typecheck_TRUE;
712 /* we cannot tell if value is assignable to dest, so we */
713 /* leave it up to the resolving code to check this */
714 return typecheck_MAYBE;
717 /* { we know that both c and dest are loaded classes } */
718 /* (c may still have a merged list containing unresolved classrefs!) */
720 TYPEINFO_ASSERT(!IS_CLASSREF(c));
721 TYPEINFO_ASSERT(!IS_CLASSREF(dest));
725 TYPEINFO_ASSERT(cls->state & CLASS_LOADED);
726 TYPEINFO_ASSERT(dest.cls->state & CLASS_LOADED);
728 /* maybe we need to link the classes */
729 if (!(cls->state & CLASS_LINKED))
730 if (!link_class(cls))
731 return typecheck_FAIL;
732 if (!(dest.cls->state & CLASS_LINKED))
733 if (!link_class(dest.cls))
734 return typecheck_FAIL;
736 /* { we know that both c and dest are linked classes } */
737 TYPEINFO_ASSERT(cls->state & CLASS_LINKED);
738 TYPEINFO_ASSERT(dest.cls->state & CLASS_LINKED);
740 if (dest.cls->flags & ACC_INTERFACE) {
741 /* We are assigning to an interface type. */
742 return merged_implements_interface(cls,value->merged,dest.cls);
745 if (CLASSINFO_IS_ARRAY(dest.cls)) {
746 arraydescriptor *arraydesc = dest.cls->vftbl->arraydesc;
747 int dimension = arraydesc->dimension;
748 classinfo *elementclass = (arraydesc->elementvftbl)
749 ? arraydesc->elementvftbl->clazz : NULL;
751 /* We are assigning to an array type. */
752 if (!TYPEINFO_IS_ARRAY(*value))
753 return typecheck_FALSE;
755 /* {Both value and dest.cls are array types.} */
757 /* value must have at least the dimension of dest.cls. */
758 if (value->dimension < dimension)
759 return typecheck_FALSE;
761 if (value->dimension > dimension) {
762 /* value has higher dimension so we need to check
763 * if its component array can be assigned to the
764 * element type of dest.cls */
766 if (!elementclass) return typecheck_FALSE;
768 if (elementclass->flags & ACC_INTERFACE) {
769 /* We are assigning to an interface type. */
770 return classinfo_implements_interface(pseudo_class_Arraystub,
774 /* We are assigning to a class type. */
775 return (typecheck_result) class_issubclass(pseudo_class_Arraystub,elementclass);
778 /* {value and dest.cls have the same dimension} */
780 if (value->elementtype != arraydesc->elementtype)
781 return typecheck_FALSE;
783 if (value->elementclass.any) {
784 /* We are assigning an array of objects so we have to
785 * check if the elements are assignable.
788 if (elementclass->flags & ACC_INTERFACE) {
789 /* We are assigning to an interface type. */
791 return merged_implements_interface(value->elementclass.cls,
796 /* We are assigning to a class type. */
797 return merged_is_subclass(value->elementclass.cls,value->merged,elementclass);
800 return typecheck_TRUE;
803 /* {dest.cls is not an array} */
804 /* {dest.cls is a loaded class} */
806 /* If there are any unresolved references in the merged list, we cannot */
807 /* tell if the assignment will be ok. */
808 /* This can only happen when cls is java.lang.Object */
809 if (cls == class_java_lang_Object && value->merged) {
810 classref_or_classinfo *mlist = value->merged->list;
811 int i = value->merged->count;
813 if (IS_CLASSREF(*mlist++))
814 return typecheck_MAYBE;
817 /* We are assigning to a class type */
818 if (cls->flags & ACC_INTERFACE)
819 cls = class_java_lang_Object;
821 return merged_is_subclass(cls,value->merged,dest.cls);
824 /* typeinfo_is_assignable ******************************************************
826 Check if a type is assignable to a given type.
829 value............the type of the value
830 dest.............the type of the destination, must not be a merged type
833 typecheck_TRUE...the type is assignable
834 typecheck_FALSE..the type is not assignable
835 typecheck_MAYBE..check cannot be performed now because of unresolved
837 typecheck_FAIL...an exception has been thrown
839 *******************************************************************************/
842 typeinfo_is_assignable(typeinfo_t *value,typeinfo_t *dest)
844 TYPEINFO_ASSERT(value);
845 TYPEINFO_ASSERT(dest);
846 TYPEINFO_ASSERT(dest->merged == NULL);
848 return typeinfo_is_assignable_to_class(value,dest->typeclass);
851 /**********************************************************************/
852 /* INITIALIZATION FUNCTIONS */
853 /* The following functions fill in uninitialized typeinfo structures. */
854 /**********************************************************************/
856 /* typeinfo_init_classinfo *****************************************************
858 Initialize a typeinfo to a resolved class.
861 c................the class
864 *info............is initialized
867 true.............success
868 false............an exception has been thrown
870 *******************************************************************************/
873 typeinfo_init_classinfo(typeinfo_t *info, classinfo *c)
875 if ((info->typeclass.cls = c)->vftbl->arraydesc) {
876 if (c->vftbl->arraydesc->elementvftbl)
877 info->elementclass.cls = c->vftbl->arraydesc->elementvftbl->clazz;
879 info->elementclass.any = NULL;
880 info->dimension = c->vftbl->arraydesc->dimension;
881 info->elementtype = c->vftbl->arraydesc->elementtype;
884 info->elementclass.any = NULL;
886 info->elementtype = 0;
891 /* typeinfo_init_class *********************************************************
893 Initialize a typeinfo to a possibly unresolved class type.
896 c................the class type
899 *info............is initialized
902 true.............success
903 false............an exception has been thrown
905 *******************************************************************************/
908 typeinfo_init_class(typeinfo_t *info,classref_or_classinfo c)
914 TYPEINFO_ASSERT(c.any);
915 TYPEINFO_ASSERT(info);
917 /* if necessary, try to resolve lazily */
918 if (!resolve_classref_or_classinfo(NULL /* XXX should know method */,
919 c,resolveLazy,false,true,&cls))
925 typeinfo_init_classinfo(info,cls);
929 /* {the type could no be resolved lazily} */
931 info->typeclass.ref = c.ref;
932 info->elementclass.any = NULL;
936 /* handle array type references */
937 utf_ptr = c.ref->name->text;
938 len = c.ref->name->blength;
939 if (*utf_ptr == '[') {
940 /* count dimensions */
941 while (*utf_ptr == '[') {
946 if (*utf_ptr == 'L') {
949 info->elementtype = ARRAYTYPE_OBJECT;
950 info->elementclass.ref = class_get_classref(c.ref->referer,utf_new(utf_ptr,len));
953 /* an array with primitive element type */
954 /* should have been resolved above */
955 TYPEINFO_ASSERT(false);
961 /* typeinfo_init_from_typedesc *************************************************
963 Initialize a typeinfo from a typedesc.
966 desc.............the typedesc
969 *type............set to the TYPE_* constant of DESC (if type != NULL)
970 *info............receives the typeinfo (if info != NULL)
973 true.............success
974 false............an exception has been thrown
976 *******************************************************************************/
979 typeinfo_init_from_typedesc(typedesc *desc,u1 *type,typeinfo_t *info)
981 TYPEINFO_ASSERT(desc);
983 #ifdef TYPEINFO_VERBOSE
984 fprintf(stderr,"typeinfo_init_from_typedesc(");
985 descriptor_debug_print_typedesc(stderr,desc);
986 fprintf(stderr,")\n");
993 if (desc->type == TYPE_ADR) {
994 TYPEINFO_ASSERT(desc->classref);
995 if (!typeinfo_init_class(info,CLASSREF_OR_CLASSINFO(desc->classref)))
999 TYPEINFO_INIT_PRIMITIVE(*info);
1005 /* typeinfos_init_from_methoddesc **********************************************
1007 Initialize an array of typeinfos and u1 TYPE_* values from a methoddesc.
1010 desc.............the methoddesc
1011 buflen...........number of parameters the buffer can hold
1012 twoword..........if true, use two parameter slots for two-word types
1015 *typebuf.........receives a TYPE_* constant for each parameter
1016 typebuf must be != NULL
1017 *infobuf.........receives a typeinfo for each parameter
1018 infobuf must be != NULL
1019 *returntype......receives a TYPE_* constant for the return type
1020 returntype may be NULL
1021 *returntypeinfo..receives a typeinfo for the return type
1022 returntypeinfo may be NULL
1025 true.............success
1026 false............an exception has been thrown
1029 If (according to BUFLEN) the buffers are to small to hold the
1030 parameter types, an internal error is thrown. This must be
1031 avoided by checking the number of parameters and allocating enough
1032 space before calling this function.
1034 *******************************************************************************/
1037 typeinfos_init_from_methoddesc(methoddesc *desc,u1 *typebuf,typeinfo_t *infobuf,
1038 int buflen,bool twoword,
1039 u1 *returntype,typeinfo_t *returntypeinfo)
1044 TYPEINFO_ASSERT(desc);
1045 TYPEINFO_ASSERT(typebuf);
1046 TYPEINFO_ASSERT(infobuf);
1048 #ifdef TYPEINFO_VERBOSE
1049 fprintf(stderr,"typeinfos_init_from_methoddesc(");
1050 descriptor_debug_print_methoddesc(stderr,desc);
1051 fprintf(stderr,")\n");
1054 /* check arguments */
1055 for (i=0; i<desc->paramcount; ++i) {
1056 if (++args > buflen) {
1057 exceptions_throw_internalerror("Buffer too small for method arguments.");
1061 if (!typeinfo_init_from_typedesc(desc->paramtypes + i,typebuf++,infobuf++))
1064 if (twoword && (typebuf[-1] == TYPE_LNG || typebuf[-1] == TYPE_DBL)) {
1065 if (++args > buflen) {
1066 exceptions_throw_internalerror("Buffer too small for method arguments.");
1070 *typebuf++ = TYPE_VOID;
1071 TYPEINFO_INIT_PRIMITIVE(*infobuf);
1076 /* check returntype */
1078 if (!typeinfo_init_from_typedesc(&(desc->returntype),returntype,returntypeinfo))
1085 /* typedescriptor_init_from_typedesc *******************************************
1087 Initialize a typedescriptor from a typedesc.
1090 desc.............the typedesc
1093 *td..............receives the typedescriptor
1097 true.............success
1098 false............an exception has been thrown
1100 *******************************************************************************/
1103 typedescriptor_init_from_typedesc(typedescriptor_t *td,
1106 TYPEINFO_ASSERT(td);
1107 TYPEINFO_ASSERT(desc);
1109 td->type = desc->type;
1110 if (td->type == TYPE_ADR) {
1111 if (!typeinfo_init_class(&(td->typeinfo),CLASSREF_OR_CLASSINFO(desc->classref)))
1115 TYPEINFO_INIT_PRIMITIVE(td->typeinfo);
1120 /* typeinfo_init_varinfo_from_typedesc *****************************************
1122 Initialize a varinfo from a typedesc.
1125 desc.............the typedesc
1128 *var.............receives the type
1132 true.............success
1133 false............an exception has been thrown
1135 *******************************************************************************/
1138 typeinfo_init_varinfo_from_typedesc(varinfo *var,
1141 TYPEINFO_ASSERT(var);
1142 TYPEINFO_ASSERT(desc);
1144 var->type = desc->type;
1145 if (var->type == TYPE_ADR) {
1146 if (!typeinfo_init_class(&(var->typeinfo),CLASSREF_OR_CLASSINFO(desc->classref)))
1150 TYPEINFO_INIT_PRIMITIVE(var->typeinfo);
1155 /* typeinfo_init_varinfos_from_methoddesc **************************************
1157 Initialize an array of varinfos from a methoddesc.
1160 desc.............the methoddesc
1161 buflen...........number of parameters the buffer can hold
1162 startindex.......the zero-based index of the first parameter to
1163 write to the array. In other words the number of
1164 parameters to skip at the beginning of the methoddesc.
1165 map..............map from parameter indices to varinfo indices
1166 (indexed like jitdata.local_map)
1169 *vars............array receiving the varinfos
1170 td[0] receives the type of the
1171 (startindex+1)th parameter of the method
1172 *returntype......receives the typedescriptor of the return type.
1173 returntype may be NULL
1176 true.............everything ok
1177 false............an exception has been thrown
1180 If (according to BUFLEN) the buffer is to small to hold the
1181 parameter types, an internal error is thrown. This must be
1182 avoided by checking the number of parameters and allocating enough
1183 space before calling this function.
1185 *******************************************************************************/
1188 typeinfo_init_varinfos_from_methoddesc(varinfo *vars,
1190 int buflen, int startindex,
1192 typedescriptor_t *returntype)
1199 /* skip arguments */
1200 for (i=0; i<startindex; ++i) {
1202 if (IS_2_WORD_TYPE(desc->paramtypes[i].type))
1206 /* check arguments */
1207 for (i=startindex; i<desc->paramcount; ++i) {
1208 type = desc->paramtypes[i].type;
1209 varindex = map[5*slot + type];
1212 if (IS_2_WORD_TYPE(type))
1215 if (varindex == UNUSED)
1218 if (varindex >= buflen) {
1219 exceptions_throw_internalerror("Buffer too small for method arguments.");
1223 if (!typeinfo_init_varinfo_from_typedesc(vars + varindex, desc->paramtypes + i))
1227 /* check returntype */
1229 if (!typedescriptor_init_from_typedesc(returntype,&(desc->returntype)))
1236 /* typedescriptors_init_from_methoddesc ****************************************
1238 Initialize an array of typedescriptors from a methoddesc.
1241 desc.............the methoddesc
1242 buflen...........number of parameters the buffer can hold
1243 twoword..........if true, use two parameter slots for two-word types
1244 startindex.......the zero-based index of the first parameter to
1245 write to the array. In other words the number of
1246 parameters to skip at the beginning of the methoddesc.
1249 *td..............array receiving the typedescriptors.
1250 td[0] receives the typedescriptor of the
1251 (startindex+1)th parameter of the method
1252 *returntype......receives the typedescriptor of the return type.
1253 returntype may be NULL
1256 >= 0.............number of typedescriptors filled in TD
1257 -1...............an exception has been thrown
1260 If (according to BUFLEN) the buffer is to small to hold the
1261 parameter types, an internal error is thrown. This must be
1262 avoided by checking the number of parameters and allocating enough
1263 space before calling this function.
1265 *******************************************************************************/
1268 typedescriptors_init_from_methoddesc(typedescriptor_t *td,
1270 int buflen,bool twoword,int startindex,
1271 typedescriptor_t *returntype)
1276 /* check arguments */
1277 for (i=startindex; i<desc->paramcount; ++i) {
1278 if (++args > buflen) {
1279 exceptions_throw_internalerror("Buffer too small for method arguments.");
1283 if (!typedescriptor_init_from_typedesc(td,desc->paramtypes + i))
1287 if (twoword && (td[-1].type == TYPE_LNG || td[-1].type == TYPE_DBL)) {
1288 if (++args > buflen) {
1289 exceptions_throw_internalerror("Buffer too small for method arguments.");
1293 td->type = TYPE_VOID;
1294 TYPEINFO_INIT_PRIMITIVE(td->typeinfo);
1299 /* check returntype */
1301 if (!typedescriptor_init_from_typedesc(returntype,&(desc->returntype)))
1308 /* typeinfo_init_component *****************************************************
1310 Initialize a typeinfo with the component type of a given array type.
1313 srcarray.........the typeinfo of the array type
1316 *dst.............receives the typeinfo of the component type
1319 true.............success
1320 false............an exception has been thrown
1322 *******************************************************************************/
1325 typeinfo_init_component(typeinfo_t *srcarray,typeinfo_t *dst)
1327 typeinfo_mergedlist_t *merged;
1329 TYPEINFO_ASSERT(srcarray);
1330 TYPEINFO_ASSERT(dst);
1332 if (TYPEINFO_IS_NULLTYPE(*srcarray)) {
1333 TYPEINFO_INIT_NULLTYPE(*dst);
1337 if (!TYPEINFO_IS_ARRAY(*srcarray)) {
1338 /* XXX should we make that a verify error? */
1339 exceptions_throw_internalerror("Trying to access component of non-array");
1343 /* save the mergedlist (maybe dst == srcarray) */
1345 merged = srcarray->merged;
1347 if (IS_CLASSREF(srcarray->typeclass)) {
1348 constant_classref *comp;
1349 comp = class_get_classref_component_of(srcarray->typeclass.ref);
1352 if (!typeinfo_init_class(dst,CLASSREF_OR_CLASSINFO(comp)))
1356 TYPEINFO_INIT_PRIMITIVE(*dst);
1362 if (!(srcarray->typeclass.cls->state & CLASS_LINKED)) {
1363 if (!link_class(srcarray->typeclass.cls)) {
1368 TYPEINFO_ASSERT(srcarray->typeclass.cls->vftbl);
1369 TYPEINFO_ASSERT(srcarray->typeclass.cls->vftbl->arraydesc);
1371 comp = srcarray->typeclass.cls->vftbl->arraydesc->componentvftbl;
1373 typeinfo_init_classinfo(dst,comp->clazz);
1375 TYPEINFO_INIT_PRIMITIVE(*dst);
1378 dst->merged = merged; /* XXX should we do a deep copy? */
1382 /* typeinfo_clone **************************************************************
1384 Create a deep copy of a typeinfo struct.
1387 src..............the typeinfo to copy
1390 *dest............receives the copy
1393 If src == dest this function is a nop.
1395 *******************************************************************************/
1398 typeinfo_clone(typeinfo_t *src,typeinfo_t *dest)
1401 classref_or_classinfo *srclist,*destlist;
1409 count = src->merged->count;
1410 TYPEINFO_ALLOCMERGED(dest->merged,count);
1411 dest->merged->count = count;
1413 srclist = src->merged->list;
1414 destlist = dest->merged->list;
1416 *destlist++ = *srclist++;
1420 /**********************************************************************/
1421 /* MISCELLANEOUS FUNCTIONS */
1422 /**********************************************************************/
1424 /* typeinfo_free ***************************************************************
1426 Free memory referenced by the given typeinfo. The typeinfo itself is not
1430 info.............the typeinfo
1432 *******************************************************************************/
1435 typeinfo_free(typeinfo_t *info)
1437 TYPEINFO_FREEMERGED_IF_ANY(info->merged);
1438 info->merged = NULL;
1441 /**********************************************************************/
1442 /* MERGING FUNCTIONS */
1443 /* The following functions are used to merge the types represented by */
1444 /* two typeinfo structures into one typeinfo structure. */
1445 /**********************************************************************/
1449 typeinfo_merge_error(methodinfo *m,char *str,typeinfo_t *x,typeinfo_t *y) {
1450 #ifdef TYPEINFO_VERBOSE
1451 fprintf(stderr,"Error in typeinfo_merge: %s\n",str);
1452 fprintf(stderr,"Typeinfo x:\n");
1453 typeinfo_print(stderr,x,1);
1454 fprintf(stderr,"Typeinfo y:\n");
1455 typeinfo_print(stderr,y,1);
1459 exceptions_throw_verifyerror(m, str);
1462 /* Condition: clsx != clsy. */
1463 /* Returns: true if dest was changed (currently always true). */
1466 typeinfo_merge_two(typeinfo_t *dest,classref_or_classinfo clsx,classref_or_classinfo clsy)
1468 TYPEINFO_ASSERT(dest);
1469 TYPEINFO_FREEMERGED_IF_ANY(dest->merged);
1470 TYPEINFO_ALLOCMERGED(dest->merged,2);
1471 dest->merged->count = 2;
1473 TYPEINFO_ASSERT(clsx.any != clsy.any);
1475 if (clsx.any < clsy.any) {
1476 dest->merged->list[0] = clsx;
1477 dest->merged->list[1] = clsy;
1480 dest->merged->list[0] = clsy;
1481 dest->merged->list[1] = clsx;
1487 /* Returns: true if dest was changed. */
1490 typeinfo_merge_add(typeinfo_t *dest,typeinfo_mergedlist_t *m,classref_or_classinfo cls)
1493 typeinfo_mergedlist_t *newmerged;
1494 classref_or_classinfo *mlist,*newlist;
1499 /* Check if cls is already in the mergedlist m. */
1501 if ((mlist++)->any == cls.any) { /* XXX check equal classrefs? */
1502 /* cls is in the list, so m is the resulting mergedlist */
1503 if (dest->merged == m)
1506 /* We have to copy the mergedlist */
1507 TYPEINFO_FREEMERGED_IF_ANY(dest->merged);
1509 TYPEINFO_ALLOCMERGED(dest->merged,count);
1510 dest->merged->count = count;
1511 newlist = dest->merged->list;
1514 *newlist++ = *mlist++;
1520 /* Add cls to the mergedlist. */
1522 TYPEINFO_ALLOCMERGED(newmerged,count+1);
1523 newmerged->count = count+1;
1524 newlist = newmerged->list;
1527 if (mlist->any > cls.any)
1529 *newlist++ = *mlist++;
1534 *newlist++ = *mlist++;
1537 /* Put the new mergedlist into dest. */
1538 TYPEINFO_FREEMERGED_IF_ANY(dest->merged);
1539 dest->merged = newmerged;
1544 /* Returns: true if dest was changed. */
1547 typeinfo_merge_mergedlists(typeinfo_t *dest,typeinfo_mergedlist_t *x,
1548 typeinfo_mergedlist_t *y)
1552 typeinfo_mergedlist_t *temp,*result;
1553 classref_or_classinfo *clsx,*clsy,*newlist;
1555 /* count the elements that will be in the resulting list */
1556 /* (Both lists are sorted, equal elements are counted only once.) */
1561 while (countx && county) {
1562 if (clsx->any == clsy->any) {
1568 else if (clsx->any < clsy->any) {
1578 count += countx + county;
1580 /* {The new mergedlist will have count entries.} */
1582 if ((x->count != count) && (y->count == count)) {
1583 temp = x; x = y; y = temp;
1585 /* {If one of x,y is already the result it is x.} */
1586 if (x->count == count) {
1587 /* x->merged is equal to the result */
1588 if (x == dest->merged)
1591 if (!dest->merged || dest->merged->count != count) {
1592 TYPEINFO_FREEMERGED_IF_ANY(dest->merged);
1593 TYPEINFO_ALLOCMERGED(dest->merged,count);
1594 dest->merged->count = count;
1597 newlist = dest->merged->list;
1600 *newlist++ = *clsx++;
1605 /* {We have to merge two lists.} */
1607 /* allocate the result list */
1608 TYPEINFO_ALLOCMERGED(result,count);
1609 result->count = count;
1610 newlist = result->list;
1612 /* merge the sorted lists */
1617 while (countx && county) {
1618 if (clsx->any == clsy->any) {
1619 *newlist++ = *clsx++;
1624 else if (clsx->any < clsy->any) {
1625 *newlist++ = *clsx++;
1629 *newlist++ = *clsy++;
1634 *newlist++ = *clsx++;
1636 *newlist++ = *clsy++;
1638 /* replace the list in dest with the result list */
1639 TYPEINFO_FREEMERGED_IF_ANY(dest->merged);
1640 dest->merged = result;
1645 /* typeinfo_merge_nonarrays ****************************************************
1647 Merge two non-array types.
1650 x................the first type
1651 y................the second type
1652 mergedx..........merged list of the first type, may be NULL
1653 mergedy..........merged list of the descond type, may be NULL
1656 *dest............receives the resulting merged list
1657 *result..........receives the resulting type
1660 typecheck_TRUE...*dest has been modified
1661 typecheck_FALSE..*dest has not been modified
1662 typecheck_FAIL...an exception has been thrown
1665 RESULT is an extra parameter so it can point to dest->typeclass or to
1668 *******************************************************************************/
1670 static typecheck_result
1671 typeinfo_merge_nonarrays(typeinfo_t *dest,
1672 classref_or_classinfo *result,
1673 classref_or_classinfo x,classref_or_classinfo y,
1674 typeinfo_mergedlist_t *mergedx,
1675 typeinfo_mergedlist_t *mergedy)
1677 classref_or_classinfo t;
1678 classinfo *tcls,*common;
1679 typeinfo_mergedlist_t *tmerged;
1685 TYPEINFO_ASSERT(dest && result && x.any && y.any);
1686 TYPEINFO_ASSERT(x.cls != pseudo_class_Null);
1687 TYPEINFO_ASSERT(y.cls != pseudo_class_Null);
1688 TYPEINFO_ASSERT(x.cls != pseudo_class_New);
1689 TYPEINFO_ASSERT(y.cls != pseudo_class_New);
1691 /*--------------------------------------------------*/
1693 /*--------------------------------------------------*/
1695 /* Common case 1: x and y are the same class or class reference */
1696 /* (This case is very simple unless *both* x and y really represent
1697 * merges of subclasses of clsx==clsy.)
1699 if ( (x.any == y.any) && (!mergedx || !mergedy) ) {
1701 /* DEBUG */ /* log_text("return simple x"); */
1702 changed = (dest->merged != NULL);
1703 TYPEINFO_FREEMERGED_IF_ANY(dest->merged);
1704 dest->merged = NULL;
1706 /* DEBUG */ /* log_text("returning"); */
1707 return (typecheck_result) changed;
1710 xname = (IS_CLASSREF(x)) ? x.ref->name : x.cls->name;
1711 yname = (IS_CLASSREF(y)) ? y.ref->name : y.cls->name;
1713 /* Common case 2: xname == yname, at least one unresolved */
1714 if ((IS_CLASSREF(x) || IS_CLASSREF(y)) && (xname == yname))
1716 /* use the loaded one if any */
1717 if (!IS_CLASSREF(y))
1719 goto return_simple_x;
1722 /*--------------------------------------------------*/
1723 /* non-trivial cases */
1724 /*--------------------------------------------------*/
1726 #ifdef TYPEINFO_VERBOSE
1728 typeinfo_t dbgx,dbgy;
1729 fprintf(stderr,"merge_nonarrays:\n");
1730 fprintf(stderr," ");if(IS_CLASSREF(x))fprintf(stderr,"<ref>");utf_fprint_printable_ascii(stderr,xname);fprintf(stderr,"\n");
1731 fprintf(stderr," ");if(IS_CLASSREF(y))fprintf(stderr,"<ref>");utf_fprint_printable_ascii(stderr,yname);fprintf(stderr,"\n");
1733 typeinfo_init_class(&dbgx,x);
1734 dbgx.merged = mergedx;
1735 typeinfo_init_class(&dbgy,y);
1736 dbgy.merged = mergedy;
1737 typeinfo_print(stderr,&dbgx,4);
1738 fprintf(stderr," with:\n");
1739 typeinfo_print(stderr,&dbgy,4);
1743 TYPEINFO_ASSERT(IS_CLASSREF(x) || (x.cls->state & CLASS_LOADED));
1744 TYPEINFO_ASSERT(IS_CLASSREF(y) || (y.cls->state & CLASS_LOADED));
1746 /* If y is unresolved or an interface, swap x and y. */
1747 if (IS_CLASSREF(y) || (!IS_CLASSREF(x) && y.cls->flags & ACC_INTERFACE))
1749 t = x; x = y; y = t;
1750 tmerged = mergedx; mergedx = mergedy; mergedy = tmerged;
1753 /* {We know: If only one of x,y is unresolved it is x,} */
1754 /* { If both x,y are resolved and only one of x,y is an interface it is x.} */
1756 if (IS_CLASSREF(x)) {
1757 /* {We know: x and y have different class names} */
1759 /* Check if we are merging an unresolved type with java.lang.Object */
1760 if (y.cls == class_java_lang_Object && !mergedy) {
1762 goto return_simple_x;
1765 common = class_java_lang_Object;
1766 goto merge_with_simple_x;
1769 /* {We know: both x and y are resolved} */
1770 /* {We know: If only one of x,y is an interface it is x.} */
1772 TYPEINFO_ASSERT(!IS_CLASSREF(x) && !IS_CLASSREF(y));
1773 TYPEINFO_ASSERT(x.cls->state & CLASS_LOADED);
1774 TYPEINFO_ASSERT(y.cls->state & CLASS_LOADED);
1776 /* Handle merging of interfaces: */
1777 if (x.cls->flags & ACC_INTERFACE) {
1778 /* {x.cls is an interface and mergedx == NULL.} */
1780 if (y.cls->flags & ACC_INTERFACE) {
1781 /* We are merging two interfaces. */
1782 /* {mergedy == NULL} */
1784 /* {We know that x.cls!=y.cls (see common case at beginning.)} */
1785 result->cls = class_java_lang_Object;
1786 return (typecheck_result) typeinfo_merge_two(dest,x,y);
1789 /* {We know: x is an interface, y is a class.} */
1791 /* Check if we are merging an interface with java.lang.Object */
1792 if (y.cls == class_java_lang_Object && !mergedy) {
1794 goto return_simple_x;
1797 /* If the type y implements x then the result of the merge
1798 * is x regardless of mergedy.
1801 /* we may have to link the classes */
1802 if (!(x.cls->state & CLASS_LINKED))
1803 if (!link_class(x.cls))
1804 return typecheck_FAIL;
1805 if (!(y.cls->state & CLASS_LINKED))
1806 if (!link_class(y.cls))
1807 return typecheck_FAIL;
1809 TYPEINFO_ASSERT(x.cls->state & CLASS_LINKED);
1810 TYPEINFO_ASSERT(y.cls->state & CLASS_LINKED);
1812 if (CLASSINFO_IMPLEMENTS_INTERFACE(y.cls,x.cls->index))
1814 /* y implements x, so the result of the merge is x. */
1815 goto return_simple_x;
1818 r = mergedlist_implements_interface(mergedy,x.cls);
1819 if (r == typecheck_FAIL)
1821 if (r == typecheck_TRUE)
1823 /* y implements x, so the result of the merge is x. */
1824 goto return_simple_x;
1827 /* {We know: x is an interface, the type y a class or a merge
1828 * of subclasses and is not guaranteed to implement x.} */
1830 common = class_java_lang_Object;
1831 goto merge_with_simple_x;
1834 /* {We know: x and y are classes (not interfaces).} */
1836 /* we may have to link the classes */
1837 if (!(x.cls->state & CLASS_LINKED))
1838 if (!link_class(x.cls))
1839 return typecheck_FAIL;
1840 if (!(y.cls->state & CLASS_LINKED))
1841 if (!link_class(y.cls))
1842 return typecheck_FAIL;
1844 TYPEINFO_ASSERT(x.cls->state & CLASS_LINKED);
1845 TYPEINFO_ASSERT(y.cls->state & CLASS_LINKED);
1847 /* If *x is deeper in the inheritance hierarchy swap x and y. */
1848 if (x.cls->index > y.cls->index) {
1849 t = x; x = y; y = t;
1850 tmerged = mergedx; mergedx = mergedy; mergedy = tmerged;
1853 /* {We know: y is at least as deep in the hierarchy as x.} */
1855 /* Find nearest common anchestor for the classes. */
1860 while (tcls->index > common->index)
1863 while (common != tcls) {
1864 common = common->super;
1868 /* {common == nearest common anchestor of x and y.} */
1870 /* If x.cls==common and x is a whole class (not a merge of subclasses)
1871 * then the result of the merge is x.
1873 if (x.cls == common && !mergedx) {
1874 goto return_simple_x;
1878 result->cls = common;
1880 return (typecheck_result) typeinfo_merge_mergedlists(dest,mergedx,mergedy);
1882 return (typecheck_result) typeinfo_merge_add(dest,mergedx,y);
1885 merge_with_simple_x:
1886 result->cls = common;
1888 return (typecheck_result) typeinfo_merge_add(dest,mergedy,x);
1890 return (typecheck_result) typeinfo_merge_two(dest,x,y);
1893 /* typeinfo_merge **************************************************************
1898 m................method for exception messages
1899 dest.............the first type
1900 y................the second type
1903 *dest............receives the result of the merge
1906 typecheck_TRUE...*dest has been modified
1907 typecheck_FALSE..*dest has not been modified
1908 typecheck_FAIL...an exception has been thrown
1911 1) *dest must be a valid initialized typeinfo
1914 *******************************************************************************/
1917 typeinfo_merge(methodinfo *m,typeinfo_t *dest,typeinfo_t* y)
1921 classref_or_classinfo common;
1922 classref_or_classinfo elementclass;
1928 /*--------------------------------------------------*/
1930 /*--------------------------------------------------*/
1932 /* Merging something with itself is a nop */
1934 return typecheck_FALSE;
1936 /* Merging two returnAddress types is ok. */
1937 /* Merging two different returnAddresses never happens, as the verifier */
1938 /* keeps them separate in order to check all the possible return paths */
1939 /* from JSR subroutines. */
1940 if (!dest->typeclass.any && !y->typeclass.any) {
1941 TYPEINFO_ASSERT(TYPEINFO_RETURNADDRESS(*dest) == TYPEINFO_RETURNADDRESS(*y));
1942 return typecheck_FALSE;
1945 /* Primitive types cannot be merged with reference types */
1946 /* This must be checked before calls to typeinfo_merge. */
1947 TYPEINFO_ASSERT(dest->typeclass.any && y->typeclass.any);
1949 /* handle uninitialized object types */
1950 if (TYPEINFO_IS_NEWOBJECT(*dest) || TYPEINFO_IS_NEWOBJECT(*y)) {
1951 if (!TYPEINFO_IS_NEWOBJECT(*dest) || !TYPEINFO_IS_NEWOBJECT(*y)) {
1952 typeinfo_merge_error(m,(char*) "Trying to merge uninitialized object type.",dest,y);
1953 return typecheck_FAIL;
1955 if (TYPEINFO_NEWOBJECT_INSTRUCTION(*dest) != TYPEINFO_NEWOBJECT_INSTRUCTION(*y)) {
1956 typeinfo_merge_error(m,(char*) "Trying to merge different uninitialized objects.",dest,y);
1957 return typecheck_FAIL;
1959 /* the same uninitialized object -- no change */
1960 return typecheck_FALSE;
1963 /*--------------------------------------------------*/
1965 /*--------------------------------------------------*/
1967 /* Common case: dest and y are the same class or class reference */
1968 /* (This case is very simple unless *both* dest and y really represent
1969 * merges of subclasses of class dest==class y.)
1971 if ((dest->typeclass.any == y->typeclass.any) && (!dest->merged || !y->merged)) {
1973 changed = (dest->merged != NULL);
1974 TYPEINFO_FREEMERGED_IF_ANY(dest->merged);
1975 dest->merged = NULL;
1976 return (typecheck_result) changed;
1979 /* Handle null types: */
1980 if (TYPEINFO_IS_NULLTYPE(*y)) {
1981 return typecheck_FALSE;
1983 if (TYPEINFO_IS_NULLTYPE(*dest)) {
1984 TYPEINFO_FREEMERGED_IF_ANY(dest->merged);
1985 TYPEINFO_CLONE(*y,*dest);
1986 return typecheck_TRUE;
1989 /* Common case: two types with the same name, at least one unresolved */
1990 if (IS_CLASSREF(dest->typeclass)) {
1991 if (IS_CLASSREF(y->typeclass)) {
1992 if (dest->typeclass.ref->name == y->typeclass.ref->name)
1996 /* XXX should we take y instead of dest here? */
1997 if (dest->typeclass.ref->name == y->typeclass.cls->name)
2002 if (IS_CLASSREF(y->typeclass)
2003 && (dest->typeclass.cls->name == y->typeclass.ref->name))
2009 /*--------------------------------------------------*/
2010 /* non-trivial cases */
2011 /*--------------------------------------------------*/
2013 #ifdef TYPEINFO_VERBOSE
2014 fprintf(stderr,"merge:\n");
2015 typeinfo_print(stderr,dest,4);
2016 typeinfo_print(stderr,y,4);
2019 /* This function uses x internally, so x and y can be swapped
2020 * without changing dest. */
2024 /* Handle merging of arrays: */
2025 if (TYPEINFO_IS_ARRAY(*x) && TYPEINFO_IS_ARRAY(*y)) {
2027 /* Make x the one with lesser dimension */
2028 if (x->dimension > y->dimension) {
2029 tmp = x; x = y; y = tmp;
2032 /* If one array (y) has higher dimension than the other,
2033 * interpret it as an array (same dim. as x) of Arraystubs. */
2034 if (x->dimension < y->dimension) {
2035 dimension = x->dimension;
2036 elementtype = ARRAYTYPE_OBJECT;
2037 elementclass.cls = pseudo_class_Arraystub;
2040 dimension = y->dimension;
2041 elementtype = y->elementtype;
2042 elementclass = y->elementclass;
2045 /* {The arrays are of the same dimension.} */
2047 if (x->elementtype != elementtype) {
2048 /* Different element types are merged, so the resulting array
2049 * type has one accessible dimension less. */
2050 if (--dimension == 0) {
2051 common.cls = pseudo_class_Arraystub;
2053 elementclass.any = NULL;
2056 common.cls = class_multiarray_of(dimension,pseudo_class_Arraystub,true);
2058 exceptions_throw_internalerror("XXX Coult not create array class");
2059 return typecheck_FAIL;
2062 elementtype = ARRAYTYPE_OBJECT;
2063 elementclass.cls = pseudo_class_Arraystub;
2067 /* {The arrays have the same dimension and elementtype.} */
2069 if (elementtype == ARRAYTYPE_OBJECT) {
2070 /* The elements are references, so their respective
2071 * types must be merged.
2073 r = typeinfo_merge_nonarrays(dest,
2077 x->merged,y->merged);
2078 TYPEINFO_ASSERT(r != typecheck_MAYBE);
2079 if (r == typecheck_FAIL)
2083 /* DEBUG */ /* log_text("finding resulting array class: "); */
2084 if (IS_CLASSREF(elementclass))
2085 common.ref = class_get_classref_multiarray_of(dimension,elementclass.ref);
2087 common.cls = class_multiarray_of(dimension,elementclass.cls,true);
2089 exceptions_throw_internalerror("XXX Coult not create array class");
2090 return typecheck_FAIL;
2093 /* DEBUG */ /* utf_display_printable_ascii(common->name); printf("\n"); */
2096 common.any = y->typeclass.any;
2101 /* {We know that at least one of x or y is no array, so the
2102 * result cannot be an array.} */
2104 r = typeinfo_merge_nonarrays(dest,
2106 x->typeclass,y->typeclass,
2107 x->merged,y->merged);
2108 TYPEINFO_ASSERT(r != typecheck_MAYBE);
2109 if (r == typecheck_FAIL)
2115 elementclass.any = NULL;
2118 /* Put the new values into dest if neccessary. */
2120 if (dest->typeclass.any != common.any) {
2121 dest->typeclass.any = common.any;
2124 if (dest->dimension != dimension) {
2125 dest->dimension = dimension;
2128 if (dest->elementtype != elementtype) {
2129 dest->elementtype = elementtype;
2132 if (dest->elementclass.any != elementclass.any) {
2133 dest->elementclass.any = elementclass.any;
2137 return (typecheck_result) changed;
2139 #endif /* ENABLE_VERIFER */
2142 /**********************************************************************/
2143 /* DEBUGGING HELPERS */
2144 /**********************************************************************/
2146 #ifdef TYPEINFO_DEBUG
2150 typeinfo_test_compare(classref_or_classinfo *a,classref_or_classinfo *b)
2152 if (a->any == b->any) return 0;
2153 if (a->any < b->any) return -1;
2158 typeinfo_test_parse(typeinfo_t *info,char *str)
2162 typeinfo_t *infobuf;
2165 utf *desc = utf_new_char(str);
2167 num = typeinfo_count_method_args(desc,false);
2169 typebuf = (u1*) DumpMemory::allocate(sizeof(u1) * num);
2170 infobuf = (typeinfo_t*) DumpMemory::allocate(sizeof(typeinfo_t) * num);
2172 typeinfo_init_from_method_args(desc,typebuf,infobuf,num,false,
2175 TYPEINFO_ALLOCMERGED(info->merged,num);
2176 info->merged->count = num;
2178 for (i=0; i<num; ++i) {
2179 if (typebuf[i] != TYPE_ADR) {
2180 log_text("non-reference type in mergedlist");
2184 info->merged->list[i].any = infobuf[i].typeclass.any;
2186 qsort(info->merged->list,num,sizeof(classref_or_classinfo),
2187 (int(*)(const void *,const void *))&typeinfo_test_compare);
2190 typeinfo_init_from_method_args(desc,NULL,NULL,0,false,
2196 #define TYPEINFO_TEST_BUFLEN 4000
2199 typeinfo_equal(typeinfo_t *x,typeinfo_t *y)
2203 if (x->typeclass.any != y->typeclass.any) return false;
2204 if (x->dimension != y->dimension) return false;
2206 if (x->elementclass.any != y->elementclass.any) return false;
2207 if (x->elementtype != y->elementtype) return false;
2210 if (TYPEINFO_IS_NEWOBJECT(*x))
2211 if (TYPEINFO_NEWOBJECT_INSTRUCTION(*x)
2212 != TYPEINFO_NEWOBJECT_INSTRUCTION(*y))
2215 if (x->merged || y->merged) {
2216 if (!(x->merged && y->merged)) return false;
2217 if (x->merged->count != y->merged->count) return false;
2218 for (i=0; i<x->merged->count; ++i)
2219 if (x->merged->list[i].any != y->merged->list[i].any)
2226 typeinfo_testmerge(typeinfo_t *a,typeinfo_t *b,typeinfo_t *result,int *failed)
2229 bool changed,changed_should_be;
2232 TYPEINFO_CLONE(*a,dest);
2235 typeinfo_print_short(stdout,&dest);
2237 typeinfo_print_short(stdout,b);
2240 r = typeinfo_merge(NULL,&dest,b);
2241 if (r == typecheck_FAIL) {
2242 printf("EXCEPTION\n");
2245 changed = (r) ? 1 : 0;
2246 changed_should_be = (!typeinfo_equal(&dest,a)) ? 1 : 0;
2248 printf(" %s\n",(changed) ? "changed" : "=");
2250 if (typeinfo_equal(&dest,result)) {
2252 typeinfo_print_short(stdout,&dest);
2254 if (changed != changed_should_be) {
2255 printf("WRONG RETURN VALUE!\n");
2261 typeinfo_print_short(stdout,&dest);
2263 printf("SHOULD BE ");
2264 typeinfo_print_short(stdout,result);
2272 typeinfo_inc_dimension(typeinfo_t *info)
2274 if (info->dimension++ == 0) {
2275 info->elementtype = ARRAYTYPE_OBJECT;
2276 info->elementclass = info->typeclass;
2278 info->typeclass = class_array_of(info->typeclass,true);
2282 #define TYPEINFO_TEST_MAXDIM 10
2285 typeinfo_testrun(char *filename)
2287 char buf[TYPEINFO_TEST_BUFLEN];
2288 char bufa[TYPEINFO_TEST_BUFLEN];
2289 char bufb[TYPEINFO_TEST_BUFLEN];
2290 char bufc[TYPEINFO_TEST_BUFLEN];
2294 FILE *file = fopen(filename,"rt");
2298 log_text("could not open typeinfo test file");
2302 while (fgets(buf,TYPEINFO_TEST_BUFLEN,file)) {
2303 if (buf[0] == '#' || !strlen(buf))
2306 res = sscanf(buf,"%s\t%s\t%s\n",bufa,bufb,bufc);
2307 if (res != 3 || !strlen(bufa) || !strlen(bufb) || !strlen(bufc)) {
2308 log_text("Invalid line in typeinfo test file (none of empty, comment or test)");
2313 typeinfo_test_parse(&a,bufa);
2314 typeinfo_test_parse(&b,bufb);
2315 typeinfo_test_parse(&c,bufc);
2320 typeinfo_testmerge(&a,&b,&c,&failed); /* check result */
2321 typeinfo_testmerge(&b,&a,&c,&failed); /* check commutativity */
2323 if (TYPEINFO_IS_NULLTYPE(a)) break;
2324 if (TYPEINFO_IS_NULLTYPE(b)) break;
2325 if (TYPEINFO_IS_NULLTYPE(c)) break;
2327 maxdim = a.dimension;
2328 if (b.dimension > maxdim) maxdim = b.dimension;
2329 if (c.dimension > maxdim) maxdim = c.dimension;
2332 if (maxdim < TYPEINFO_TEST_MAXDIM) {
2333 typeinfo_inc_dimension(&a);
2334 typeinfo_inc_dimension(&b);
2335 typeinfo_inc_dimension(&c);
2337 } while (maxdim < TYPEINFO_TEST_MAXDIM);
2344 fprintf(stderr,"Failed typeinfo_merge tests: %d\n",failed);
2345 log_text("Failed test");
2353 log_text("Running typeinfo test file...");
2354 typeinfo_testrun("typeinfo.tst");
2355 log_text("Finished typeinfo test file.");
2360 typeinfo_init_from_fielddescriptor(typeinfo_t *info,char *desc)
2362 typeinfo_init_from_descriptor(info,desc,desc+strlen(desc));
2366 #define TYPEINFO_MAXINDENT 80
2369 typeinfo_print_class(FILE *file,classref_or_classinfo c)
2371 /*fprintf(file,"<class %p>",c.any);*/
2374 fprintf(file,"<null>");
2377 if (IS_CLASSREF(c)) {
2378 fprintf(file,"<ref>");
2379 utf_fprint_printable_ascii(file,c.ref->name);
2382 utf_fprint_printable_ascii(file,c.cls->name);
2388 typeinfo_print(FILE *file,typeinfo_t *info,int indent)
2391 char ind[TYPEINFO_MAXINDENT + 1];
2395 if (indent > TYPEINFO_MAXINDENT) indent = TYPEINFO_MAXINDENT;
2397 for (i=0; i<indent; ++i)
2401 if (TYPEINFO_IS_PRIMITIVE(*info)) {
2402 bptr = (basicblock*) TYPEINFO_RETURNADDRESS(*info);
2404 fprintf(file,"%sreturnAddress (L%03d)\n",ind,bptr->nr);
2406 fprintf(file,"%sprimitive\n",ind);
2410 if (TYPEINFO_IS_NULLTYPE(*info)) {
2411 fprintf(file,"%snull\n",ind);
2415 if (TYPEINFO_IS_NEWOBJECT(*info)) {
2416 ins = (instruction *) TYPEINFO_NEWOBJECT_INSTRUCTION(*info);
2418 fprintf(file,"%sNEW(%p):",ind,(void*)ins);
2419 typeinfo_print_class(file,ins[-1].sx.val.c);
2423 fprintf(file,"%sNEW(this)",ind);
2428 fprintf(file,"%sClass: ",ind);
2429 typeinfo_print_class(file,info->typeclass);
2432 if (TYPEINFO_IS_ARRAY(*info)) {
2433 fprintf(file,"%sDimension: %d",ind,(int)info->dimension);
2434 fprintf(file,"\n%sElements: ",ind);
2435 switch (info->elementtype) {
2436 case ARRAYTYPE_INT : fprintf(file,"int\n"); break;
2437 case ARRAYTYPE_LONG : fprintf(file,"long\n"); break;
2438 case ARRAYTYPE_FLOAT : fprintf(file,"float\n"); break;
2439 case ARRAYTYPE_DOUBLE : fprintf(file,"double\n"); break;
2440 case ARRAYTYPE_BYTE : fprintf(file,"byte\n"); break;
2441 case ARRAYTYPE_CHAR : fprintf(file,"char\n"); break;
2442 case ARRAYTYPE_SHORT : fprintf(file,"short\n"); break;
2443 case ARRAYTYPE_BOOLEAN : fprintf(file,"boolean\n"); break;
2445 case ARRAYTYPE_OBJECT:
2446 typeinfo_print_class(file,info->elementclass);
2451 fprintf(file,"INVALID ARRAYTYPE!\n");
2456 fprintf(file,"%sMerged: ",ind);
2457 for (i=0; i<info->merged->count; ++i) {
2458 if (i) fprintf(file,", ");
2459 typeinfo_print_class(file,info->merged->list[i]);
2466 typeinfo_print_short(FILE *file,typeinfo_t *info)
2472 /*fprintf(file,"<typeinfo %p>",info);*/
2475 fprintf(file,"(typeinfo*)NULL");
2479 if (TYPEINFO_IS_PRIMITIVE(*info)) {
2480 bptr = (basicblock*) TYPEINFO_RETURNADDRESS(*info);
2482 fprintf(file,"ret(L%03d)",bptr->nr);
2484 fprintf(file,"primitive");
2488 if (TYPEINFO_IS_NULLTYPE(*info)) {
2489 fprintf(file,"null");
2493 if (TYPEINFO_IS_NEWOBJECT(*info)) {
2494 ins = (instruction *) TYPEINFO_NEWOBJECT_INSTRUCTION(*info);
2496 /*fprintf(file,"<ins %p>",ins);*/
2497 fprintf(file,"NEW(%p):",(void*)ins);
2498 typeinfo_print_class(file,ins[-1].sx.val.c);
2501 fprintf(file,"NEW(this)");
2505 typeinfo_print_class(file,info->typeclass);
2509 for (i=0; i<info->merged->count; ++i) {
2510 if (i) fprintf(file,",");
2511 typeinfo_print_class(file,info->merged->list[i]);
2518 typeinfo_print_type(FILE *file,int type,typeinfo_t *info)
2521 case TYPE_VOID: fprintf(file,"V"); break;
2522 case TYPE_INT: fprintf(file,"I"); break;
2523 case TYPE_FLT: fprintf(file,"F"); break;
2524 case TYPE_DBL: fprintf(file,"D"); break;
2525 case TYPE_LNG: fprintf(file,"J"); break;
2526 case TYPE_RET: fprintf(file,"R:"); /* FALLTHROUGH! */
2528 typeinfo_print_short(file,info);
2537 typedescriptor_print(FILE *file,typedescriptor_t *td)
2539 typeinfo_print_type(file,td->type,&(td->typeinfo));
2543 typevector_print(FILE *file,varinfo *vec,int size)
2547 for (i=0; i<size; ++i) {
2548 fprintf(file," %d=",i);
2549 typeinfo_print_type(file, vec[i].type, &(vec[i].typeinfo));
2553 #if defined(__cplusplus)
2557 #endif /* TYPEINFO_DEBUG */
2561 * These are local overrides for various environment variables in Emacs.
2562 * Please do not remove this and leave it at the end of the file, where
2563 * Emacs will automagically detect them.
2564 * ---------------------------------------------------------------------
2567 * indent-tabs-mode: t
2571 * vim:noexpandtab:sw=4:ts=4: