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