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