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