1 /********************** parseRT.h ******************************************
2 Parser and print functions for Rapid Type Analyis
3 used to only compile methods that may actually be used.
4 ***************************************************************************/
7 #include "parseRTprint.h" /* RTAPRINT trace/info/debug prints */
10 /*------------ global variables -----------------------------------------*/
11 #define MAXCALLGRAPH 5000
13 bool XTAOPTbypass = false;
14 bool XTAOPTbypass2 = false; /* for now invokeinterface */
15 bool XTAOPTbypass3 = false; /* print XTA classsets in stats */
19 int I; /* ASTORE /ALOAD index */
23 int methRTmax=MAXCALLGRAPH;
24 static methodinfo **callgraph;
28 int methXTAlast = -1;;
29 int methXTAmax=MAXCALLGRAPH;
30 static methodinfo **XTAcallgraph;
32 static bool nativecallcompdone=0 ;
34 static bool firstCall= true;
35 static bool AfterMain = false;
36 static FILE *rtMissed; /* Methods missed during RTA parse of Main */
37 /* so easier to build dynmanic calls file */
39 static utf *utf_MAIN; /* utf_new_char("main"); */
40 static utf *INIT ; /* utf_new_char("<init>"); */
41 static utf *CLINIT ; /* utf_new_char("<clinit>"); */
42 static utf *FINALIZE; /* utf_new_char("finalize"); */
43 static utf *EMPTY_DESC; /* utf_new_char("V()"); */
44 static int missedCnt = 0;
46 #include "jit/parseRTstats.h"
48 /*--------------------------------------------------------------*/
49 /* addToCallgraph - adds to RTA callgraph and */
50 /* sets meth->methodUsed to USED */
51 /*--------------------------------------------------------------*/
52 #define ADDTOCALLGRAPH(meth) if ((meth->methodUsed != USED) && (!(meth->flags & ACC_ABSTRACT)) ) { \
53 callgraph[++methRTlast] = meth ; \
54 meth->methodUsed = USED; \
56 {printf("\n Added to Call Graph #%i:", \
58 printf("\t <used flags c/m> <%i/%i> %i\t", \
59 meth->class->classUsed, \
62 printf(" method name ="); \
63 utf_display(meth->class->name);printf("."); \
64 method_display(meth);fflush(stdout);} \
68 /*--------------------------------------------------------------*/
69 bool rtaSubUsed(classinfo *class, methodinfo *meth) {
72 for (subs=class->sub; subs != NULL; subs = subs->nextsub) {
73 if (subs->classUsed == USED) {
74 if (class_findmethod(class, meth->name, meth->descriptor) == NULL)
79 if (rtaSubUsed(subs, meth))
86 /*--------------------------------------------------------------*/
87 /* Mark the method with same name /descriptor in topmethod */
90 /* Class not marked USED and method defined in this class -> */
91 /* -> if Method NOTUSED mark method as MARKED */
92 /* Class marked USED and method defined in this class -> */
93 /* -> mark method as USED */
95 /* Class USED, but method not defined in this class -> */
96 /* -> search up the heirarchy and mark method where defined */
97 /* if class where method is defined is not USED -> */
98 /* -> mark class with defined method as PARTUSED */
99 /*--------------------------------------------------------------*/
101 void rtaMarkMethod(classinfo *class, methodinfo *topmethod) {
103 utf *name = topmethod -> name;
104 utf *descriptor = topmethod -> descriptor;
107 submeth = class_resolvemethod(class, name, descriptor);
109 panic("parse RT: Method not found in class hierarchy");
110 if (submeth->methodUsed == USED) return;
112 if (submeth->class == class) {
114 /*--- Method defined in class -----------------------------*/
115 if (submeth->class->classUsed != USED) {
116 if (submeth->methodUsed == NOTUSED) {
118 /* Class NOT marked USED and method defined in this class -> */
119 /* -> if Method NOTUSED mark method as MARKED */
120 if (pWhenMarked >= 1) {
121 printf("MARKED class.method\t");
122 utf_display(submeth->class->name);printf(".");method_display(submeth);
124 if (rtaSubUsed(submeth->class,submeth)) {
125 submeth->class->classUsed = PARTUSED;
126 ADDTOCALLGRAPH(submeth)
129 submeth->methodUsed = MARKED;
134 /* Class IS marked USED and method defined in this class -> */
135 /* -> mark method as USED */
136 ADDTOCALLGRAPH(submeth)
138 } /* end defined in class */
141 /*--- Method NOT defined in class -----------------------------*/
142 if (submeth->class->classUsed == NOTUSED) {
143 submeth->class->classUsed = PARTUSED;
144 if (class->classUsed != USED) {
145 submeth->methodUsed = MARKED;
148 if ( (submeth->class->classUsed == USED)
149 || (class->classUsed == USED)) {
150 ADDTOCALLGRAPH(submeth)
152 } /* end NOT defined in class */
155 /*-------------------------------------------------------------------------------*/
156 /* Mark the method with the same name and descriptor as topmethod */
157 /* and any subclass where the method is defined and/or class is used */
159 /*-------------------------------------------------------------------------------*/
160 void rtaMarkSubs(classinfo *class, methodinfo *topmethod) {
162 rtaMarkMethod(class, topmethod); /* Mark method in class where it was found */
163 if (class->sub != NULL) {
166 if (!(topmethod->flags & ACC_FINAL )) {
167 for (subs = class->sub;subs != NULL;subs = subs->nextsub) {
169 rtaMarkSubs(subs, topmethod);
176 /*-------------------------------------------------------------------------------*/
177 /* Add Marked methods for input class ci */
178 /* Add methods with the same name and descriptor as implemented interfaces */
179 /* with the same method name */
181 /*-------------------------------------------------------------------------------*/
182 void addMarkedMethods(classinfo *ci) {
185 /* add marked methods to callgraph */
186 for (ii=0; ii<ci->methodscount; ii++) {
187 methodinfo *mi = &(ci->methods[ii]);
188 if (mi->methodUsed == MARKED) {
189 if (pWhenMarked >= 1) {
190 printf("ADDED a method that was MARKED\n");
196 for (jj=0; jj < ci -> interfacescount; jj++) {
197 classinfo *ici = ci -> interfaces [jj];
198 /* use resolve method....!!!! */
199 if (ici -> classUsed != NOTUSED) {
200 for (mm=0; mm< ici->methodscount; mm++) {
201 methodinfo *imi = &(ici->methods[mm]);
203 if ( (imi->methodUsed == USED)
204 && ( (imi->name == mi->name)
205 && (imi->descriptor == mi->descriptor))) {
206 if (pWhenMarked >= 1)
207 printf("ADDED a method that was used by an interface\n");
216 /*-------------------------------------------------------------------------------*/
218 /*-------------------------------------------------------------------------------*/
219 bool xtaPassParams (methodinfo *SmCalled, methodinfo *SmCalls, methSetNode *lastptrInto) {
228 printf("\n>>>>>>>>>>>>>>>>><<<xtaPassParams \n");fflush(stdout);
230 printf("\tIN SmCalled set : ");
231 utf_display(SmCalled->class->name);printf("."); method_display(SmCalled);
232 printClassSet(SmCalled->xta->XTAclassSet); printf("\n");
234 printf("\tIN SmCalls set: ");
235 utf_display(SmCalls->class->name);printf("."); method_display(SmCalls);
236 printClassSet(SmCalls->xta->XTAclassSet); printf("\n");
238 printf("\tIN lastptrInto : (");
239 if (lastptrInto->lastptrIntoClassSet2 != NULL) {
240 utf_display(lastptrInto->lastptrIntoClassSet2->classType->name); printf(") ");
242 else {printf("NULL) ");}
244 utf_display(lastptrInto->methRef->class->name);printf("."); fflush(stdout);
245 method_display(lastptrInto->methRef); fflush(stdout);
246 printf("\n");fflush(stdout);
249 /* Get SmCalled ParamType set if null */
250 if (SmCalled->xta->paramClassSet == NULL) {
251 SmCalled->xta->paramClassSet = descriptor2typesL(SmCalled);
254 printf("\tParamPassed\n"); fflush(stdout);
255 printSet(SmCalled->xta->paramClassSet);fflush(stdout);
256 printf("\n"); fflush(stdout);
259 if (lastptrInto->lastptrIntoClassSet2 == NULL) {
260 if (SmCalls->xta->XTAclassSet != NULL)
261 c1 = SmCalls->xta->XTAclassSet->head;
266 /* start with type where left off */
267 c1 = lastptrInto->lastptrIntoClassSet2;
268 c1 = c1 -> nextClass; /* even if NULL */
273 printf("\tIN SmCalls ... start with NULL\n"); fflush(stdout);
276 printf("\tIN SmCalls ... start with :");fflush(stdout);
277 utf_display(c1->classType->name); printf("\n");
281 /* for each Param Class */
282 for ( p=SmCalled->xta->paramClassSet; p != NULL; p = p->nextClass) {
284 /* for each SmCalls class */
285 for (c=c1; c != NULL; c = c->nextClass) {
286 vftbl *p_cl_vt = p->classType->vftbl;
287 vftbl *c_cl_vt = c->classType->vftbl;
289 /* if SmCalls class is in the Params Class range */
290 if ( (p_cl_vt->baseval <= c_cl_vt->baseval)
291 && (c_cl_vt->baseval <= (p_cl_vt->baseval+p_cl_vt->diffval)) ) {
293 /* add SmCalls class to SmCalledBy Class set */
294 SmCalled->xta->XTAclassSet = SmCalled->xta->XTAclassSet = add2ClassSet(SmCalled->xta->XTAclassSet, c->classType);
300 lastptrInto->lastptrIntoClassSet2 = cprev;
302 printf("\tOUT SmCalled set: ");fflush(stdout);
303 printClassSet(SmCalled->xta->XTAclassSet);fflush(stdout);
305 printf("\tOUT SmCalls set: ");fflush(stdout);
306 printClassSet(SmCalls->xta->XTAclassSet);fflush(stdout);
308 printf("\tOUT lastptrInto="); fflush(stdout);
309 if (lastptrInto->lastptrIntoClassSet2 != NULL)
310 utf_display(lastptrInto->lastptrIntoClassSet2->classType->name);
312 printf("<rc=%i>\n",rc);fflush(stdout);
317 /*-------------------------------------------------------------------------------*/
318 bool xtaPassReturnType(methodinfo *SmCalled, methodinfo *SmCalls) {
325 printf("xtaPassReturnType \n");
327 /* Get SmCalled return class is null */
328 if ((SmCalled->returnclass == NULL) && (SmCalled->xta->paramClassSet == NULL)) {
329 SmCalled->xta->paramClassSet = descriptor2typesL(SmCalled);
332 if (SmCalled->returnclass == NULL) {
334 printf("\tReturn type is NULL\n");
339 printf("\tReturn type is: ");
340 utf_display(SmCalled->returnclass->name);
343 printf("\tIN SmCalls set: ");
344 utf_display(SmCalls->class->name); printf("."); method_display(SmCalls);
345 printClassSet(SmCalls->xta->XTAclassSet);
347 printf("\tIN SmCalled set: ");
348 utf_display(SmCalled->class->name); printf("."); method_display(SmCalled);
349 printClassSet(SmCalled->xta->XTAclassSet);
353 if (SmCalled->xta->XTAclassSet == NULL)
356 cs1 = SmCalled->xta->XTAclassSet->head;
357 for (cs =cs1; cs != NULL; cs = cs->nextClass) {
358 classinfo *c = cs->classType;
359 vftbl *r_cl_vt = SmCalled->returnclass->vftbl;
360 vftbl *c_cl_vt = c->vftbl;
362 /* if class is a subtype of the return type, then add to SmCalls class set (ie.interscection)*/
363 if ( (r_cl_vt->baseval <= r_cl_vt->baseval)
364 && (c_cl_vt->baseval <= (r_cl_vt->baseval+r_cl_vt->diffval)) ) {
365 SmCalls->xta->XTAclassSet = add2ClassSet(SmCalls->xta->XTAclassSet, c);
371 printf("\tOUT SmCalls set: ");
372 printClassSet(SmCalls->xta->XTAclassSet);
377 /*-------------------------------------------------------------------------------*/
378 void xtaAddCallEdges(methodinfo *mi, s4 monoPoly) {
380 if (mi->xta->XTAmethodUsed != USED) { /* if static method not in callgraph */
381 XTAcallgraph[++methXTAlast] = mi;
382 mi->xta->XTAmethodUsed = USED;
386 rt_method->xta->calls = add2MethSet(rt_method->xta->calls, mi);
387 rt_method->xta->calls->tail->monoPoly = monoPoly;
388 mi->xta->calledBy = add2MethSet(mi->xta->calledBy, rt_method);
389 if (mi->xta->calledBy == NULL) panic("mi->xta->calledBy is NULL!!!");
390 if (rt_method->xta->calls == NULL) panic("rt_method->xta->calls is NULL!!!");
394 /*--------------------------------------------------------------*/
395 bool xtaSubUsed(classinfo *class, methodinfo *meth, classSetNode *subtypesUsedSet) {
398 for (subs=class->sub; subs != NULL; subs = subs->nextsub) {
400 if (inSet(subtypesUsedSet,subs)) {
401 if (class_findmethod(class, meth->name, meth->descriptor) == NULL)
406 if (xtaSubUsed(subs, meth, subtypesUsedSet))
413 /*-------------------------------------------------------------------------------*/
414 void xtaMarkMethod(classinfo *class, methodinfo *topmethod, classSetNode *subtypesUsedSet)
419 utf *name = topmethod -> name;
420 utf *descriptor = topmethod -> descriptor;
421 printf("xtaMarkMethod for:"); utf_display(class->name);fflush(stdout);
422 method_display(topmethod);
423 submeth = class_resolvemethod(class, name, descriptor);
424 printf(" def: "); utf_display(submeth->class->name);fflush(stdout);
425 method_display(submeth);
430 panic("parse XTA: Method not found in class hierarchy");
432 if (rt_method->xta->calls != NULL) {
433 if (inMethSet(rt_method->xta->calls->head,submeth)) return;
436 if (submeth->class == class) {
438 /*--- Method defined in class -----------------------------*/
439 if (inSet(subtypesUsedSet,submeth->class)) {
440 xtaAddCallEdges(submeth,POLY);
443 if (subtypesUsedSet != NULL) {
444 if (xtaSubUsed (class,submeth,subtypesUsedSet)) {
445 xtaAddCallEdges(submeth,POLY);
449 rt_method->xta->marked = add2MethSet(rt_method->xta->marked, submeth);
454 /*--- Method NOT defined in class -----------------------------*/
455 if (!(inSet(subtypesUsedSet,submeth->class) )){ /* class with method def is not used */
456 if (!(inSet(subtypesUsedSet,class) )) { /* class currently resolving is not used */
457 rt_method->xta->marked = add2MethSet(rt_method->xta->marked, submeth);
458 /*printf("Added to marked Set: "); fflush(stdout);printMethodSet(rt_method->xta->marked);*/
461 if ( (inSet(subtypesUsedSet,submeth->class)) /* class with method def is used */
462 || (inSet(subtypesUsedSet,class)) ) { /* class currently resolving is used */
463 xtaAddCallEdges(submeth,POLY);
466 } /* end defined in class */
469 /*-------------------------------------------------------------------------------*/
470 void xtaMarkSubs(classinfo *class, methodinfo *topmethod, classSetNode *subtypesUsedSet) {
471 /* xtaPRINTmarkSubs1*/
472 xtaMarkMethod(class, topmethod,subtypesUsedSet); /* Mark method in class where it was found */
473 if (class->sub != NULL) {
476 if (!(topmethod->flags & ACC_FINAL )) {
477 for (subs = class->sub; subs != NULL; subs = subs->nextsub) {
478 /* xtaPRINTmarkSubs1 */
479 xtaMarkSubs(subs, topmethod, subtypesUsedSet);
486 /*-------------------------------------------------------------------------------*/
487 /*-------------------------------------------------------------------------------*/
489 int addClassInit(classinfo *ci) {
490 /* CHANGE to a kind of table look-up for a list of class/methods (currently 3)
493 utf* utf_java_lang_system = utf_new_char("java/lang/System");
494 utf* utf_initializeSystemClass = utf_new_char("initializeSystemClass");
495 utf* utf_java_lang_Object = utf_new_char("java/lang/Object");
497 int m, m1=-1, m2=-1, mf=-1;
500 for (m=0; m < ci->methodscount; m++) {
501 /*<clnit> class init method */
502 if (ci->methods[m].name == CLINIT) {
505 /* Special case: System class has an extra initializer method */
506 if ((utf_java_lang_system == ci->name)
507 && (utf_initializeSystemClass == ci->methods[m].name)) {
511 /* Finalize methods */
512 if ((ci->methods[m].name == FINALIZE)
513 && (ci->name != utf_java_lang_Object)) {
519 if (m1 >= 0) { /* No <clinit> available - ignore */
521 /* Get clinit methodinfo ptr */
522 mi = class_findmethod (ci,ci->methods[m1].name , NULL);
525 if ( mi->methodUsed != USED) {
526 mi->class->classUsed = PARTUSED;
531 if ((XTAOPTbypass) || (opt_xta)) {
532 xtaAddCallEdges(mi,MONO);
539 /* Get finalize methodinfo ptr */
540 mi = class_findmethod (ci,ci->methods[mf].name , NULL);
543 if ( mi->methodUsed != USED) {
544 mi->class->classUsed = PARTUSED;
549 if ((XTAOPTbypass) || (opt_xta)) {
550 xtaAddCallEdges(mi,MONO);
554 /*Special Case for System class init:
555 add java/lang/initializeSystemClass to callgraph */
557 /* Get clinit methodinfo ptr */
558 mi = class_findmethod (ci,ci->methods[m2].name , NULL);
561 if ( mi->methodUsed != USED) {
562 mi->class->classUsed = PARTUSED;
567 if ((XTAOPTbypass) || (opt_xta)) {
568 xtaAddCallEdges(mi,MONO);
572 /* add marked methods to callgraph */
573 addMarkedMethods(ci);
579 #define rt_code_get_u1(p) rt_jcode[p]
580 #define rt_code_get_s1(p) ((s1)rt_jcode[p])
581 #define rt_code_get_u2(p) ((((u2)rt_jcode[p])<<8)+rt_jcode[p+1])
582 #define rt_code_get_s2(p) ((s2)((((u2)rt_jcode[p])<<8)+rt_jcode[p+1]))
583 #define rt_code_get_u4(p) ((((u4)rt_jcode[p])<<24)+(((u4)rt_jcode[p+1])<<16)\
584 +(((u4)rt_jcode[p+2])<<8)+rt_jcode[p+3])
585 #define rt_code_get_s4(p) ((s4)((((u4)rt_jcode[p])<<24)+(((u4)rt_jcode[p+1])<<16)\
586 +(((u4)rt_jcode[p+2])<<8)+rt_jcode[p+3]))
590 /*-------------------------------------------------------------------------------*/
591 /*xx*/ void addUsedInterfaceMethods(classinfo *ci) {
594 /* add used interfaces methods to callgraph */
595 for (jj=0; jj < ci -> interfacescount; jj++) {
596 classinfo *ici = ci -> interfaces [jj];
598 if (pWhenMarked >= 1) {
599 printf("BInterface used: ");fflush(stdout);
600 utf_display(ici->name);
601 printf("<%i>\t",ici -> classUsed ); fflush(stdout);
602 if (ici -> classUsed == NOTUSED) printf("\t classUsed=NOTUSED\n" );
603 if (ici -> classUsed == USED) printf("\t classUsed=USED\n");
604 if (ici -> classUsed == PARTUSED) printf("\t classUsed=PARTUSED\n");
607 /* add class to interfaces list of classes that implement it */
608 ici -> impldBy = addElement(ici -> impldBy, ci);
610 /* if interface class is used */
611 if (ici -> classUsed != NOTUSED) {
613 /* for each interface method implementation that has already been used */
614 for (mm=0; mm< ici->methodscount; mm++) {
615 methodinfo *imi = &(ici->methods[mm]);
616 if (pWhenMarked >= 1) {
617 if (imi->methodUsed != USED) {
618 if (imi->methodUsed == NOTUSED) printf("Interface Method notused: ");
619 if (imi->methodUsed == MARKED) printf("Interface Method marked: ");
620 utf_display(ici->name);printf(".");method_display(imi);fflush(stdout);
623 if (imi->methodUsed == USED) {
624 if (pWhenMarked >= 1) {
625 printf("Interface Method used: "); utf_display(ici->name);printf(".");method_display(imi);fflush(stdout);
627 /* Mark this method used in the (used) implementing class and its subclasses */
628 printf("MAY ADD methods that was used by an interface\n");
637 /*-------------------------------------------------------------------------------*/
638 /*-------------------------------------------------------------------------------*/
641 /*-------------------------------------------------------------------------------*/
642 void xtaMarkInterfaceSubs(methodinfo *mCalled) {
645 /* for every class that implements the interface of the method called */
646 for (Si = mCalled->class->impldBy; Si != NULL; Si = Si->nextClass) {
647 /* add all definitions of this method for this interface */
650 submeth = class_findmethod(Si->classType, mCalled->name, mCalled->descriptor);
651 if (submeth == NULL) ; /* search up the heir - ignore for now!!! */
653 classSetNode *subtypesUsedSet = NULL;
655 if (rt_method->xta->XTAclassSet != NULL)
656 subtypesUsedSet = intersectSubtypesWithSet(submeth->class, rt_method->xta->XTAclassSet->head);
658 printf(" \nXTA subtypesUsedSet: "); fflush(stdout);
659 printSet(subtypesUsedSet);
660 xtaMarkSubs(submeth->class, submeth, subtypesUsedSet);
665 /*-------------------------------------------------------------------------------*/
666 bool xtaAddFldClassTypeInfo(fieldinfo *fi) {
670 if (fi->xta->fieldChecked) {
671 if (fi->xta->fldClassType != NULL)
672 return true; /* field has a class type */
676 fi->xta->fieldChecked = true;
678 if (fi->type == TYPE_ADDRESS) {
679 char *utf_ptr = fi->descriptor->text; /* current position in utf text */
681 if (*utf_ptr != 'L') {
682 while (*utf_ptr++ =='[') ;
685 if (*utf_ptr =='L') {
687 if (fi->xta->fldClassType== NULL) {
692 desc = MNEW (char, 256);
693 strcpy (desc,++utf_ptr);
694 cname = strtok(desc,";");
696 printf("STATIC field's type is: %s\n",cname);
699 class = class_get(utf_new_char(cname));
700 fi->xta->fldClassType= class; /* save field's type class ptr */
707 /*-------------------------------------------------------------------------------*/
708 void xtaPassFldPUT(fldSetNode *fN)
710 /* Field type is a class */
712 classSetNode *c1 = NULL;
713 classSetNode *cp = NULL;
714 classSetNode *cprev= NULL;
722 /* Use lastptr so don't check whole XTA class set each time */
725 if (cp->nextClass != NULL)
726 c1 = cp -> nextClass;
729 if (rt_method->xta->XTAclassSet != NULL)
730 c1 = rt_method->xta->XTAclassSet->head;
733 printf("rt XTA class set =");fflush(stdout);
734 printClassSet(rt_method->xta->XTAclassSet);
735 printf("\t\tField class type = ");fflush(stdout);
736 utf_display(fi->xta->fldClassType->name); printf("\n");
740 /*--- PUTSTATIC specific ---*/
741 /* Sx = intersection of type+subtypes(field x) */
742 /* and Sm (where putstatic code is) */
743 for (c=c1; c != NULL; c=c->nextClass) {
744 vftbl *f_cl_vt = fi->xta->fldClassType->vftbl;
745 vftbl *c_cl_vt = c-> classType->vftbl;
747 printf("\tXTA class = ");fflush(stdout);
748 utf_display(c->classType->name);
749 printf("<b=%i> ",c_cl_vt->baseval); fflush(stdout);
750 if (c->nextClass == NULL) {
751 printf("next=NULL ");fflush(stdout);
754 printf("next="); fflush(stdout);
755 utf_display(c->nextClass->classType->name);
756 printf("\n"); fflush(stdout);
759 printf("\t\tField class type = ");fflush(stdout);
760 utf_display(fi->xta->fldClassType->name);
761 printf("<b=%i/+d=%i> \n",f_cl_vt->baseval,(f_cl_vt->baseval+f_cl_vt->diffval)); fflush(stdout);
764 if ((f_cl_vt->baseval <= c_cl_vt->baseval)
765 && (c_cl_vt->baseval <= (f_cl_vt->baseval+f_cl_vt->diffval)) ) {
766 fi->xta->XTAclassSet = add2ClassSet(fi->xta->XTAclassSet,c->classType);
770 fN->lastptrPUT = cprev;
772 /*-------------------------------------------------------------------------------*/
773 void xtaPassFldGET(fldSetNode *fN)
775 /* Field type is a class */
777 classSetNode *c1 = NULL;
778 classSetNode *cp = NULL;
779 classSetNode *cprev= NULL;
787 /* Use lastptr so don't check whole XTA class set each time */
790 if (cp->nextClass != NULL)
791 c1 = cp -> nextClass;
794 if (fi->xta->XTAclassSet != NULL)
795 c1 = fi->xta->XTAclassSet->head;
798 printf("fld XTA class set =");fflush(stdout);
799 printClassSet(fi->xta->XTAclassSet);
800 printf("\t\tField class type = ");fflush(stdout);
801 utf_display(fi->xta->fldClassType->name); printf("\n");
805 /*--- GETSTATIC specific ---*/
806 /* Sm = union of Sm and Sx */
807 for (c=c1; c != NULL; c=c->nextClass) {
809 if (rt_method->xta->XTAclassSet ==NULL)
812 if (!(inSet (rt_method->xta->XTAclassSet->head, c->classType) ))
816 rt_method->xta->XTAclassSet
817 = add2ClassSet(rt_method->xta->XTAclassSet,c->classType);
822 fN->lastptrGET = cprev;
826 /*-------------------------------------------------------------------------------*/
827 void xtaPassAllCalledByParams () {
828 methSetNode *SmCalled;
831 printf("xta->calledBy method set: "); fflush(stdout);
832 printMethodSet(rt_method->xta->calledBy); fflush(stdout);
834 if (rt_method->xta->calledBy == NULL)
837 s1 = rt_method->xta->calledBy->head;
838 for (SmCalled=s1; SmCalled != NULL; SmCalled = SmCalled->nextmethRef) {
840 printf("SmCalled = "); fflush(stdout);
841 utf_display(SmCalled->methRef->class->name); fflush(stdout);
842 printf(".");fflush(stdout); method_display(SmCalled->methRef);
845 rt_method->xta->chgdSinceLastParse = false;
846 xtaPassParams(rt_method, SmCalled->methRef,SmCalled); /* chg flag output ignored for 1st regular parse */
850 /*-------------------------------------------------------------------------------*/
851 void xtaAllFldsUsed ( ){
854 /* bool chgd = false */
856 if (rt_method->xta->fldsUsed == NULL) return;
858 /* for each field that this method uses */
859 f1 = rt_method->xta->fldsUsed->head;
861 for (f=f1; f != NULL; f = f->nextfldRef) {
869 /*-------------------------------------------------------------------------------*/
870 void xtaMethodCalls_and_sendReturnType()
872 methSetNode *SmCalled; /* for return type */
873 methSetNode *SmCalls; /* for calls param types */
874 methSetNode *s1=NULL;
877 printf("calls method set Return type: ");
878 printMethodSet(rt_method->xta->calls);
879 printf("AAAAAAAAAAAAAAFTER printMethSett(rt_method->xta->calls)\n");fflush(stdout);
883 /* for each method that this method calls */
884 if (rt_method->xta->calls == NULL)
887 s1 = SmCalls=rt_method->xta->calls->head;
889 for (SmCalls=s1; SmCalls != NULL; SmCalls = SmCalls->nextmethRef) {
890 /* pass param types */
892 chgd = xtaPassParams (SmCalls->methRef, rt_method, SmCalls);
893 /* if true chgd after its own parse */
894 if (!(SmCalls->methRef->xta->chgdSinceLastParse)) {
895 SmCalls->methRef->xta->chgdSinceLastParse = true;
899 /* for each calledBy method */
900 /* send return type */
901 if (rt_method->xta->calledBy == NULL)
904 s1 = rt_method->xta->calledBy->head;
905 for (SmCalled=s1; SmCalled != NULL; SmCalled = SmCalled->nextmethRef) {
908 printf("\tSmCalled = ");fflush(stdout); utf_display(SmCalled->methRef->class->name);
909 printf("."); method_display(SmCalled->methRef);
912 chgd = xtaPassReturnType(rt_method, SmCalled->methRef);
913 if (!(SmCalled->methRef->xta->chgdSinceLastParse)) {
914 SmCalled->methRef->xta->chgdSinceLastParse = chgd;
920 /*-------------------------------------------------------------------------------*/
921 static void parseRT()
923 int p; /* java instruction counter */
924 int nextp; /* start of next java instruction */
925 int opcode; /* java opcode */
926 int i; /* temporary for different uses (counters) */
927 bool iswide = false; /* true if last instruction was a wide */
931 if ( ((XTAOPTbypass) || (opt_xta)) && (rt_method->name != utf_MAIN)) {
933 xtaPassAllCalledByParams ();
936 /* scan all java instructions */
938 for (p = 0; p < rt_jcodelength; p = nextp) {
939 opcode = rt_code_get_u1 (p); /* fetch op code */
942 nextp = p + jcommandsize[opcode]; /* compute next instruction start */
945 /*--------------------------------*/
946 /* Code just to get the correct next instruction */
985 /* wider index for loading, storing and incrementing */
999 /* table jumps ********************************/
1001 case JAVA_LOOKUPSWITCH:
1004 nextp = ALIGN((p + 1), 4);
1005 num = rt_code_get_u4(nextp + 4);
1006 nextp = nextp + 8 + 8 * num;
1011 case JAVA_TABLESWITCH:
1014 nextp = ALIGN ((p + 1),4);
1015 num = rt_code_get_s4(nextp + 4);
1016 num = rt_code_get_s4(nextp + 8) - num;
1017 nextp = nextp + 16 + 4 * num;
1021 /*-------------------------------*/
1022 case JAVA_PUTSTATIC:
1023 i = rt_code_get_u2(p + 1);
1025 constant_FMIref *fr;
1028 fr = class_getconstant (rt_class, i, CONSTANT_Fieldref);
1029 /* descr has type of field ref'd */
1030 fi = class_findfield (fr->class,fr->name, fr->descriptor);
1031 RTAPRINT03putstatic1
1034 /* class with field - marked in addClassinit */
1035 addClassInit(fr->class);
1038 if ((XTAOPTbypass) || (opt_xta))
1040 if (xtaAddFldClassTypeInfo(fi)) {
1041 rt_method->xta->fldsUsed = add2FldSet(rt_method->xta->fldsUsed, fi, true,false);
1047 case JAVA_GETSTATIC:
1048 i = rt_code_get_u2(p + 1);
1050 constant_FMIref *fr;
1053 fr = class_getconstant (rt_class, i, CONSTANT_Fieldref);
1054 /* descr has type of field ref'd */
1055 fi = class_findfield (fr->class,fr->name, fr->descriptor);
1056 RTAPRINT03putstatic1
1059 /* class with field - marked in addClassinit */
1060 addClassInit(fr->class);
1063 if ((XTAOPTbypass) || (opt_xta) )
1065 if (xtaAddFldClassTypeInfo(fi)) {
1066 rt_method->xta->fldsUsed = add2FldSet(rt_method->xta->fldsUsed, fi, false, true);
1074 /*-------------------- method invocation ---------------------*/
1076 case JAVA_INVOKESTATIC:
1077 i = rt_code_get_u2(p + 1);
1079 constant_FMIref *mr;
1082 mr = class_getconstant (rt_class, i, CONSTANT_Methodref);
1083 mi = class_findmethod (mr->class, mr->name, mr->descriptor);
1085 RTAPRINT04invokestatic1
1086 if (mi->class->classUsed == NOTUSED) {
1087 mi->class->classUsed = USED;
1088 RTAPRINT05invokestatic2
1090 addClassInit(mi->class);
1095 if ((XTAOPTbypass) || (opt_xta)) {
1096 xtaAddCallEdges(mi,MONO);
1101 case JAVA_INVOKESPECIAL:
1102 i = rt_code_get_u2(p + 1);
1104 constant_FMIref *mr;
1108 mr = class_getconstant (rt_class, i, CONSTANT_Methodref);
1109 mi = class_findmethod (mr->class, mr->name, mr->descriptor);
1111 RTAPRINT06invoke_spec_virt1
1112 /*--- PRIVATE Method -----------------------------------------------------*/
1113 if (mi->name != INIT) { /* if method called is PRIVATE */
1114 RTAPRINT07invoke_spec_virt2
1115 RTAPRINT04invokestatic1
1116 /*-- RTA --*/ /* was just markSubs(mi); */
1120 if ((XTAOPTbypass) || (opt_xta)) {
1121 xtaAddCallEdges(mi,MONO);
1126 /*--- Test for super <init> which is: <init> calling its super class <init> -*/
1128 /* new class so add marked methods */
1129 if (( mi->methodUsed != USED) || (mi->class->classUsed == PARTUSED)) {
1130 /*--- process NORMAL <init> method ---------------------------------------------*/
1131 if ( mi->methodUsed != USED) {
1133 - mark class as USED and <init> to callgraph */
1136 ci->classUsed = USED;
1137 addMarkedMethods(ci); /* add to callgraph marked methods */
1138 RTAPRINT06Binvoke_spec_init
1139 addUsedInterfaceMethods(ci);
1143 if ((XTAOPTbypass) || (opt_xta)) {
1144 rt_method->xta->XTAclassSet = add2ClassSet(rt_method->xta->XTAclassSet,ci );
1145 xtaAddCallEdges(mi,MONO);
1146 RTAPRINT06CXTAinvoke_spec_init1
1156 case JAVA_INVOKEVIRTUAL:
1157 i = rt_code_get_u2(p + 1);
1159 constant_FMIref *mr;
1162 mr = class_getconstant (rt_class, i, CONSTANT_Methodref);
1163 mi = class_findmethod (mr->class, mr->name, mr->descriptor);
1166 RTAPRINT07invoke_spec_virt2
1167 mi->monoPoly = POLY;
1168 rtaMarkSubs(mi->class,mi);
1171 if ((XTAOPTbypass) || (opt_xta)) {
1172 classSetNode *subtypesUsedSet = NULL;
1173 if (rt_method->xta->XTAclassSet != NULL)
1174 subtypesUsedSet = intersectSubtypesWithSet(mi->class, rt_method->xta->XTAclassSet->head);
1176 printf(" \nXTA subtypesUsedSet: "); fflush(stdout);
1177 printSet(subtypesUsedSet);
1179 xtaMarkSubs(mi->class, mi, subtypesUsedSet);
1184 case JAVA_INVOKEINTERFACE:
1185 i = rt_code_get_u2(p + 1);
1187 constant_FMIref *mr;
1191 mr = class_getconstant (rt_class, i, CONSTANT_InterfaceMethodref);
1192 mi = class_findmethod (mr->class, mr->name, mr->descriptor);
1194 if (mi->flags & ACC_STATIC)
1195 panic ("Static/Nonstatic mismatch calling static method");
1198 RTAPRINT08AinvokeInterface0
1199 if (mi->class->classUsed == NOTUSED) {
1200 mi->class->classUsed = USED; /*??PARTUSED;*/
1201 class_java_lang_Object->impldBy = addElement(class_java_lang_Object -> impldBy, mi->class);
1204 /* add interface class to list kept in Object */
1205 mi->methodUsed = USED;
1206 mi->monoPoly = POLY;
1208 subs = mi->class->impldBy;
1209 RTAPRINT08invokeInterface1
1210 while (subs != NULL) {
1211 classinfo * isubs = subs->classType;
1212 RTAPRINT09invokeInterface2
1213 /* Mark method (mark/used) in classes that implement the method */
1214 if (isubs->classUsed != NOTUSED) {
1215 methodinfo *submeth;
1217 submeth = class_findmethod(isubs,mi->name, mi->descriptor);
1218 if (submeth != NULL)
1219 submeth->monoPoly = POLY; /* poly even if nosubs */
1220 rtaMarkSubs(isubs, mi);
1222 subs = subs->nextClass;
1226 if ((XTAOPTbypass2) || (opt_xta))
1228 xtaMarkInterfaceSubs(mi);
1233 /* miscellaneous object operations *******/
1236 i = rt_code_get_u2 (p+1);
1240 ci = class_getconstant (rt_class, i, CONSTANT_Class);
1241 if (pWhenMarked >= 1) {
1242 printf("\tclass=");fflush(stdout);
1243 utf_display(ci->name); fflush(stdout);
1244 printf("=\n");fflush(stdout);
1247 if (ci->classUsed != USED) {
1249 ci->classUsed = USED; /* add to heirarchy */
1250 /* Add this class to the implemented by list of the abstract interface */
1251 addUsedInterfaceMethods(ci);
1255 if ((XTAOPTbypass) || (opt_xta))
1257 rt_method->xta->XTAclassSet = add2ClassSet(rt_method->xta->XTAclassSet,ci ); /*XTA*/
1271 if (p != rt_jcodelength)
1272 panic("Command-sequence crosses code-boundary");
1274 if ((XTAOPTbypass) || (opt_xta))
1275 xtaMethodCalls_and_sendReturnType();
1280 /*-------------------------------------------------------------------------------*/
1281 /* RTA add Native Methods/ Class functions */
1282 /*-------------------------------------------------------------------------------*/
1283 void findMarkNativeUsedMeth (utf * c1, utf* m1, utf* d1) {
1288 class = class_get(c1);
1289 if (class == NULL) {
1290 return; /*Note: Since NativeCalls is for mult programs some may not be loaded - that's ok */
1293 if (class->classUsed == NOTUSED) {
1294 class->classUsed = USED; /* MARK CLASS USED */
1295 /* add marked methods to callgraph */
1296 addMarkedMethods(class);
1299 meth = class_findmethod (class, m1, d1);
1301 utf_display(class->name);printf(".");utf_display(m1);printf(" ");utf_display(d1);
1302 printf("WARNING from parseRT: Method given is used by Native method call, but NOT FOUND\n");
1305 rtaMarkSubs(class,meth);
1308 /*-------------------------------------------------------------------------------*/
1310 void findMarkNativeUsedClass (utf * c) {
1313 class = class_get(c);
1314 if (class == NULL) panic("parseRT: Class used by Native method called not loaded!!!");
1315 class->classUsed = USED;
1317 /* add marked methods to callgraph */
1318 addMarkedMethods(class);
1322 /*-------------------------------------------------------------------------------*/
1324 void markNativeMethodsRT(utf *rt_class, utf* rt_method, utf* rt_descriptor) {
1328 nativecallcompdone = natcall2utf(nativecallcompdone);
1330 for (i=0; i<NATIVECALLSSIZE; i++) {
1331 if (rt_class == nativeCompCalls[i].classname) {
1333 /* find native class.method invoked */
1334 for (j=0; (!(found) && (j<nativeCompCalls[i].methCnt)); j++) {
1336 if ( (rt_method == nativeCompCalls[i].methods[j].methodname)
1337 && (rt_descriptor == nativeCompCalls[i].methods[j].descriptor)) {
1341 /* mark methods and classes used by this native class.method */
1342 for (k=0; k < nativeCompCalls[i].callCnt[j]; k++) {
1343 if (nativeCompCalls[i].methods[j].methodCalls[k].methodname != NULL) {
1344 /* mark method used */
1345 findMarkNativeUsedMeth(
1346 nativeCompCalls[i].methods[j].methodCalls[k].classname,
1347 nativeCompCalls[i].methods[j].methodCalls[k].methodname,
1348 nativeCompCalls[i].methods[j].methodCalls[k].descriptor);
1351 printf("\nmark method used: "); fflush(stdout);
1352 utf_display(nativeCompCalls[i].methods[j].methodCalls[k].classname); printf(".");fflush(stdout);
1353 utf_display(nativeCompCalls[i].methods[j].methodCalls[k].methodname); printf("=="); fflush(stdout);
1354 utf_display(nativeCompCalls[i].methods[j].methodCalls[k].descriptor); printf("==\n"); fflush(stdout);
1358 /* mark class used */
1359 findMarkNativeUsedClass( nativeCompCalls[i].methods[j].methodCalls[k].classname);
1373 /*-------------------------------------------------------------------------------*/
1374 /*-------------------------------------------------------------------------------*/
1375 void mainRTAparseInit (methodinfo *m )
1377 /*printf("MAIN_NOT_STARTED \n");*/
1378 if (class_java_lang_Object->sub != NULL) {
1385 utf_MAIN = utf_new_char("main");
1386 INIT = utf_new_char("<init>");
1387 CLINIT = utf_new_char("<clinit>");
1388 FINALIZE = utf_new_char("finalize");
1389 EMPTY_DESC= utf_new_char("()V");
1391 if ( (rtMissed = fopen("rtMissed", "w")) == NULL) {
1392 printf("CACAO - rtMissed file: can't open file to write\n");
1395 fprintf(rtMissed,"To Help User create a dymLoad file \n");
1397 "Not parsed in the static analysis parse of Main: #rt parse / #missed class.method (descriptor) \n");
1398 fprintf(rtMissed,"\n\tBEFORE MAIN RT PARSE\n");
1402 callgraph = MNEW (methodinfo*, MAXCALLGRAPH);
1403 if ((XTAOPTbypass) || (opt_xta)) {
1404 printf("XTAXTA CALLGRAPHS allocated\n");
1405 XTAcallgraph = MNEW (methodinfo*, MAXCALLGRAPH);
1409 if (m->name == utf_MAIN) {
1410 rtMissed = fopen("rtMissed","a");
1411 fprintf(rtMissed,"\n\n\tAFTER MAIN RT PARSE\n");
1416 if ( (rtMissed = fopen("rtMissed", "a")) == NULL) {
1417 printf("CACAO - rtMissed file: can't open file to write\n");
1420 fprintf(rtMissed,"#%i/#%i ",methRTlast+1,missedCnt++ );
1421 utf_fprint(rtMissed,m->class->name);
1422 fprintf(rtMissed," ");
1423 fprintflags(rtMissed,m->flags);
1424 fprintf(rtMissed," ");
1425 utf_fprint(rtMissed,m->name);
1426 fprintf(rtMissed," ");
1427 utf_fprint(rtMissed,m->descriptor);
1428 fprintf(rtMissed,"\n");
1433 panic("Method missed by static analysis Main parse. See rtMissed file");
1436 /* At moment start RTA before main when parsed */
1437 /* Will definitely use flag with to know if ok to apply in-lining. */
1441 /*-------------------------------------------------------------------------------*/
1442 /*-------------------------------------------------------------------------------*/
1443 /* still need to look at field sets in 2nd pass and clinit ..... */
1444 void XTA_jit_parse2(methodinfo *m)
1447 printf("\n\nStarting Round 2 XTA !!!!!!!!!!!!!!\n");
1449 /* for each method in XTA worklist = callgraph (use RTA for now) */
1451 while (methRT <= methRTlast) {
1452 rt_method = callgraph[methRT];
1453 rt_class = rt_method->class;
1454 rt_descriptor = rt_method->descriptor;
1455 rt_jcodelength = rt_method->jcodelength;
1456 rt_jcode = rt_method->jcode;
1458 if (! ( (rt_method->flags & ACC_NATIVE )
1459 || (rt_method->flags & ACC_ABSTRACT) ) ) {
1460 if (XTAdebug >= 1) {
1461 printf("\n!!!!! XTA Round 2 Parse of #%i:",methRT);fflush(stdout);
1462 utf_display(rt_class->name); printf("."); fflush(stdout);
1463 method_display(rt_method);
1465 /* if XTA type set changed since last parse */
1466 if (rt_method->xta->chgdSinceLastParse) {
1468 /* get types from methods it is calledBy */
1469 xtaPassAllCalledByParams ();
1471 /* Pass parameter types to methods it calls and send the return type those called by */
1472 xtaMethodCalls_and_sendReturnType();
1477 if (XTAdebug >= 1) {
1479 printf("\n\nEND_OF Round 2 XTA !!!!!!!!!!!!!!\n");
1480 printXTACallgraph ();
1483 RTAPRINT14CallgraphLast /*was >=2 */
1484 RTAPRINT15HeirarchyiLast /*was >= 2 */
1488 /*-------------------------------------------------------------------------------*/
1490 void RT_jit_parse(methodinfo *m)
1493 if (m->methodUsed == USED) return;
1494 mainRTAparseInit (m);
1496 /* initialise parameter type descriptor */
1497 callgraph[++methRTlast] = m; /*-- RTA --*/
1498 m->methodUsed = USED;
1499 RTAPRINT11addedtoCallgraph
1501 /* <init> then like a new class so add marked methods to callgraph */
1502 if (m->name == INIT) { /* need for <init>s parsed efore Main */
1505 ci->classUsed = USED;
1506 if (pWhenMarked >= 1) {
1507 printf("Class=");utf_display(ci->name);
1509 /* add marked methods to callgraph */
1510 RTAPRINT11addedtoCallgraph2
1511 addMarkedMethods(ci);
1515 if ((XTAOPTbypass) || (opt_xta)) {
1516 XTAcallgraph[++methXTAlast] = m;
1517 m->xta->XTAmethodUsed = USED;
1518 {methodinfo *mi = m;
1523 /*-- Call graph work list loop -----------------*/
1525 while (methRT <= methRTlast) {
1526 rt_method = callgraph[methRT];
1527 rt_class = rt_method->class;
1528 rt_descriptor = rt_method->descriptor;
1529 rt_jcodelength = rt_method->jcodelength;
1530 rt_jcode = rt_method->jcode;
1532 if (! ( (rt_method->flags & ACC_NATIVE )
1533 || (rt_method->flags & ACC_ABSTRACT) ) ) {
1537 RTAPRINT12bAbstractNative
1538 if (rt_method->flags & ACC_NATIVE ) {
1540 /* mark used and add to callgraph methods and classes used by NATIVE method */
1541 markNativeMethodsRT(rt_class->name,rt_method->name,rt_descriptor);
1543 if (rt_method->flags & ACC_ABSTRACT) {
1544 panic("ABSTRACT_SHOULD not ever get into the callgraph!!!!!****!!!****!!!!****!!!!\n");
1553 if (m->class->classUsed == NOTUSED)
1554 m->class->classUsed = USED; /* say Main's class has a method used ??*/
1555 printXTACallgraph ();
1556 RTAPRINT14CallgraphLast /* was >=2*/
1557 //RTAPRINT15HeirarchyiLast /*was >= 2 */
1559 if ((XTAOPTbypass) || (opt_xta)) {
1560 /*--- XTA round 2+ "parse" - use info structures only so not a real parse */
1564 if (m->name == utf_MAIN) {
1565 MFREE(callgraph,methodinfo*,MAXCALLGRAPH);
1566 if ((XTAOPTbypass) || (opt_xta)) {
1567 printf("XTAXTA CALLGRAPHS returned \n");
1568 MFREE(XTAcallgraph,methodinfo*,MAXCALLGRAPH);