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