Line data Source code
1 : /* src/vm/jit/verify/typeinfo.cpp - type system used by the type checker
2 :
3 : Copyright (C) 1996-2014
4 : CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
5 :
6 : This file is part of CACAO.
7 :
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.
12 :
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.
17 :
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
21 : 02110-1301, USA.
22 :
23 : */
24 :
25 :
26 : #include "config.h"
27 :
28 : #include <assert.h>
29 : #include <string.h>
30 :
31 : #include "mm/dumpmemory.hpp"
32 :
33 : #include "toolbox/logging.hpp"
34 :
35 : #include "vm/array.hpp"
36 : #include "vm/class.hpp"
37 : #include "vm/descriptor.hpp"
38 : #include "vm/exceptions.hpp"
39 : #include "vm/globals.hpp"
40 : #include "vm/primitive.hpp"
41 : #include "vm/resolve.hpp"
42 :
43 : #include "vm/jit/jit.hpp"
44 : #include "vm/jit/verify/typeinfo.hpp"
45 :
46 : #include "vm/jit/ir/instruction.hpp"
47 :
48 :
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)
51 :
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 ) )
56 :
57 : /******************************************************************************/
58 : /* DEBUG HELPERS */
59 : /******************************************************************************/
60 :
61 : #ifdef TYPEINFO_DEBUG
62 : #define TYPEINFO_ASSERT(cond) assert(cond)
63 : #else
64 : #define TYPEINFO_ASSERT(cond)
65 : #endif
66 :
67 : /**********************************************************************/
68 : /* TYPEVECTOR FUNCTIONS */
69 : /**********************************************************************/
70 :
71 : #if defined(ENABLE_VERIFIER)
72 :
73 : /* typevector_copy *************************************************************
74 :
75 : Return a copy of the given typevector.
76 :
77 : IN:
78 : src..............typevector set to copy, must be != NULL
79 : size.............number of elements per typevector
80 :
81 : RETURN VALUE:
82 : a pointer to the new typevector set
83 :
84 : *******************************************************************************/
85 :
86 : varinfo *
87 0 : typevector_copy(varinfo *src, int size)
88 : {
89 : varinfo *dst;
90 :
91 0 : TYPEINFO_ASSERT(src);
92 :
93 0 : dst = DNEW_TYPEVECTOR(size);
94 0 : memcpy(dst,src,TYPEVECTOR_SIZE(size));
95 :
96 0 : return dst;
97 : }
98 :
99 : /* typevector_copy_inplace *****************************************************
100 :
101 : Copy a typevector to a given destination.
102 :
103 : IN:
104 : src..............typevector to copy, must be != NULL
105 : dst..............destination to write the copy to
106 : size.............number of elements per typevector
107 :
108 : *******************************************************************************/
109 :
110 : void
111 560781 : typevector_copy_inplace(varinfo *src,varinfo *dst,int size)
112 : {
113 560781 : memcpy(dst,src,TYPEVECTOR_SIZE(size));
114 560781 : }
115 :
116 : /* typevector_checktype ********************************************************
117 :
118 : Check if the typevector contains a given type at a given index.
119 :
120 : IN:
121 : vec..............typevector set, must be != NULL
122 : index............index of component to check
123 : type.............TYPE_* constant to check against
124 :
125 : RETURN VALUE:
126 : true if the typevector contains TYPE at INDEX,
127 : false otherwise
128 :
129 : *******************************************************************************/
130 :
131 : bool
132 564964 : typevector_checktype(varinfo *vec,int index,int type)
133 : {
134 564964 : TYPEINFO_ASSERT(vec);
135 :
136 564964 : return vec[index].type == type;
137 : }
138 :
139 : /* typevector_checkreference ***************************************************
140 :
141 : Check if the typevector contains a reference at a given index.
142 :
143 : IN:
144 : vec..............typevector, must be != NULL
145 : index............index of component to check
146 :
147 : RETURN VALUE:
148 : true if the typevector contains a reference at INDEX,
149 : false otherwise
150 :
151 : *******************************************************************************/
152 :
153 : bool
154 0 : typevector_checkreference(varinfo *vec, int index)
155 : {
156 0 : TYPEINFO_ASSERT(vec);
157 0 : return vec[index].is_reference();
158 : }
159 :
160 : /* typevectorset_checkretaddr **************************************************
161 :
162 : Check if the typevectors contains a returnAddress at a given index.
163 :
164 : IN:
165 : vec..............typevector, must be != NULL
166 : index............index of component to check
167 :
168 : RETURN VALUE:
169 : true if the typevector contains a returnAddress at INDEX,
170 : false otherwise
171 :
172 : *******************************************************************************/
173 :
174 : bool
175 15 : typevector_checkretaddr(varinfo *vec,int index)
176 : {
177 15 : TYPEINFO_ASSERT(vec);
178 15 : return vec[index].is_returnaddress();
179 : }
180 :
181 : /* typevector_store ************************************************************
182 :
183 : Store a type at a given index in the typevector.
184 :
185 : IN:
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,
190 : if TYPE != TYPE_ADR
191 :
192 : *******************************************************************************/
193 :
194 : void
195 125849 : typevector_store(varinfo *vec,int index, Type type, typeinfo_t *info)
196 : {
197 125849 : TYPEINFO_ASSERT(vec);
198 :
199 125849 : vec[index].type = type;
200 125849 : if (info)
201 0 : vec[index].typeinfo = *info;
202 125849 : }
203 :
204 : /* typevector_store_retaddr ****************************************************
205 :
206 : Store a returnAddress type at a given index in the typevector.
207 :
208 : IN:
209 : vec..............typevector set, must be != NULL
210 : index............index of component to set
211 : info.............typeinfo of the returnAddress.
212 :
213 : *******************************************************************************/
214 :
215 : void
216 0 : typevector_store_retaddr(varinfo *vec,int index,typeinfo_t *info)
217 : {
218 0 : TYPEINFO_ASSERT(vec);
219 0 : TYPEINFO_ASSERT(info->is_primitive());
220 :
221 0 : vec[index].type = TYPE_ADR;
222 0 : vec[index].typeinfo.init_returnaddress(info->returnaddress());
223 0 : }
224 :
225 : /* typevector_init_object ******************************************************
226 :
227 : Replace all uninitialized object types in the typevector set which were
228 : created by the given instruction by initialized object types.
229 :
230 : IN:
231 : set..............typevector set
232 : ins..............instruction which created the uninitialized object type
233 : initclass........class of the initialized object type to set
234 : size.............number of elements per typevector
235 :
236 : RETURN VALUE:
237 : true.............success
238 : false............an exception has been thrown
239 :
240 : XXX maybe we should do the lazy resolving before calling this function
241 :
242 : *******************************************************************************/
243 :
244 : bool
245 78462 : typevector_init_object(varinfo *set,void *ins,
246 : classref_or_classinfo initclass,
247 : int size)
248 : {
249 : int i;
250 :
251 411708 : for (i=0; i<size; ++i) {
252 497665 : if (set[i].type == TYPE_ADR
253 164130 : && set[i].typeinfo.is_newobject()
254 289 : && set[i].typeinfo.newobject_instruction() == ins)
255 : {
256 284 : if (!set[i].typeinfo.init_class(initclass))
257 0 : return false;
258 : }
259 : }
260 78462 : return true;
261 : }
262 :
263 : /* typevector_merge ************************************************************
264 :
265 : Merge a typevector with another one.
266 : The given typevectors must have the same number of components.
267 :
268 : IN:
269 : m................method for exception messages
270 : dst..............the first typevector
271 : y................the second typevector
272 : size.............number of elements per typevector
273 :
274 : OUT:
275 : *dst.............the resulting typevector
276 :
277 : RETURN VALUE:
278 : typecheck_TRUE...dst has been modified
279 : typecheck_FALSE..dst has not been modified
280 : typecheck_FAIL...an exception has been thrown
281 :
282 : *******************************************************************************/
283 :
284 : typecheck_result
285 191330 : typevector_merge(methodinfo *m,varinfo *dst,varinfo *y,int size)
286 : {
287 191330 : bool changed = false;
288 : typecheck_result r;
289 :
290 191330 : varinfo *a = dst;
291 191330 : varinfo *b = y;
292 2129047 : while (size--) {
293 1749270 : if (a->type != TYPE_VOID && a->type != b->type) {
294 2883 : a->type = TYPE_VOID;
295 2883 : changed = true;
296 : }
297 1743504 : else if (a->type == TYPE_ADR) {
298 737114 : if (a->typeinfo.is_primitive()) {
299 : /* 'a' is a returnAddress */
300 0 : if (!b->typeinfo.is_primitive()
301 : || (a->typeinfo.returnaddress() != b->typeinfo.returnaddress()))
302 : {
303 0 : a->type = TYPE_VOID;
304 0 : changed = true;
305 : }
306 : }
307 : else {
308 : /* 'a' is a reference */
309 737114 : if (b->typeinfo.is_primitive()) {
310 0 : a->type = TYPE_VOID;
311 0 : changed = true;
312 : }
313 : else {
314 : /* two reference types are merged. There cannot be */
315 : /* a merge error. In the worst case we get j.l.O. */
316 737114 : r = a->typeinfo.merge(m, &(b->typeinfo));
317 737114 : if (r == typecheck_FAIL)
318 0 : return r;
319 737114 : changed |= r;
320 : }
321 : }
322 : }
323 1746387 : a++;
324 1746387 : b++;
325 : }
326 191330 : return (typecheck_result) changed;
327 : }
328 :
329 : /**********************************************************************/
330 : /* READ-ONLY FUNCTIONS */
331 : /* The following functions don't change typeinfo data. */
332 : /**********************************************************************/
333 :
334 : /* interface_extends_interface *************************************************
335 :
336 : Check if a resolved interface extends a given resolved interface.
337 :
338 : IN:
339 : cls..............the interface, must be linked
340 : interf...........the interface to check against
341 :
342 : RETURN VALUE:
343 : true.............CLS extends INTERF
344 : false............CLS does not extend INTERF
345 :
346 : *******************************************************************************/
347 :
348 : static bool
349 441 : interface_extends_interface(classinfo *cls,classinfo *interf)
350 : {
351 : int i;
352 :
353 441 : TYPEINFO_ASSERT(cls);
354 441 : TYPEINFO_ASSERT(interf);
355 441 : TYPEINFO_ASSERT((interf->flags & ACC_INTERFACE) != 0);
356 441 : TYPEINFO_ASSERT((cls->flags & ACC_INTERFACE) != 0);
357 441 : TYPEINFO_ASSERT(cls->state & CLASS_LINKED);
358 :
359 : /* first check direct superinterfaces */
360 441 : for (i=0; i<cls->interfacescount; ++i) {
361 441 : if (cls->interfaces[i] == interf)
362 441 : return true;
363 : }
364 :
365 : /* check indirect superinterfaces */
366 0 : for (i=0; i<cls->interfacescount; ++i) {
367 0 : if (interface_extends_interface(cls->interfaces[i],interf))
368 0 : return true;
369 : }
370 :
371 0 : return false;
372 : }
373 :
374 : /* classinfo_implements_interface **********************************************
375 :
376 : Check if a resolved class implements a given resolved interface.
377 :
378 : IN:
379 : cls..............the class
380 : interf...........the interface
381 :
382 : RETURN VALUE:
383 : typecheck_TRUE...CLS implements INTERF
384 : typecheck_FALSE..CLS does not implement INTERF
385 : typecheck_FAIL...an exception has been thrown
386 :
387 : *******************************************************************************/
388 :
389 : static typecheck_result
390 6179 : classinfo_implements_interface(classinfo *cls,classinfo *interf)
391 : {
392 6179 : TYPEINFO_ASSERT(cls);
393 6179 : TYPEINFO_ASSERT(interf);
394 6179 : TYPEINFO_ASSERT((interf->flags & ACC_INTERFACE) != 0);
395 :
396 6179 : if (!(cls->state & CLASS_LINKED))
397 0 : if (!link_class(cls))
398 0 : return typecheck_FAIL;
399 :
400 6179 : if (cls->flags & ACC_INTERFACE) {
401 : /* cls is an interface */
402 1750 : if (cls == interf)
403 1309 : return typecheck_TRUE;
404 :
405 : /* check superinterfaces */
406 441 : return (typecheck_result) interface_extends_interface(cls,interf);
407 : }
408 :
409 4429 : TYPEINFO_ASSERT(cls->state & CLASS_LINKED);
410 4429 : return (typecheck_result) CLASSINFO_IMPLEMENTS_INTERFACE(cls,interf->index);
411 : }
412 :
413 : /* mergedlist_implements_interface *********************************************
414 :
415 : Check if all the classes in a given merged list implement a given resolved
416 : interface.
417 :
418 : IN:
419 : merged...........the list of merged class types
420 : interf...........the interface to check against
421 :
422 : RETURN VALUE:
423 : typecheck_TRUE...all classes implement INTERF
424 : typecheck_FALSE..there is at least one class that does not implement
425 : INTERF
426 : typecheck_MAYBE..check cannot be performed now because of unresolved
427 : classes
428 : typecheck_FAIL...an exception has been thrown
429 :
430 : *******************************************************************************/
431 :
432 : static typecheck_result
433 143 : mergedlist_implements_interface(typeinfo_mergedlist_t *merged,
434 : classinfo *interf)
435 : {
436 : int i;
437 : classref_or_classinfo *mlist;
438 : typecheck_result r;
439 :
440 143 : TYPEINFO_ASSERT(interf);
441 143 : TYPEINFO_ASSERT((interf->flags & ACC_INTERFACE) != 0);
442 :
443 : /* Check if there is an non-empty mergedlist. */
444 143 : if (!merged)
445 2 : return typecheck_FALSE;
446 :
447 : /* If all classinfos in the (non-empty) merged array implement the
448 : * interface return true, otherwise false.
449 : */
450 141 : mlist = merged->list;
451 141 : i = merged->count;
452 423 : while (i--) {
453 282 : if (mlist->is_classref()) {
454 141 : return typecheck_MAYBE;
455 : }
456 141 : r = classinfo_implements_interface((mlist++)->cls,interf);
457 141 : if (r != typecheck_TRUE)
458 0 : return r;
459 : }
460 0 : return typecheck_TRUE;
461 : }
462 :
463 : /* merged_implements_interface *************************************************
464 :
465 : Check if a possible merged type implements a given resolved interface
466 : interface.
467 :
468 : IN:
469 : typeclass........(common) class of the (merged) type
470 : merged...........the list of merged class types
471 : interf...........the interface to check against
472 :
473 : RETURN VALUE:
474 : typecheck_TRUE...the type implement INTERF
475 : typecheck_FALSE..the type does not implement INTERF
476 : typecheck_MAYBE..check cannot be performed now because of unresolved
477 : classes
478 : typecheck_FAIL...an exception has been thrown
479 :
480 : *******************************************************************************/
481 :
482 : static typecheck_result
483 6038 : merged_implements_interface(classinfo *typeclass,typeinfo_mergedlist_t *merged,
484 : classinfo *interf)
485 : {
486 : typecheck_result r;
487 :
488 : /* primitive types don't support interfaces. */
489 6038 : if (!typeclass)
490 0 : return typecheck_FALSE;
491 :
492 : /* the null type can be cast to any interface type. */
493 6038 : if (typeclass == pseudo_class_Null)
494 0 : return typecheck_TRUE;
495 :
496 : /* check if typeclass implements the interface. */
497 6038 : r = classinfo_implements_interface(typeclass,interf);
498 6038 : if (r != typecheck_FALSE)
499 5897 : return r;
500 :
501 : /* check the mergedlist */
502 141 : if (!merged)
503 0 : return typecheck_FALSE;
504 141 : return mergedlist_implements_interface(merged,interf);
505 : }
506 :
507 : /* merged_is_subclass **********************************************************
508 :
509 : Check if a possible merged type is a subclass of a given class.
510 : A merged type is a subclass of a class C if all types in the merged list
511 : are subclasses of C. A sufficient condition for this is that the
512 : common type of the merged type is a subclass of C.
513 :
514 : IN:
515 : typeclass........(common) class of the (merged) type
516 : MUST be a loaded and linked class
517 : merged...........the list of merged class types
518 : cls..............the class to theck against
519 :
520 : RETURN VALUE:
521 : typecheck_TRUE...the type is a subclass of CLS
522 : typecheck_FALSE..the type is not a subclass of CLS
523 : typecheck_MAYBE..check cannot be performed now because of unresolved
524 : classes
525 : typecheck_FAIL...an exception has been thrown
526 :
527 : *******************************************************************************/
528 :
529 : static typecheck_result
530 71185 : merged_is_subclass(classinfo *typeclass,typeinfo_mergedlist_t *merged,
531 : classinfo *cls)
532 : {
533 : int i;
534 : classref_or_classinfo *mlist;
535 :
536 71185 : TYPEINFO_ASSERT(cls);
537 :
538 : /* primitive types aren't subclasses of anything. */
539 71185 : if (!typeclass)
540 0 : return typecheck_FALSE;
541 :
542 : /* the null type can be cast to any reference type. */
543 71185 : if (typeclass == pseudo_class_Null)
544 0 : return typecheck_TRUE;
545 :
546 71185 : TYPEINFO_ASSERT(typeclass->state & CLASS_LOADED);
547 71185 : TYPEINFO_ASSERT(typeclass->state & CLASS_LINKED);
548 :
549 : /* check if the common typeclass is a subclass of CLS. */
550 71185 : if (class_issubclass(typeclass,cls))
551 71179 : return typecheck_TRUE;
552 :
553 : /* check the mergedlist */
554 6 : if (!merged)
555 6 : return typecheck_FALSE;
556 : /* If all classinfos in the (non-empty) merged list are subclasses
557 : * of CLS, return true, otherwise false.
558 : * If there is at least one unresolved type in the list,
559 : * return typecheck_MAYBE.
560 : */
561 0 : mlist = merged->list;
562 0 : i = merged->count;
563 0 : while (i--) {
564 0 : if (mlist->is_classref()) {
565 0 : return typecheck_MAYBE;
566 : }
567 0 : if (!(mlist->cls->state & CLASS_LINKED))
568 0 : if (!link_class(mlist->cls))
569 0 : return typecheck_FAIL;
570 0 : if (!class_issubclass(mlist->cls,cls))
571 0 : return typecheck_FALSE;
572 0 : mlist++;
573 : }
574 0 : return typecheck_TRUE;
575 : }
576 :
577 : /***
578 : * Check if a type is assignable to a given class type.
579 : *
580 : * RETURN VALUE:
581 : * typecheck_TRUE...the type is assignable
582 : * typecheck_FALSE..the type is not assignable
583 : * typecheck_MAYBE..check cannot be performed now because of unresolved classes
584 : * typecheck_FAIL...an exception has been thrown
585 : */
586 106174 : typecheck_result typeinfo_t::is_assignable_to_class(classref_or_classinfo dest) const {
587 106174 : classref_or_classinfo c = typeclass;
588 :
589 : /* assignments of primitive values are not checked here. */
590 106174 : if (!c.any && !dest.any)
591 0 : return typecheck_TRUE;
592 :
593 : /* primitive and reference types are not assignment compatible. */
594 106174 : if (!c.any || !dest.any)
595 0 : return typecheck_FALSE;
596 :
597 : /* the null type can be assigned to any type */
598 106174 : if (is_nulltype())
599 3127 : return typecheck_TRUE;
600 :
601 : /* uninitialized objects are not assignable */
602 103047 : if (is_newobject())
603 0 : return typecheck_FALSE;
604 :
605 103047 : Utf8String classname = CLASSREF_OR_CLASSINFO_NAME(c);
606 :
607 103047 : if (dest.is_classref()) {
608 : /* the destination type is an unresolved class reference */
609 : /* In this case we cannot tell a lot about assignability. */
610 :
611 : /* the common case of value and dest type having the same classname */
612 7177 : if (dest.ref->name == classname && !merged)
613 2972 : return typecheck_TRUE;
614 :
615 : /* we cannot tell if value is assignable to dest, so we */
616 : /* leave it up to the resolving code to check this */
617 4205 : return typecheck_MAYBE;
618 : }
619 :
620 : /* { we know that dest is a loaded class } */
621 :
622 95870 : if (c.is_classref()) {
623 : /* the value type is an unresolved class reference */
624 :
625 : /* the common case of value and dest type having the same classname */
626 17506 : if (dest.cls->name == classname)
627 2 : return typecheck_TRUE;
628 :
629 : /* we cannot tell if value is assignable to dest, so we */
630 : /* leave it up to the resolving code to check this */
631 17504 : return typecheck_MAYBE;
632 : }
633 :
634 : /* { we know that both c and dest are loaded classes } */
635 : /* (c may still have a merged list containing unresolved classrefs!) */
636 :
637 78364 : TYPEINFO_ASSERT(c.is_classinfo());
638 78364 : TYPEINFO_ASSERT(dest.is_classinfo());
639 :
640 78364 : classinfo *cls = c.cls;
641 :
642 78364 : TYPEINFO_ASSERT(cls->state & CLASS_LOADED);
643 78364 : TYPEINFO_ASSERT(dest.cls->state & CLASS_LOADED);
644 :
645 : /* maybe we need to link the classes */
646 78364 : if (!(cls->state & CLASS_LINKED))
647 0 : if (!link_class(cls))
648 0 : return typecheck_FAIL;
649 78364 : if (!(dest.cls->state & CLASS_LINKED))
650 0 : if (!link_class(dest.cls))
651 0 : return typecheck_FAIL;
652 :
653 : /* { we know that both c and dest are linked classes } */
654 78364 : TYPEINFO_ASSERT(cls->state & CLASS_LINKED);
655 78364 : TYPEINFO_ASSERT(dest.cls->state & CLASS_LINKED);
656 :
657 78364 : if (dest.cls->flags & ACC_INTERFACE) {
658 : /* We are assigning to an interface type. */
659 5988 : return merged_implements_interface(cls, merged, dest.cls);
660 : }
661 :
662 72376 : if (CLASSINFO_IS_ARRAY(dest.cls)) {
663 3156 : arraydescriptor *arraydesc = dest.cls->vftbl->arraydesc;
664 3156 : int dimension = arraydesc->dimension;
665 3156 : classinfo *elementclass = (arraydesc->elementvftbl) ? arraydesc->elementvftbl->clazz : NULL;
666 :
667 : /* We are assigning to an array type. */
668 3156 : if (!is_array())
669 0 : return typecheck_FALSE;
670 :
671 : /* {Both value and dest.cls are array types.} */
672 :
673 : /* value must have at least the dimension of dest.cls. */
674 3156 : if (this->dimension < dimension)
675 0 : return typecheck_FALSE;
676 :
677 3156 : if (this->dimension > dimension) {
678 : /* value has higher dimension so we need to check
679 : * if its component array can be assigned to the
680 : * element type of dest.cls */
681 :
682 3 : if (!elementclass) return typecheck_FALSE;
683 :
684 3 : if (elementclass->flags & ACC_INTERFACE) {
685 : /* We are assigning to an interface type. */
686 0 : return classinfo_implements_interface(pseudo_class_Arraystub, elementclass);
687 : }
688 :
689 : /* We are assigning to a class type. */
690 3 : return (typecheck_result) class_issubclass(pseudo_class_Arraystub, elementclass);
691 : }
692 :
693 : /* {value and dest.cls have the same dimension} */
694 :
695 3153 : if (elementtype != arraydesc->elementtype)
696 0 : return typecheck_FALSE;
697 :
698 3153 : if (this->elementclass.any) {
699 : /* We are assigning an array of objects so we have to
700 : * check if the elements are assignable.
701 : */
702 :
703 2089 : if (elementclass->flags & ACC_INTERFACE) {
704 : /* We are assigning to an interface type. */
705 :
706 50 : return merged_implements_interface(this->elementclass.cls, merged, elementclass);
707 : }
708 :
709 : /* We are assigning to a class type. */
710 2039 : return merged_is_subclass(this->elementclass.cls, merged, elementclass);
711 : }
712 :
713 1064 : return typecheck_TRUE;
714 : }
715 :
716 : /* {dest.cls is not an array} */
717 : /* {dest.cls is a loaded class} */
718 :
719 : /* If there are any unresolved references in the merged list, we cannot */
720 : /* tell if the assignment will be ok. */
721 : /* This can only happen when cls is java.lang.Object */
722 69220 : if (cls == class_java_lang_Object && merged) {
723 89 : classref_or_classinfo *mlist = merged->list;
724 89 : int i = merged->count;
725 237 : while (i--) {
726 133 : if (mlist->is_classref())
727 74 : return typecheck_MAYBE;
728 59 : mlist++;
729 : }
730 : }
731 :
732 : /* We are assigning to a class type */
733 69146 : if (cls->flags & ACC_INTERFACE)
734 143 : cls = class_java_lang_Object;
735 :
736 69146 : return merged_is_subclass(cls, merged, dest.cls);
737 : }
738 :
739 : /***
740 : *
741 : * Check if a type is assignable to a given type.
742 : *
743 : * @param dest the type of the destination, must not be a merged type
744 : *
745 : * RETURN VALUE:
746 : * typecheck_TRUE...the type is assignable
747 : * typecheck_FALSE..the type is not assignable
748 : * typecheck_MAYBE..check cannot be performed now because of unresolved classes
749 : * typecheck_FAIL...an exception has been thrown
750 : */
751 39056 : typecheck_result typeinfo_t::is_assignable_to(typeinfo_t *dest) const {
752 39056 : TYPEINFO_ASSERT(dest);
753 39056 : TYPEINFO_ASSERT(dest->merged == NULL);
754 :
755 39056 : return is_assignable_to_class(dest->typeclass);
756 : }
757 :
758 : /**********************************************************************/
759 : /* INITIALIZATION FUNCTIONS */
760 : /* The following functions fill in uninitialized typeinfo structures. */
761 : /**********************************************************************/
762 :
763 : /* internally used macros ***************************************************/
764 :
765 : #define TYPEINFO_ALLOCMERGED(mergedlist,count) \
766 : do {(mergedlist) = (typeinfo_mergedlist_t *) DumpMemory::allocate(sizeof(typeinfo_mergedlist_t) \
767 : + ((count)-1)*sizeof(classinfo*));} while(0)
768 :
769 : #define TYPEINFO_FREEMERGED(mergedlist)
770 :
771 : #define TYPEINFO_FREEMERGED_IF_ANY(mergedlist)
772 :
773 :
774 : /* typeinfo_t::init_class ******************************************************
775 :
776 : Initialize a typeinfo to a resolved class.
777 :
778 : IN:
779 : c................the class
780 :
781 : OUT:
782 : *info............is initialized
783 :
784 : RETURN VALUE:
785 : true.............success
786 : false............an exception has been thrown
787 :
788 : *******************************************************************************/
789 :
790 658999 : void typeinfo_t::init_class(classinfo *c) {
791 658999 : if ((typeclass.cls = c)->vftbl->arraydesc) {
792 79568 : if (c->vftbl->arraydesc->elementvftbl)
793 39557 : elementclass.cls = c->vftbl->arraydesc->elementvftbl->clazz;
794 : else
795 40011 : elementclass.any = NULL;
796 79568 : dimension = c->vftbl->arraydesc->dimension;
797 79568 : elementtype = c->vftbl->arraydesc->elementtype;
798 : }
799 : else {
800 579431 : elementclass.any = NULL;
801 579431 : dimension = 0;
802 579431 : elementtype = ARRAYTYPE_INT;
803 : }
804 658999 : merged = NULL;
805 658999 : }
806 :
807 : /* typeinfo_t::init_class ******************************************************
808 :
809 : Initialize a typeinfo to a possibly unresolved class type.
810 :
811 : IN:
812 : c................the class type
813 :
814 : OUT:
815 : *info............is initialized
816 :
817 : RETURN VALUE:
818 : true.............success
819 : false............an exception has been thrown
820 :
821 : *******************************************************************************/
822 :
823 456281 : bool typeinfo_t::init_class(classref_or_classinfo c) {
824 456281 : TYPEINFO_ASSERT(c.any);
825 :
826 : classinfo *cls;
827 :
828 : /* if necessary, try to resolve lazily */
829 456281 : if (!resolve_classref_or_classinfo(NULL /* XXX should know method */,
830 : c,resolveLazy,false,true,&cls))
831 : {
832 0 : return false;
833 : }
834 :
835 456281 : if (cls) {
836 366213 : init_class(cls);
837 366213 : return true;
838 : }
839 :
840 : /* {the type could no be resolved lazily} */
841 :
842 90068 : typeclass.ref = c.ref;
843 90068 : elementclass.any = NULL;
844 90068 : dimension = 0;
845 90068 : merged = NULL;
846 :
847 : /* handle array type references */
848 90068 : const char *utf_ptr = c.ref->name.begin();
849 90068 : int len = c.ref->name.size();
850 90068 : if (*utf_ptr == '[') {
851 : /* count dimensions */
852 8272 : while (*utf_ptr == '[') {
853 2760 : utf_ptr++;
854 2760 : dimension++;
855 2760 : len--;
856 : }
857 2756 : if (*utf_ptr == 'L') {
858 2756 : utf_ptr++;
859 2756 : len -= 2;
860 2756 : elementtype = ARRAYTYPE_OBJECT;
861 2756 : elementclass.ref = class_get_classref(c.ref->referer, Utf8String::from_utf8(utf_ptr,len));
862 : }
863 : else {
864 : /* an array with primitive element type */
865 : /* should have been resolved above */
866 0 : TYPEINFO_ASSERT(false);
867 : }
868 : }
869 90068 : return true;
870 : }
871 :
872 : /* typeinfo_t::init_from_typedesc **********************************************
873 :
874 : Initialize a typeinfo from a typedesc.
875 :
876 : IN:
877 : desc.............the typedesc
878 :
879 : OUT:
880 : *type............set to the TYPE_* constant of DESC (if type != NULL)
881 : *info............receives the typeinfo (if info != NULL)
882 :
883 : RETURN VALUE:
884 : true.............success
885 : false............an exception has been thrown
886 :
887 : *******************************************************************************/
888 :
889 282924 : bool typeinfo_t::init_from_typedesc(const typedesc *desc, u1 *type) {
890 : #ifdef TYPEINFO_VERBOSE
891 : fprintf(stderr,"typeinfo_init_from_typedesc(");
892 : descriptor_debug_print_typedesc(stderr,this);
893 : fprintf(stderr,")\n");
894 : #endif
895 :
896 282924 : if (type)
897 0 : *type = desc->type;
898 :
899 282924 : if (desc->type == TYPE_ADR) {
900 228950 : TYPEINFO_ASSERT(desc->classref);
901 228950 : if (!init_class(desc->classref))
902 0 : return false;
903 : }
904 : else {
905 53974 : init_primitive();
906 : }
907 282924 : return true;
908 : }
909 :
910 :
911 : /* typedescriptor_init_from_typedesc *******************************************
912 :
913 : Initialize a typedescriptor from a typedesc.
914 :
915 : IN:
916 : desc.............the typedesc
917 :
918 : OUT:
919 : *td..............receives the typedescriptor
920 : td must be != NULL
921 :
922 : RETURN VALUE:
923 : true.............success
924 : false............an exception has been thrown
925 :
926 : *******************************************************************************/
927 :
928 86416 : static bool typedescriptor_init_from_typedesc(typedescriptor_t *td, typedesc *desc) {
929 86416 : TYPEINFO_ASSERT(td);
930 86416 : TYPEINFO_ASSERT(desc);
931 :
932 86416 : td->type = desc->type;
933 86416 : if (td->type == TYPE_ADR) {
934 29037 : if (!td->typeinfo.init_class(desc->classref))
935 0 : return false;
936 : }
937 : else {
938 57379 : td->typeinfo.init_primitive();
939 : }
940 86416 : return true;
941 : }
942 :
943 : /* typeinfo_init_varinfo_from_typedesc *****************************************
944 :
945 : Initialize a varinfo from a typedesc.
946 :
947 : IN:
948 : desc.............the typedesc
949 :
950 : OUT:
951 : *var.............receives the type
952 : var must be != NULL
953 :
954 : RETURN VALUE:
955 : true.............success
956 : false............an exception has been thrown
957 :
958 : *******************************************************************************/
959 :
960 72140 : static bool typeinfo_init_varinfo_from_typedesc(varinfo *var, typedesc *desc) {
961 72140 : TYPEINFO_ASSERT(var);
962 72140 : TYPEINFO_ASSERT(desc);
963 :
964 72140 : var->type = desc->type;
965 72140 : if (var->type == TYPE_ADR) {
966 47477 : if (!var->typeinfo.init_class(desc->classref))
967 0 : return false;
968 : }
969 : else {
970 24663 : var->typeinfo.init_primitive();
971 : }
972 72140 : return true;
973 : }
974 :
975 : /* typeinfo_init_varinfos_from_methoddesc **************************************
976 :
977 : Initialize an array of varinfos from a methoddesc.
978 :
979 : IN:
980 : desc.............the methoddesc
981 : buflen...........number of parameters the buffer can hold
982 : startindex.......the zero-based index of the first parameter to
983 : write to the array. In other words the number of
984 : parameters to skip at the beginning of the methoddesc.
985 : map..............map from parameter indices to varinfo indices
986 : (indexed like jitdata.local_map)
987 :
988 : OUT:
989 : *vars............array receiving the varinfos
990 : td[0] receives the type of the
991 : (startindex+1)th parameter of the method
992 : *returntype......receives the typedescriptor of the return type.
993 : returntype may be NULL
994 :
995 : RETURN VALUE:
996 : true.............everything ok
997 : false............an exception has been thrown
998 :
999 : NOTE:
1000 : If (according to BUFLEN) the buffer is to small to hold the
1001 : parameter types, an internal error is thrown. This must be
1002 : avoided by checking the number of parameters and allocating enough
1003 : space before calling this function.
1004 :
1005 : *******************************************************************************/
1006 :
1007 : bool
1008 86416 : typeinfo_init_varinfos_from_methoddesc(varinfo *vars,
1009 : methoddesc *desc,
1010 : int buflen, int startindex,
1011 : s4 *map,
1012 : typedescriptor_t *returntype)
1013 : {
1014 : s4 i;
1015 : s4 varindex;
1016 : s4 type;
1017 86416 : s4 slot = 0;
1018 :
1019 : /* skip arguments */
1020 154009 : for (i=0; i<startindex; ++i) {
1021 67593 : slot++;
1022 67593 : if (IS_2_WORD_TYPE(desc->paramtypes[i].type))
1023 0 : slot++;
1024 : }
1025 :
1026 : /* check arguments */
1027 160088 : for (i=startindex; i<desc->paramcount; ++i) {
1028 73672 : type = desc->paramtypes[i].type;
1029 73672 : varindex = map[5*slot + type];
1030 :
1031 73672 : slot++;
1032 73672 : if (IS_2_WORD_TYPE(type))
1033 412 : slot++;
1034 :
1035 73672 : if (varindex == jitdata::UNUSED)
1036 1532 : continue;
1037 :
1038 72140 : if (varindex >= buflen) {
1039 0 : exceptions_throw_internalerror("Buffer too small for method arguments.");
1040 0 : return false;
1041 : }
1042 :
1043 72140 : if (!typeinfo_init_varinfo_from_typedesc(vars + varindex, desc->paramtypes + i))
1044 0 : return false;
1045 : }
1046 :
1047 : /* check returntype */
1048 86416 : if (returntype) {
1049 86416 : if (!typedescriptor_init_from_typedesc(returntype,&(desc->returntype)))
1050 0 : return false;
1051 : }
1052 :
1053 86416 : return true;
1054 : }
1055 :
1056 : /* typedescriptors_init_from_methoddesc ****************************************
1057 :
1058 : Initialize an array of typedescriptors from a methoddesc.
1059 :
1060 : IN:
1061 : desc.............the methoddesc
1062 : buflen...........number of parameters the buffer can hold
1063 : twoword..........if true, use two parameter slots for two-word types
1064 : startindex.......the zero-based index of the first parameter to
1065 : write to the array. In other words the number of
1066 : parameters to skip at the beginning of the methoddesc.
1067 :
1068 : OUT:
1069 : *td..............array receiving the typedescriptors.
1070 : td[0] receives the typedescriptor of the
1071 : (startindex+1)th parameter of the method
1072 : *returntype......receives the typedescriptor of the return type.
1073 : returntype may be NULL
1074 :
1075 : RETURN VALUE:
1076 : >= 0.............number of typedescriptors filled in TD
1077 : -1...............an exception has been thrown
1078 :
1079 : NOTE:
1080 : If (according to BUFLEN) the buffer is to small to hold the
1081 : parameter types, an internal error is thrown. This must be
1082 : avoided by checking the number of parameters and allocating enough
1083 : space before calling this function.
1084 :
1085 : *******************************************************************************/
1086 :
1087 : int
1088 0 : typedescriptors_init_from_methoddesc(typedescriptor_t *td,
1089 : methoddesc *desc,
1090 : int buflen,bool twoword,int startindex,
1091 : typedescriptor_t *returntype)
1092 : {
1093 : int i;
1094 0 : int args = 0;
1095 :
1096 : /* check arguments */
1097 0 : for (i=startindex; i<desc->paramcount; ++i) {
1098 0 : if (++args > buflen) {
1099 0 : exceptions_throw_internalerror("Buffer too small for method arguments.");
1100 0 : return -1;
1101 : }
1102 :
1103 0 : if (!typedescriptor_init_from_typedesc(td,desc->paramtypes + i))
1104 0 : return -1;
1105 0 : td++;
1106 :
1107 0 : if (twoword && (td[-1].type == TYPE_LNG || td[-1].type == TYPE_DBL)) {
1108 0 : if (++args > buflen) {
1109 0 : exceptions_throw_internalerror("Buffer too small for method arguments.");
1110 0 : return -1;
1111 : }
1112 :
1113 0 : td->type = TYPE_VOID;
1114 0 : td->typeinfo.init_primitive();
1115 0 : td++;
1116 : }
1117 : }
1118 :
1119 : /* check returntype */
1120 0 : if (returntype) {
1121 0 : if (!typedescriptor_init_from_typedesc(returntype,&(desc->returntype)))
1122 0 : return -1;
1123 : }
1124 :
1125 0 : return args;
1126 : }
1127 :
1128 : /* typeinfo_t::init_component ***************************************************
1129 :
1130 : Initialize a typeinfo with the component type of a given array type.
1131 :
1132 : IN:
1133 : srcarray.........the typeinfo of the array type
1134 :
1135 : OUT:
1136 : *dst.............receives the typeinfo of the component type
1137 :
1138 : RETURN VALUE:
1139 : true.............success
1140 : false............an exception has been thrown
1141 :
1142 : *******************************************************************************/
1143 :
1144 21280 : bool typeinfo_t::init_component(const typeinfo_t& srcarray) {
1145 21280 : if (srcarray.is_nulltype()) {
1146 1 : init_nulltype();
1147 1 : return true;
1148 : }
1149 :
1150 21279 : if (!srcarray.is_array()) {
1151 : /* XXX should we make that a verify error? */
1152 0 : exceptions_throw_internalerror("Trying to access component of non-array");
1153 0 : return false;
1154 : }
1155 :
1156 : /* save the mergedlist (maybe this == srcarray) */
1157 :
1158 21279 : typeinfo_mergedlist_t *merged = srcarray.merged;
1159 :
1160 21279 : if (srcarray.typeclass.is_classref()) {
1161 181 : constant_classref *comp = class_get_classref_component_of(srcarray.typeclass.ref);
1162 :
1163 181 : if (comp) {
1164 181 : if (!init_class(comp))
1165 0 : return false;
1166 : }
1167 : else {
1168 0 : init_primitive();
1169 : }
1170 : }
1171 : else {
1172 21098 : if (!(srcarray.typeclass.cls->state & CLASS_LINKED)) {
1173 0 : if (!link_class(srcarray.typeclass.cls)) {
1174 0 : return false;
1175 : }
1176 : }
1177 :
1178 21098 : TYPEINFO_ASSERT(srcarray.typeclass.cls->vftbl);
1179 21098 : TYPEINFO_ASSERT(srcarray.typeclass.cls->vftbl->arraydesc);
1180 :
1181 21098 : if (vftbl_t *comp = srcarray.typeclass.cls->vftbl->arraydesc->componentvftbl)
1182 21098 : init_class(comp->clazz);
1183 : else
1184 0 : init_primitive();
1185 : }
1186 :
1187 21279 : this->merged = merged; /* XXX should we do a deep copy? */
1188 21279 : return true;
1189 : }
1190 :
1191 : /***
1192 : * Create a deep copy of the `merged' list of a typeinfo
1193 : */
1194 2268 : void typeinfo_t::clone_merged(const typeinfo_t& src, typeinfo_t& dst) {
1195 2268 : int count = src.merged->count;
1196 2268 : TYPEINFO_ALLOCMERGED(dst.merged,count);
1197 2268 : dst.merged->count = count;
1198 :
1199 2268 : classref_or_classinfo *srclist = src.merged->list;
1200 2268 : classref_or_classinfo *dstlist = dst.merged->list;
1201 :
1202 38556 : while (count--)
1203 34020 : *dstlist++ = *srclist++;
1204 2268 : }
1205 :
1206 :
1207 : /**********************************************************************/
1208 : /* MISCELLANEOUS FUNCTIONS */
1209 : /**********************************************************************/
1210 :
1211 : /**********************************************************************/
1212 : /* MERGING FUNCTIONS */
1213 : /* The following functions are used to merge the types represented by */
1214 : /* two typeinfo structures into one typeinfo structure. */
1215 : /**********************************************************************/
1216 :
1217 3 : static void typeinfo_merge_error(methodinfo *m, const char *str, const typeinfo_t *x, const typeinfo_t *y) {
1218 : #ifdef TYPEINFO_VERBOSE
1219 : fprintf(stderr,"Error in typeinfo_merge: %s\n",str);
1220 : fprintf(stderr,"Typeinfo x:\n");
1221 : typeinfo_print(stderr,x,1);
1222 : fprintf(stderr,"Typeinfo y:\n");
1223 : typeinfo_print(stderr,y,1);
1224 : log_text(str);
1225 : #endif
1226 :
1227 3 : exceptions_throw_verifyerror(m, str);
1228 3 : }
1229 :
1230 : /* Condition: clsx != clsy. */
1231 : /* Returns: true if dest was changed (currently always true). */
1232 : static
1233 : bool
1234 1040 : typeinfo_merge_two(typeinfo_t *dest,classref_or_classinfo clsx,classref_or_classinfo clsy)
1235 : {
1236 1040 : TYPEINFO_ASSERT(dest);
1237 : TYPEINFO_FREEMERGED_IF_ANY(dest->merged);
1238 1040 : TYPEINFO_ALLOCMERGED(dest->merged,2);
1239 1040 : dest->merged->count = 2;
1240 :
1241 1040 : TYPEINFO_ASSERT(clsx.any != clsy.any);
1242 :
1243 1040 : if (clsx.any < clsy.any) {
1244 445 : dest->merged->list[0] = clsx;
1245 445 : dest->merged->list[1] = clsy;
1246 : }
1247 : else {
1248 595 : dest->merged->list[0] = clsy;
1249 595 : dest->merged->list[1] = clsx;
1250 : }
1251 :
1252 1040 : return true;
1253 : }
1254 :
1255 : /* Returns: true if dest was changed. */
1256 : static
1257 : bool
1258 2673 : typeinfo_merge_add(typeinfo_t *dest,typeinfo_mergedlist_t *m,classref_or_classinfo cls)
1259 : {
1260 : int count;
1261 : typeinfo_mergedlist_t *newmerged;
1262 : classref_or_classinfo *mlist,*newlist;
1263 :
1264 2673 : count = m->count;
1265 2673 : mlist = m->list;
1266 :
1267 : /* Check if cls is already in the mergedlist m. */
1268 10602 : while (count--) {
1269 7489 : if ((mlist++)->any == cls.any) { /* XXX check equal classrefs? */
1270 : /* cls is in the list, so m is the resulting mergedlist */
1271 2233 : if (dest->merged == m)
1272 1951 : return false;
1273 :
1274 : /* We have to copy the mergedlist */
1275 : TYPEINFO_FREEMERGED_IF_ANY(dest->merged);
1276 282 : count = m->count;
1277 282 : TYPEINFO_ALLOCMERGED(dest->merged,count);
1278 282 : dest->merged->count = count;
1279 282 : newlist = dest->merged->list;
1280 282 : mlist = m->list;
1281 1128 : while (count--) {
1282 564 : *newlist++ = *mlist++;
1283 : }
1284 282 : return true;
1285 : }
1286 : }
1287 :
1288 : /* Add cls to the mergedlist. */
1289 440 : count = m->count;
1290 440 : TYPEINFO_ALLOCMERGED(newmerged,count+1);
1291 440 : newmerged->count = count+1;
1292 440 : newlist = newmerged->list;
1293 440 : mlist = m->list;
1294 2055 : while (count) {
1295 1307 : if (mlist->any > cls.any)
1296 132 : break;
1297 1175 : *newlist++ = *mlist++;
1298 1175 : count--;
1299 : }
1300 440 : *newlist++ = cls;
1301 1161 : while (count--) {
1302 281 : *newlist++ = *mlist++;
1303 : }
1304 :
1305 : /* Put the new mergedlist into dest. */
1306 : TYPEINFO_FREEMERGED_IF_ANY(dest->merged);
1307 440 : dest->merged = newmerged;
1308 :
1309 440 : return true;
1310 : }
1311 :
1312 : /* Returns: true if dest was changed. */
1313 : static
1314 : bool
1315 2021 : typeinfo_merge_mergedlists(typeinfo_t *dest,typeinfo_mergedlist_t *x,
1316 : typeinfo_mergedlist_t *y)
1317 : {
1318 2021 : int count = 0;
1319 : int countx,county;
1320 : typeinfo_mergedlist_t *temp,*result;
1321 : classref_or_classinfo *clsx,*clsy,*newlist;
1322 :
1323 : /* count the elements that will be in the resulting list */
1324 : /* (Both lists are sorted, equal elements are counted only once.) */
1325 2021 : clsx = x->list;
1326 2021 : clsy = y->list;
1327 2021 : countx = x->count;
1328 2021 : county = y->count;
1329 23707 : while (countx && county) {
1330 19665 : if (clsx->any == clsy->any) {
1331 19581 : clsx++;
1332 19581 : clsy++;
1333 19581 : countx--;
1334 19581 : county--;
1335 : }
1336 84 : else if (clsx->any < clsy->any) {
1337 60 : clsx++;
1338 60 : countx--;
1339 : }
1340 : else {
1341 24 : clsy++;
1342 24 : county--;
1343 : }
1344 19665 : count++;
1345 : }
1346 2021 : count += countx + county;
1347 :
1348 : /* {The new mergedlist will have count entries.} */
1349 :
1350 2021 : if ((x->count != count) && (y->count == count)) {
1351 0 : temp = x; x = y; y = temp;
1352 : }
1353 : /* {If one of x,y is already the result it is x.} */
1354 2021 : if (x->count == count) {
1355 : /* x->merged is equal to the result */
1356 2015 : if (x == dest->merged)
1357 2015 : return false;
1358 :
1359 0 : if (!dest->merged || dest->merged->count != count) {
1360 : TYPEINFO_FREEMERGED_IF_ANY(dest->merged);
1361 0 : TYPEINFO_ALLOCMERGED(dest->merged,count);
1362 0 : dest->merged->count = count;
1363 : }
1364 :
1365 0 : newlist = dest->merged->list;
1366 0 : clsx = x->list;
1367 0 : while (count--) {
1368 0 : *newlist++ = *clsx++;
1369 : }
1370 0 : return true;
1371 : }
1372 :
1373 : /* {We have to merge two lists.} */
1374 :
1375 : /* allocate the result list */
1376 6 : TYPEINFO_ALLOCMERGED(result,count);
1377 6 : result->count = count;
1378 6 : newlist = result->list;
1379 :
1380 : /* merge the sorted lists */
1381 6 : clsx = x->list;
1382 6 : clsy = y->list;
1383 6 : countx = x->count;
1384 6 : county = y->count;
1385 48 : while (countx && county) {
1386 36 : if (clsx->any == clsy->any) {
1387 0 : *newlist++ = *clsx++;
1388 0 : clsy++;
1389 0 : countx--;
1390 0 : county--;
1391 : }
1392 36 : else if (clsx->any < clsy->any) {
1393 12 : *newlist++ = *clsx++;
1394 12 : countx--;
1395 : }
1396 : else {
1397 24 : *newlist++ = *clsy++;
1398 24 : county--;
1399 : }
1400 : }
1401 18 : while (countx--)
1402 6 : *newlist++ = *clsx++;
1403 12 : while (county--)
1404 0 : *newlist++ = *clsy++;
1405 :
1406 : /* replace the list in dest with the result list */
1407 : TYPEINFO_FREEMERGED_IF_ANY(dest->merged);
1408 6 : dest->merged = result;
1409 :
1410 6 : return true;
1411 : }
1412 :
1413 : /* typeinfo_merge_nonarrays ****************************************************
1414 :
1415 : Merge two non-array types.
1416 :
1417 : IN:
1418 : x................the first type
1419 : y................the second type
1420 : mergedx..........merged list of the first type, may be NULL
1421 : mergedy..........merged list of the descond type, may be NULL
1422 :
1423 : OUT:
1424 : *dest............receives the resulting merged list
1425 : *result..........receives the resulting type
1426 :
1427 : RETURN VALUE:
1428 : typecheck_TRUE...*dest has been modified
1429 : typecheck_FALSE..*dest has not been modified
1430 : typecheck_FAIL...an exception has been thrown
1431 :
1432 : NOTE:
1433 : RESULT is an extra parameter so it can point to dest->typeclass or to
1434 : dest->elementclass.
1435 :
1436 : *******************************************************************************/
1437 :
1438 : static typecheck_result
1439 5788 : typeinfo_merge_nonarrays(typeinfo_t *dest,
1440 : classref_or_classinfo *result,
1441 : classref_or_classinfo x,classref_or_classinfo y,
1442 : typeinfo_mergedlist_t *mergedx,
1443 : typeinfo_mergedlist_t *mergedy)
1444 : {
1445 : classinfo *tcls,*common;
1446 : bool changed;
1447 : typecheck_result r;
1448 :
1449 5788 : TYPEINFO_ASSERT(dest && result && x.any && y.any);
1450 5788 : TYPEINFO_ASSERT(x.cls != pseudo_class_Null);
1451 5788 : TYPEINFO_ASSERT(y.cls != pseudo_class_Null);
1452 5788 : TYPEINFO_ASSERT(x.cls != pseudo_class_New);
1453 5788 : TYPEINFO_ASSERT(y.cls != pseudo_class_New);
1454 :
1455 : /*--------------------------------------------------*/
1456 : /* common cases */
1457 : /*--------------------------------------------------*/
1458 :
1459 : /* Common case 1: x and y are the same class or class reference */
1460 : /* (This case is very simple unless *both* x and y really represent
1461 : * merges of subclasses of clsx==clsy.)
1462 : */
1463 5788 : if ( (x.any == y.any) && (!mergedx || !mergedy) ) {
1464 : return_simple_x:
1465 : /* DEBUG */ /* log_text("return simple x"); */
1466 54 : changed = (dest->merged != NULL);
1467 : TYPEINFO_FREEMERGED_IF_ANY(dest->merged);
1468 54 : dest->merged = NULL;
1469 54 : *result = x;
1470 : /* DEBUG */ /* log_text("returning"); */
1471 54 : return (typecheck_result) changed;
1472 : }
1473 :
1474 5788 : Utf8String xname = CLASSREF_OR_CLASSINFO_NAME(x);
1475 5788 : Utf8String yname = CLASSREF_OR_CLASSINFO_NAME(y);
1476 :
1477 : /* Common case 2: xname == yname, at least one unresolved */
1478 5788 : if ((xname == yname) && (x.is_classref() || y.is_classref()))
1479 : {
1480 : /* use the loaded one if any */
1481 0 : if (y.is_classinfo())
1482 0 : x = y;
1483 0 : goto return_simple_x;
1484 : }
1485 :
1486 : /*--------------------------------------------------*/
1487 : /* non-trivial cases */
1488 : /*--------------------------------------------------*/
1489 :
1490 : #ifdef TYPEINFO_VERBOSE
1491 : {
1492 : typeinfo_t dbgx,dbgy;
1493 : fprintf(stderr,"merge_nonarrays:\n");
1494 : fprintf(stderr," ");if(x.is_classref())fprintf(stderr,"<ref>");utf_fprint_printable_ascii(stderr,xname);fprintf(stderr,"\n");
1495 : fprintf(stderr," ");if(y.is_classref())fprintf(stderr,"<ref>");utf_fprint_printable_ascii(stderr,yname);fprintf(stderr,"\n");
1496 : fflush(stderr);
1497 : dbgx.init_class(x);
1498 : dbgx.merged = mergedx;
1499 : dbgy.init_class(y);
1500 : dbgy.merged = mergedy;
1501 : typeinfo_print(stderr,&dbgx,4);
1502 : fprintf(stderr," with:\n");
1503 : typeinfo_print(stderr,&dbgy,4);
1504 : }
1505 : #endif
1506 :
1507 5788 : TYPEINFO_ASSERT(x.is_classref() || (x.cls->state & CLASS_LOADED));
1508 5788 : TYPEINFO_ASSERT(y.is_classref() || (y.cls->state & CLASS_LOADED));
1509 :
1510 : /* If y is unresolved or an interface, swap x and y. */
1511 5788 : if (y.is_classref() || (x.is_classinfo() && y.cls->flags & ACC_INTERFACE)) {
1512 1793 : classref_or_classinfo tmp = x; x = y; y = tmp;
1513 1793 : typeinfo_mergedlist_t *tmerged = mergedx; mergedx = mergedy; mergedy = tmerged;
1514 : }
1515 :
1516 : /* {We know: If only one of x,y is unresolved it is x,} */
1517 : /* { If both x,y are resolved and only one of x,y is an interface it is x.} */
1518 :
1519 5788 : if (x.is_classref()) {
1520 : /* {We know: x and y have different class names} */
1521 :
1522 : /* Check if we are merging an unresolved type with java.lang.Object */
1523 1798 : if (y.cls == class_java_lang_Object && !mergedy) {
1524 17 : x = y;
1525 17 : goto return_simple_x;
1526 : }
1527 :
1528 1781 : common = class_java_lang_Object;
1529 1781 : goto merge_with_simple_x;
1530 : }
1531 :
1532 : /* {We know: both x and y are resolved} */
1533 : /* {We know: If only one of x,y is an interface it is x.} */
1534 :
1535 3990 : TYPEINFO_ASSERT(x.is_classinfo() && y.is_classinfo());
1536 3990 : TYPEINFO_ASSERT(x.cls->state & CLASS_LOADED);
1537 3990 : TYPEINFO_ASSERT(y.cls->state & CLASS_LOADED);
1538 :
1539 : /* Handle merging of interfaces: */
1540 3990 : if (x.cls->flags & ACC_INTERFACE) {
1541 : /* {x.cls is an interface and mergedx == NULL.} */
1542 :
1543 27 : if (y.cls->flags & ACC_INTERFACE) {
1544 : /* We are merging two interfaces. */
1545 : /* {mergedy == NULL} */
1546 :
1547 : /* {We know that x.cls!=y.cls (see common case at beginning.)} */
1548 0 : result->cls = class_java_lang_Object;
1549 0 : return (typecheck_result) typeinfo_merge_two(dest,x,y);
1550 : }
1551 :
1552 : /* {We know: x is an interface, y is a class.} */
1553 :
1554 : /* Check if we are merging an interface with java.lang.Object */
1555 27 : if (y.cls == class_java_lang_Object && !mergedy) {
1556 3 : x = y;
1557 3 : goto return_simple_x;
1558 : }
1559 :
1560 : /* If the type y implements x then the result of the merge
1561 : * is x regardless of mergedy.
1562 : */
1563 :
1564 : /* we may have to link the classes */
1565 24 : if (!(x.cls->state & CLASS_LINKED))
1566 0 : if (!link_class(x.cls))
1567 0 : return typecheck_FAIL;
1568 24 : if (!(y.cls->state & CLASS_LINKED))
1569 0 : if (!link_class(y.cls))
1570 0 : return typecheck_FAIL;
1571 :
1572 24 : TYPEINFO_ASSERT(x.cls->state & CLASS_LINKED);
1573 24 : TYPEINFO_ASSERT(y.cls->state & CLASS_LINKED);
1574 :
1575 24 : if (CLASSINFO_IMPLEMENTS_INTERFACE(y.cls,x.cls->index))
1576 : {
1577 : /* y implements x, so the result of the merge is x. */
1578 22 : goto return_simple_x;
1579 : }
1580 :
1581 2 : r = mergedlist_implements_interface(mergedy,x.cls);
1582 2 : if (r == typecheck_FAIL)
1583 0 : return r;
1584 2 : if (r == typecheck_TRUE)
1585 : {
1586 : /* y implements x, so the result of the merge is x. */
1587 0 : goto return_simple_x;
1588 : }
1589 :
1590 : /* {We know: x is an interface, the type y a class or a merge
1591 : * of subclasses and is not guaranteed to implement x.} */
1592 :
1593 2 : common = class_java_lang_Object;
1594 2 : goto merge_with_simple_x;
1595 : }
1596 :
1597 : /* {We know: x and y are classes (not interfaces).} */
1598 :
1599 : /* we may have to link the classes */
1600 3963 : if (!(x.cls->state & CLASS_LINKED))
1601 0 : if (!link_class(x.cls))
1602 0 : return typecheck_FAIL;
1603 3963 : if (!(y.cls->state & CLASS_LINKED))
1604 0 : if (!link_class(y.cls))
1605 0 : return typecheck_FAIL;
1606 :
1607 3963 : TYPEINFO_ASSERT(x.cls->state & CLASS_LINKED);
1608 3963 : TYPEINFO_ASSERT(y.cls->state & CLASS_LINKED);
1609 :
1610 : /* If *x is deeper in the inheritance hierarchy swap x and y. */
1611 3963 : if (x.cls->index > y.cls->index) {
1612 282 : classref_or_classinfo tmp = x; x = y; y = tmp;
1613 282 : typeinfo_mergedlist_t *tmerged = mergedx; mergedx = mergedy; mergedy = tmerged;
1614 : }
1615 :
1616 : /* {We know: y is at least as deep in the hierarchy as x.} */
1617 :
1618 : /* Find nearest common anchestor for the classes. */
1619 :
1620 3963 : common = x.cls;
1621 3963 : tcls = y.cls;
1622 :
1623 9552 : while (tcls->index > common->index)
1624 1626 : tcls = tcls->super;
1625 :
1626 8419 : while (common != tcls) {
1627 493 : common = common->super;
1628 493 : tcls = tcls->super;
1629 : }
1630 :
1631 : /* {common == nearest common anchestor of x and y.} */
1632 :
1633 : /* If x.cls==common and x is a whole class (not a merge of subclasses)
1634 : * then the result of the merge is x.
1635 : */
1636 3963 : if (x.cls == common && !mergedx) {
1637 12 : goto return_simple_x;
1638 : }
1639 :
1640 3951 : if (mergedx) {
1641 3458 : result->cls = common;
1642 3458 : if (mergedy)
1643 2021 : return (typecheck_result) typeinfo_merge_mergedlists(dest,mergedx,mergedy);
1644 : else
1645 1437 : return (typecheck_result) typeinfo_merge_add(dest,mergedx,y);
1646 : }
1647 :
1648 : merge_with_simple_x:
1649 2276 : result->cls = common;
1650 2276 : if (mergedy)
1651 1236 : return (typecheck_result) typeinfo_merge_add(dest,mergedy,x);
1652 : else
1653 1040 : return (typecheck_result) typeinfo_merge_two(dest,x,y);
1654 : }
1655 :
1656 : /***
1657 : *
1658 : * Merge two types, stores result of merge in `this'.
1659 : *
1660 : * @param m method for exception messages
1661 : * @param t the second type
1662 : *
1663 : * RETURN VALUE:
1664 : * typecheck_TRUE...*dest has been modified
1665 : * typecheck_FALSE..*dest has not been modified
1666 : * typecheck_FAIL...an exception has been thrown
1667 : *
1668 : * @pre
1669 : * 1) *dest must be a valid initialized typeinfo
1670 : * 2) dest != y
1671 : */
1672 839745 : typecheck_result typeinfo_t::merge(methodinfo *m, const typeinfo_t *src) {
1673 : const typeinfo_t *x;
1674 : classref_or_classinfo common;
1675 : classref_or_classinfo elementclass;
1676 : int dimension;
1677 : ArrayType new_elementtype;
1678 : bool changed;
1679 : typecheck_result r;
1680 :
1681 : /*--------------------------------------------------*/
1682 : /* fast checks */
1683 : /*--------------------------------------------------*/
1684 :
1685 : /* Merging something with itself is a nop */
1686 839745 : if (this == src)
1687 1 : return typecheck_FALSE;
1688 :
1689 : /* Merging two returnAddress types is ok. */
1690 : /* Merging two different returnAddresses never happens, as the verifier */
1691 : /* keeps them separate in order to check all the possible return paths */
1692 : /* from JSR subroutines. */
1693 839744 : if (!typeclass.any && !src->typeclass.any) {
1694 0 : TYPEINFO_ASSERT(returnaddress() == src->returnaddress());
1695 0 : return typecheck_FALSE;
1696 : }
1697 :
1698 : /* Primitive types cannot be merged with reference types */
1699 : /* This must be checked before calls to typeinfo_merge. */
1700 839744 : TYPEINFO_ASSERT(this->typeclass.any && src->typeclass.any);
1701 :
1702 : /* handle uninitialized object types */
1703 839744 : if (is_newobject() || src->is_newobject()) {
1704 1515 : if (!is_newobject() || !src->is_newobject()) {
1705 1 : typeinfo_merge_error(m,(char*) "Trying to merge uninitialized object type.", this, src);
1706 1 : return typecheck_FAIL;
1707 : }
1708 1514 : if (newobject_instruction() != src->newobject_instruction()) {
1709 2 : typeinfo_merge_error(m,(char*) "Trying to merge different uninitialized objects.", this, src);
1710 2 : return typecheck_FAIL;
1711 : }
1712 : /* the same uninitialized object -- no change */
1713 1512 : return typecheck_FALSE;
1714 : }
1715 :
1716 : /*--------------------------------------------------*/
1717 : /* common cases */
1718 : /*--------------------------------------------------*/
1719 :
1720 : /* Common case: dest and y are the same class or class reference */
1721 : /* (This case is very simple unless *both* dest and y really represent
1722 : * merges of subclasses of class dest==class y.)
1723 : */
1724 838229 : if ((this->typeclass.any == src->typeclass.any) && (!this->merged || !src->merged)) {
1725 : return_simple:
1726 811191 : changed = (merged != NULL);
1727 : TYPEINFO_FREEMERGED_IF_ANY(merged);
1728 811191 : merged = NULL;
1729 811191 : return (typecheck_result) changed;
1730 : }
1731 :
1732 : /* Handle null types: */
1733 27045 : if (src->is_nulltype()) {
1734 5870 : return typecheck_FALSE;
1735 : }
1736 21175 : if (is_nulltype()) {
1737 : TYPEINFO_FREEMERGED_IF_ANY(dest->merged);
1738 15380 : typeinfo_t::clone(*src, *this);
1739 15380 : return typecheck_TRUE;
1740 : }
1741 :
1742 : /* Common case: two types with the same name, at least one unresolved */
1743 5795 : if (typeclass.is_classref()) {
1744 223 : if (src->typeclass.is_classref()) {
1745 201 : if (typeclass.ref->name == src->typeclass.ref->name)
1746 0 : goto return_simple;
1747 : }
1748 : else {
1749 : /* XXX should we take y instead of dest here? */
1750 22 : if (typeclass.ref->name == src->typeclass.cls->name)
1751 0 : goto return_simple;
1752 : }
1753 : }
1754 : else {
1755 5572 : if (src->typeclass.is_classref() && (typeclass.cls->name == src->typeclass.ref->name))
1756 : {
1757 7 : goto return_simple;
1758 : }
1759 : }
1760 :
1761 : /*--------------------------------------------------*/
1762 : /* non-trivial cases */
1763 : /*--------------------------------------------------*/
1764 :
1765 : #ifdef TYPEINFO_VERBOSE
1766 : fprintf(stderr,"merge:\n");
1767 : typeinfo_print(stderr,dest,4);
1768 : typeinfo_print(stderr,y,4);
1769 : #endif
1770 :
1771 : /* This function uses x internally, so x and y can be swapped
1772 : * without changing dest. */
1773 5788 : x = this;
1774 5788 : changed = false;
1775 :
1776 : /* Handle merging of arrays: */
1777 5788 : if (x->is_array() && src->is_array()) {
1778 :
1779 : /* Make x the one with lesser dimension */
1780 1974 : if (x->dimension > src->dimension) {
1781 0 : const typeinfo_t *tmp = x; x = src; src = tmp;
1782 : }
1783 :
1784 : /* If one array (y) has higher dimension than the other,
1785 : * interpret it as an array (same dim. as x) of Arraystubs. */
1786 1974 : if (x->dimension < src->dimension) {
1787 0 : dimension = x->dimension;
1788 0 : new_elementtype = ARRAYTYPE_OBJECT;
1789 0 : elementclass.cls = pseudo_class_Arraystub;
1790 : }
1791 : else {
1792 1974 : dimension = src->dimension;
1793 1974 : new_elementtype = src->elementtype;
1794 1974 : elementclass = src->elementclass;
1795 : }
1796 :
1797 : /* {The arrays are of the same dimension.} */
1798 :
1799 1974 : if (x->elementtype != new_elementtype) {
1800 : /* Different element types are merged, so the resulting array
1801 : * type has one accessible dimension less. */
1802 0 : if (--dimension == 0) {
1803 0 : common.cls = pseudo_class_Arraystub;
1804 0 : new_elementtype = ARRAYTYPE_INT;
1805 0 : elementclass.any = NULL;
1806 : }
1807 : else {
1808 0 : common.cls = class_multiarray_of(dimension,pseudo_class_Arraystub,true);
1809 0 : if (!common.cls) {
1810 0 : exceptions_throw_internalerror("XXX Coult not create array class");
1811 0 : return typecheck_FAIL;
1812 : }
1813 :
1814 0 : new_elementtype = ARRAYTYPE_OBJECT;
1815 0 : elementclass.cls = pseudo_class_Arraystub;
1816 : }
1817 : }
1818 : else {
1819 : /* {The arrays have the same dimension and elementtype.} */
1820 :
1821 1974 : if (new_elementtype == ARRAYTYPE_OBJECT) {
1822 : /* The elements are references, so their respective
1823 : * types must be merged.
1824 : */
1825 : r = typeinfo_merge_nonarrays(this,
1826 : &elementclass,
1827 : x->elementclass,
1828 : elementclass,
1829 1974 : x->merged, src->merged);
1830 1974 : TYPEINFO_ASSERT(r != typecheck_MAYBE);
1831 1974 : if (r == typecheck_FAIL)
1832 0 : return r;
1833 1974 : changed |= r;
1834 :
1835 : /* DEBUG */ /* log_text("finding resulting array class: "); */
1836 1974 : if (elementclass.is_classref())
1837 0 : common.ref = class_get_classref_multiarray_of(dimension,elementclass.ref);
1838 : else {
1839 1974 : common.cls = class_multiarray_of(dimension,elementclass.cls,true);
1840 1974 : if (!common.cls) {
1841 0 : exceptions_throw_internalerror("XXX Coult not create array class");
1842 0 : return typecheck_FAIL;
1843 : }
1844 : }
1845 : /* DEBUG */ /* utf_display_printable_ascii(common->name); printf("\n"); */
1846 : }
1847 : else {
1848 0 : common.any = src->typeclass.any;
1849 : }
1850 : }
1851 : }
1852 : else {
1853 : /* {We know that at least one of x or y is no array, so the
1854 : * result cannot be an array.} */
1855 :
1856 : r = typeinfo_merge_nonarrays(this,
1857 : &common,
1858 : x->typeclass, src->typeclass,
1859 3814 : x->merged, src->merged);
1860 3814 : TYPEINFO_ASSERT(r != typecheck_MAYBE);
1861 3814 : if (r == typecheck_FAIL)
1862 0 : return r;
1863 3814 : changed |= r;
1864 :
1865 3814 : dimension = 0;
1866 3814 : new_elementtype = ARRAYTYPE_INT;
1867 3814 : elementclass.any = NULL;
1868 : }
1869 :
1870 : /* Put the new values into dest if neccessary. */
1871 :
1872 5788 : if (this->typeclass.any != common.any) {
1873 1334 : this->typeclass.any = common.any;
1874 1334 : changed = true;
1875 : }
1876 5788 : if (this->dimension != dimension) {
1877 14 : this->dimension = dimension;
1878 14 : changed = true;
1879 : }
1880 5788 : if (elementtype != new_elementtype) {
1881 11 : elementtype = new_elementtype;
1882 11 : changed = true;
1883 : }
1884 5788 : if (this->elementclass.any != elementclass.any) {
1885 431 : this->elementclass.any = elementclass.any;
1886 431 : changed = true;
1887 : }
1888 :
1889 5788 : return (typecheck_result) changed;
1890 : }
1891 : #endif /* ENABLE_VERIFER */
1892 :
1893 :
1894 : /**********************************************************************/
1895 : /* DEBUGGING HELPERS */
1896 : /**********************************************************************/
1897 :
1898 : #ifdef TYPEINFO_DEBUG
1899 :
1900 : #if 0
1901 : static int
1902 : typeinfo_test_compare(classref_or_classinfo *a,classref_or_classinfo *b)
1903 : {
1904 : if (a->any == b->any) return 0;
1905 : if (a->any < b->any) return -1;
1906 : return +1;
1907 : }
1908 :
1909 : static void
1910 : typeinfo_test_parse(typeinfo_t *info,char *str)
1911 : {
1912 : int num;
1913 : int i;
1914 : typeinfo_t *infobuf;
1915 : u1 *typebuf;
1916 : int returntype;
1917 : Utf8String desc = Utf8String::from_utf8(str);
1918 :
1919 : num = typeinfo_count_method_args(desc,false);
1920 : if (num) {
1921 : typebuf = (u1*) DumpMemory::allocate(sizeof(u1) * num);
1922 : infobuf = (typeinfo_t*) DumpMemory::allocate(sizeof(typeinfo_t) * num);
1923 :
1924 : typeinfo_init_from_method_args(desc,typebuf,infobuf,num,false,
1925 : &returntype,info);
1926 :
1927 : TYPEINFO_ALLOCMERGED(info->merged,num);
1928 : info->merged->count = num;
1929 :
1930 : for (i=0; i<num; ++i) {
1931 : if (typebuf[i] != TYPE_ADR) {
1932 : log_text("non-reference type in mergedlist");
1933 : assert(0);
1934 : }
1935 :
1936 : info->merged->list[i].any = infobuf[i].typeclass.any;
1937 : }
1938 : qsort(info->merged->list,num,sizeof(classref_or_classinfo),
1939 : (int(*)(const void *,const void *))&typeinfo_test_compare);
1940 : }
1941 : else {
1942 : typeinfo_init_from_method_args(desc,NULL,NULL,0,false,
1943 : &returntype,info);
1944 : }
1945 : }
1946 : #endif
1947 :
1948 : #define TYPEINFO_TEST_BUFLEN 4000
1949 :
1950 : static bool
1951 0 : typeinfo_equal(typeinfo_t *x,typeinfo_t *y)
1952 : {
1953 : int i;
1954 :
1955 0 : if (x->typeclass.any != y->typeclass.any) return false;
1956 0 : if (x->dimension != y->dimension) return false;
1957 0 : if (x->dimension) {
1958 0 : if (x->elementclass.any != y->elementclass.any) return false;
1959 0 : if (x->elementtype != y->elementtype) return false;
1960 : }
1961 :
1962 0 : if (x->is_newobject())
1963 0 : if (x->newobject_instruction() != y->newobject_instruction())
1964 0 : return false;
1965 :
1966 0 : if (x->merged || y->merged) {
1967 0 : if (!(x->merged && y->merged)) return false;
1968 0 : if (x->merged->count != y->merged->count) return false;
1969 0 : for (i=0; i<x->merged->count; ++i)
1970 0 : if (x->merged->list[i].any != y->merged->list[i].any)
1971 0 : return false;
1972 : }
1973 0 : return true;
1974 : }
1975 :
1976 : static void
1977 0 : typeinfo_testmerge(typeinfo_t *a,typeinfo_t *b,typeinfo_t *result,int *failed)
1978 : {
1979 : typeinfo_t dest;
1980 :
1981 0 : typeinfo_t::clone(*a,dest);
1982 :
1983 0 : printf("\n ");
1984 0 : typeinfo_print_short(stdout,&dest);
1985 0 : printf("\n ");
1986 0 : typeinfo_print_short(stdout,b);
1987 0 : printf("\n");
1988 :
1989 0 : typecheck_result r = dest.merge(NULL, b);
1990 0 : if (r == typecheck_FAIL) {
1991 0 : printf("EXCEPTION\n");
1992 0 : return;
1993 : }
1994 :
1995 0 : bool changed = (r) ? 1 : 0;
1996 0 : bool changed_should_be = (!typeinfo_equal(&dest,a)) ? 1 : 0;
1997 :
1998 0 : printf(" %s\n",(changed) ? "changed" : "=");
1999 :
2000 0 : if (typeinfo_equal(&dest,result)) {
2001 0 : printf("OK ");
2002 0 : typeinfo_print_short(stdout,&dest);
2003 0 : printf("\n");
2004 0 : if (changed != changed_should_be) {
2005 0 : printf("WRONG RETURN VALUE!\n");
2006 0 : (*failed)++;
2007 : }
2008 : }
2009 : else {
2010 0 : printf("RESULT ");
2011 0 : typeinfo_print_short(stdout,&dest);
2012 0 : printf("\n");
2013 0 : printf("SHOULD BE ");
2014 0 : typeinfo_print_short(stdout,result);
2015 0 : printf("\n");
2016 0 : (*failed)++;
2017 : }
2018 : }
2019 :
2020 : #if 0
2021 : static void
2022 : typeinfo_inc_dimension(typeinfo_t *info)
2023 : {
2024 : if (info->dimension++ == 0) {
2025 : info->elementtype = ARRAYTYPE_OBJECT;
2026 : info->elementclass = info->typeclass;
2027 : }
2028 : info->typeclass = class_array_of(info->typeclass,true);
2029 : }
2030 : #endif
2031 :
2032 : #define TYPEINFO_TEST_MAXDIM 10
2033 :
2034 : static void
2035 0 : typeinfo_testrun(const char *filename)
2036 : {
2037 : char buf[TYPEINFO_TEST_BUFLEN];
2038 : char bufa[TYPEINFO_TEST_BUFLEN];
2039 : char bufb[TYPEINFO_TEST_BUFLEN];
2040 : char bufc[TYPEINFO_TEST_BUFLEN];
2041 : typeinfo_t a,b,c;
2042 : int maxdim;
2043 0 : int failed = 0;
2044 0 : FILE *file = fopen(filename,"rt");
2045 : int res;
2046 :
2047 0 : if (!file) {
2048 0 : log_text("could not open typeinfo test file");
2049 0 : assert(0);
2050 : }
2051 :
2052 0 : while (fgets(buf,TYPEINFO_TEST_BUFLEN,file)) {
2053 0 : if (buf[0] == '#' || !strlen(buf))
2054 0 : continue;
2055 :
2056 0 : res = sscanf(buf,"%s\t%s\t%s\n",bufa,bufb,bufc);
2057 0 : if (res != 3 || !strlen(bufa) || !strlen(bufb) || !strlen(bufc)) {
2058 0 : log_text("Invalid line in typeinfo test file (none of empty, comment or test)");
2059 0 : assert(0);
2060 : }
2061 :
2062 : #if 0
2063 : typeinfo_test_parse(&a,bufa);
2064 : typeinfo_test_parse(&b,bufb);
2065 : typeinfo_test_parse(&c,bufc);
2066 : #endif
2067 : #if 0
2068 : do {
2069 : #endif
2070 0 : typeinfo_testmerge(&a,&b,&c,&failed); /* check result */
2071 0 : typeinfo_testmerge(&b,&a,&c,&failed); /* check commutativity */
2072 :
2073 0 : if (a.is_nulltype()) break;
2074 0 : if (b.is_nulltype()) break;
2075 0 : if (c.is_nulltype()) break;
2076 :
2077 0 : maxdim = a.dimension;
2078 0 : if (b.dimension > maxdim) maxdim = b.dimension;
2079 0 : if (c.dimension > maxdim) maxdim = c.dimension;
2080 :
2081 : #if 0
2082 : if (maxdim < TYPEINFO_TEST_MAXDIM) {
2083 : typeinfo_inc_dimension(&a);
2084 : typeinfo_inc_dimension(&b);
2085 : typeinfo_inc_dimension(&c);
2086 : }
2087 : } while (maxdim < TYPEINFO_TEST_MAXDIM);
2088 : #endif
2089 : }
2090 :
2091 0 : fclose(file);
2092 :
2093 0 : if (failed) {
2094 0 : fprintf(stderr,"Failed typeinfo_merge tests: %d\n",failed);
2095 0 : log_text("Failed test");
2096 0 : assert(0);
2097 : }
2098 0 : }
2099 :
2100 : void
2101 0 : typeinfo_test()
2102 : {
2103 0 : log_text("Running typeinfo test file...");
2104 0 : typeinfo_testrun("typeinfo.tst");
2105 0 : log_text("Finished typeinfo test file.");
2106 0 : }
2107 :
2108 : #if 0
2109 : void
2110 : typeinfo_init_from_fielddescriptor(typeinfo_t *info,char *desc)
2111 : {
2112 : typeinfo_init_from_descriptor(info,desc,desc+strlen(desc));
2113 : }
2114 : #endif
2115 :
2116 : #define TYPEINFO_MAXINDENT 80
2117 :
2118 : void
2119 0 : typeinfo_print_class(FILE *file,classref_or_classinfo c)
2120 : {
2121 : /*fprintf(file,"<class %p>",c.any);*/
2122 :
2123 0 : if (!c.any) {
2124 0 : fprintf(file,"<null>");
2125 : }
2126 : else {
2127 0 : if (c.is_classref()) {
2128 0 : fprintf(file,"<ref>");
2129 0 : utf_fprint_printable_ascii(file,c.ref->name);
2130 : }
2131 : else {
2132 0 : utf_fprint_printable_ascii(file,c.cls->name);
2133 : }
2134 : }
2135 0 : }
2136 :
2137 : void
2138 0 : typeinfo_print(FILE *file, const typeinfo_t *info, int indent)
2139 : {
2140 : char ind[TYPEINFO_MAXINDENT + 1];
2141 :
2142 0 : if (indent > TYPEINFO_MAXINDENT)
2143 0 : indent = TYPEINFO_MAXINDENT;
2144 :
2145 0 : for (int i = 0; i < indent; ++i)
2146 0 : ind[i] = ' ';
2147 0 : ind[indent] = (char) 0;
2148 :
2149 0 : if (info->is_primitive()) {
2150 0 : if (basicblock *bptr = (basicblock*) info->returnaddress())
2151 0 : fprintf(file,"%sreturnAddress (L%03d)\n",ind,bptr->nr);
2152 : else
2153 0 : fprintf(file,"%sprimitive\n",ind);
2154 0 : return;
2155 : }
2156 :
2157 0 : if (info->is_nulltype()) {
2158 0 : fprintf(file,"%snull\n",ind);
2159 0 : return;
2160 : }
2161 :
2162 0 : if (info->is_newobject()) {
2163 0 : if (instruction *ins = info->newobject_instruction()) {
2164 0 : fprintf(file,"%sNEW(%p):",ind,(void*)ins);
2165 0 : typeinfo_print_class(file,ins[-1].sx.val.c);
2166 0 : fprintf(file,"\n");
2167 : }
2168 : else {
2169 0 : fprintf(file,"%sNEW(this)",ind);
2170 : }
2171 0 : return;
2172 : }
2173 :
2174 0 : fprintf(file,"%sClass: ",ind);
2175 0 : typeinfo_print_class(file,info->typeclass);
2176 0 : fprintf(file,"\n");
2177 :
2178 0 : if (info->is_array()) {
2179 0 : fprintf(file,"%sDimension: %d",ind,(int)info->dimension);
2180 0 : fprintf(file,"\n%sElements: ",ind);
2181 0 : switch (info->elementtype) {
2182 0 : case ARRAYTYPE_INT : fprintf(file,"int\n"); break;
2183 0 : case ARRAYTYPE_LONG : fprintf(file,"long\n"); break;
2184 0 : case ARRAYTYPE_FLOAT : fprintf(file,"float\n"); break;
2185 0 : case ARRAYTYPE_DOUBLE : fprintf(file,"double\n"); break;
2186 0 : case ARRAYTYPE_BYTE : fprintf(file,"byte\n"); break;
2187 0 : case ARRAYTYPE_CHAR : fprintf(file,"char\n"); break;
2188 0 : case ARRAYTYPE_SHORT : fprintf(file,"short\n"); break;
2189 0 : case ARRAYTYPE_BOOLEAN : fprintf(file,"boolean\n"); break;
2190 :
2191 : case ARRAYTYPE_OBJECT:
2192 0 : typeinfo_print_class(file,info->elementclass);
2193 0 : fprintf(file,"\n");
2194 0 : break;
2195 :
2196 : default:
2197 0 : fprintf(file,"INVALID ARRAYTYPE!\n");
2198 : }
2199 : }
2200 :
2201 0 : if (info->merged) {
2202 0 : fprintf(file,"%sMerged: ",ind);
2203 0 : for (int i = 0; i < info->merged->count; ++i) {
2204 0 : if (i) fprintf(file,", ");
2205 0 : typeinfo_print_class(file,info->merged->list[i]);
2206 : }
2207 0 : fprintf(file,"\n");
2208 : }
2209 : }
2210 :
2211 : void
2212 0 : typeinfo_print_short(FILE *file, const typeinfo_t *info)
2213 : {
2214 : int i;
2215 : instruction *ins;
2216 : basicblock *bptr;
2217 :
2218 : /*fprintf(file,"<typeinfo %p>",info);*/
2219 :
2220 0 : if (!info) {
2221 0 : fprintf(file,"(typeinfo*)NULL");
2222 0 : return;
2223 : }
2224 :
2225 0 : if (info->is_primitive()) {
2226 0 : bptr = (basicblock*) info->returnaddress();
2227 0 : if (bptr)
2228 0 : fprintf(file,"ret(L%03d)",bptr->nr);
2229 : else
2230 0 : fprintf(file,"primitive");
2231 0 : return;
2232 : }
2233 :
2234 0 : if (info->is_nulltype()) {
2235 0 : fprintf(file,"null");
2236 0 : return;
2237 : }
2238 :
2239 0 : if (info->is_newobject()) {
2240 0 : ins = (instruction *) info->newobject_instruction();
2241 0 : if (ins) {
2242 : /*fprintf(file,"<ins %p>",ins);*/
2243 0 : fprintf(file,"NEW(%p):",(void*)ins);
2244 0 : typeinfo_print_class(file,ins[-1].sx.val.c);
2245 : }
2246 : else
2247 0 : fprintf(file,"NEW(this)");
2248 0 : return;
2249 : }
2250 :
2251 0 : typeinfo_print_class(file,info->typeclass);
2252 :
2253 0 : if (info->merged) {
2254 0 : fprintf(file,"{");
2255 0 : for (i=0; i<info->merged->count; ++i) {
2256 0 : if (i) fprintf(file,",");
2257 0 : typeinfo_print_class(file,info->merged->list[i]);
2258 : }
2259 0 : fprintf(file,"}");
2260 : }
2261 : }
2262 :
2263 : void
2264 0 : typeinfo_print_type(FILE *file, int type, const typeinfo_t *info)
2265 : {
2266 0 : switch (type) {
2267 0 : case TYPE_VOID: fprintf(file,"V"); break;
2268 0 : case TYPE_INT: fprintf(file,"I"); break;
2269 0 : case TYPE_FLT: fprintf(file,"F"); break;
2270 0 : case TYPE_DBL: fprintf(file,"D"); break;
2271 0 : case TYPE_LNG: fprintf(file,"J"); break;
2272 0 : case TYPE_RET: fprintf(file,"R:"); /* FALLTHROUGH! */
2273 : case TYPE_ADR:
2274 0 : typeinfo_print_short(file,info);
2275 0 : break;
2276 :
2277 : default:
2278 0 : fprintf(file,"!");
2279 : }
2280 0 : }
2281 :
2282 : void
2283 0 : typedescriptor_print(FILE *file, const typedescriptor_t *td)
2284 : {
2285 0 : typeinfo_print_type(file,td->type, &(td->typeinfo));
2286 0 : }
2287 :
2288 : void
2289 0 : typevector_print(FILE *file, const varinfo *vec, int size)
2290 : {
2291 : int i;
2292 :
2293 0 : for (i=0; i<size; ++i) {
2294 0 : fprintf(file," %d=",i);
2295 0 : typeinfo_print_type(file, vec[i].type, &(vec[i].typeinfo));
2296 : }
2297 0 : }
2298 :
2299 : #endif /* TYPEINFO_DEBUG */
2300 :
2301 :
2302 : /*
2303 : * These are local overrides for various environment variables in Emacs.
2304 : * Please do not remove this and leave it at the end of the file, where
2305 : * Emacs will automagically detect them.
2306 : * ---------------------------------------------------------------------
2307 : * Local variables:
2308 : * mode: c++
2309 : * indent-tabs-mode: t
2310 : * c-basic-offset: 4
2311 : * tab-width: 4
2312 : * End:
2313 : * vim:noexpandtab:sw=4:ts=4:
2314 : */
|