77c4486382c620ad24a4d06e185b5b3cb1c2b893
[cacao.git] / src / vm / jit / inline / parseXTA.c
1 /*****
2 If V() then why add call edges since no type info passed? 
3    does nothing happen when the method with V() is XTA parsed? class info is standalone then
4    what about clinits?
5 Check initialization... need at least a dummy called by ...
6
7 ... why no error now????
8
9 What about recursion???  x.a calls x.a
10
11 Now wondering if there is a memory corruption because XTA seems to finish ok
12 ****/
13
14 /* src/vm/jit/inline/parseXTA.c - parser and print functions for
15                                   Rapid Type Analyis
16
17    Copyright (C) 1996-2005 R. Grafl, A. Krall, C. Kruegel, C. Oates,
18    R. Obermaisser, M. Platter, M. Probst, S. Ring, E. Steiner,
19    C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich, J. Wenninger,
20    Institut f. Computersprachen - TU Wien
21
22    This file is part of CACAO.
23
24    This program is free software; you can redistribute it and/or
25    modify it under the terms of the GNU General Public License as
26    published by the Free Software Foundation; either version 2, or (at
27    your option) any later version.
28
29    This program is distributed in the hope that it will be useful, but
30    WITHOUT ANY WARRANTY; without even the implied warranty of
31    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
32    General Public License for more details.
33
34    You should have received a copy of the GNU General Public License
35    along with this program; if not, write to the Free Software
36    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
37    02111-1307, USA.
38
39    Contact: cacao@complang.tuwien.ac.at
40
41    Authors: Carolyn Oates
42
43    Changes: Christian Thalinger
44
45    $Id: parseXTA.c 4302 2006-01-19 20:00:11Z twisti $
46
47 */
48
49 /*--------------------------------------
50 XTA so far
51 static
52 fields
53 virtual 
54 interfaces - started
55 clinit / final
56 general initialization 
57 ----
58 interfaces
59 + hand coded calls for system
60 2nd interation (want to try it in inlining)
61
62 Testing
63
64 ?? PARTUSED???
65 ----------------------------------*/
66
67 /***************
68  XTA Type Static Analysis of Java program
69    used -xta option is turned on either explicitly 
70  or automatically with inlining of virtuals.
71
72  XTA is called for reachable methods and keeps sets for each Method and Field used as follows:
73 1. Work list of reachable methods is initialized to main + JVM called methods 
74                                                 + missed methods
75 2. For virtual method call from M of e.m then
76   a. Add all static lookup of m in the cone of e = ce.mi to reachable worklist
77         JAVA_INVOKESTATIC/ JAVA_INVOKESPECIAL - xtaAddCallEdges
78         JAVA_INVOKEVIRTUAL - xtaMarkSubs 
79         JAVA_INVOKEINTERFACES
80   b. Add mi's parameters class + subtypes that are used by M to mi used classes
81         When XTA parsed follow the calls list (beg. parseXTA)
82   c. Add mi's return type + subtypes used by mi to M's used classes
83         When XTA parsed follow the calledBy list (end parseXTA)
84   d. Add ce of mi to mi's used classes
85         static/special  - addXTAcalledges
86         virtual - xtaMarkSubs if subclass used     -> xtaAddCallEdges
87                               if subclass not used -> add ce.mi to markedby temp set 
88
89 3. new C (new, <init>, & similiar) then add  C to M's used classes
90         JAVA_NEW, INVOKE_SPECIAL <init>, JAVA_CHECKCAST / JAVA_INSTANCEOF - classinit 
91 4. read Field X.f: add X to M's used classes
92         JAVA_GETSTATIC
93 5. write Field X.f: add X+subtypes that are used by M to X's classes
94         JAVA_PUTSTATIC
95
96  
97  If M calls 
98  USAGE:
99  Methods called by NATIVE methods and classes loaded dynamically
100  cannot be found by parsing. The following files supply missing methods:
101
102  xtaMissedIn0 - (provided) has the methods missed by every java program
103  xtaMissed||mainClassName - is program specific.
104
105  A file xtaMissed will be written by XTA analysis of any methods missed.
106
107  This file can be renamed to xtaMissed concatenated with the main class name.
108
109  Example:
110  ./cacao -xta hello
111
112  inlining with virtuals should fail if the returned xtaMissed is not empty.
113  so...
114  mv xtaMissed xtaMissedhello
115  ./cacao hello
116
117 Results: (currently) with -stat see # methods marked used
118  
119 ****************/
120
121
122 #include <assert.h>
123 #include <stdio.h>
124 #include <string.h>
125
126 #include "config.h"
127 #include "cacao/cacao.h"
128 #include "mm/memory.h"   
129 #include "toolbox/list.h"
130 #include "toolbox/logging.h"
131 #include "vm/class.h"
132 #include "vm/linker.h"
133 #include "vm/loader.h"
134 #include "vm/resolve.h"
135 #include "vm/options.h"
136 #include "vm/statistics.h"
137 #include "vm/jit/jit.h"
138 #include "vm/jit/parse.h"
139 #include "vm/jit/inline/parseXTA.h"
140 #include "vm/jit/inline/parseRTstats.h"
141 #include "vm/jit/inline/parseRTprint.h"
142
143
144
145 static bool firstCall= true;
146 static list *xtaWorkList;
147 FILE *xtaMissed;   /* Methods missed during XTA parse of Main  */
148
149 bool XTA_DEBUGinf = false;
150 bool XTA_DEBUGr = false;
151 bool XTA_DEBUGopcodes = false;
152
153 char * clsFlgs  [] = {"NOTUSED", "PARTUSED", "USED"};
154 char * methFlgs [] = {"NOTUSED", "MARKED",   "USED"};
155
156 /*********************************************************************/
157 /*********************************************************************/
158
159 /* function descriptor2typesL ***************************************************
160
161         decodes a already checked method descriptor. The parameter count, the
162         return type and the argument types are stored in the passed methodinfo.
163         gets and saves classptr for object ref.s
164
165 *******************************************************************************/                
166
167 static classSetNode *descriptor2typesL(methodinfo *m)
168 {
169         int debugInfo = 0;
170         int i;
171         u1 *types, *tptr;
172         int pcount, c;
173         char *utf_ptr;
174         classinfo** classtypes;
175         char *class; 
176         char *desc;
177         classSetNode *p=NULL;
178         classinfo *clsinfo;
179         
180         if (debugInfo >= 1) {
181                 printf("In descriptor2typesL >>>\t"); fflush(stdout);
182                 utf_display(m->class->name); printf(".");
183                 method_println(m);fflush(stdout);
184         }
185
186         pcount = 0;
187         desc =       MNEW (char, 256); 
188         types = DMNEW (u1, m->descriptor->blength); 
189         classtypes = MNEW (classinfo*, m->descriptor->blength+1);
190         m->returnclass = NULL;
191         tptr = types;
192         if (!(m->flags & ACC_STATIC)) {
193                 *tptr++ = TYPE_ADR;
194                 if (debugInfo >= 1) {
195                         printf("param #0 (this?) method class =");utf_display(m->class->name);printf("\n");
196                 }
197                 classtypes[pcount] = m->class;
198                 p = addClassCone(p,  m->class);
199                 pcount++;
200         }
201
202         utf_ptr = m->descriptor->text + 1;
203         strcpy (desc,utf_ptr);
204    
205         while ((c = *desc++) != ')') {
206                 pcount++;
207                 switch (c) {
208                 case 'B':
209                 case 'C':
210                 case 'I':
211                 case 'S':
212                 case 'Z':  *tptr++ = TYPE_INT;
213                         break;
214                 case 'J':  *tptr++ = TYPE_LNG;
215                         break;
216                 case 'F':  *tptr++ = TYPE_FLT;
217                         break;
218                 case 'D':  *tptr++ = TYPE_DBL;
219                         break;
220                 case 'L':  *tptr++ = TYPE_ADR;
221                         /* get class string */
222                         class = strtok(desc,";");
223                         desc = strtok(NULL,"\0");
224                         /* get/save classinfo ptr */
225                         if (!(clsinfo = load_class_bootstrap(utf_new_char(class)))) {
226                                 log_text("could not load class in descriptor2typesL");
227                                 assert(0);
228                         }
229                         classtypes[pcount-1] = clsinfo;
230                         p = addClassCone(p, clsinfo);
231                         if (debugInfo >= 1) {
232                                 printf("LParam#%i 's class type is: %s\n",pcount-1,class);fflush(stdout);
233                                 printf("Lclasstypes[%i]=",pcount-1);fflush(stdout);
234                                 utf_display(classtypes[pcount-1]->name);
235                         }
236                         break;
237                 case '[':  *tptr++ = TYPE_ADR;
238                         while (c == '[')
239                                 c = *desc++;
240                         /* get class string */
241                         if (c == 'L') {
242                                 class = strtok(desc,";");
243                                 desc = strtok(NULL,"\0");
244                                 /* get/save classinfo ptr */
245                                 if (!(clsinfo = load_class_bootstrap(utf_new_char(class)))) {
246                                         log_text("could not load class in descriptor2typesL");
247                                         assert(0);
248                                 }
249                                 classtypes[pcount-1] = clsinfo;
250                                 p= addClassCone(p, clsinfo);
251                                 if (debugInfo >= 1) {
252                                         printf("[Param#%i 's class type is: %s\n",pcount-1,class);
253                                         printf("[classtypes[%i]=",pcount-1);fflush(stdout);
254                                         utf_display(classtypes[pcount-1]->name);
255                                         printf("\n");
256                                 }
257                         }
258                         else
259                                 classtypes[pcount-1] = NULL;
260                         break;
261                 default:   
262                         log_text("Ill formed methodtype-descriptor");
263                         assert(0);
264                 }
265         }
266
267         /* compute return type */
268         switch (*desc++) {
269         case 'B':
270         case 'C':
271         case 'I':
272         case 'S':
273         case 'Z':  m->returntype = TYPE_INT;
274                 break;
275         case 'J':  m->returntype = TYPE_LNG;
276                 break;
277         case 'F':  m->returntype = TYPE_FLT;
278                 break;
279         case 'D':  m->returntype = TYPE_DBL;
280                 break;
281         case '[':
282                 m->returntype = TYPE_ADR;
283                 c = *desc;
284                 while (c == '[') {
285                         c = *desc++;
286                         }
287                 if (c != 'L') break;
288                 c = *desc;
289                 if (c == 'L')
290                         *(desc++); 
291         case 'L':  
292                 m->returntype = TYPE_ADR;
293                           
294                 /* get class string */
295                 class = strtok(desc,";");
296                 if (!(clsinfo = load_class_bootstrap(utf_new_char(class)))) {
297                         log_text("could not load class in descriptor2typesL");
298                         assert(0);
299                 }
300                 m->returnclass = clsinfo;
301                 if (m->returnclass == NULL) {
302                         printf("class=<%s>\t",class); fflush(stdout);
303                         log_text("return class not found");
304                         assert(0);
305                 }
306                 break;
307         case 'V':  m->returntype = TYPE_VOID;
308                 break;
309
310         default:
311                 log_text("Ill formed methodtype-descriptor-ReturnType");
312                 assert(0);
313         }
314
315         m->paramcount = pcount;
316         m->paramtypes = types;
317         m->paramclass = classtypes;
318
319         if (debugInfo >=1) {
320                 if (pcount > 0) {
321                         for (i=0; i< m->paramcount; i++) {
322                         if ((m->paramtypes[i] == TYPE_ADR) && (m->paramclass[i] != NULL)) {
323                                         printf("Param #%i is:\t",i);
324                                         utf_display(m->paramclass[i]->name);
325                                         printf("\n");
326                                 }
327                         }
328                 }
329                 if ((m->returntype == TYPE_ADR) && (m->returnclass != NULL)) { 
330                         printf("\tReturn Type is:\t"); fflush(stdout);
331                         utf_display(m->returnclass->name);
332                         printf("\n");
333                 }
334
335                 printf("params2types: START  results in a set \n");
336                 printf("param2types: A Set size=%i=\n",sizeOfSet(p));
337                 printSet(p);
338         }
339
340         return p;
341 }
342
343
344
345 /*-------------------------------------------------------------------------------*/
346
347 xtafldinfo * xtafldinfoInit (fieldinfo *f)
348 {
349         if (f->xta != NULL)
350                 return f->xta;
351
352         f->xta = NEW(xtafldinfo);
353
354         f->xta->fieldChecked = false;
355         f->xta->fldClassType = NULL;
356         f->xta->XTAclassSet = NULL;
357
358         return f->xta;
359 }
360
361 /*-------------------------------------------------------------------------------*/
362
363 xtainfo *xtainfoInit(methodinfo *m)
364 {
365         if (m->xta != NULL)
366                 return m->xta; /* already initialized */
367
368 #if defined(ENABLE_STATISTICS)
369         count_methods_marked_used++;
370 #endif
371
372         m ->xta = (xtainfo *) NEW(xtainfo);
373         m ->xta-> XTAmethodUsed = NOTUSED;
374
375         /* xta sets for a method */
376         m->xta->fldsUsed        = NULL;
377         m ->xta-> XTAclassSet   = NULL;
378                                 /* Methods's have access to the class they are a part of */
379         m ->xta-> XTAclassSet   = add2ClassSet ( m ->xta-> XTAclassSet, m->class);  
380         /* cone set of methods parameters */ 
381                  /* what if no param?? is it NULL then, too? */ 
382    /****** class not loaded so take param info from superclass ??? */
383         m->xta->paramClassSet = descriptor2typesL(m); 
384
385         /* Edges */
386         m->xta->calls         = NULL;
387         m->xta->calledBy      = NULL;
388         m ->xta->markedBy     = NULL; 
389
390         m->xta->chgdSinceLastParse = false;
391         return m->xta;
392
393         /* thought needed at some earlier point */
394         /*m ->xta->interfaceCalls    = NULL*/
395 }
396
397 /*-------------------------------------------------------------------------------*/
398 void xtaAddCallEdges(methodinfo *mCalls, methodinfo *mCalled, s4 monoPoly, char *info) {
399     xtaNode    *xta = NULL;
400
401
402 if (mCalled->flags & ACC_ABSTRACT) return;
403 /* First call to this method initializations */
404                 /******
405 printf("mCalled->methodUsed =%i != %i = USED is ",mCalled->methodUsed, USED); fflush(stdout);
406 printf(" <%i> T%i/%iF\n",(mCalled->methodUsed!= USED), true,false); fflush(stdout);
407                 ******/
408
409 if (mCalled->methodUsed != USED) {
410                 /******
411                 printf("\n>>>>>>%s:\n",info); fflush(stdout);
412                 printf("Add to Worklist mCalls_=");fflush(stdout);
413                 if (mCalls!=NULL) {
414                         printf("<"); fflush(stdout);
415                         METHINFOx(mCalls)
416                         printf("> "); fflush(stdout);
417                         }
418                 else
419                         {
420                         printf("NULL\n");fflush(stdout);
421                         }
422
423                 printf("mCalled=");fflush(stdout);
424                 if (mCalled!=NULL) {
425                         printf("<"); fflush(stdout);
426                         METHINFOx(mCalled)
427                         printf("> "); fflush(stdout);
428                         }
429                 else
430                         {printf("NULL\n");fflush(stdout);}
431                 ****/
432     mCalled->xta = xtainfoInit(mCalled);
433     mCalled ->methodUsed = USED; /* used to see if method in the work list of methods */ 
434     xta = NEW(xtaNode);
435     xta->method = mCalled ;
436     list_addlast(xtaWorkList,xta);  
437     }
438
439 if ((mCalls == NULL) && (!(monoPoly == SYSCALL)) ) {} /* panic when init file correct is */
440
441 if ((mCalls == mCalled)  /* recursion doesn't change class set nor field set so ignore */
442   || (mCalls == NULL)) {return; }  
443
444
445 /***            printf(" AddCallEdges\n"); fflush(stdout); ***/
446 /* Add call edges */
447 mCalls->xta = xtainfoInit(mCalls);
448 mCalls->xta->calls = add2MethSet(mCalls->xta->calls, mCalled);
449                         /* mono if static, private, final else virtual so poly */
450 mCalls->xta->calls->tail->monoPoly = monoPoly;  
451
452 mCalled->xta->calledBy = add2MethSet(mCalled->xta->calledBy, mCalls);
453
454 /* IS THIS REALLY NEEDED???? */
455 if (mCalled->xta->calledBy == NULL) {
456         log_text("mCalled->xta->calledBy is NULL!!!");
457         assert(0);
458 }
459 if (mCalls->xta->calls == NULL) {
460         log_text("mCalls->xta->calls is NULL!!!");
461         assert(0);
462 }
463
464 }
465
466
467 /*-------------------------------------------------------------------------------*/
468 bool xtaPassParams (methodinfo *Called, methodinfo *Calls, methSetNode *lastptrInto)
469 {
470         classSetNode *p;
471         classSetNode *c;
472         classSetNode *c1;
473         classSetNode *cprev;
474         bool          chgd = false;
475
476                 /* prevent compiler warnings */
477
478                 c1 = NULL;
479
480         if (lastptrInto->lastptrIntoClassSet2 == NULL) {
481                 if (Calls->xta->XTAclassSet != NULL)
482                         c1 = Calls->xta->XTAclassSet->head;
483                  /*else already c1 = NULL; */
484         }
485         else    {
486                 /* start with type where left off */
487                 c1 = lastptrInto->lastptrIntoClassSet2;
488                 c1 = c1 -> nextClass;  /* even if NULL */
489         }
490         if (c1 == NULL) return false;
491
492         cprev = NULL;
493        /* for each Param Class */
494         for (   p=Called->xta->paramClassSet; p != NULL; p = p->nextClass) {
495
496                 /* for each SmCalls class */
497                 for (c=c1; c != NULL; c = c->nextClass) {
498                         vftbl_t *p_cl_vt;
499                         vftbl_t *c_cl_vt;
500
501                         LAZYLOADING(c->classType)  /* if not loaded is it really needed ??? */
502
503                         p_cl_vt = p->classType->vftbl;
504                         c_cl_vt = c->classType->vftbl;
505
506                         /* if SmCalls class is in the Params Class range */
507                         if (  (p_cl_vt->baseval <=  c_cl_vt->baseval)
508                                   && (c_cl_vt->baseval <= (p_cl_vt->baseval+p_cl_vt->diffval)) ) {
509
510                                 /*    add Calls class to CalledBy Class set */
511                                 Called->xta->XTAclassSet = Called->xta->XTAclassSet = add2ClassSet(Called->xta->XTAclassSet, c->classType);
512                               chgd = true;
513                         }
514                         cprev = c;
515                 }
516         }
517         lastptrInto->lastptrIntoClassSet2 = cprev;
518         return chgd;
519 }
520
521
522 /*-------------------------------------------------------------------------------*/
523 void xtaPassAllCalledByParams (methodinfo *m) {
524         methSetNode *SmCalled;
525         if (m->xta->calledBy == NULL)
526                 return;
527         for (SmCalled  = m->xta->calledBy->head; 
528              SmCalled != NULL; 
529              SmCalled = SmCalled->nextmethRef) {
530                 m->xta->chgdSinceLastParse = false;             /* re'init flag */
531                 xtaPassParams(m, SmCalled->methRef,SmCalled);   /* chg flag output ignored for 1st regular parse */
532         }
533 }
534
535
536 /*-------------------------------------------------------------------------------*/
537 void xtaPassFldPUT(methodinfo *m, fldSetNode *fN)
538 {
539         /* Field type is a class */
540         classSetNode *c;
541         classSetNode *c1 = NULL;
542         classSetNode *cp = NULL;
543         classSetNode *cprev= NULL;
544
545         fieldinfo *fi;
546                 
547         if (fN != NULL)
548                 fi = fN->fldRef;
549         else
550                 return;
551         
552 /* Use lastptr  so don't check whole XTA class set each time */
553         cp = fN->lastptrPUT;
554         if (cp != NULL) {
555                 if (cp->nextClass != NULL)
556                         c1 = cp -> nextClass;
557         } 
558         else    {
559                 if (m->xta->XTAclassSet != NULL)
560                         c1  = m->xta->XTAclassSet->head;
561         }
562
563         /*--- PUTSTATIC specific ---*/
564         /* Sx = intersection of type+subtypes(field x)   */
565         /*   and Sm (where putstatic code is)            */
566         for (c=c1; c != NULL; c=c->nextClass) {
567                 vftbl_t *f_cl_vt;
568                 vftbl_t *c_cl_vt;
569
570                 LAZYLOADING1(fi->xta->fldClassType)
571
572                 f_cl_vt = fi->xta->fldClassType->vftbl;
573                 c_cl_vt = c->   classType->vftbl;
574                 if ((f_cl_vt->baseval <= c_cl_vt->baseval)
575                         && (c_cl_vt->baseval <= (f_cl_vt->baseval+f_cl_vt->diffval)) ) {
576                         fi->xta->XTAclassSet = add2ClassSet(fi->xta->XTAclassSet,c->classType);
577                 }
578                 cprev = c;
579         }
580         fN->lastptrPUT = cprev;
581 }
582 /*-------------------------------------------------------------------------------*/
583 void xtaPassFldGET(methodinfo *m, fldSetNode *fN)
584 {
585         /* Field type is a class */
586         classSetNode *c;
587         classSetNode *c1 = NULL;
588         classSetNode *cp = NULL;
589         classSetNode *cprev= NULL;
590
591         fieldinfo *fi;
592         if (fN != NULL)
593                 fi = fN->fldRef;
594         else
595                 return;
596
597 /* Use lastptr  so don't check whole XTA class set each time */
598         cp = fN->lastptrGET;
599         if (cp != NULL) {
600                 if (cp->nextClass != NULL)
601                         c1 = cp -> nextClass;
602         } 
603         else    {
604                 if (fi->xta->XTAclassSet != NULL)
605                         c1  = fi->xta->XTAclassSet->head;
606         }
607
608         /*--- GETSTATIC specific ---*/
609         /* Sm = union of Sm and Sx */
610         for (c=c1; c != NULL; c=c->nextClass) {
611                 bool addFlg = false;
612                 if (m->xta->XTAclassSet ==NULL) 
613                         addFlg = true;
614                 else    {
615                         if (!(inSet (m->xta->XTAclassSet->head, c->classType) )) 
616                                 addFlg = true;
617                         }
618                 if (addFlg) {
619                         m->xta->XTAclassSet 
620                                 = add2ClassSet(m->xta->XTAclassSet,c->classType);
621                 }
622                 cprev = c;
623         }
624
625         fN->lastptrGET = cprev;
626 }
627
628
629 /*-------------------------------------------------------------------------------*/
630 void xtaAllFldsUsed (methodinfo *m) {
631         fldSetNode  *f;
632         fldSetNode *f1=NULL;
633         /*      bool chgd = false */
634
635         if (m->xta->fldsUsed == NULL) return;
636
637         /* for each field that this method uses */
638         f1 = m->xta->fldsUsed->head;
639
640         for (f=f1; f != NULL; f = f->nextfldRef) {
641
642                 if (f->writePUT)
643                         xtaPassFldPUT(m,f);
644                 if (f->readGET)
645                         xtaPassFldGET(m,f);
646         }
647 }
648
649 /*-------------------------------------------------------------------------------*/
650 bool xtaPassReturnType(methodinfo *Called, methodinfo *Calls) {
651
652         classSetNode* cs;
653         classSetNode* cs1;
654         bool          fchgd = false;
655
656         /* Get Called return class is null */
657         if ((Called->returnclass == NULL) && (Called->xta->paramClassSet == NULL)) {
658                 Called->xta->paramClassSet = descriptor2typesL(Called); /* old comment - in new xta struc init */ 
659         }
660
661         if (Called->returnclass == NULL) {
662                 return fchgd;
663         }
664         
665         if (Called->xta->XTAclassSet == NULL) 
666                 cs1 = NULL;
667         else
668                 cs1 =  Called->xta->XTAclassSet->head;
669
670         for (cs =cs1; cs != NULL; cs = cs->nextClass) {
671                 classinfo *c = cs->classType;
672                 vftbl_t *r_cl_vt; 
673                 vftbl_t *c_cl_vt; 
674                 LAZYLOADING(c)
675                 LAZYLOADING(Called->returnclass)
676                 r_cl_vt = Called->returnclass->vftbl; 
677                 c_cl_vt = c->vftbl; 
678
679                 /* if class is a subtype of the return type, then add to Calls class set (ie.interscection)*/
680                 if (  (r_cl_vt->baseval <=  r_cl_vt->baseval)
681                           && (c_cl_vt->baseval <= (r_cl_vt->baseval+r_cl_vt->diffval)) ) {
682                         Calls->xta->XTAclassSet = add2ClassSet(Calls->xta->XTAclassSet, c);  
683                         fchgd = true;
684                 }
685         } 
686
687         return fchgd; 
688 }
689
690
691 /*-------------------------------------------------------------------------------*/
692 void  xtaMethodCalls_and_sendReturnType(methodinfo *m)
693 {
694         methSetNode *SmCalled;  /* for return type       */
695         methSetNode *SmCalls;   /* for calls param types */
696         methSetNode *s1=NULL;
697         bool chgd = false;
698
699         xtaAllFldsUsed (m);
700
701                 if (m->xta == NULL) {
702                         log_text("m->xta null for return type");
703                         assert(0);
704                 }
705
706         /* for each method that this method calls */
707         if (m->xta->calls == NULL)
708                 s1 = NULL;
709         else
710                 s1 = SmCalls=m->xta->calls->head;
711
712         for (SmCalls=s1; SmCalls != NULL; SmCalls = SmCalls->nextmethRef) {
713                 /*    pass param types  */
714                 bool chgd = false;
715                 chgd = xtaPassParams (SmCalls->methRef, m, SmCalls);
716                 /* if true chgd after its own parse */
717                 if (!(SmCalls->methRef->xta->chgdSinceLastParse)) {
718                         SmCalls->methRef->xta->chgdSinceLastParse = true;
719                 }
720         }
721
722         /* for each calledBy method */
723         /*    send return type */
724         if (m->xta->calledBy == NULL)
725                 s1 = NULL;
726         else
727                 s1 = m->xta->calledBy->head;
728         for (SmCalled=s1; SmCalled != NULL; SmCalled = SmCalled->nextmethRef) {
729
730                 chgd = xtaPassReturnType(m, SmCalled->methRef);
731                 if (!(SmCalled->methRef->xta->chgdSinceLastParse)) {
732                         SmCalled->methRef->xta->chgdSinceLastParse = chgd;
733                 }
734         }
735
736 }
737
738 /*-------------------------------------------------------------------------------*/
739 bool xtaAddFldClassTypeInfo(fieldinfo *fi) {
740
741         bool is_classtype = false; /* return value */
742
743         if (fi->xta->fieldChecked) {
744                 if (fi->xta->fldClassType != NULL)
745                         return true;  /* field has a class type */
746                 else
747                         return false;
748         }
749         fi->xta->fieldChecked = true;
750
751         if (fi->type == TYPE_ADDRESS) {
752                 char *utf_ptr = fi->descriptor->text;  /* current position in utf text */
753
754                 if (*utf_ptr != 'L') {
755                         while (*utf_ptr++ =='[') ;
756                 }
757
758                 if (*utf_ptr =='L') {
759                         is_classtype = true;
760                         if  (fi->xta->fldClassType== NULL) {
761                                 char *desc;
762                                 char *cname;
763                                 classinfo * class;
764
765                                 desc = MNEW(char, 256);
766                                 strcpy(desc,++utf_ptr);
767                                 cname = strtok(desc,";");
768                                 if (!(class = load_class_bootstrap(utf_new_char(cname)))) {
769                                         log_text("could not load class in xtaAddFldClassTypeInfo");
770                                         assert(0);
771                                 }
772                                 fi->xta->fldClassType= class;    /* save field's type class ptr */      
773                         } 
774                 }
775         }
776         return is_classtype;
777 }
778
779 /*--------------------------------------------------------------*/
780 /* Mark the method with same name /descriptor in topmethod      */
781 /* in class                                                     */
782 /*                                                              */
783 /* Class marked USED and method defined in this class ->        */
784 /*    -> add call edges = USED                                  */
785 /* Class not marked USED and method defined in this class ->    */
786 /*    -> if Method NOTUSED mark method as MARKED                */
787 /*                                                              */
788 /* Class USED, but method not defined in this class ->          */
789 /* -> 1) search up the heirarchy and mark method where defined  */
790 /*    2) if class where method is defined is not USED ->        */
791 /*       -> ????mark class with defined method as PARTUSED          */
792 /*--------------------------------------------------------------*/
793
794
795 void xtaMarkMethod(classinfo *class, methodinfo *mCalls, methodinfo *topmethod, classSetNode *subtypesUsedSet) {
796
797 utf *name       = topmethod->name; 
798 utf *descriptor = topmethod->descriptor;
799 methodinfo *submeth;
800
801 /* See if method defined in class heirarchy */
802 submeth = class_resolvemethod(class, name, descriptor); 
803 METHINFOt(submeth,"xtaMarkMethod submeth:",XTA_DEBUGr);
804 if (submeth == NULL) {
805         utf_display(class->name); printf(".");
806         METHINFOx(topmethod);
807         printf("parse XTA: Method not found in class hierarchy");fflush(stdout);
808         assert(0);
809 }
810
811 /* if submeth called previously from this method then return */
812 if (mCalls->xta->calls != NULL) {
813         if (inMethSet(mCalls->xta->calls->head,submeth)) return;
814         }
815
816 #undef CTA 
817 #ifdef CTA
818   XTAaddClassInit(submeth,      submeth->class,
819                 CLINITS_T,FINALIZE_T,ADDMARKED_T);
820   if (inSet(subtypesUsedSet,submeth->class)) {
821       submeth->monoPoly = POLY;
822       xtaAddCallEdges(mCalls, submeth, submeth->monoPoly, 
823                       "00addTo XTA VIRT CONE:");
824       }
825   return;
826 #endif
827
828   if (submeth->class == class) { 
829
830         /*--- Method defined in class -----------------------------*/
831         if (inSet(subtypesUsedSet,submeth->class)) {
832                 /* method defined in this class -> */
833                 /* Class IS  marked USED           */ 
834                 /*    -> mark method as USED       */
835                 submeth->monoPoly = POLY;
836                 xtaAddCallEdges(mCalls, submeth, submeth->monoPoly, 
837                         "01addTo VIRT CONE 1:");
838                 }
839         else    {
840                 /* method defined in this class -> */
841                 /* Class IS NOT  marked USED (PART or NOTUSED) */ 
842                 /* -> if Method NOTUSED mark method as  MARKED */
843                 METHINFOt(submeth,
844                         "\tmarked VIRT CONE 2:",XTA_DEBUGr);
845                 submeth->monoPoly = POLY;
846                 if (submeth->xta == NULL) {
847                         submeth->xta = xtainfoInit(submeth);
848                         }
849                 submeth->methodUsed = MARKED; /* used to see if method in the work list of methods */ 
850                 submeth->xta->markedBy = add2MethSet(submeth->xta->markedBy,mCalls);
851                 /* Note: if class NOTUSED and subclass is used handled  */
852                 /*       by subsequent calls to xtaMarkMethods for cone */
853                 }
854         } /* end defined in class */
855
856   else {
857         /*--- Method NOT defined in class  - defined up the heirarchy ---------------*/
858         /* then check class the method could be called with */
859
860         /* first mark classes if needed */
861         if (!(inSet(subtypesUsedSet,submeth->class))) {
862                 submeth->class->classUsed = PARTUSED; 
863                 if (!(inSet(subtypesUsedSet,class))) {
864                         submeth->monoPoly = POLY;
865                         if (submeth->xta == NULL)
866                                 submeth->xta = xtainfoInit(submeth);
867                         submeth->methodUsed = MARKED; /* used to see if method in the work list of methods */ 
868                         submeth->xta->markedBy = add2MethSet(submeth->xta->markedBy,mCalls);
869                         METHINFOt(submeth,"JUST MARKED :",XTA_DEBUGr);
870                         }
871                 }
872         /* add method to xta work list if conditions met */
873         if (inSet(subtypesUsedSet,class)) {
874                 submeth->monoPoly = POLY;
875                 xtaAddCallEdges(mCalls, submeth, submeth->monoPoly, 
876                                 "02addTo VIRT CONE 3:");
877                 }
878         } /* end NOT defined in class */
879
880
881
882 /*----------------------------------------------------------------------*/
883 /* Mark the method with the same name and descriptor as topmethod       */
884 /*   and any subclass where the method is defined and/or class is used  */
885 /*                                                                      */
886 /*----------------------------------------------------------------------*/
887
888 void xtaMarkSubs(methodinfo *mCalls, classinfo *class, methodinfo *topmethod, classSetNode *subtypesUsedSet) {
889         /* xtaPRINTmarkSubs1*/
890         xtaMarkMethod(class, mCalls, topmethod, subtypesUsedSet);   /* Mark method in class where it was found */
891         if (class->sub != NULL) {
892                 classinfo *subs;
893
894                 if (!(topmethod->flags & ACC_FINAL )) {
895                         for (subs = class->sub; subs != NULL; subs = subs->nextsub) {
896                                 xtaMarkSubs(mCalls, subs, topmethod, subtypesUsedSet);
897                                 }
898                         }
899                 }
900 }
901
902
903 /**************************************************************************/
904 /* Add Marked methods for input class ci                                  */
905 /* Add methods with the same name and descriptor as implemented interfaces*/
906 /*   with the same method name                                            */
907 /*  ??? interface part not XTA checked                                    */
908 /*------------------------------------------------------------------------*/
909 void xtaAddMarkedMethods(methodinfo *mCalls, classinfo *ci) {
910 int ii,jj,mm;
911
912 /* add marked methods to callgraph */ 
913 for (ii=0; ii<ci->methodscount; ii++) { 
914         methodinfo *mi = &(ci->methods[ii]);
915
916         if (mi->xta != NULL) {
917                 if (mi->xta->markedBy != NULL) {
918                         methSetNode *mcnode;
919                         for (mcnode = mi->xta->markedBy->head; mcnode  != NULL; mcnode  = mcnode ->nextmethRef) {
920                                 methodinfo *mCalls = mcnode->methRef;
921                                 xtaAddCallEdges(mCalls, mi, mi->monoPoly, 
922                                         "03addToInit was Marked added:");
923                                 }
924                         }
925
926                 else    { /* NOT XTA checked yet */
927                         for (jj=0; jj < ci -> interfacescount; jj++) {
928                                 classinfo *ici = ci -> interfaces [jj].cls;
929                                 /*  use resolve method....!!!! */
930                                 if (ici -> classUsed != NOTUSED) {
931                                         for (mm=0; mm< ici->methodscount; mm++) {
932                                                 methodinfo *imi = &(ici->methods[mm]);
933                                                 METHINFOt(imi,"NEW IMPD INTERFACE:",XTA_DEBUGinf)
934                                               /*if interface method=method is used*/
935                                                 if  (      (imi->methodUsed == USED)
936                                                    &&    ( (imi->name == mi->name) 
937                                                    &&      (imi->descriptor == mi->descriptor))) {
938                                                         xtaAddCallEdges(mCalls, mi, mi->monoPoly, 
939                                                                  "04addTo was interfaced used/MARKED:");
940                                                         } 
941                                                 } /*end for */  
942                                         }
943                                 }
944                         }
945                 }       
946         }
947 }    
948
949
950 /*------------------------------------------------------------------------*/
951 void xtaAddUsedInterfaceMethods(methodinfo *m, classinfo *ci) {
952         int jj,mm;
953
954         /* add used interfaces methods to callgraph */
955         for (jj=0; jj < ci -> interfacescount; jj++) {
956                 classinfo *ici = ci -> interfaces [jj].cls;
957         
958                 if (XTA_DEBUGinf) { 
959                         printf("BInterface used: ");fflush(stdout); 
960                         utf_display(ici->name);
961                         printf("<%i>\tclassUsed=%s\n",ici -> classUsed,clsFlgs[ici->classUsed] ); fflush(stdout); 
962                         }
963                 /* add class to interfaces list of classes that implement it */
964                 ici -> impldBy =  addElement(ici -> impldBy,  ci);
965
966                 /* if interface class is used */
967                  if (ici -> classUsed != NOTUSED) {
968
969                         /* for each interface method implementation that has already been used */
970                         for (mm=0; mm< ici->methodscount; mm++) {
971                                 methodinfo *imi = &(ici->methods[mm]);
972                                         if  ( (XTA_DEBUGinf) && (imi->methodUsed != USED)) {
973                                                 printf("Interface Method %s: ", methFlgs[imi->methodUsed]); 
974                                                 utf_display(ici->name);printf(".");method_println(imi);fflush(stdout);
975                                         }
976                                 if  (imi->methodUsed == USED) {
977                                             if (XTA_DEBUGinf) { 
978                                                 printf("Interface Method used: "); utf_display(ici->name);printf(".");method_println(imi);fflush(stdout);
979                                                 /* Mark this method used in the (used) implementing class &its subclasses */
980                                                 printf("rMAY ADD methods that was used by an interface\n");
981                                                 }
982                                         if ((utf_clinit != imi->name) &&
983                                             (utf_init   != imi->name))
984                                                 {
985                                                 classSetNode *subtypesUsedSet = NULL;
986                                                 if (m->xta->XTAclassSet != NULL) {
987                                                         subtypesUsedSet =
988                                                                 intersectSubtypesWithSet
989                                                                 (imi->class, m->xta->XTAclassSet->head);
990                                                         }
991                                                 else /* can any methods be added if 1 set is NULL ??? */
992                                                         subtypesUsedSet = addElement(subtypesUsedSet, m->class);
993                                                 xtaMarkSubs(m, ci, imi, subtypesUsedSet); 
994                                                 imi->monoPoly = POLY;
995
996                                                 }
997                                         }       
998                                 } /* end for method */
999                         } /* end != NOTUSED */
1000                 } /* end for interface */
1001
1002 }
1003
1004
1005 /*----------------------------------------------------------------------*/
1006
1007 #define CLINITS_T   true
1008 #define FINALIZE_T  true
1009 #define ADDMARKED_T true
1010
1011 #define CLINITS_F   false 
1012 #define FINALIZE_F  false 
1013 #define ADDMARKED_F false
1014 /*-----------------------*/
1015
1016 void XTAaddClassInit(methodinfo *mCalls, classinfo *ci, bool clinits, bool finalizes, bool addmark)
1017 {
1018   methodinfo *mi;
1019
1020   if (addmark)
1021         ci->classUsed = USED;
1022         
1023   if (clinits) { /* No <clinit>  available - ignore */
1024     mi = class_findmethod(ci, utf_clinit, utf_void__void); 
1025     if (mi) { 
1026         if (ci->classUsed != USED)
1027             ci->classUsed = PARTUSED;
1028         mi->monoPoly = MONO;
1029         xtaAddCallEdges(mCalls, mi, mi->monoPoly, 
1030                         "05addTo CLINIT added:");
1031       }     
1032     }        
1033
1034   /*Special Case for System class init:
1035     add java/lang/initializeSystemClass to callgraph */
1036   if (ci->name == utf_new_char("initializeSystemClass")) {
1037     /* ?? what is name of method ?? */ 
1038     } 
1039
1040   if (finalizes) {
1041     mi = class_findmethod(ci, utf_finalize, utf_void__void);
1042     if (mi) { 
1043         if (ci->classUsed != USED)
1044             ci->classUsed = PARTUSED;
1045         mi->monoPoly = MONO;
1046         xtaAddCallEdges(mCalls, mi, mi->monoPoly, 
1047                         "06addTo FINALIZE added:");
1048       }     
1049     }        
1050
1051   if (addmark) {
1052     xtaAddMarkedMethods(mCalls, ci);
1053     }
1054
1055   /* always so know have access to the interface methods */
1056   xtaAddUsedInterfaceMethods(mCalls,ci);
1057
1058 }
1059
1060 /*-------------------------------------------------------------------------------*/
1061
1062 /*********************************************************************/
1063 /*********************************************************************/
1064
1065 /*-------------------------------------------------------------------*/
1066
1067 void xtaMarkInterfaceSubs(methodinfo *m, methodinfo *mi) {                              
1068         classSetNode *subs;
1069         if (mi->class->classUsed == NOTUSED) {
1070                 mi->class->classUsed = USED; 
1071                 /* add interface class to list kept in Object */
1072                 class_java_lang_Object->impldBy =  addElement(class_java_lang_Object -> impldBy,  mi->class);
1073                 }
1074
1075         mi->methodUsed = USED;
1076         mi->monoPoly   = POLY;
1077
1078                    /*XTAPRINT08invokeInterface1*/
1079                    if (XTA_DEBUGinf) {
1080                         subs =  mi->class->impldBy; 
1081                         METHINFO(mi,XTA_DEBUGinf)
1082                         printf("Implemented By classes :\n");fflush(stdout);
1083                         if (subs == NULL) printf("\tNOT IMPLEMENTED !!!\n"); fflush(stdout);
1084                         }
1085         for (subs =  mi->class->impldBy; subs != NULL; subs = subs->nextClass) {
1086                 methodinfo *submeth;
1087                    if (XTA_DEBUGinf) {
1088                        printf("\t");utf_display(subs->classType->name);fflush(stdout);
1089                         printf(" <%i>\n",subs->classType->classUsed);fflush(stdout);
1090                         }
1091
1092                 /*Mark method (mark/used) in classes that implement method*/
1093                 submeth = class_findmethod(subs->classType, mi->name, mi->descriptor); 
1094                 if (submeth != NULL) {
1095                         classSetNode *subtypesUsedSet = NULL;
1096                         submeth->monoPoly = POLY; /*  poly even if nosubs */
1097                         submeth->xta = xtainfoInit(submeth);
1098                         
1099                         submeth->xta->XTAmethodUsed = USED;
1100                         if (m->xta->XTAclassSet != NULL) {
1101                                 subtypesUsedSet =     /* interface classes cone */
1102                                 intersectSubtypesWithSet(subs->classType, m->xta->XTAclassSet->head);
1103                                 }
1104                          else {  /* can any methods be added if 1 set is NULL ??? */
1105                                  subtypesUsedSet = addElement(subtypesUsedSet, m->class);
1106                                 }
1107                          xtaMarkSubs(m, subs->classType, submeth, subtypesUsedSet);
1108                          }
1109                                 
1110                 } /* end for */
1111
1112
1113                                 
1114
1115 /*********************************************************************/
1116
1117 int parseXTA(methodinfo *m)
1118 {
1119         int  p;                     /* java instruction counter */ 
1120         int  nextp;                 /* start of next java instruction */
1121         int  opcode;                /* java opcode */
1122         int  i;                     /* temp for different uses (counters)*/
1123         bool iswide = false;        /* true if last instruction was a wide*/
1124         int rc = 1;
1125
1126 if (m->methodXTAparsed) return 0;
1127 else m->methodXTAparsed = true;
1128
1129 /***XTA_DEBUGopcodes=false;***/
1130 /***printf("\n-----------------------------------\n"); **/
1131 METHINFOt(m,"\n----XTA PARSING:",XTA_DEBUGopcodes); 
1132 if ((XTA_DEBUGr)||(XTA_DEBUGopcodes)) printf("\n");
1133 /***XTA_DEBUGopcodes=false;***/
1134         if (m->xta == NULL) {
1135                 xtainfoInit (m);
1136                 }
1137         else    {
1138                 xtaPassAllCalledByParams (m); 
1139                 }
1140
1141 /* scan all java instructions */
1142         for (p = 0; p < m->jcodelength; p = nextp) {
1143
1144                 opcode = code_get_u1(p,m);            /* fetch op code  */
1145                 SHOWOPCODE(XTA_DEBUGopcodes)
1146
1147                 nextp = p + jcommandsize[opcode];   /* compute next instr start */
1148                 if (nextp > m->jcodelength) {
1149                         log_text("Unexpected end of bytecode");
1150                         assert(0);
1151                 }
1152
1153                 switch (opcode) {
1154
1155                 case JAVA_ILOAD:
1156                 case JAVA_LLOAD:
1157                 case JAVA_FLOAD:
1158                 case JAVA_DLOAD:
1159                 case JAVA_ALOAD:
1160
1161                 case JAVA_ISTORE:
1162                 case JAVA_LSTORE:
1163                 case JAVA_FSTORE:
1164                 case JAVA_DSTORE:
1165                 case JAVA_ASTORE:
1166
1167                         if (iswide) {
1168                                 nextp = p + 3;
1169                                 iswide = false;
1170                         }
1171                         break;
1172
1173                 case JAVA_IINC: 
1174                         {
1175                                 
1176                                 if (iswide) {
1177                                         iswide = false;
1178                                         nextp = p + 5;
1179                                 }
1180                         }
1181                         break;
1182
1183                         /* wider index for loading, storing and incrementing */
1184
1185                 case JAVA_WIDE:
1186                         iswide = true;
1187                         nextp = p + 1;
1188                         break;
1189
1190                 case JAVA_RET:
1191                         if (iswide) {
1192                                 nextp = p + 3;
1193                                 iswide = false;
1194                         }
1195                         break;
1196
1197                 case JAVA_LOOKUPSWITCH:
1198                         {
1199                         s4 num;
1200                         nextp = ALIGN((p + 1), 4) + 4;
1201                         num = code_get_u4(nextp,m);
1202                         nextp += (code_get_u4(nextp,m)) * 8 + 4;
1203                         break;
1204                         }
1205
1206
1207                 case JAVA_TABLESWITCH:
1208                        {
1209                                 s4 num;
1210                                 nextp = ALIGN ((p + 1),4);
1211                                 num = code_get_s4(nextp + 4, m);
1212                                 num = code_get_s4(nextp + 8, m) - num;
1213                                 nextp = nextp + 16 + 4 * num;
1214                                 break;
1215                         }
1216  /*********************/
1217
1218                 case JAVA_PUTSTATIC: /* write */
1219
1220                         i = code_get_u2(p + 1,m);
1221                         {
1222                                 constant_FMIref *fr;
1223                                 fieldinfo *fi;
1224                                 classinfo *frclass;
1225
1226                                 fr = class_getconstant(m->class, i, CONSTANT_Fieldref);
1227                                 if (!fr)
1228                                         return 0;
1229                                 if (!resolve_classref(m,fr->classref,resolveEager,true, true,&frclass)) {
1230                                         log_text("Could not resolve class reference");
1231                                         assert(0);
1232                                 }
1233                                 LAZYLOADING(frclass)
1234
1235                                 fi = class_resolvefield(frclass,
1236                                                         fr->name,
1237                                                         fr->descriptor,
1238                                                         m->class,
1239                                                         true);
1240
1241                                 if (!fi)
1242                                         return 0; /* was NULL */
1243 /***
1244 printf(" PUTSTATIC:");fflush(stdout); utf_display(fi->class->name);printf(".");fflush(stdout);
1245                                       utf_display(fi->name);printf("\n");fflush(stdout);
1246 ***/
1247                                 fi->xta = xtafldinfoInit(fi);
1248                                 XTAaddClassInit(m,      fi->class,
1249                                                 CLINITS_T,FINALIZE_T,ADDMARKED_F);
1250                                 if (xtaAddFldClassTypeInfo(fi)) {
1251                                         m->xta->fldsUsed = add2FldSet(m->xta->fldsUsed, fi, true,false);
1252                                         }
1253                         }
1254                         break;
1255
1256
1257                 case JAVA_GETSTATIC: /* read */
1258
1259                         i = code_get_u2(p + 1,m);
1260                         {
1261                                 constant_FMIref *fr;
1262                                 fieldinfo *fi;
1263                                 classinfo *frclass;
1264
1265                                 fr = class_getconstant(m->class, i, CONSTANT_Fieldref);
1266                                 if (!fr)
1267                                         return 0;
1268                                 if (!resolve_classref(m,fr->classref,resolveEager,true, true,&frclass)) {
1269                                         log_text("Could not resolve class reference");
1270                                         assert(0);
1271                                 }
1272
1273                                 LAZYLOADING(frclass)
1274
1275                                 fi = class_resolvefield(frclass,
1276                                                         fr->name,
1277                                                         fr->descriptor,
1278                                                         m->class,
1279                                                         true);
1280
1281                                 if (!fi)
1282                                         return 0; /* was NULL */
1283
1284 /***
1285 printf(" GETSTATIC:");fflush(stdout); utf_display(fi->class->name);printf(".");fflush(stdout);
1286                                       utf_display(fi->name);printf("\n");fflush(stdout);
1287 ***/
1288                                 fi->xta = xtafldinfoInit(fi);
1289                                 XTAaddClassInit(m,      fi->class,
1290                                                 CLINITS_T,FINALIZE_T,ADDMARKED_F);
1291                                 if (xtaAddFldClassTypeInfo(fi)) {
1292                                         m->xta->fldsUsed = add2FldSet(m->xta->fldsUsed, fi, false, true);
1293                                         }
1294
1295                         }
1296                         break;
1297
1298
1299                                                                 
1300                         case JAVA_INVOKESTATIC:
1301                         case JAVA_INVOKESPECIAL:
1302                                 i = code_get_u2(p + 1,m);
1303                                 {
1304                                 constant_FMIref *mr;
1305                                 methodinfo *mi;
1306                                 classinfo *mrclass;
1307
1308                                 mr = class_getconstant(m->class, i, CONSTANT_Methodref);
1309                                 if (!mr)
1310                                         return 0;
1311                                 if (!resolve_classref(m,mr->classref,resolveEager,true, true,&mrclass)) {
1312                                         log_text("Could not resolve class reference");
1313                                         assert(0);
1314                                 }
1315
1316                                 LAZYLOADING(mrclass) 
1317                                 mi = class_resolveclassmethod(  mrclass,
1318                                                                                                 mr->name,
1319                                                                                                 mr->descriptor,
1320                                                                                                 m->class,
1321                                                                                                 false);
1322
1323                                 if (mi) 
1324                                    {
1325                                    METHINFOt(mi,"INVOKESTAT/SPEC:: ",XTA_DEBUGopcodes)
1326                                    mi->monoPoly = MONO;
1327                                    
1328                                    /*---- Handle "leaf" = static, private, final calls-------------*/
1329                                    if ((opcode == JAVA_INVOKESTATIC)       
1330                                      || (mi->flags & ACC_STATIC)  
1331                                      || (mi->flags & ACC_PRIVATE)  
1332                                      || (mi->flags & ACC_FINAL) )  
1333                                         {
1334                                         if (mi->class->classUsed != USED) { /* = NOTUSED or PARTUSED */ 
1335                                                 XTAaddClassInit(m, mi->class, 
1336                                                                 CLINITS_T,FINALIZE_T,ADDMARKED_T); 
1337                                                                 /* Leaf methods are used whether class is or not */
1338                                                                 /*   so mark class as PARTlyUSED                 */
1339                                                 mi->class->classUsed = PARTUSED; 
1340                                                 } 
1341                                         /* Add to XTA working list/set of reachable methods     */
1342                                         if (opcode == JAVA_INVOKESTATIC)  /* if stmt just for debug tracing */     
1343                                                              /* calls , called */
1344                                                 xtaAddCallEdges(m, mi, MONO, 
1345                                                         "07addTo INVOKESTATIC "); 
1346                                         else 
1347                                                 xtaAddCallEdges(m, mi, MONO, 
1348                                                         "08addTo INVOKESPECIAL ");      
1349                                         } /* end STATIC, PRIVATE, FINAL */ 
1350                                         
1351                                    else {
1352                                         /*---- Handle special <init> calls ---------------------------------------------*/
1353                                    
1354                                         if (mi->class->classUsed != USED) {
1355                                         /* XTA special case:
1356                                                 call of super's <init> then
1357                                                 methods of super class not all used */
1358                                                         
1359                                                 /*--- <init>  ()V  is equivalent to "new" 
1360                                                         indicating a class is used = instaniated ---- */        
1361                                                 if (utf_init==mi->name) {
1362                                                         if ((m->class->super.cls == mi->class) 
1363                                                         &&  (m->descriptor == utf_void__void) ) 
1364                                                                 {
1365                                                                 METHINFOt(mi,"SUPER INIT:",XTA_DEBUGopcodes);
1366                                                                 /* super init so class may be only used because of its sub-class */
1367                                                                 XTAaddClassInit(m,mi->class,
1368                                                                         CLINITS_T,FINALIZE_T,ADDMARKED_F);
1369                                                                 if (mi->class->classUsed == NOTUSED) mi->class->classUsed = PARTUSED;
1370                                                                 }
1371                                                         else {
1372                                                                 /* since <init> indicates classes is used, then add marked methods, too */
1373                                                                         METHINFOt(mi,"NORMAL INIT:",XTA_DEBUGopcodes);
1374                                                                 XTAaddClassInit(m, mi->class,
1375                                                                                 CLINITS_T,FINALIZE_T,ADDMARKED_T);
1376                                                                 }
1377                                                         xtaAddCallEdges(m, mi, MONO, 
1378                                                                         "09addTo INIT ");
1379                                                         } /* end just for <init> ()V */
1380                                                         
1381                                                 /* <clinit> for class inits do not add marked methods; 
1382                                                                 class not yet instaniated */ 
1383                                                 if (utf_clinit==mi->name)
1384                                                         XTAaddClassInit(m,      mi->class,
1385                                                                         CLINITS_T,FINALIZE_T,ADDMARKED_F);
1386
1387                                                 if (!((utf_init==mi->name))
1388                                                 ||   (utf_clinit==mi->name)) {
1389                                                         METHINFOt(mi,"SPECIAL not init:",XTA_DEBUGopcodes)
1390                                                         if (mi->class->classUsed !=USED)
1391                                                                 mi->class->classUsed = PARTUSED;
1392                                                         xtaAddCallEdges(m, mi, MONO, 
1393                                                                 "10addTo SPEC notINIT ");
1394                                                         } 
1395                                                                 
1396                                                 } /* end init'd class not used = class init process was needed */ 
1397                                                         
1398                                         /* add method to XTA list = set of reachable methods */ 
1399                                         xtaAddCallEdges(m, mi, MONO, 
1400                                                 "11addTo SPEC whymissed ");
1401                                         } /* end inits */
1402                                 } 
1403 /***  assume if method can't be resolved won't actually be called or
1404       there is a real error in classpath and in normal parse an exception
1405       will be thrown. Following debug print can verify this
1406 else  from if (mi) {
1407 CLASSNAME1(mrclass,"CouldNOT Resolve method:",,XTA_DEBUGr);printf(".");fflush(stdout);
1408 utf_display(mr->name); printf(" "); fflush(stdout);
1409 utf_display(mr->descriptor); printf("\n");fflush(stdout);
1410 ***/
1411                         }
1412                         break;
1413
1414                 case JAVA_INVOKEVIRTUAL:
1415                         i = code_get_u2(p + 1,m);
1416                         {
1417                                 constant_FMIref *mr;
1418                                 methodinfo *mi;
1419                                                                 classinfo *mrclass;
1420
1421                                                                 /* XXX remove direct access */
1422                                 mr = m->class->cpinfos[i];
1423                                 /*mr = class_getconstant(m->class, i, CONSTANT_Methodref)*/
1424                                         if (!resolve_classref(m,mr->classref,resolveEager,true, true,&mrclass)) {
1425                                                 log_text("Could not resolve class reference");
1426                                                 assert(0);
1427                                         }
1428
1429                                 LAZYLOADING(mrclass) 
1430                                 mi = class_resolveclassmethod(mrclass,
1431                                                 mr->name,
1432                                                 mr->descriptor,
1433                                                 m->class,
1434                                                 false);
1435
1436
1437                                 if (mi) 
1438                                    {
1439                                    METHINFOt(mi,"INVOKEVIRTUAL ::",XTA_DEBUGopcodes);
1440                                    if ((mi->flags & ACC_STATIC) 
1441                                    ||  (mi->flags & ACC_PRIVATE)  
1442                                    ||  (mi->flags & ACC_FINAL) )  
1443                                      { /*** DOES THIS EVER OCCUR ??? */
1444                                      if (mi->class->classUsed == NOTUSED){
1445                                        XTAaddClassInit(m, mi->class,
1446                                                     CLINITS_T,FINALIZE_T,ADDMARKED_T);
1447                                        }
1448                                       mi->monoPoly = MONO;
1449                                       xtaAddCallEdges(m, mi, MONO, 
1450                                                     "12addTo INVOKEVIRTUAL ");
1451                                       } 
1452                                    else { /* normal virtual */
1453                                           /* get the set of used subtypes if none at least the current methods class */
1454                                         classSetNode *subtypesUsedSet = NULL;
1455                                         if (m->xta->XTAclassSet != NULL) {
1456                                                 subtypesUsedSet =
1457                                                 intersectSubtypesWithSet(mi->class, m->xta->XTAclassSet->head);
1458                                                 }
1459                                         else { /* can any methods be added if 1 set is NULL ??? */
1460                                                 subtypesUsedSet = addElement(subtypesUsedSet, m->class);
1461                                                 }
1462                                        mi->monoPoly = POLY;
1463                                        xtaMarkSubs(m, mi->class, mi, subtypesUsedSet);
1464                                        }
1465                                    } 
1466                                 else {
1467 CLASSNAME1(mrclass,"CouldNOT Resolve virt meth:",XTA_DEBUGr);printf(".");fflush(stdout);
1468 utf_display(mr->name); printf(" "); fflush(stdout);
1469 utf_display(mr->descriptor); printf("\n");fflush(stdout);
1470                                    }
1471                                 }
1472                                 break;
1473
1474                 case JAVA_INVOKEINTERFACE:
1475                         i = code_get_u2(p + 1,m);
1476                         {
1477                                 constant_FMIref *mr;
1478                                 methodinfo *mi;
1479                                                                 classinfo *mrclass;
1480
1481                                 mr = class_getconstant(m->class, i, CONSTANT_InterfaceMethodref);
1482                                                                 if (!mr)
1483                                                                         return 0;
1484                                                                 if (!resolve_classref(m,mr->classref,resolveEager,true, true,&mrclass)) {
1485                                                                         log_text("Could not resolve class reference");
1486                                                                         assert(0);
1487                                                                 }
1488
1489                                 LAZYLOADING(mrclass)
1490
1491                                 mi = class_resolveinterfacemethod(mrclass,
1492                                                           mr->name,
1493                                                           mr->descriptor,
1494                                                           m->class,
1495                                                           false);
1496                                         if (mi)
1497                                            {
1498                                            METHINFOt(mi,"\tINVOKEINTERFACE: ",XTA_DEBUGopcodes)
1499                                            xtaMarkInterfaceSubs(m,mi);
1500                                            }
1501                                 /* see INVOKESTATIC for explanation about */
1502                                 /*   case when Interface is not resolved  */
1503                                 /*method_descriptor2types(mi); 
1504                                 ?? do need paramcnt? for XTA (or just XTA)*/
1505                         }
1506                         break;
1507
1508                 case JAVA_NEW:
1509                 /* means class is at least passed as a parameter */
1510                 /* class is really instantiated when class.<init> called*/
1511                         i = code_get_u2(p + 1,m);
1512                         {
1513                         classinfo *cls;
1514                         constant_classref *cr;
1515                         cr = (constant_classref *)class_getconstant(m->class, i, CONSTANT_Class);
1516                         if (!cr)
1517                                 return 0;
1518                         resolve_classref(NULL,cr,resolveEager,true, false,&cls);
1519                         /*** s_count++; look for s_counts for VTA */
1520                         /* add marked methods */
1521                         CLASSNAME(cls,"NEW : do nothing",XTA_DEBUGr);
1522                         XTAaddClassInit(m, cls, CLINITS_T, FINALIZE_T,ADDMARKED_T); 
1523                         m->xta->XTAclassSet = add2ClassSet(m->xta->XTAclassSet,cls );
1524                         }
1525                         break;
1526
1527                 case JAVA_CHECKCAST:
1528                 case JAVA_INSTANCEOF:
1529                 /* class used */
1530                         i = code_get_u2(p + 1,m);
1531                         {
1532                                                         constant_classref *cr;
1533                                                         classinfo *cls;
1534                                                         cr = (constant_classref*) class_getconstant(m->class, i, CONSTANT_Class);
1535                                                         if (!cr)
1536                                                                 return 0;
1537                                                         resolve_classref(NULL,cr,resolveEager,true, false,&cls);
1538                         LAZYLOADING(cls)
1539                         CLASSNAMEop(cls,XTA_DEBUGr);
1540                         if (cls->classUsed == NOTUSED){
1541                                 XTAaddClassInit(m, cls,
1542                                             CLINITS_T,FINALIZE_T,ADDMARKED_T);
1543                                 m->xta->XTAclassSet = add2ClassSet(m->xta->XTAclassSet,cls );
1544                                 }
1545                         }
1546                         break;
1547
1548                 default:
1549                         break;
1550                                 
1551                 } /* end switch */
1552
1553                 } /* end for */
1554         xtaMethodCalls_and_sendReturnType(m);
1555
1556         return rc;
1557 }
1558
1559 /* Helper fn for initialize **********************************************/
1560
1561 int XTAgetline(char *line, int max, FILE *inFP) {
1562 if (fgets(line, max, inFP) == NULL) 
1563   return 0;
1564 else
1565   return strlen((const char *) line);
1566 }
1567
1568 /* Initialize XTA Work list ***********************************************/
1569
1570 /*-- Get meth ptr for class.meth desc and add to XTA worklist --*/
1571 #define SYSADD(cls,meth,desc, is_mono_poly, txt) \
1572   c = load_class_bootstrap(utf_new_char(cls)); \
1573   LAZYLOADING(c) \
1574   callmeth = class_resolveclassmethod(c, \
1575     utf_new_char(meth), \
1576     utf_new_char(desc), \
1577     c, \
1578     false); \
1579   if (callmeth->class->classUsed != USED) {  \
1580       c->classUsed = PARTUSED; \
1581       XTAaddClassInit(callmeth, callmeth->class, \
1582                    CLINITS_T,FINALIZE_T,ADDMARKED_T);\
1583       } \
1584   callmeth->monoPoly = is_mono_poly; \
1585   xtaAddCallEdges(NULL, callmeth, is_mono_poly, txt); 
1586
1587 /*-- ---------------------------------------------------------------------------- 
1588     Initialize XTA work list with methods/classes from:  
1589       System calls 
1590         and 
1591       xtaMissedIn list (missed becaused called from NATIVE &/or dynamic calls
1592 -------------------------------------------------------------------------------*/
1593 methodinfo *initializeXTAworklist(methodinfo *m) {
1594         classinfo  *c;
1595         methodinfo* callmeth;
1596         char systxt[]    = "2S addTo System     Call :";
1597         char missedtxt[] = "2M addTo xtaMissedIn Call :";
1598
1599         FILE *xtaMissedIn; /* Methods missed during previous XTA parse */
1600         char line[256];
1601         char* class, *meth, *desc;
1602         methodinfo *rm =NULL;  /* return methodinfo ptr to main method */
1603
1604
1605         /* Create XTA call work list */
1606         xtaWorkList = NEW(list);
1607         list_init(xtaWorkList, OFFSET(xtaNode,linkage) );
1608
1609         /* Add first method to call list */
1610         m->class->classUsed = USED; 
1611         xtaAddCallEdges(NULL, m, SYSCALL, systxt); 
1612
1613         /* Add system called methods */
1614 /***    SYSADD(mainstring, "main","([Ljava/lang/String;)V", SYSCALL, systxt) ***/
1615         SYSADD(MAINCLASS, MAINMETH, MAINDESC, SYSCALL, systxt)
1616         rm = callmeth;  
1617 /***    SYSADD("java/lang/System","exit","(I)V",SYSCALL, systxt) ***/
1618         SYSADD(EXITCLASS, EXITMETH, EXITDESC, SYSCALL, systxt)
1619         /*----- xtaMissedIn 0 */
1620         if ( (xtaMissedIn = fopen("xtaMissedIn0", "r")) == NULL) {
1621                 /*if (opt_verbose) */
1622                     {printf("No xtaMissedIn0 file\n");fflush(stdout);} 
1623                 return  rm;
1624                 }
1625         while (XTAgetline(line,256,xtaMissedIn)) {
1626             class = strtok(line, " \n");
1627             meth  = strtok(NULL, " \n");
1628             desc  = strtok(NULL, " \n");
1629                 SYSADD(class,meth,desc, POLY, missedtxt)
1630                 /* ??? Need to hand / hard code who calls it ??? */
1631                 }
1632         fclose(xtaMissedIn);
1633
1634
1635
1636
1637         return rm;
1638
1639 }
1640
1641 /*- end initializeXTAworklist-------- */
1642
1643
1644 /*-------------------------------------------------------------------------------*/
1645 methodinfo *missedXTAworklist()  
1646 {
1647         FILE *xtaMissedIn; /* Methods missed during previous XTA parse */
1648         char filenameIn[256] = "xtaIn/";
1649         char line[256];
1650         char* class, *meth, *desc;
1651         /****
1652         char* calls_class, *calls_meth, *calls_desc;
1653         ****/
1654         char missedtxt[] = "xtaIn/ missed Call :";
1655         classinfo  *c;
1656         methodinfo* callmeth;
1657
1658         methodinfo *rm =NULL;  /* return methodinfo ptr to main method */
1659
1660
1661 #if defined(USE_THREADS)
1662         SYSADD(THREADCLASS, THREADMETH, THREADDESC, SYSCALL, "systxt2")
1663         SYSADD(THREADGROUPCLASS, THREADGROUPMETH, THREADGROUPDESC, SYSCALL, "systxt2")
1664 #endif
1665         /*----- xtaMissedIn pgm specific */
1666         strcat(filenameIn, (const char *)mainstring);  
1667         if ( (xtaMissedIn = fopen(filenameIn, "r")) == NULL) {
1668                 /*if (opt_verbose)*/ 
1669                     {printf("No xtaIn/=%s file\n",filenameIn);fflush(stdout);} 
1670                 return rm;
1671                 }
1672         while (XTAgetline(line,256,xtaMissedIn)) {
1673         /****
1674             calls_class = strtok(line, " \n");
1675             calls_meth  = strtok(NULL, " \n");
1676             calls_desc  = strtok(NULL, " \n");
1677             
1678             class = strtok(NULL, " \n");
1679         ****/
1680             class = strtok(line, " \n");
1681             meth  = strtok(NULL, " \n");
1682             desc  = strtok(NULL, " \n");
1683             
1684         /****
1685             if ((calls_class == NULL) || (calls_meth == NULL) || (calls_desc == NULL) 
1686             ||        (class == NULL) ||       (meth == NULL) ||       (desc == NULL))  
1687         ****/
1688             if (        (class == NULL) ||       (meth == NULL) ||       (desc == NULL)) {
1689                         log_text("Error in xtaMissedIn file: Missing a part of calls_class.calls_meth calls calls_desc class.meth desc");
1690                         assert(0);
1691                 }
1692             SYSADD(class,meth,desc, POLY, missedtxt)
1693             }
1694         fclose(xtaMissedIn);
1695
1696         return rm;
1697 }
1698
1699
1700
1701 /*--------------------------------------------------------*/
1702 /* parseXTAmethod                                          */
1703 /* input: method to be XTA static parsed                  */
1704 /*--------------------------------------------------------*/
1705 void parseXTAmethod(methodinfo *xta_method) {
1706         if (! (  (xta_method->flags & ACC_NATIVE  )
1707             ||   (xta_method->flags & ACC_ABSTRACT) ) ) 
1708             {
1709             /* XTA parse to approxmate....
1710                 what classes/methods will really be used during execution */
1711             parseXTA(xta_method);  
1712             }
1713         else {
1714             if (xta_method->flags & ACC_NATIVE  )
1715                 {
1716                METHINFOt(xta_method,"TO BE NATIVE XTA PARSED :",XTA_DEBUGopcodes);
1717                 /* parseXTApseudo(xta_method); */
1718                 }   
1719             else {
1720                printf("Abstract method in XTA Work List: ");
1721                METHINFOx(xta_method);
1722                log_text("Abstract method in XTA Work List.");
1723                    assert(0);
1724                 }
1725         }               
1726 }
1727
1728 void XTAprintCallgraph (list *xtaWorkList, char * txt);
1729
1730 /*-- XTA -- *******************************************************/
1731 int XTA_jit_parse(methodinfo *m)
1732 {
1733   xtaNode    *xta;
1734   methodinfo *mainmeth;
1735
1736   /* Should only be called once */
1737   if (firstCall) {
1738
1739     /*----- XTA initializations --------*/
1740     if (opt_verbose) 
1741             log_text("XTA static analysis started.\n");
1742
1743     mainmeth = initializeXTAworklist(m);
1744 /**     XTAprintCallgraph (xtaWorkList, "after init1"); **/
1745     firstCall = false; /* turn flag off */
1746
1747     if ( (xtaMissed = fopen("xtaMissed", "w")) == NULL) {
1748         printf("CACAO - xtaMissed file: cant open file to write\n");
1749         }
1750     /* Note: xtaMissed must be renamed to xtaMissedIn to be used as input */
1751         
1752     /*------ process XTA call work list --------*/
1753     for (xta =list_first(xtaWorkList); 
1754          xta != NULL; 
1755          xta =list_next(xtaWorkList,xta)) 
1756         { 
1757         parseXTAmethod(xta->method);
1758 /**     XTAprintCallgraph (xtaWorkList, "after an XTA method parse 1"); **/
1759         }       
1760     missedXTAworklist();  
1761 /**     XTAprintCallgraph (xtaWorkList, "after missed"); **/
1762     for (xta =list_first(xtaWorkList); 
1763          xta != NULL; 
1764          xta =list_next(xtaWorkList,xta)) 
1765         { 
1766         parseXTAmethod(xta->method);
1767 /**     XTAprintCallgraph (xtaWorkList, "after an XTA method parse 2"); **/
1768         }       
1769
1770     fclose(xtaMissed);
1771     if (opt_verbose) {
1772         if (opt_stat) {
1773           printf("printXTAhierarchyInfo(m); not yet there\n");
1774           }
1775         XTAprintCallgraph (xtaWorkList, "After all XTA parses");
1776       }
1777
1778     if (opt_verbose) {
1779       log_text("XTA static analysis done.\n");
1780       }
1781   }
1782 return 0;
1783 }
1784
1785 /*--------------------------------------------------------------*/
1786 void XTAprintCallgraph (list *xtaWorkList, char * txt)
1787 {
1788     int i = 1;
1789     xtaNode    *xta;
1790     methodinfo *xta_meth;
1791
1792  printf("\n%s\n",txt);
1793 #if defined(ENABLE_STATISTICS)
1794  printf("-*-*-*-*- XTA Callgraph Worklist:<%i>\n",count_methods_marked_used);
1795 #endif
1796
1797    for (xta =list_first(xtaWorkList);
1798          xta != NULL;
1799          xta =list_next(xtaWorkList,xta))
1800         {
1801          xta_meth = xta->method;
1802
1803          printf("  (%i): ",i++);
1804          method_println(xta_meth);
1805         }
1806
1807  printf("\n\n");
1808
1809 }
1810
1811
1812 /*
1813  * These are local overrides for various environment variables in Emacs.
1814  * Please do not remove this and leave it at the end of the file, where
1815  * Emacs will automagically detect them.
1816  * ---------------------------------------------------------------------
1817  * Local variables:
1818  * mode: c
1819  * indent-tabs-mode: t
1820  * c-basic-offset: 4
1821  * tab-width: 4
1822  * End:
1823  */
1824