2 If V() then why add call edges since no type info passed?
3 does nothing happen when the method with V() is XTA parsed? class info is standalone then
5 Check initialization... need at least a dummy called by ...
7 ... why no error now????
9 What about recursion??? x.a calls x.a
11 Now wondering if there is a memory corruption because XTA seems to finish ok
14 /* jit/parseXTA.c - parser and print functions for Rapid Type Analyis
16 Copyright (C) 1996-2005 R. Grafl, A. Krall, C. Kruegel, C. Oates,
17 R. Obermaisser, M. Platter, M. Probst, S. Ring, E. Steiner,
18 C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich, J. Wenninger,
19 Institut f. Computersprachen - TU Wien
21 This file is part of CACAO.
23 This program is free software; you can redistribute it and/or
24 modify it under the terms of the GNU General Public License as
25 published by the Free Software Foundation; either version 2, or (at
26 your option) any later version.
28 This program is distributed in the hope that it will be useful, but
29 WITHOUT ANY WARRANTY; without even the implied warranty of
30 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
31 General Public License for more details.
33 You should have received a copy of the GNU General Public License
34 along with this program; if not, write to the Free Software
35 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
38 Contact: cacao@complang.tuwien.ac.at
40 Authors: Carolyn Oates
42 $Id: parseXTA.c 2107 2005-03-28 22:44:28Z twisti $
46 /*--------------------------------------
53 general initialization
56 + hand coded calls for system
57 2nd interation (want to try it in inlining)
62 ----------------------------------*/
65 XTA Type Static Analysis of Java program
66 used -xta option is turned on either explicitly
67 or automatically with inlining of virtuals.
69 XTA is called for reachable methods and keeps sets for each Method and Field used as follows:
70 1. Work list of reachable methods is initialized to main + JVM called methods
72 2. For virtual method call from M of e.m then
73 a. Add all static lookup of m in the cone of e = ce.mi to reachable worklist
74 JAVA_INVOKESTATIC/ JAVA_INVOKESPECIAL - xtaAddCallEdges
75 JAVA_INVOKEVIRTUAL - xtaMarkSubs
77 b. Add mi's parameters class + subtypes that are used by M to mi used classes
78 When XTA parsed follow the calls list (beg. parseXTA)
79 c. Add mi's return type + subtypes used by mi to M's used classes
80 When XTA parsed follow the calledBy list (end parseXTA)
81 d. Add ce of mi to mi's used classes
82 static/special - addXTAcalledges
83 virtual - xtaMarkSubs if subclass used -> xtaAddCallEdges
84 if subclass not used -> add ce.mi to markedby temp set
86 3. new C (new, <init>, & similiar) then add C to M's used classes
87 JAVA_NEW, INVOKE_SPECIAL <init>, JAVA_CHECKCAST / JAVA_INSTANCEOF - classinit
88 4. read Field X.f: add X to M's used classes
90 5. write Field X.f: add X+subtypes that are used by M to X's classes
96 Methods called by NATIVE methods and classes loaded dynamically
97 cannot be found by parsing. The following files supply missing methods:
99 xtaMissedIn0 - (provided) has the methods missed by every java program
100 xtaMissed||mainClassName - is program specific.
102 A file xtaMissed will be written by XTA analysis of any methods missed.
104 This file can be renamed to xtaMissed concatenated with the main class name.
109 inlining with virtuals should fail if the returned xtaMissed is not empty.
111 mv xtaMissed xtaMissedhello
114 Results: (currently) with -stat see # methods marked used
122 #include "cacao/cacao.h"
123 #include "mm/memory.h"
124 #include "toolbox/list.h"
125 #include "vm/class.h"
126 #include "vm/linker.h"
127 #include "vm/loader.h"
128 #include "vm/options.h"
129 #include "vm/statistics.h"
130 #include "vm/tables.h"
131 #include "vm/jit/jit.h"
132 #include "vm/jit/parse.h"
133 #include "vm/jit/inline/parseXTA.h"
134 #include "vm/jit/inline/parseRTstats.h"
135 #include "vm/jit/inline/parseRTprint.h"
139 static bool firstCall= true;
140 static list *xtaWorkList;
141 FILE *xtaMissed; /* Methods missed during XTA parse of Main */
143 bool XTA_DEBUGinf = false;
144 bool XTA_DEBUGr = false;
145 bool XTA_DEBUGopcodes = false;
147 char * clsFlgs [] = {"NOTUSED", "PARTUSED", "USED"};
148 char * methFlgs [] = {"NOTUSED", "MARKED", "USED"};
150 /*********************************************************************/
151 /*********************************************************************/
153 /*-------------------------------------------------------------------------------*/
155 xtafldinfo * xtafldinfoInit (fieldinfo *f)
160 f->xta = NEW(xtafldinfo);
162 f->xta->fieldChecked = false;
163 f->xta->fldClassType = NULL;
164 f->xta->XTAclassSet = NULL;
169 /*-------------------------------------------------------------------------------*/
171 xtainfo *xtainfoInit(methodinfo *m)
174 return m->xta; /* already initialized */
176 #if defined(STATISTICS)
177 count_methods_marked_used++;
180 m ->xta = (xtainfo *) NEW(xtainfo);
181 m ->xta-> XTAmethodUsed = NOTUSED;
183 /* xta sets for a method */
184 m->xta->fldsUsed = NULL;
185 m ->xta-> XTAclassSet = NULL;
186 /* Methods's have access to the class they are a part of */
187 m ->xta-> XTAclassSet = add2ClassSet ( m ->xta-> XTAclassSet, m->class);
188 /* cone set of methods parameters */
189 /* what if no param?? is it NULL then, too? */
190 /****** class not loaded so take param info from superclass ??? */
191 m->xta->paramClassSet = descriptor2typesL(m);
194 m->xta->calls = NULL;
195 m->xta->calledBy = NULL;
196 m ->xta->markedBy = NULL;
198 m->xta->chgdSinceLastParse = false;
201 /* thought needed at some earlier point */
202 /*m ->xta->interfaceCalls = NULL*/
205 /*-------------------------------------------------------------------------------*/
206 void xtaAddCallEdges(methodinfo *mCalls, methodinfo *mCalled, s4 monoPoly, char *info) {
210 if (mCalled->flags & ACC_ABSTRACT) return;
211 /* First call to this method initializations */
213 printf("mCalled->methodUsed =%i != %i = USED is ",mCalled->methodUsed, USED); fflush(stdout);
214 printf(" <%i> T%i/%iF\n",(mCalled->methodUsed!= USED), true,false); fflush(stdout);
217 if (mCalled->methodUsed != USED) {
219 printf("\n>>>>>>%s:\n",info); fflush(stdout);
220 printf("Add to Worklist mCalls_=");fflush(stdout);
222 printf("<"); fflush(stdout);
224 printf("> "); fflush(stdout);
228 printf("NULL\n");fflush(stdout);
231 printf("mCalled=");fflush(stdout);
233 printf("<"); fflush(stdout);
235 printf("> "); fflush(stdout);
238 {printf("NULL\n");fflush(stdout);}
240 mCalled->xta = xtainfoInit(mCalled);
241 mCalled ->methodUsed = USED; /* used to see if method in the work list of methods */
243 xta->method = mCalled ;
244 list_addlast(xtaWorkList,xta);
247 if ((mCalls == NULL) && (!(monoPoly == SYSCALL)) ) {} /* panic when init file correct is */
249 if ((mCalls == mCalled) /* recursion doesn't change class set nor field set so ignore */
250 || (mCalls == NULL)) {return; }
253 /*** printf(" AddCallEdges\n"); fflush(stdout); ***/
255 mCalls->xta = xtainfoInit(mCalls);
256 mCalls->xta->calls = add2MethSet(mCalls->xta->calls, mCalled);
257 /* mono if static, private, final else virtual so poly */
258 mCalls->xta->calls->tail->monoPoly = monoPoly;
260 mCalled->xta->calledBy = add2MethSet(mCalled->xta->calledBy, mCalls);
262 /* IS THIS REALLY NEEDED???? */
263 if (mCalled->xta->calledBy == NULL) panic("mCalled->xta->calledBy is NULL!!!");
264 if (mCalls->xta->calls == NULL) panic("mCalls->xta->calls is NULL!!!");
269 /*-------------------------------------------------------------------------------*/
270 bool xtaPassParams (methodinfo *Called, methodinfo *Calls, methSetNode *lastptrInto)
278 if (lastptrInto->lastptrIntoClassSet2 == NULL) {
279 if (Calls->xta->XTAclassSet != NULL)
280 c1 = Calls->xta->XTAclassSet->head;
281 /*else already c1 = NULL; */
284 /* start with type where left off */
285 c1 = lastptrInto->lastptrIntoClassSet2;
286 c1 = c1 -> nextClass; /* even if NULL */
288 if (c1 == NULL) return false;
291 /* for each Param Class */
292 for ( p=Called->xta->paramClassSet; p != NULL; p = p->nextClass) {
294 /* for each SmCalls class */
295 for (c=c1; c != NULL; c = c->nextClass) {
299 LAZYLOADING(c->classType) /* if not loaded is it really needed ??? */
301 p_cl_vt = p->classType->vftbl;
302 c_cl_vt = c->classType->vftbl;
304 /* if SmCalls class is in the Params Class range */
305 if ( (p_cl_vt->baseval <= c_cl_vt->baseval)
306 && (c_cl_vt->baseval <= (p_cl_vt->baseval+p_cl_vt->diffval)) ) {
308 /* add Calls class to CalledBy Class set */
309 Called->xta->XTAclassSet = Called->xta->XTAclassSet = add2ClassSet(Called->xta->XTAclassSet, c->classType);
315 lastptrInto->lastptrIntoClassSet2 = cprev;
320 /*-------------------------------------------------------------------------------*/
321 void xtaPassAllCalledByParams (methodinfo *m) {
322 methSetNode *SmCalled;
323 if (m->xta->calledBy == NULL)
325 for (SmCalled = m->xta->calledBy->head;
327 SmCalled = SmCalled->nextmethRef) {
328 m->xta->chgdSinceLastParse = false; /* re'init flag */
329 xtaPassParams(m, SmCalled->methRef,SmCalled); /* chg flag output ignored for 1st regular parse */
334 /*-------------------------------------------------------------------------------*/
335 void xtaPassFldPUT(methodinfo *m, fldSetNode *fN)
337 /* Field type is a class */
339 classSetNode *c1 = NULL;
340 classSetNode *cp = NULL;
341 classSetNode *cprev= NULL;
350 /* Use lastptr so don't check whole XTA class set each time */
353 if (cp->nextClass != NULL)
354 c1 = cp -> nextClass;
357 if (m->xta->XTAclassSet != NULL)
358 c1 = m->xta->XTAclassSet->head;
361 /*--- PUTSTATIC specific ---*/
362 /* Sx = intersection of type+subtypes(field x) */
363 /* and Sm (where putstatic code is) */
364 for (c=c1; c != NULL; c=c->nextClass) {
368 LAZYLOADING1(fi->xta->fldClassType)
370 f_cl_vt = fi->xta->fldClassType->vftbl;
371 c_cl_vt = c-> classType->vftbl;
372 if ((f_cl_vt->baseval <= c_cl_vt->baseval)
373 && (c_cl_vt->baseval <= (f_cl_vt->baseval+f_cl_vt->diffval)) ) {
374 fi->xta->XTAclassSet = add2ClassSet(fi->xta->XTAclassSet,c->classType);
378 fN->lastptrPUT = cprev;
380 /*-------------------------------------------------------------------------------*/
381 void xtaPassFldGET(methodinfo *m, fldSetNode *fN)
383 /* Field type is a class */
385 classSetNode *c1 = NULL;
386 classSetNode *cp = NULL;
387 classSetNode *cprev= NULL;
395 /* Use lastptr so don't check whole XTA class set each time */
398 if (cp->nextClass != NULL)
399 c1 = cp -> nextClass;
402 if (fi->xta->XTAclassSet != NULL)
403 c1 = fi->xta->XTAclassSet->head;
406 /*--- GETSTATIC specific ---*/
407 /* Sm = union of Sm and Sx */
408 for (c=c1; c != NULL; c=c->nextClass) {
410 if (m->xta->XTAclassSet ==NULL)
413 if (!(inSet (m->xta->XTAclassSet->head, c->classType) ))
418 = add2ClassSet(m->xta->XTAclassSet,c->classType);
423 fN->lastptrGET = cprev;
427 /*-------------------------------------------------------------------------------*/
428 void xtaAllFldsUsed (methodinfo *m) {
431 /* bool chgd = false */
433 if (m->xta->fldsUsed == NULL) return;
435 /* for each field that this method uses */
436 f1 = m->xta->fldsUsed->head;
438 for (f=f1; f != NULL; f = f->nextfldRef) {
447 /*-------------------------------------------------------------------------------*/
448 bool xtaPassReturnType(methodinfo *Called, methodinfo *Calls) {
454 /* Get Called return class is null */
455 if ((Called->returnclass == NULL) && (Called->xta->paramClassSet == NULL)) {
456 Called->xta->paramClassSet = descriptor2typesL(Called); /* old comment - in new xta struc init */
459 if (Called->returnclass == NULL) {
463 if (Called->xta->XTAclassSet == NULL)
466 cs1 = Called->xta->XTAclassSet->head;
468 for (cs =cs1; cs != NULL; cs = cs->nextClass) {
469 classinfo *c = cs->classType;
473 LAZYLOADING(Called->returnclass)
474 r_cl_vt = Called->returnclass->vftbl;
477 /* if class is a subtype of the return type, then add to Calls class set (ie.interscection)*/
478 if ( (r_cl_vt->baseval <= r_cl_vt->baseval)
479 && (c_cl_vt->baseval <= (r_cl_vt->baseval+r_cl_vt->diffval)) ) {
480 Calls->xta->XTAclassSet = add2ClassSet(Calls->xta->XTAclassSet, c);
489 /*-------------------------------------------------------------------------------*/
490 void xtaMethodCalls_and_sendReturnType(methodinfo *m)
492 methSetNode *SmCalled; /* for return type */
493 methSetNode *SmCalls; /* for calls param types */
494 methSetNode *s1=NULL;
499 if (m->xta == NULL) panic("m->xta null for return type\n");
500 /* for each method that this method calls */
501 if (m->xta->calls == NULL)
504 s1 = SmCalls=m->xta->calls->head;
506 for (SmCalls=s1; SmCalls != NULL; SmCalls = SmCalls->nextmethRef) {
507 /* pass param types */
509 chgd = xtaPassParams (SmCalls->methRef, m, SmCalls);
510 /* if true chgd after its own parse */
511 if (!(SmCalls->methRef->xta->chgdSinceLastParse)) {
512 SmCalls->methRef->xta->chgdSinceLastParse = true;
516 /* for each calledBy method */
517 /* send return type */
518 if (m->xta->calledBy == NULL)
521 s1 = m->xta->calledBy->head;
522 for (SmCalled=s1; SmCalled != NULL; SmCalled = SmCalled->nextmethRef) {
524 chgd = xtaPassReturnType(m, SmCalled->methRef);
525 if (!(SmCalled->methRef->xta->chgdSinceLastParse)) {
526 SmCalled->methRef->xta->chgdSinceLastParse = chgd;
532 /*-------------------------------------------------------------------------------*/
533 bool xtaAddFldClassTypeInfo(fieldinfo *fi) {
535 bool is_classtype = false; /* return value */
537 if (fi->xta->fieldChecked) {
538 if (fi->xta->fldClassType != NULL)
539 return true; /* field has a class type */
543 fi->xta->fieldChecked = true;
545 if (fi->type == TYPE_ADDRESS) {
546 char *utf_ptr = fi->descriptor->text; /* current position in utf text */
548 if (*utf_ptr != 'L') {
549 while (*utf_ptr++ =='[') ;
552 if (*utf_ptr =='L') {
554 if (fi->xta->fldClassType== NULL) {
559 desc = MNEW(char, 256);
560 strcpy(desc,++utf_ptr);
561 cname = strtok(desc,";");
562 class = class_get(utf_new_char(cname));
563 fi->xta->fldClassType= class; /* save field's type class ptr */
570 /*--------------------------------------------------------------*/
571 /* Mark the method with same name /descriptor in topmethod */
574 /* Class marked USED and method defined in this class -> */
575 /* -> add call edges = USED */
576 /* Class not marked USED and method defined in this class -> */
577 /* -> if Method NOTUSED mark method as MARKED */
579 /* Class USED, but method not defined in this class -> */
580 /* -> 1) search up the heirarchy and mark method where defined */
581 /* 2) if class where method is defined is not USED -> */
582 /* -> ????mark class with defined method as PARTUSED */
583 /*--------------------------------------------------------------*/
586 void xtaMarkMethod(classinfo *class, methodinfo *mCalls, methodinfo *topmethod, classSetNode *subtypesUsedSet) {
588 utf *name = topmethod->name;
589 utf *descriptor = topmethod->descriptor;
592 /* See if method defined in class heirarchy */
593 submeth = class_resolvemethod(class, name, descriptor);
594 METHINFOt(submeth,"xtaMarkMethod submeth:",XTA_DEBUGr);
595 if (submeth == NULL) {
596 utf_display(class->name); printf(".");
597 METHINFOx(topmethod);
598 printf("parse XTA: Method not found in class hierarchy");fflush(stdout);
599 panic("parse XTA: Method not found in class hierarchy");
602 /* if submeth called previously from this method then return */
603 if (mCalls->xta->calls != NULL) {
604 if (inMethSet(mCalls->xta->calls->head,submeth)) return;
609 XTAaddClassInit(submeth, submeth->class,
610 CLINITS_T,FINALIZE_T,ADDMARKED_T);
611 if (inSet(subtypesUsedSet,submeth->class)) {
612 submeth->monoPoly = POLY;
613 xtaAddCallEdges(mCalls, submeth, submeth->monoPoly,
614 "00addTo XTA VIRT CONE:");
619 if (submeth->class == class) {
621 /*--- Method defined in class -----------------------------*/
622 if (inSet(subtypesUsedSet,submeth->class)) {
623 /* method defined in this class -> */
624 /* Class IS marked USED */
625 /* -> mark method as USED */
626 submeth->monoPoly = POLY;
627 xtaAddCallEdges(mCalls, submeth, submeth->monoPoly,
628 "01addTo VIRT CONE 1:");
631 /* method defined in this class -> */
632 /* Class IS NOT marked USED (PART or NOTUSED) */
633 /* -> if Method NOTUSED mark method as MARKED */
635 "\tmarked VIRT CONE 2:",XTA_DEBUGr);
636 submeth->monoPoly = POLY;
637 if (submeth->xta == NULL) {
638 submeth->xta = xtainfoInit(submeth);
640 submeth->methodUsed = MARKED; /* used to see if method in the work list of methods */
641 submeth->xta->markedBy = add2MethSet(submeth->xta->markedBy,mCalls);
642 /* Note: if class NOTUSED and subclass is used handled */
643 /* by subsequent calls to xtaMarkMethods for cone */
645 } /* end defined in class */
648 /*--- Method NOT defined in class - defined up the heirarchy ---------------*/
649 /* then check class the method could be called with */
651 /* first mark classes if needed */
652 if (!(inSet(subtypesUsedSet,submeth->class))) {
653 submeth->class->classUsed = PARTUSED;
654 if (!(inSet(subtypesUsedSet,class))) {
655 submeth->monoPoly = POLY;
656 if (submeth->xta == NULL)
657 submeth->xta = xtainfoInit(submeth);
658 submeth->methodUsed = MARKED; /* used to see if method in the work list of methods */
659 submeth->xta->markedBy = add2MethSet(submeth->xta->markedBy,mCalls);
660 METHINFOt(submeth,"JUST MARKED :",XTA_DEBUGr);
663 /* add method to xta work list if conditions met */
664 if (inSet(subtypesUsedSet,class)) {
665 submeth->monoPoly = POLY;
666 xtaAddCallEdges(mCalls, submeth, submeth->monoPoly,
667 "02addTo VIRT CONE 3:");
669 } /* end NOT defined in class */
673 /*----------------------------------------------------------------------*/
674 /* Mark the method with the same name and descriptor as topmethod */
675 /* and any subclass where the method is defined and/or class is used */
677 /*----------------------------------------------------------------------*/
679 void xtaMarkSubs(methodinfo *mCalls, classinfo *class, methodinfo *topmethod, classSetNode *subtypesUsedSet) {
680 /* xtaPRINTmarkSubs1*/
681 xtaMarkMethod(class, mCalls, topmethod, subtypesUsedSet); /* Mark method in class where it was found */
682 if (class->sub != NULL) {
685 if (!(topmethod->flags & ACC_FINAL )) {
686 for (subs = class->sub; subs != NULL; subs = subs->nextsub) {
687 xtaMarkSubs(mCalls, subs, topmethod, subtypesUsedSet);
694 /**************************************************************************/
695 /* Add Marked methods for input class ci */
696 /* Add methods with the same name and descriptor as implemented interfaces*/
697 /* with the same method name */
698 /* ??? interface part not XTA checked */
699 /*------------------------------------------------------------------------*/
700 void xtaAddMarkedMethods(methodinfo *mCalls, classinfo *ci) {
703 /* add marked methods to callgraph */
704 for (ii=0; ii<ci->methodscount; ii++) {
705 methodinfo *mi = &(ci->methods[ii]);
707 if (mi->xta != NULL) {
708 if (mi->xta->markedBy != NULL) {
710 for (mcnode = mi->xta->markedBy->head; mcnode != NULL; mcnode = mcnode ->nextmethRef) {
711 methodinfo *mCalls = mcnode->methRef;
712 xtaAddCallEdges(mCalls, mi, mi->monoPoly,
713 "03addToInit was Marked added:");
717 else { /* NOT XTA checked yet */
718 for (jj=0; jj < ci -> interfacescount; jj++) {
719 classinfo *ici = ci -> interfaces [jj];
720 /* use resolve method....!!!! */
721 if (ici -> classUsed != NOTUSED) {
722 for (mm=0; mm< ici->methodscount; mm++) {
723 methodinfo *imi = &(ici->methods[mm]);
724 METHINFOt(imi,"NEW IMPD INTERFACE:",XTA_DEBUGinf)
725 /*if interface method=method is used*/
726 if ( (imi->methodUsed == USED)
727 && ( (imi->name == mi->name)
728 && (imi->descriptor == mi->descriptor))) {
729 xtaAddCallEdges(mCalls, mi, mi->monoPoly,
730 "04addTo was interfaced used/MARKED:");
741 /*------------------------------------------------------------------------*/
742 void xtaAddUsedInterfaceMethods(methodinfo *m, classinfo *ci) {
745 /* add used interfaces methods to callgraph */
746 for (jj=0; jj < ci -> interfacescount; jj++) {
747 classinfo *ici = ci -> interfaces [jj];
750 printf("BInterface used: ");fflush(stdout);
751 utf_display(ici->name);
752 printf("<%i>\tclassUsed=%s\n",ici -> classUsed,clsFlgs[ici->classUsed] ); fflush(stdout);
754 /* add class to interfaces list of classes that implement it */
755 ici -> impldBy = addElement(ici -> impldBy, ci);
757 /* if interface class is used */
758 if (ici -> classUsed != NOTUSED) {
760 /* for each interface method implementation that has already been used */
761 for (mm=0; mm< ici->methodscount; mm++) {
762 methodinfo *imi = &(ici->methods[mm]);
763 if ( (XTA_DEBUGinf) && (imi->methodUsed != USED)) {
764 printf("Interface Method %s: ", methFlgs[imi->methodUsed]);
765 utf_display(ici->name);printf(".");method_display(imi);fflush(stdout);
767 if (imi->methodUsed == USED) {
769 printf("Interface Method used: "); utf_display(ici->name);printf(".");method_display(imi);fflush(stdout);
770 /* Mark this method used in the (used) implementing class &its subclasses */
771 printf("rMAY ADD methods that was used by an interface\n");
773 if ((utf_clinit != imi->name) &&
774 (utf_init != imi->name))
776 classSetNode *subtypesUsedSet = NULL;
777 if (m->xta->XTAclassSet != NULL) {
779 intersectSubtypesWithSet
780 (imi->class, m->xta->XTAclassSet->head);
782 else /* can any methods be added if 1 set is NULL ??? */
783 subtypesUsedSet = addElement(subtypesUsedSet, m->class);
784 xtaMarkSubs(m, ci, imi, subtypesUsedSet);
785 imi->monoPoly = POLY;
789 } /* end for method */
790 } /* end != NOTUSED */
791 } /* end for interface */
796 /*----------------------------------------------------------------------*/
798 #define CLINITS_T true
799 #define FINALIZE_T true
800 #define ADDMARKED_T true
802 #define CLINITS_F false
803 #define FINALIZE_F false
804 #define ADDMARKED_F false
805 /*-----------------------*/
807 void XTAaddClassInit(methodinfo *mCalls, classinfo *ci, bool clinits, bool finalizes, bool addmark)
812 ci->classUsed = USED;
814 if (clinits) { /* No <clinit> available - ignore */
815 mi = class_findmethod(ci, utf_clinit, utf_void__void);
817 if (ci->classUsed != USED)
818 ci->classUsed = PARTUSED;
820 xtaAddCallEdges(mCalls, mi, mi->monoPoly,
821 "05addTo CLINIT added:");
825 /*Special Case for System class init:
826 add java/lang/initializeSystemClass to callgraph */
827 if (ci->name == utf_new_char("initializeSystemClass")) {
828 /* ?? what is name of method ?? */
832 mi = class_findmethod(ci, utf_finalize, utf_void__void);
834 if (ci->classUsed != USED)
835 ci->classUsed = PARTUSED;
837 xtaAddCallEdges(mCalls, mi, mi->monoPoly,
838 "06addTo FINALIZE added:");
843 xtaAddMarkedMethods(mCalls, ci);
846 /* always so know have access to the interface methods */
847 xtaAddUsedInterfaceMethods(mCalls,ci);
851 /*-------------------------------------------------------------------------------*/
853 /*********************************************************************/
854 /*********************************************************************/
856 /*-------------------------------------------------------------------*/
858 void xtaMarkInterfaceSubs(methodinfo *m, methodinfo *mi) {
860 if (mi->class->classUsed == NOTUSED) {
861 mi->class->classUsed = USED;
862 /* add interface class to list kept in Object */
863 class_java_lang_Object->impldBy = addElement(class_java_lang_Object -> impldBy, mi->class);
866 mi->methodUsed = USED;
869 /*XTAPRINT08invokeInterface1*/
871 subs = mi->class->impldBy;
872 METHINFO(mi,XTA_DEBUGinf)
873 printf("Implemented By classes :\n");fflush(stdout);
874 if (subs == NULL) printf("\tNOT IMPLEMENTED !!!\n"); fflush(stdout);
876 for (subs = mi->class->impldBy; subs != NULL; subs = subs->nextClass) {
879 printf("\t");utf_display(subs->classType->name);fflush(stdout);
880 printf(" <%i>\n",subs->classType->classUsed);fflush(stdout);
883 /*Mark method (mark/used) in classes that implement method*/
884 submeth = class_findmethod(subs->classType, mi->name, mi->descriptor);
885 if (submeth != NULL) {
886 classSetNode *subtypesUsedSet = NULL;
887 submeth->monoPoly = POLY; /* poly even if nosubs */
888 submeth->xta = xtainfoInit(submeth);
890 submeth->xta->XTAmethodUsed = USED;
891 if (m->xta->XTAclassSet != NULL) {
892 subtypesUsedSet = /* interface classes cone */
893 intersectSubtypesWithSet(subs->classType, m->xta->XTAclassSet->head);
895 else { /* can any methods be added if 1 set is NULL ??? */
896 subtypesUsedSet = addElement(subtypesUsedSet, m->class);
898 xtaMarkSubs(m, subs->classType, submeth, subtypesUsedSet);
906 /*********************************************************************/
908 int parseXTA(methodinfo *m)
910 int p; /* java instruction counter */
911 int nextp; /* start of next java instruction */
912 int opcode; /* java opcode */
913 int i; /* temp for different uses (counters)*/
914 bool iswide = false; /* true if last instruction was a wide*/
917 if (m->methodXTAparsed) return 0;
918 else m->methodXTAparsed = true;
920 /***XTA_DEBUGopcodes=false;***/
921 /***printf("\n-----------------------------------\n"); **/
922 METHINFOt(m,"\n----XTA PARSING:",XTA_DEBUGopcodes);
923 if ((XTA_DEBUGr)||(XTA_DEBUGopcodes)) printf("\n");
924 /***XTA_DEBUGopcodes=false;***/
925 if (m->xta == NULL) {
929 xtaPassAllCalledByParams (m);
932 /* scan all java instructions */
933 for (p = 0; p < m->jcodelength; p = nextp) {
935 opcode = code_get_u1(p,m); /* fetch op code */
936 SHOWOPCODE(XTA_DEBUGopcodes)
938 nextp = p + jcommandsize[opcode]; /* compute next instr start */
939 if (nextp > m->jcodelength)
940 panic("Unexpected end of bytecode");
972 /* wider index for loading, storing and incrementing */
986 case JAVA_LOOKUPSWITCH:
989 nextp = ALIGN((p + 1), 4) + 4;
990 num = code_get_u4(nextp,m);
991 nextp += (code_get_u4(nextp,m)) * 8 + 4;
996 case JAVA_TABLESWITCH:
999 nextp = ALIGN ((p + 1),4);
1000 num = code_get_s4(nextp + 4, m);
1001 num = code_get_s4(nextp + 8, m) - num;
1002 nextp = nextp + 16 + 4 * num;
1005 /*********************/
1007 case JAVA_PUTSTATIC: /* write */
1009 i = code_get_u2(p + 1,m);
1011 constant_FMIref *fr;
1014 fr = class_getconstant(m->class, i, CONSTANT_Fieldref);
1015 LAZYLOADING(fr->class)
1017 fi = class_resolvefield(fr->class,
1024 return 0; /* was NULL */
1026 printf(" PUTSTATIC:");fflush(stdout); utf_display(fi->class->name);printf(".");fflush(stdout);
1027 utf_display(fi->name);printf("\n");fflush(stdout);
1029 fi->xta = xtafldinfoInit(fi);
1030 XTAaddClassInit(m, fi->class,
1031 CLINITS_T,FINALIZE_T,ADDMARKED_F);
1032 if (xtaAddFldClassTypeInfo(fi)) {
1033 m->xta->fldsUsed = add2FldSet(m->xta->fldsUsed, fi, true,false);
1039 case JAVA_GETSTATIC: /* read */
1041 i = code_get_u2(p + 1,m);
1043 constant_FMIref *fr;
1046 fr = class_getconstant(m->class, i, CONSTANT_Fieldref);
1047 LAZYLOADING(fr->class)
1049 fi = class_resolvefield(fr->class,
1056 return 0; /* was NULL */
1059 printf(" GETSTATIC:");fflush(stdout); utf_display(fi->class->name);printf(".");fflush(stdout);
1060 utf_display(fi->name);printf("\n");fflush(stdout);
1062 fi->xta = xtafldinfoInit(fi);
1063 XTAaddClassInit(m, fi->class,
1064 CLINITS_T,FINALIZE_T,ADDMARKED_F);
1065 if (xtaAddFldClassTypeInfo(fi)) {
1066 m->xta->fldsUsed = add2FldSet(m->xta->fldsUsed, fi, false, true);
1074 case JAVA_INVOKESTATIC:
1075 case JAVA_INVOKESPECIAL:
1076 i = code_get_u2(p + 1,m);
1078 constant_FMIref *mr;
1081 mr = class_getconstant(m->class, i, CONSTANT_Methodref);
1082 LAZYLOADING(mr->class)
1083 mi = class_resolveclassmethod( mr->class,
1091 METHINFOt(mi,"INVOKESTAT/SPEC:: ",XTA_DEBUGopcodes)
1092 mi->monoPoly = MONO;
1094 /*---- Handle "leaf" = static, private, final calls-------------*/
1095 if ((opcode == JAVA_INVOKESTATIC)
1096 || (mi->flags & ACC_STATIC)
1097 || (mi->flags & ACC_PRIVATE)
1098 || (mi->flags & ACC_FINAL) )
1100 if (mi->class->classUsed != USED) { /* = NOTUSED or PARTUSED */
1101 XTAaddClassInit(m, mi->class,
1102 CLINITS_T,FINALIZE_T,ADDMARKED_T);
1103 /* Leaf methods are used whether class is or not */
1104 /* so mark class as PARTlyUSED */
1105 mi->class->classUsed = PARTUSED;
1107 /* Add to XTA working list/set of reachable methods */
1108 if (opcode == JAVA_INVOKESTATIC) /* if stmt just for debug tracing */
1109 /* calls , called */
1110 xtaAddCallEdges(m, mi, MONO,
1111 "07addTo INVOKESTATIC ");
1113 xtaAddCallEdges(m, mi, MONO,
1114 "08addTo INVOKESPECIAL ");
1115 } /* end STATIC, PRIVATE, FINAL */
1118 /*---- Handle special <init> calls ---------------------------------------------*/
1120 if (mi->class->classUsed != USED) {
1121 /* XTA special case:
1122 call of super's <init> then
1123 methods of super class not all used */
1125 /*--- <init> ()V is equivalent to "new"
1126 indicating a class is used = instaniated ---- */
1127 if (utf_init==mi->name) {
1128 if ((m->class->super == mi->class)
1129 && (m->descriptor == utf_void__void) )
1131 METHINFOt(mi,"SUPER INIT:",XTA_DEBUGopcodes);
1132 /* super init so class may be only used because of its sub-class */
1133 XTAaddClassInit(m,mi->class,
1134 CLINITS_T,FINALIZE_T,ADDMARKED_F);
1135 if (mi->class->classUsed == NOTUSED) mi->class->classUsed = PARTUSED;
1138 /* since <init> indicates classes is used, then add marked methods, too */
1139 METHINFOt(mi,"NORMAL INIT:",XTA_DEBUGopcodes);
1140 XTAaddClassInit(m, mi->class,
1141 CLINITS_T,FINALIZE_T,ADDMARKED_T);
1143 xtaAddCallEdges(m, mi, MONO,
1145 } /* end just for <init> ()V */
1147 /* <clinit> for class inits do not add marked methods;
1148 class not yet instaniated */
1149 if (utf_clinit==mi->name)
1150 XTAaddClassInit(m, mi->class,
1151 CLINITS_T,FINALIZE_T,ADDMARKED_F);
1153 if (!((utf_init==mi->name))
1154 || (utf_clinit==mi->name)) {
1155 METHINFOt(mi,"SPECIAL not init:",XTA_DEBUGopcodes)
1156 if (mi->class->classUsed !=USED)
1157 mi->class->classUsed = PARTUSED;
1158 xtaAddCallEdges(m, mi, MONO,
1159 "10addTo SPEC notINIT ");
1162 } /* end init'd class not used = class init process was needed */
1164 /* add method to XTA list = set of reachable methods */
1165 xtaAddCallEdges(m, mi, MONO,
1166 "11addTo SPEC whymissed ");
1169 /*** assume if method can't be resolved won't actually be called or
1170 there is a real error in classpath and in normal parse an exception
1171 will be thrown. Following debug print can verify this
1173 CLASSNAME1(mr->class,"CouldNOT Resolve method:",,XTA_DEBUGr);printf(".");fflush(stdout);
1174 utf_display(mr->name); printf(" "); fflush(stdout);
1175 utf_display(mr->descriptor); printf("\n");fflush(stdout);
1180 case JAVA_INVOKEVIRTUAL:
1181 i = code_get_u2(p + 1,m);
1183 constant_FMIref *mr;
1186 mr = m->class->cpinfos[i];
1187 /*mr = class_getconstant(m->class, i, CONSTANT_Methodref)*/
1188 LAZYLOADING(mr->class)
1189 mi = class_resolveclassmethod(mr->class,
1198 METHINFOt(mi,"INVOKEVIRTUAL ::",XTA_DEBUGopcodes);
1199 if ((mi->flags & ACC_STATIC)
1200 || (mi->flags & ACC_PRIVATE)
1201 || (mi->flags & ACC_FINAL) )
1202 { /*** DOES THIS EVER OCCUR ??? */
1203 if (mi->class->classUsed == NOTUSED){
1204 XTAaddClassInit(m, mi->class,
1205 CLINITS_T,FINALIZE_T,ADDMARKED_T);
1207 mi->monoPoly = MONO;
1208 xtaAddCallEdges(m, mi, MONO,
1209 "12addTo INVOKEVIRTUAL ");
1211 else { /* normal virtual */
1212 /* get the set of used subtypes if none at least the current methods class */
1213 classSetNode *subtypesUsedSet = NULL;
1214 if (m->xta->XTAclassSet != NULL) {
1216 intersectSubtypesWithSet(mi->class, m->xta->XTAclassSet->head);
1218 else { /* can any methods be added if 1 set is NULL ??? */
1219 subtypesUsedSet = addElement(subtypesUsedSet, m->class);
1221 mi->monoPoly = POLY;
1222 xtaMarkSubs(m, mi->class, mi, subtypesUsedSet);
1226 CLASSNAME1(mr->class,"CouldNOT Resolve virt meth:",XTA_DEBUGr);printf(".");fflush(stdout);
1227 utf_display(mr->name); printf(" "); fflush(stdout);
1228 utf_display(mr->descriptor); printf("\n");fflush(stdout);
1233 case JAVA_INVOKEINTERFACE:
1234 i = code_get_u2(p + 1,m);
1236 constant_FMIref *mr;
1239 mr = class_getconstant(m->class, i, CONSTANT_InterfaceMethodref);
1240 LAZYLOADING(mr->class)
1242 mi = class_resolveinterfacemethod(mr->class,
1249 METHINFOt(mi,"\tINVOKEINTERFACE: ",XTA_DEBUGopcodes)
1250 xtaMarkInterfaceSubs(m,mi);
1252 /* see INVOKESTATIC for explanation about */
1253 /* case when Interface is not resolved */
1254 /*descriptor2types(mi);
1255 ?? do need paramcnt? for XTA (or just XTA)*/
1260 /* means class is at least passed as a parameter */
1261 /* class is really instantiated when class.<init> called*/
1262 i = code_get_u2(p + 1,m);
1265 cls = class_getconstant(m->class, i, CONSTANT_Class);
1266 /*** s_count++; look for s_counts for VTA */
1267 /* add marked methods */
1268 CLASSNAME(cls,"NEW : do nothing",XTA_DEBUGr);
1269 XTAaddClassInit(m, cls, CLINITS_T, FINALIZE_T,ADDMARKED_T);
1270 m->xta->XTAclassSet = add2ClassSet(m->xta->XTAclassSet,cls );
1274 case JAVA_CHECKCAST:
1275 case JAVA_INSTANCEOF:
1277 i = code_get_u2(p + 1,m);
1281 class_getconstant(m->class, i, CONSTANT_Class);
1283 CLASSNAMEop(cls,XTA_DEBUGr);
1284 if (cls->classUsed == NOTUSED){
1285 XTAaddClassInit(m, cls,
1286 CLINITS_T,FINALIZE_T,ADDMARKED_T);
1287 m->xta->XTAclassSet = add2ClassSet(m->xta->XTAclassSet,cls );
1298 xtaMethodCalls_and_sendReturnType(m);
1303 /* Helper fn for initialize **********************************************/
1305 int XTAgetline(char *line, int max, FILE *inFP) {
1306 if (fgets(line, max, inFP) == NULL)
1309 return strlen((const char *) line);
1312 /* Initialize XTA Work list ***********************************************/
1314 /*-- Get meth ptr for class.meth desc and add to XTA worklist --*/
1315 #define SYSADD(cls,meth,desc, is_mono_poly, txt) \
1316 c = class_new(utf_new_char(cls)); \
1318 callmeth = class_resolveclassmethod(c, \
1319 utf_new_char(meth), \
1320 utf_new_char(desc), \
1323 if (callmeth->class->classUsed != USED) { \
1324 c->classUsed = PARTUSED; \
1325 XTAaddClassInit(callmeth, callmeth->class, \
1326 CLINITS_T,FINALIZE_T,ADDMARKED_T);\
1328 callmeth->monoPoly = is_mono_poly; \
1329 xtaAddCallEdges(NULL, callmeth, is_mono_poly, txt);
1331 /*-- ----------------------------------------------------------------------------
1332 Initialize XTA work list with methods/classes from:
1335 xtaMissedIn list (missed becaused called from NATIVE &/or dynamic calls
1336 -------------------------------------------------------------------------------*/
1337 methodinfo *initializeXTAworklist(methodinfo *m) {
1339 methodinfo* callmeth;
1340 char systxt[] = "2S addTo System Call :";
1341 char missedtxt[] = "2M addTo xtaMissedIn Call :";
1343 FILE *xtaMissedIn; /* Methods missed during previous XTA parse */
1345 char* class, *meth, *desc;
1346 methodinfo *rm =NULL; /* return methodinfo ptr to main method */
1349 /* Create XTA call work list */
1350 xtaWorkList = NEW(list);
1351 list_init(xtaWorkList, OFFSET(xtaNode,linkage) );
1353 /* Add first method to call list */
1354 m->class->classUsed = USED;
1355 xtaAddCallEdges(NULL, m, SYSCALL, systxt);
1357 /* Add system called methods */
1358 /*** SYSADD(mainstring, "main","([Ljava/lang/String;)V", SYSCALL, systxt) ***/
1359 SYSADD(MAINCLASS, MAINMETH, MAINDESC, SYSCALL, systxt)
1361 /*** SYSADD("java/lang/System","exit","(I)V",SYSCALL, systxt) ***/
1362 SYSADD(EXITCLASS, EXITMETH, EXITDESC, SYSCALL, systxt)
1363 /*----- xtaMissedIn 0 */
1364 if ( (xtaMissedIn = fopen("xtaMissedIn0", "r")) == NULL) {
1365 /*if (opt_verbose) */
1366 {printf("No xtaMissedIn0 file\n");fflush(stdout);}
1369 while (XTAgetline(line,256,xtaMissedIn)) {
1370 class = strtok(line, " \n");
1371 meth = strtok(NULL, " \n");
1372 desc = strtok(NULL, " \n");
1373 SYSADD(class,meth,desc, POLY, missedtxt)
1374 /* ??? Need to hand / hard code who calls it ??? */
1376 fclose(xtaMissedIn);
1385 /*- end initializeXTAworklist-------- */
1388 /*-------------------------------------------------------------------------------*/
1389 methodinfo *missedXTAworklist()
1391 FILE *xtaMissedIn; /* Methods missed during previous XTA parse */
1392 char filenameIn[256] = "xtaIn/";
1394 char* class, *meth, *desc;
1396 char* calls_class, *calls_meth, *calls_desc;
1398 char missedtxt[] = "xtaIn/ missed Call :";
1400 methodinfo* callmeth;
1402 methodinfo *rm =NULL; /* return methodinfo ptr to main method */
1405 #if defined(USE_THREADS)
1406 SYSADD(THREADCLASS, THREADMETH, THREADDESC, SYSCALL, "systxt2")
1407 SYSADD(THREADGROUPCLASS, THREADGROUPMETH, THREADGROUPDESC, SYSCALL, "systxt2")
1409 /*----- xtaMissedIn pgm specific */
1410 strcat(filenameIn, (const char *)mainstring);
1411 if ( (xtaMissedIn = fopen(filenameIn, "r")) == NULL) {
1412 /*if (opt_verbose)*/
1413 {printf("No xtaIn/=%s file\n",filenameIn);fflush(stdout);}
1416 while (XTAgetline(line,256,xtaMissedIn)) {
1418 calls_class = strtok(line, " \n");
1419 calls_meth = strtok(NULL, " \n");
1420 calls_desc = strtok(NULL, " \n");
1422 class = strtok(NULL, " \n");
1424 class = strtok(line, " \n");
1425 meth = strtok(NULL, " \n");
1426 desc = strtok(NULL, " \n");
1429 if ((calls_class == NULL) || (calls_meth == NULL) || (calls_desc == NULL)
1430 || (class == NULL) || (meth == NULL) || (desc == NULL))
1432 if ( (class == NULL) || (meth == NULL) || (desc == NULL))
1434 "Error in xtaMissedIn file: Missing a part of calls_class.calls_meth calls calls_desc class.meth desc \n");
1435 SYSADD(class,meth,desc, POLY, missedtxt)
1437 fclose(xtaMissedIn);
1444 /*--------------------------------------------------------*/
1445 /* parseXTAmethod */
1446 /* input: method to be XTA static parsed */
1447 /*--------------------------------------------------------*/
1448 void parseXTAmethod(methodinfo *xta_method) {
1449 if (! ( (xta_method->flags & ACC_NATIVE )
1450 || (xta_method->flags & ACC_ABSTRACT) ) )
1452 /* XTA parse to approxmate....
1453 what classes/methods will really be used during execution */
1454 parseXTA(xta_method);
1457 if (xta_method->flags & ACC_NATIVE )
1459 METHINFOt(xta_method,"TO BE NATIVE XTA PARSED :",XTA_DEBUGopcodes);
1460 /* parseXTApseudo(xta_method); */
1463 printf("Abstract method in XTA Work List: ");
1464 METHINFOx(xta_method);
1465 panic("Abstract method in XTA Work List.");
1470 void XTAprintCallgraph (list *xtaWorkList, char * txt);
1472 /*-- XTA -- *******************************************************/
1473 int XTA_jit_parse(methodinfo *m)
1476 methodinfo *mainmeth;
1478 /* Should only be called once */
1481 /*----- XTA initializations --------*/
1483 log_text("XTA static analysis started.\n");
1485 mainmeth = initializeXTAworklist(m);
1486 /** XTAprintCallgraph (xtaWorkList, "after init1"); **/
1487 firstCall = false; /* turn flag off */
1489 if ( (xtaMissed = fopen("xtaMissed", "w")) == NULL) {
1490 printf("CACAO - xtaMissed file: cant open file to write\n");
1492 /* Note: xtaMissed must be renamed to xtaMissedIn to be used as input */
1494 /*------ process XTA call work list --------*/
1495 for (xta =list_first(xtaWorkList);
1497 xta =list_next(xtaWorkList,xta))
1499 parseXTAmethod(xta->method);
1500 /** XTAprintCallgraph (xtaWorkList, "after an XTA method parse 1"); **/
1502 missedXTAworklist();
1503 /** XTAprintCallgraph (xtaWorkList, "after missed"); **/
1504 for (xta =list_first(xtaWorkList);
1506 xta =list_next(xtaWorkList,xta))
1508 parseXTAmethod(xta->method);
1509 /** XTAprintCallgraph (xtaWorkList, "after an XTA method parse 2"); **/
1515 printf("printXTAhierarchyInfo(m); not yet there\n");
1517 XTAprintCallgraph (xtaWorkList, "After all XTA parses");
1521 log_text("XTA static analysis done.\n");
1527 /*--------------------------------------------------------------*/
1528 void XTAprintCallgraph (list *xtaWorkList, char * txt)
1532 methodinfo *xta_meth;
1534 printf("\n%s\n",txt);
1535 #if defined(STATISTICS)
1536 printf("-*-*-*-*- XTA Callgraph Worklist:<%i>\n",count_methods_marked_used);
1539 for (xta =list_first(xtaWorkList);
1541 xta =list_next(xtaWorkList,xta))
1543 xta_meth = xta->method;
1545 printf(" (%i): ",i++);
1546 method_display_w_class(xta_meth);
1555 * These are local overrides for various environment variables in Emacs.
1556 * Please do not remove this and leave it at the end of the file, where
1557 * Emacs will automagically detect them.
1558 * ---------------------------------------------------------------------
1561 * indent-tabs-mode: t