* Updated header: Added 2006. Changed address of FSF. Changed email
[cacao.git] / src / vm / jit / inline / parseRT.c
1 /* src/vm/jit/inline/parseRT.c - parser and print functions for Rapid Type
2                                  Analyis
3
4    Copyright (C) 1996-2005, 2006 R. Grafl, A. Krall, C. Kruegel,
5    C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
6    E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
7    J. Wenninger, Institut f. Computersprachen - TU Wien
8
9    This file is part of CACAO.
10
11    This program is free software; you can redistribute it and/or
12    modify it under the terms of the GNU General Public License as
13    published by the Free Software Foundation; either version 2, or (at
14    your option) any later version.
15
16    This program is distributed in the hope that it will be useful, but
17    WITHOUT ANY WARRANTY; without even the implied warranty of
18    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
19    General Public License for more details.
20
21    You should have received a copy of the GNU General Public License
22    along with this program; if not, write to the Free Software
23    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
24    02110-1301, USA.
25
26    Contact: cacao@cacaojvm.org
27
28    Authors: Carolyn Oates
29
30    Changes: Christian Thalinger
31
32    $Id: parseRT.c 4357 2006-01-22 23:33:38Z twisti $
33
34 */
35
36 /***************
37  Rapid Type Static Analysis of Java program
38    used -rt option is turned on either explicitly 
39  or automatically with inlining of virtuals.
40
41  USAGE:
42  Methods called by NATIVE methods and classes loaded dynamically
43  cannot be found by parsing. The following files supply missing methods:
44
45  rtMissedIn0 - (provided) has the methods missed by every java program
46  rtMissed||mainClassName - is program specific.
47
48  A file rtMissed will be written by RT analysis of any methods missed.
49
50  This file can be renamed to rtMissed concatenated with the main class name.
51
52  Example:
53  ./cacao -rt hello
54
55  inlining with virtuals should fail if the returned rtMissed is not empty.
56  so...
57  mv rtMissed rtMissedhello
58  ./cacao hello
59
60 Results: (currently) with -stat see # methods marked used
61  
62 ****************/
63
64
65 #include <assert.h>
66 #include <stdio.h>
67 #include <string.h>
68
69 #include "config.h"
70 #include "cacao/cacao.h"
71 #include "mm/memory.h"   
72 #include "toolbox/list.h"
73 #include "toolbox/logging.h"
74 #include "vm/class.h"
75 #include "vm/linker.h"
76 #include "vm/loader.h"
77 #include "vm/resolve.h"
78 #include "vm/options.h"
79 #include "vm/statistics.h"
80 #include "vm/jit/jit.h"
81 #include "vm/jit/parse.h"
82 #include "vm/jit/inline/parseRT.h"
83 #include "vm/jit/inline/parseRTstats.h"
84 #include "vm/jit/inline/parseRTprint.h"
85
86
87
88 static bool firstCall= true;
89 static list *rtaWorkList;
90 FILE *rtMissed;   /* Methods missed during RTA parse of Main  */
91
92 bool RTA_DEBUGinf = false;
93 bool RTA_DEBUGr = false;
94 bool RTA_DEBUGopcodes = false;
95  
96
97
98 /*********************************************************************/
99
100 void addToRtaWorkList(methodinfo *meth, char *info) {
101     rtaNode    *rta;
102
103 if (meth->methodUsed == USED) return;
104
105 if (!(meth->flags & ACC_ABSTRACT))  {
106 #if defined(ENABLE_STATISTICS)
107     count_methods_marked_used++;
108 #endif
109     METHINFOt(meth,info,RTA_DEBUGopcodes)
110         if (meth->class->super.cls != NULL) {
111                 CLASSNAME(meth->class->super.cls,"\tsuper=",RTA_DEBUGr)
112                 }
113         else {
114                 if (RTA_DEBUGr) printf("\tsuper=NULL\n");}
115         fflush(stdout);
116     meth ->methodUsed = USED;
117     rta = NEW(rtaNode);
118     rta->method = meth ;
119     list_addlast(rtaWorkList,rta);
120 if (meth->class->classUsed == NOTUSED) {
121         METHINFOx(meth)
122         printf("\nADDED method in class not used at all!\n");
123         fflush(stdout);
124         }
125     }
126 /***
127 else {
128      printf("Method not added to work list!!!<%i> : ",
129      meth->methodUsed); fflush(stdout);
130      METHINFO(meth,true)
131      }
132 ***/
133 }
134
135 /**************************************************************************/
136 void rtaMarkSubs(classinfo *class, methodinfo *topmethod); 
137
138 /*------------------------------------------------------------------------*/
139 void rtaAddUsedInterfaceMethods(classinfo *ci) {
140         int jj,mm;
141
142         /* add used interfaces methods to callgraph */
143         for (jj=0; jj < ci -> interfacescount; jj++) {
144                 classinfo *ici = ci -> interfaces [jj].cls;
145         
146                 if (RTA_DEBUGinf) { 
147                         printf("BInterface used: ");fflush(stdout); 
148                         utf_display(ici->name);
149                         printf("<%i>\t",ici -> classUsed ); fflush(stdout); 
150                         if (ici -> classUsed == NOTUSED) printf("\t classUsed=NOTUSED\n" );
151                         if (ici -> classUsed == USED) printf("\t classUsed=USED\n");
152                         if (ici -> classUsed == PARTUSED) printf("\t classUsed=PARTUSED\n");
153                         fflush(stdout);
154                 }
155                 /* add class to interfaces list of classes that implement it */
156                 ici -> impldBy =  addElement(ici -> impldBy,  ci);
157
158                 /* if interface class is used */
159         if (ici -> classUsed != NOTUSED) {
160
161                         /* for each interface method implementation that has already been used */
162                         for (mm=0; mm< ici->methodscount; mm++) {
163                                 methodinfo *imi = &(ici->methods[mm]);
164                                 if (RTA_DEBUGinf) { 
165                                         if  (imi->methodUsed != USED) {
166                                                 if (imi->methodUsed == NOTUSED) printf("Interface Method notused: "); 
167                                                 if (imi->methodUsed == MARKED) printf("Interface Method marked: "); 
168                                                 utf_display(ici->name);printf(".");method_println(imi);fflush(stdout);
169                                         }
170                                 } 
171                                 if  (imi->methodUsed == USED) {
172                                         if (RTA_DEBUGinf) { 
173                                                 printf("Interface Method used: "); utf_display(ici->name);printf(".");method_println(imi);fflush(stdout);
174
175                                                 /* Mark this method used in the (used) implementing class and its subclasses */
176                                                 printf("rMAY ADD methods that was used by an interface\n");
177                                         }
178                                         if ((utf_clinit != imi->name) &&
179                                             (utf_init != imi->name))
180                                             rtaMarkSubs(ci,imi);
181                                 }
182                         }
183                 }
184         }
185
186 }
187
188
189 /**************************************************************************/
190 /* Add Marked methods for input class ci                                  */
191 /* Add methods with the same name and descriptor as implemented interfaces*/
192 /*   with the same method name                                            */
193 /*                                                                        */
194 /*------------------------------------------------------------------------*/
195 void rtaAddMarkedMethods(classinfo *ci) {
196 int ii,jj,mm;
197
198 /* add marked methods to callgraph */ 
199 for (ii=0; ii<ci->methodscount; ii++) { 
200         methodinfo *mi = &(ci->methods[ii]);
201
202         if (mi->methodUsed == MARKED) { 
203                 addToRtaWorkList(mi,
204                                 "addTo was MARKED:");
205                 }
206         else    { /*** ??? Should this be an else or ??? */
207                 for (jj=0; jj < ci -> interfacescount; jj++) {
208                         classinfo *ici = ci -> interfaces [jj].cls;
209                         /*  use resolve method....!!!! */
210                         if (ici -> classUsed != NOTUSED) {
211                                 for (mm=0; mm< ici->methodscount; mm++) {
212                                         methodinfo *imi = &(ici->methods[mm]);
213                                         METHINFOt(imi,"NEW IMPD INTERFACE:",RTA_DEBUGinf)
214                                       /*if interface method=method is used*/
215                                         if  (      (imi->methodUsed == USED)
216                            &&    ( (imi->name == mi->name) 
217                            &&      (imi->descriptor == mi->descriptor))) {
218                                           addToRtaWorkList(mi,
219                                      "addTo was interfaced used/MARKED:");
220                                           }
221                                         } /*end for */  
222                                 }
223                         }
224                 }
225         }
226 }    
227
228 #define CLINITS_T   true
229 #define FINALIZE_T  true
230 #define ADDMARKED_T true
231
232 #define CLINITS_F   false 
233 #define FINALIZE_F  false 
234 #define ADDMARKED_F false
235 /*********************************************************************/
236 void RTAaddClassInit(classinfo *ci, bool clinits, bool finalizes, bool addmark)
237 {
238   methodinfo *mi;
239
240   if (addmark)
241         ci->classUsed = USED;
242         
243   if (clinits) { /* No <clinit>  available - ignore */
244     mi = class_findmethod(ci, 
245                         utf_clinit, 
246                         utf_void__void);
247     if (mi) { 
248         if (ci->classUsed != USED)
249             ci->classUsed = PARTUSED;
250         mi->monoPoly = MONO;
251         addToRtaWorkList(mi,"addTo CLINIT added:");
252       }     
253     }        
254
255   /*Special Case for System class init:
256     add java/lang/initializeSystemClass to callgraph */
257   if (ci->name == utf_new_char("initializeSystemClass")) {
258     /* ?? what is name of method ?? */ 
259     } 
260
261   if (finalizes) {
262     mi = class_findmethod(ci, 
263                         utf_new_char("finalize"), 
264                         utf_void__void);
265     if (mi) { 
266         if (ci->classUsed != USED)
267             ci->classUsed = PARTUSED;
268         mi->monoPoly = MONO;
269         addToRtaWorkList(mi,"addTo FINALIZE added:");
270       }     
271     }        
272
273   if (addmark) {
274     rtaAddMarkedMethods(ci);
275     }
276   rtaAddUsedInterfaceMethods(ci);
277
278 }
279
280
281 /*--------------------------------------------------------------*/
282 /* Mark the method with same name /descriptor in topmethod      */
283 /* in class                                                     */
284 /*                                                              */
285 /* Class marked USED and method defined in this class ->        */
286 /*    -> mark method as USED                                    */
287 /* Class not marked USED and method defined in this class ->    */
288 /*    -> if Method NOTUSED mark method as MARKED                */
289 /*                                                              */
290 /* Class USED, but method not defined in this class ->          */
291 /* -> 1) search up the heirarchy and mark method where defined  */
292 /*    2) if class where method is defined is not USED ->        */
293 /*       -> mark class with defined method as PARTUSED          */
294 /*--------------------------------------------------------------*/
295
296 void rtaMarkMethod(classinfo *class, methodinfo *topmethod) {
297
298 utf *name       = topmethod->name; 
299 utf *descriptor = topmethod->descriptor;
300 methodinfo *submeth;
301
302 /* See if method defined in class heirarchy */
303 submeth = class_resolvemethod(class, name, descriptor); 
304 METHINFOt(submeth,"rtaMarkMethod submeth:",RTA_DEBUGr);
305 if (submeth == NULL) {
306         utf_display(class->name); printf(".");
307         METHINFOx(topmethod);
308         printf("parse RT: Method not found in class hierarchy");fflush(stdout);
309         assert(0);
310         }
311 if (submeth->methodUsed == USED) return;
312   
313 #undef CTA 
314 #ifdef CTA
315   /* Class Type Analysis if class.method in virt cone marks it used */
316   /*   very inexact, too many extra methods */
317   RTAaddClassInit(      submeth->class,
318                 CLINITS_T,FINALIZE_T,ADDMARKED_T);
319   submeth->monoPoly = POLY;
320   addToRtaWorkList(submeth,
321                    "addTo RTA VIRT CONE:");
322   return;
323 #endif
324
325   if (submeth->class == class) { 
326
327         /*--- Method defined in class -----------------------------*/
328         if (  submeth->class->classUsed == USED) { 
329                 /* method defined in this class -> */
330                 /* Class IS  marked USED           */ 
331                 /*    -> mark method as USED       */
332                 submeth->monoPoly = POLY;
333                 addToRtaWorkList(submeth,
334                         "addTo VIRT CONE 1:");
335                 }
336         else    {
337                 /* method defined in this class -> */
338                 /* Class IS NOT  marked USED (PART or NOTUSED) */ 
339                 /* -> if Method NOTUSED mark method as  MARKED */
340                 METHINFOt(submeth,
341                         "\tmarked VIRT CONE 2:",RTA_DEBUGr);
342                 submeth->monoPoly = POLY;
343                 submeth->methodUsed = MARKED;
344                 /* Note: if class NOTUSED and subclass is used handled  */
345                 /*       by subsequent calls to rtaMarkMethods for cone */
346                 }
347         } /* end defined in class */
348
349   else {
350         /*--- Method NOT defined in class ---------------*/
351         /* then check class the method could be called with */
352
353         /* first mark classes if needed */
354         if (submeth->class->classUsed == NOTUSED) {
355                 submeth->class->classUsed = PARTUSED;
356                 if (class->classUsed != USED) {
357                         submeth->monoPoly = POLY;
358                         submeth->methodUsed = MARKED;
359                         METHINFOt(submeth,"JUST MARKED :",RTA_DEBUGr);
360                         }
361                 }
362         /* add method to rta work list if conditions met */
363                 /*??if ( (submeth->class->classUsed == USED) ||  */
364         if (class->classUsed == USED) {
365                 submeth->monoPoly = POLY;
366                 addToRtaWorkList(submeth,
367                                 "addTo VIRT CONE 3:");
368                 }
369         } /* end NOT defined in class */
370
371
372
373 /*----------------------------------------------------------------------*/
374 /* Mark the method with the same name and descriptor as topmethod       */
375 /*   and any subclass where the method is defined and/or class is used  */
376 /*                                                                      */
377 /*----------------------------------------------------------------------*/
378 void rtaMarkSubs(classinfo *class, methodinfo *topmethod) {
379
380   /* Mark method in class  */
381   CLASSNAME1(class," MARKSUBS ",RTA_DEBUGr);
382   METHINFOt(topmethod," TOP ",RTA_DEBUGr);
383   rtaMarkMethod(class, topmethod);  
384
385   /* Mark method in subclasses */
386   if (class->sub != NULL) {
387      classinfo *subs;
388         
389      if (!(topmethod->flags & ACC_FINAL )) {
390         for (subs = class->sub;subs != NULL;subs = subs->nextsub) {
391           CLASSNAME1(subs," SUBS ",RTA_DEBUGr);
392           rtaMarkSubs(subs, topmethod); 
393           }
394         }
395      }
396   return;
397 }
398
399
400 /*********************************************************************/
401
402 void rtaMarkInterfaceSubs(methodinfo *mi) {                             
403         classSetNode *subs;
404         if (mi->class->classUsed == NOTUSED) {
405                 mi->class->classUsed = USED; 
406                 class_java_lang_Object->impldBy =  addElement(class_java_lang_Object -> impldBy,  mi->class);
407                 }
408
409         /* add interface class to list kept in Object */
410         mi->methodUsed = USED;
411         mi->monoPoly   = POLY;
412
413         subs =  mi->class->impldBy; 
414             /*RTAPRINT08invokeInterface1*/
415                    if (RTA_DEBUGinf) {
416                         METHINFO(mi,RTA_DEBUGinf)
417                         printf("Implemented By classes :\n");fflush(stdout);
418                         if (subs == NULL) printf("\tNOT IMPLEMENTED !!!\n");
419                         fflush(stdout);
420                         }
421         while (subs != NULL) {                  
422                 classinfo * isubs = subs->classType;
423                 methodinfo *submeth;
424                    if (RTA_DEBUGinf) {
425                        printf("\t");utf_display(isubs->name);fflush(stdout);
426                         printf(" <%i>\n",isubs->classUsed);fflush(stdout);
427                         }
428                 /*Mark method (mark/used) in classes that implement method*/
429                                                 
430                 submeth = class_findmethod(isubs,mi->name, mi->descriptor); 
431                 if (submeth != NULL)
432                         submeth->monoPoly = POLY; /*  poly even if nosubs */
433                 rtaMarkSubs(isubs, mi);  
434                                 
435                 subs = subs->nextClass;
436                 } /* end while */
437
438
439 /*********************************************************************/
440
441 int parseRT(methodinfo *m)
442 {
443         int  p;                     /* java instruction counter */ 
444         int  nextp;                 /* start of next java instruction */
445         int  opcode;                /* java opcode */
446         int  i;                     /* temp for different uses (counters)*/
447         bool iswide = false;        /* true if last instruction was a wide*/
448         int rc = 1;
449
450 METHINFOt(m,"\n----RT PARSING:",RTA_DEBUGopcodes); 
451 if ((RTA_DEBUGr)||(RTA_DEBUGopcodes)) printf("\n");
452
453 /* scan all java instructions */
454         for (p = 0; p < m->jcodelength; p = nextp) {
455
456                 opcode = code_get_u1(p,m);            /* fetch op code  */
457                 SHOWOPCODE(RTA_DEBUGopcodes)
458
459                 nextp = p + jcommandsize[opcode];   /* compute next instrtart */
460                 if (nextp > m->jcodelength) {
461                         log_text("Unexpected end of bytecode");
462                         assert(0);
463                 }
464
465                 switch (opcode) {
466
467                 case JAVA_ILOAD:
468                 case JAVA_LLOAD:
469                 case JAVA_FLOAD:
470                 case JAVA_DLOAD:
471                 case JAVA_ALOAD:
472
473                 case JAVA_ISTORE:
474                 case JAVA_LSTORE:
475                 case JAVA_FSTORE:
476                 case JAVA_DSTORE:
477                 case JAVA_ASTORE:
478
479                         if (iswide) {
480                                 nextp = p + 3;
481                                 iswide = false;
482                         }
483                         break;
484
485                 case JAVA_IINC: 
486                         {
487                                 
488                                 if (iswide) {
489                                         iswide = false;
490                                         nextp = p + 5;
491                                 }
492                         }
493                         break;
494
495                         /* wider index for loading, storing and incrementing */
496
497                 case JAVA_WIDE:
498                         iswide = true;
499                         nextp = p + 1;
500                         break;
501
502                 case JAVA_RET:
503                         if (iswide) {
504                                 nextp = p + 3;
505                                 iswide = false;
506                         }
507                         break;
508
509                 case JAVA_LOOKUPSWITCH:
510                         {
511                         s4 num;
512                         nextp = ALIGN((p + 1), 4) + 4;
513                         num = code_get_u4(nextp,m);
514                         nextp += (code_get_u4(nextp,m)) * 8 + 4;
515                         break;
516                         }
517
518
519                 case JAVA_TABLESWITCH:
520                        {
521                                 s4 num;
522                                 nextp = ALIGN ((p + 1),4);
523                                 num = code_get_s4(nextp + 4, m);
524                                 num = code_get_s4(nextp + 8, m) - num;
525                                 nextp = nextp + 16 + 4 * num;
526                                 break;
527                         }
528  /*********************/
529                 case JAVA_PUTSTATIC:
530                 case JAVA_GETSTATIC:
531
532                         i = code_get_u2(p + 1,m);
533                         {
534                                 constant_FMIref *fr;
535                                 fieldinfo *fi;
536                                 classinfo *frclass;
537
538                                 fr = class_getconstant(m->class, i, CONSTANT_Fieldref);
539                                 if (!fr)
540                                         return 0;
541                                 if (!resolve_classref(m,fr->classref,resolveEager,true, true,&frclass)) {
542                                         log_text("Could not resolve class reference");
543                                         assert(0);
544                                 }
545
546                                 LAZYLOADING(frclass);
547
548                                 fi = class_resolvefield(frclass,
549                                                         fr->name,
550                                                         fr->descriptor,
551                                                         m->class,
552                                                         true);
553
554                                 if (!fi)
555                                         return 0; /* was NULL */
556
557                                 CLASSNAME(fi->class,"\tPUT/GETSTATIC: ",RTA_DEBUGr);
558                                 RTAaddClassInit(        fi->class,
559                                                 CLINITS_T,FINALIZE_T,ADDMARKED_F);
560                         }
561                         break;
562
563
564                                                                 
565                         case JAVA_INVOKESTATIC:
566                         case JAVA_INVOKESPECIAL:
567                                 i = code_get_u2(p + 1,m);
568                                 {
569                                 constant_FMIref *mr;
570                                 methodinfo *mi;
571                                 classinfo *mrclass;
572
573                                 mr = class_getconstant(m->class, i, CONSTANT_Methodref);
574                                 if (!mr)
575                                         return 0;
576                                 if (!resolve_classref(m,mr->classref,resolveEager,true, true,&mrclass)) {
577                                         log_text("Could not resolve class reference");
578                                         assert(0);
579                                 }
580
581                                 LAZYLOADING(mrclass) 
582                                 mi = class_resolveclassmethod(  mrclass,
583                                                                                                 mr->name,
584                                                                                                 mr->descriptor,
585                                                                                                 m->class,
586                                                                                                 false);
587
588                                 if (mi) 
589                                    {
590                                    METHINFOt(mi,"INVOKESTAT/SPEC:: ",RTA_DEBUGopcodes)
591                                    mi->monoPoly = MONO;
592                                    
593                                    /*---- Handle "leaf" = static, private, final calls----------------------------*/
594                                    if ((opcode == JAVA_INVOKESTATIC)       
595                                      || (mi->flags & ACC_STATIC)  
596                                      || (mi->flags & ACC_PRIVATE)  
597                                      || (mi->flags & ACC_FINAL) )  
598                                         {
599                                         if (mi->class->classUsed != USED){ /* = NOTUSED or PARTUSED */
600                                                 RTAaddClassInit(mi->class, 
601                                                                 CLINITS_T,FINALIZE_T,ADDMARKED_T); 
602                                                                 /* Leaf methods are used whether class is or not */
603                                                                 /*   so mark class as PARTlyUSED                 */
604                                                 mi->class->classUsed = PARTUSED; 
605                                                 } 
606                                         /* Add to RTA working list/set of reachable methods     */
607                                         if (opcode == JAVA_INVOKESTATIC)  /* if stmt just for debug tracing */     
608                                                 addToRtaWorkList(mi, 
609                                                                 "addTo INVOKESTATIC "); 
610                                         else 
611                                                 addToRtaWorkList(mi, 
612                                                                 "addTo INVOKESPECIAL ");        
613                                         } 
614                                         
615                                    else {
616                                         /*---- Handle special <init> calls ---------------------------------------------*/
617                                    
618                                         if (mi->class->classUsed != USED) {
619                                         /* RTA special case:
620                                                 call of super's <init> then
621                                                 methods of super class not all used */
622                                                         
623                                                 /*--- <init>  ()V  is equivalent to "new" 
624                                                 indicating a class is used = instaniated ---- */        
625                                                 if (utf_init==mi->name) {
626                                                         if ((m->class->super.cls == mi->class) 
627                                                         &&  (m->descriptor == utf_void__void) ) 
628                                                                 {
629                                                                 METHINFOt(mi,"SUPER INIT:",RTA_DEBUGopcodes);
630                                                                 /* super init so class may be only used because of its sub-class */
631                                                                 RTAaddClassInit(mi->class,
632                                                                         CLINITS_T,FINALIZE_T,ADDMARKED_F);
633                                                                 if (mi->class->classUsed == NOTUSED) mi->class->classUsed = PARTUSED;
634                                                                 }
635                                                         else {
636                                                                 /* since <init> indicates classes is used, then add marked methods, too */
637                                                                 METHINFOt(mi,"NORMAL INIT:",RTA_DEBUGopcodes);
638                                                                 RTAaddClassInit(mi->class,
639                                                                         CLINITS_T,FINALIZE_T,ADDMARKED_T);
640                                                                 }
641                                                         addToRtaWorkList(mi,
642                                                                 "addTo INIT ");
643                                                         } /* end just for <init> ()V */
644                                                         
645                                                 /* <clinit> for class inits do not add marked methods; class not yet instaniated */      
646                                                 if (utf_clinit==mi->name)
647                                                         RTAaddClassInit(        mi->class,
648                                                                                 CLINITS_T,FINALIZE_T,ADDMARKED_F);
649
650                                                 if (!((utf_init==mi->name))
651                                                 ||   (utf_clinit==mi->name)) {
652                                                         METHINFOt(mi,"SPECIAL not init:",RTA_DEBUGopcodes)
653                                                         if (mi->class->classUsed !=USED)
654                                                                 mi->class->classUsed = PARTUSED;
655                                                         addToRtaWorkList(mi,
656                                                                 "addTo SPEC notINIT ");
657                                                         } 
658                                                                         
659                                                 } /* end init'd class not used = class init process was needed */ 
660                                                         
661                                         /* add method to RTA list = set of reachable methods */ 
662                                         addToRtaWorkList(mi,
663                                                         "addTo SPEC whymissed ");
664                                         } /* end inits */
665                                    } 
666 /***  assume if method can't be resolved won't actually be called or
667       there is a real error in classpath and in normal parse an exception
668       will be thrown. Following debug print can verify this
669 else  from if (mi) {
670 CLASSNAME1(mr->class,"CouldNOT Resolve method:",,RTA_DEBUGr);printf(".");fflush(stdout);
671 utf_display(mr->name); printf(" "); fflush(stdout);
672 utf_display(mr->descriptor); printf("\n");fflush(stdout);
673 ***/
674                         }
675                         break;
676
677                 case JAVA_INVOKEVIRTUAL:
678                         i = code_get_u2(p + 1,m);
679                         {
680                                 constant_FMIref *mr;
681                                 methodinfo *mi;
682                                                                 classinfo *mrclass;
683
684                                                                 /* XXX why this direct access, this should not be! */
685                                 mr = m->class->cpinfos[i];
686                                 /*mr = class_getconstant(m->class, i, CONSTANT_Methodref)*/
687                                         if (!resolve_classref(m,mr->classref,resolveEager,true, true,&mrclass)) {
688                                                 log_text("Could not resolve class reference");
689                                                 assert(0);
690                                         }
691
692                                 LAZYLOADING(mrclass) 
693                                 mi = class_resolveclassmethod(mrclass,
694                                                 mr->name,
695                                                 mr->descriptor,
696                                                 m->class,
697                                                 false);
698
699
700                                 if (mi) 
701                                    {
702                                    METHINFOt(mi,"INVOKEVIRTUAL ::",RTA_DEBUGopcodes);
703                                    if ((mi->flags & ACC_STATIC) 
704                                    ||  (mi->flags & ACC_PRIVATE)  
705                                    ||  (mi->flags & ACC_FINAL) )  
706                                      {
707                                      if (mi->class->classUsed == NOTUSED){
708                                        RTAaddClassInit(mi->class,
709                                                     CLINITS_T,FINALIZE_T,ADDMARKED_T);
710                                        }
711                                       mi->monoPoly = MONO;
712                                       addToRtaWorkList(mi,
713                                                     "addTo INVOKEVIRTUAL ");
714                                       } 
715                                    else {
716                                      mi->monoPoly = POLY;
717                                      rtaMarkSubs(mi->class,mi);
718                                      }
719                                    } 
720                                 else {
721 CLASSNAME1(mrclass,"CouldNOT Resolve virt meth:",RTA_DEBUGr);printf(".");fflush(stdout);
722 utf_display(mr->name); printf(" "); fflush(stdout);
723 utf_display(mr->descriptor); printf("\n");fflush(stdout);
724                                    }
725                                 }
726                                 break;
727
728                 case JAVA_INVOKEINTERFACE:
729                         i = code_get_u2(p + 1,m);
730                         {
731                                 constant_FMIref *mr;
732                                 methodinfo *mi;
733                                                                 classinfo *mrclass;
734
735                                 mr = class_getconstant(m->class, i, CONSTANT_InterfaceMethodref);
736                                                                 if (!mr)
737                                                                         return 0;
738                                                                 if (!resolve_classref(m,mr->classref,resolveEager,true, true,&mrclass)) {
739                                                                         log_text("Could not resolve class reference");
740                                                                         assert(0);
741                                                                 }
742
743                                 LAZYLOADING(mrclass)
744
745                                 mi = class_resolveinterfacemethod(mrclass,
746                                                           mr->name,
747                                                           mr->descriptor,
748                                                           m->class,
749                                                           false);
750                                         if (mi)
751                                            {
752                                            METHINFOt(mi,"\tINVOKEINTERFACE: ",RTA_DEBUGopcodes)
753                                            rtaMarkInterfaceSubs(mi);
754                                            }
755                                 /* see INVOKESTATIC for explanation about */
756                                 /*   case when Interface is not resolved  */
757                                 /*method_descriptor2types(mi); 
758                                 ?? do need paramcnt? for RTA (or just XTA)*/
759                         }
760                         break;
761
762                 case JAVA_NEW:
763                 /* means class is at least passed as a parameter */
764                 /* class is really instantiated when class.<init> called*/
765                         i = code_get_u2(p + 1,m);
766                         {
767                                 constant_classref *cr;
768                                 classinfo *ci;
769                 cr = (constant_classref *)class_getconstant(m->class, i, CONSTANT_Class);
770                                 if (!cr)
771                                         return 0;
772                                 resolve_classref(NULL,cr,resolveEager,true, false,&ci);
773                         /*** s_count++; look for s_counts for VTA */
774                         /* add marked methods */
775                         CLASSNAME(ci,"NEW : do nothing",RTA_DEBUGr);
776                         RTAaddClassInit(ci, CLINITS_T, FINALIZE_T,ADDMARKED_T);   
777                         }
778                         break;
779
780                 case JAVA_CHECKCAST:
781                 case JAVA_INSTANCEOF:
782                 /* class used */
783                         i = code_get_u2(p + 1,m);
784                         {
785                                                         constant_classref *cr;
786                                 classinfo *cls;
787
788                                                         cr = (constant_classref*) class_getconstant(m->class, i, CONSTANT_Class);
789                                                         if (!cr)
790                                                                 return 0;
791                                                         resolve_classref(NULL,cr,resolveEager,true, false,&cls);
792
793                         LAZYLOADING(cls)
794                         CLASSNAMEop(cls,RTA_DEBUGr);
795                         if (cls->classUsed == NOTUSED){
796                                 RTAaddClassInit(cls,
797                                             CLINITS_T,FINALIZE_T,ADDMARKED_T);
798                                 }
799                         }
800                         break;
801
802                 default:
803                         break;
804                                 
805                 } /* end switch */
806
807                 } /* end for */
808
809         return rc;
810 }
811
812 /* Helper fn for initialize **********************************************/
813
814 int RTAgetline(char *line, int max, FILE *inFP) {
815 if (fgets(line, max, inFP) == NULL) 
816   return 0;
817 else
818   return strlen((const char *) line);
819 }
820
821 /* Initialize RTA Work list ***********************************************/
822
823 /*-- Get meth ptr for class.meth desc and add to RTA worklist --*/
824 #define SYSADD(cls,meth,desc,txt) \
825         c = load_class_bootstrap(utf_new_char(cls)); \
826         LAZYLOADING(c) \
827         callmeth = class_resolveclassmethod(c, \
828               utf_new_char(meth), \
829               utf_new_char(desc), \
830               c, \
831               false); \
832         if (callmeth->class->classUsed != USED) {  \
833               c->classUsed = PARTUSED; \
834               RTAaddClassInit(callmeth->class, \
835                            CLINITS_T,FINALIZE_T,ADDMARKED_T);\
836               } \
837         callmeth->monoPoly = POLY; \
838         addToRtaWorkList(callmeth,txt);
839
840
841 /*-- ----------------------------------------------------------------------------- 
842       System calls 
843         and 
844       rtMissedIn list (missed becaused called from NATIVE &/or dynamic calls
845  *-- -----------------------------------------------------------------------------*/
846 methodinfo *initializeRTAworklist(methodinfo *m) {
847         classinfo  *c;
848         methodinfo* callmeth;
849                 char systxt[]    = "System     Call :";
850         char missedtxt[] = "rtMissedIn Call :";
851
852         FILE *rtMissedIn; /* Methods missed during previous RTA parse */
853         char line[256];
854         char* class, *meth, *desc;
855         methodinfo *rm =NULL;  /* return methodinfo ptr to main method */
856
857
858         /* Create RTA call work list */
859         rtaWorkList = NEW(list);
860         list_init(rtaWorkList, OFFSET(rtaNode,linkage) );
861
862         /* Add first method to call list */
863         m->class->classUsed = USED; 
864         addToRtaWorkList(m,systxt);
865         /* Add system called methods */
866 /***    SYSADD(mainstring, "main","([Ljava/lang/String;)V",systxt) ***/
867         SYSADD(MAINCLASS, MAINMETH, MAINDESC,systxt)
868         rm = callmeth;  
869 /***    SYSADD("java/lang/System","exit","(I)V",systxt) ***/
870         SYSADD(EXITCLASS, EXITMETH, EXITDESC, systxt)
871         /*----- rtMissedIn 0 */
872         if ( (rtMissedIn = fopen("rtMissedIn0", "r")) == NULL) {
873                 /*if (opt_verbose) */
874                     {printf("No rtMissedIn0 file\n");fflush(stdout);} 
875                 return  rm;
876                 }
877         while (RTAgetline(line,256,rtMissedIn)) {
878             class = strtok(line, " \n");
879             meth  = strtok(NULL, " \n");
880             desc  = strtok(NULL, " \n");
881                 SYSADD(class,meth,desc,missedtxt)
882                 }
883         fclose(rtMissedIn);
884
885
886
887
888         return rm;
889
890 }
891
892 /*- end initializeRTAworklist-------- */
893
894
895
896 /*-------------------------------------------------------------------------------*/
897 methodinfo *missedRTAworklist()  
898 {
899         FILE *rtMissedIn; /* Methods missed during previous RTA parse */
900         char filenameIn[256] = "rtIn/";
901         char line[256];
902         char* class, *meth, *desc;
903         char missedtxt[] = "rtIn/ missed Call :";
904         classinfo  *c;
905         methodinfo* callmeth;
906
907         methodinfo *rm =NULL;  /* return methodinfo ptr to main method */
908
909
910 #if defined(USE_THREADS)
911         SYSADD(THREADCLASS, THREADMETH, THREADDESC, "systxt2")
912         SYSADD(THREADGROUPCLASS, THREADGROUPMETH, THREADGROUPDESC, "systxt2")
913 #endif
914         /*----- rtMissedIn pgm specific */
915         strcat(filenameIn, (const char *)mainstring);  
916         if ( (rtMissedIn = fopen(filenameIn, "r")) == NULL) {
917                 /*if (opt_verbose)*/ 
918                     {printf("No rtIn/=%s file\n",filenameIn);fflush(stdout);} 
919                 return rm;
920                 }
921         while (RTAgetline(line,256,rtMissedIn)) {
922             class = strtok(line, " \n");
923             meth  = strtok(NULL, " \n");
924             desc  = strtok(NULL, " \n");
925             if ((class == NULL) || (meth == NULL) || (desc == NULL)) {
926                         log_text("Error in rtMissedIn file for: class.meth, desc");
927                         assert(0);
928                 }
929             SYSADD(class,meth,desc,missedtxt)
930             }
931         fclose(rtMissedIn);
932
933         return rm;
934 }
935
936
937
938 /*--------------------------------------------------------*/
939 /* parseRTmethod                                          */
940 /* input: method to be RTA static parsed                  */
941 /*--------------------------------------------------------*/
942 void parseRTmethod(methodinfo *rt_method) {
943         if (! (  (rt_method->flags & ACC_NATIVE  )
944             ||   (rt_method->flags & ACC_ABSTRACT) ) )  
945             {
946             /* RTA parse to approxmate....
947                 what classes/methods will really be used during execution */
948             parseRT(rt_method);  
949             }
950         else {
951             if (rt_method->flags & ACC_NATIVE  )
952                 {
953                METHINFOt(rt_method,"TO BE NATIVE RTA PARSED :",RTA_DEBUGopcodes);
954                 /* parseRTpseudo(rt_method); */
955                 }   
956             else {
957                printf("Abstract method in RTA Work List: ");
958                METHINFOx(rt_method);
959                log_text("Abstract method in RTA Work List.");
960                    assert(0);
961                 }
962         }               
963 }
964
965
966 /*-- RTA -- *******************************************************/
967 int RT_jit_parse(methodinfo *m)
968 {
969   rtaNode    *rta;
970   methodinfo *mainmeth;
971
972   /* Should only be called once */
973   if (firstCall) {
974
975         /*----- RTA initializations --------*/
976         if (opt_verbose) 
977             log_text("RTA static analysis started.\n");
978
979         mainmeth = initializeRTAworklist(m);
980         firstCall = false; /* turn flag off */
981
982     if ( (rtMissed = fopen("rtMissed", "w")) == NULL) {
983         printf("CACAO - rtMissed file: cant open file to write\n");
984         }
985     /* Note: rtMissed must be renamed to rtMissedIn to be used as input */
986         
987     /*------ process RTA call work list --------*/
988     for (rta =list_first(rtaWorkList); 
989          rta != NULL; 
990          rta =list_next(rtaWorkList,rta)) 
991         { 
992         parseRTmethod(rta->method);
993         }       
994     missedRTAworklist();  
995     for (rta =list_first(rtaWorkList); 
996          rta != NULL; 
997          rta =list_next(rtaWorkList,rta)) 
998         { 
999         parseRTmethod(rta->method);
1000         }       
1001
1002     fclose(rtMissed);
1003     if (opt_verbose) {
1004         if (opt_stat) {
1005           printRThierarchyInfo(m); 
1006           }
1007       printCallgraph(rtaWorkList); 
1008       }
1009
1010     if (opt_verbose) {
1011       log_text("RTA static analysis done.\n");
1012       }
1013   }
1014 return 0;
1015 }
1016
1017 /*
1018  * These are local overrides for various environment variables in Emacs.
1019  * Please do not remove this and leave it at the end of the file, where
1020  * Emacs will automagically detect them.
1021  * ---------------------------------------------------------------------
1022  * Local variables:
1023  * mode: c
1024  * indent-tabs-mode: t
1025  * c-basic-offset: 4
1026  * tab-width: 4
1027  * End:
1028  */
1029