/*--- Statistics ----------------------------------------------------------*/ int unRTclassHeirCnt=0; int unRTmethodCnt = 0; /*-----*/ int RTclassHeirNotUsedCnt=0; int RTclassHeirUsedCnt=0; int RTclassHeirPartUsedCnt=0; int RTclassHeirSuperCnt=0; int RTmethodNotUsedCnt = 0; int RTmethodNotUsedCnt1= 0; int RTmethodNotUsedCnt2= 0; int RTmethodUsedCnt = 0; int RTmethodMarkedCnt= 0; /* What might be inlined of the Used Methods */ int RTmethodFinal = 0; int RTmethodStatic = 0; int RTmethodFinalStatic = 0; int RTmethodNoSubs = 0; int RTmethodMono; int RTmethodPossiblePoly; int RTmethodPolyReallyMono; int RTmethodPoly; int RTmethodFinal100 = 0; int RTmethodStatic100 = 0; int RTmethodFinalStatic100 = 0; int RTmethodNoSubs100 = 0; #define MAXCODLEN 10 int RTmethodNoSubsAbstract = 0; int RTmethod1Used = 0; int RTmethodAbstract = 0; int subRedefsCnt =0; int subRedefsCntUsed =0; /*------------- RTAprint flags ------------------------------------------------------------------*/ int pCallgraph = 0; /* 0 - dont print 1 - print at end from main */ /* 2 - print at end of RT parse call */ /* 3- print after each method RT parse */ int pClassHeir = 1; /* 0 - dont print 1 - print at end from main */ /* 2 - print at end of RT parse call 3-print after each method RT parse */ int pClassHeirStatsOnly = 1; /* usually 2 Print only the statistical summary info for class heirarchy */ int pOpcodes = 0; /* 0 - don't print 1- print in parse RT 2- print in parse */ /* 3 - print in both */ int pWhenMarked = 0; /* 0 - don't print 1 - print when added to callgraph + when native parsed*/ /* 2 - print when marked+methods called */ /* 3 - print when class/method looked at */ int pStats = 0; /* 0 - don't print; 1= analysis only; 2= whole unanalysed class heirarchy*/ /*-----------------------------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------------------------*/ void printXTACallgraph () { int i; if (XTAdebug >= 1) { printf("----- XTA Callgraph Worklist:<%i>\n",methXTAlast); for (i=0;i<=methXTAlast;i++) { printf(" (%i): ",i); utf_display(XTAcallgraph[i]->class->name); printf(":"); method_display(XTAcallgraph[i]); } printf("\n\n"); } } /*-----------------------------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------------------------*/ void printCallgraph () { int i; printf("----- RTA Callgraph Worklist:<%i>\n",methRTlast); for (i=0;i<=methRTlast;i++) { printf(" (%i): ",i); utf_display(callgraph[i]->class->name); printf(":"); method_display(callgraph[i]); } printf("\n\n"); } /*--------------------------------------------------------------*/ void printObjectClassHeirarchy1() { if (pStats >= 1) { unRTclassHeirCnt=0; unRTmethodCnt = 0; printObjectClassHeirarchy(class_java_lang_Object); printf("\n >>>>>>>>>>>>>>>>>>>> END of unanalysed Class Heirarchy: #%i classes / #%i methods\n\n", unRTclassHeirCnt,unRTmethodCnt); } } /*--------------------------------------------------------------*/ void printObjectClassHeirarchy(classinfo *class) { classinfo *subs; methodinfo *meth; int t,m,cnt; if (class == NULL) {return;} unRTclassHeirCnt++; unRTmethodCnt += class->methodscount; if (pStats == 2) { printf("\n"); /* Class Name */ for (t=0;tindex;t++) printf("\t"); if (class->flags & ACC_INTERFACE) printf("ABSTRACT "); printf("Class: "); utf_display(class->name); printf(" <%i> (depth=%i) \n",class->classUsed,class->index); /* Print methods used */ cnt=0; for (m=0; m < class->methodscount; m++) { meth = &class->methods[m]; if (cnt == 0) { for (t=0;tindex;t++) printf("\t"); printf("aMethods used:\n"); } for (t=0;tindex;t++) printf("\t"); printf("\t"); utf_display(meth->class->name); printf("."); method_display(meth); cnt++; } if (cnt > 0) printf("> %i of %i methods\n",cnt, class->methodscount); } for (subs = class->sub;subs != NULL;subs = subs->nextsub) { printObjectClassHeirarchy(subs); } } /*--------------------------------------------------------------*/ /*--------------------------------------------------------------*/ int subdefd(methodinfo *meth) { classinfo *subs; methodinfo *submeth; /*printf("subdefd for:");utf_display(meth->class->name);printf(".");method_display(meth); fflush(stdout);*/ if ( (meth->flags & ACC_STATIC) && (meth->flags & ACC_FINAL ) ) panic("Possible Poly call for FINAL or STATIC\n"); if ((meth->class->sub == NULL) && (!(meth->flags & ACC_ABSTRACT )) ) { return 0; } if (meth->flags & ACC_ABSTRACT ) ; /*printf("AB\n"); fflush(stdout); */ /*printf("s exist for:");utf_display(meth->class->name);printf(".");method_display(meth);*/ for (subs = meth->class->sub;subs != NULL;subs = subs->nextsub) { submeth = class_findmethod(subs, meth->name, meth->descriptor); if (submeth != NULL) { subRedefsCnt++; if (submeth->methodUsed == USED) { subRedefsCntUsed++; /*return 1;*/ } else { if (subdefd(submeth) > 0) ; /*return 1;*/ } } } if (subRedefsCntUsed > 0) return 1; return 0; } /*--------------------------------------------------------------*/ void printRTClassHeirarchy(classinfo *class) { classinfo *subs; methodinfo *meth; int m,cnt; if (class == NULL) {return;} /* Class Name */ if (class->classUsed == NOTUSED) { RTclassHeirNotUsedCnt++; RTmethodNotUsedCnt = RTmethodNotUsedCnt + class->methodscount; RTmethodNotUsedCnt1 = RTmethodNotUsedCnt1 + class->methodscount; for (m=0; m < class->methodscount; m++) { meth = &class->methods[m]; if (meth->methodUsed == USED) { if (pClassHeirStatsOnly >= 2) { printf("METHOD marked used in CLASS marked NOTUSED: "); utf_display(class->name); printf("."); method_display(meth); printf("<%i>\n\t",meth->methodUsed); fflush(stdout); printf("\n\n\n\nMETHOD marked used in CLASS marked NOTUSED\n\n\n\n"); } } } } if (class->classUsed != NOTUSED) { if (pClassHeirStatsOnly >= 2) { printf("\nClass: "); utf_display(class->name); printf(" <%i> (depth=%i) ",class->classUsed,class->index); printf("\tbase/diff =%3d/%3d\n", class->vftbl->baseval, class->vftbl->diffval); } if (class->classUsed == PARTUSED) { if (pClassHeirStatsOnly >= 2) { printf("\tClass not instanciated - but methods/fields resolved to this class' code (static,inits,fields,super)\n"); } RTclassHeirPartUsedCnt++; } else { if (pClassHeirStatsOnly >= 2) { printf("\n"); } RTclassHeirUsedCnt++; } /* Print methods used */ cnt=0; for (m=0; m < class->methodscount; m++) { meth = &class->methods[m]; if (meth->methodUsed == NOTUSED) RTmethodNotUsedCnt2++; if (meth->methodUsed == MARKED) RTmethodMarkedCnt++; if (meth->methodUsed == USED) { RTmethodUsedCnt++; if ( (meth->flags & ACC_FINAL ) && (!(meth->flags & ACC_STATIC)) ) { RTmethodFinal++; if (meth->jcodelength < MAXCODLEN) RTmethodFinal100++; } if ( (meth->flags & ACC_STATIC) && (!(meth->flags & ACC_FINAL )) ) { RTmethodStatic++; if (meth->jcodelength < MAXCODLEN) RTmethodStatic100++; } if ( (meth->flags & ACC_STATIC) && (meth->flags & ACC_FINAL ) ) { RTmethodFinalStatic++; if (meth->jcodelength < MAXCODLEN) RTmethodFinalStatic100++; } if ((! ((meth->flags & ACC_FINAL ) && (meth->flags & ACC_STATIC)) ) && ((meth->class->sub == NULL) && (!(meth->flags & ACC_ABSTRACT)) )) { RTmethodNoSubs++; if (meth->jcodelength < MAXCODLEN) RTmethodNoSubs100++; } if ((! ((meth->flags & ACC_FINAL ) && (meth->flags & ACC_STATIC)) ) && ((meth->class->sub == NULL) && (meth->flags & ACC_ABSTRACT) )) RTmethodNoSubsAbstract++; if (meth->flags & ACC_ABSTRACT) RTmethodAbstract++; if (meth->monoPoly == MONO) RTmethodMono++; if (meth->monoPoly == POLY) { RTmethodPossiblePoly++; subRedefsCnt = 0; subRedefsCntUsed = 0; if (meth->flags & ACC_ABSTRACT ) { if (pClassHeirStatsOnly >= 2) { printf("STATS: abstract_method="); utf_display(meth->class->name);printf("."); method_display(meth); } } else { if (subdefd(meth) == 0) { meth->monoPoly = MONO1; RTmethodPolyReallyMono++; } else { RTmethodPoly++; meth->subRedefs = subRedefsCnt; meth->subRedefsUsed = subRedefsCntUsed; } } } if (pClassHeirStatsOnly >= 2) { if (cnt == 0) { printf("bMethods used:\n"); } cnt++; printf("\t"); utf_display(meth->class->name); printf("."); method_display(meth); printf("\t\t"); if (meth->monoPoly != MONO) printf("\t\tRedefs used/total<%i/%i>\t", meth->subRedefsUsed, meth->subRedefs); if ( (XTAOPTbypass3) || (opt_xta)) { if (meth->XTAclassSet == NULL) printf("class set never created\n"); else printSet(meth->XTAclassSet->head); } } } } if (pClassHeirStatsOnly >= 2) { if (cnt > 0) printf("> %i of %i methods used\n",cnt, class->methodscount); } } for (subs = class->sub; subs != NULL; subs = subs->nextsub) { printRTClassHeirarchy(subs); } } /*--------------------------------------------------------------*/ void printRTInterfaceClasses() { int ii,jj,mm; classinfo *ci = class_java_lang_Object; classSetNode *subs; int RTmethodInterfaceClassImplementedCnt = 0; int RTmethodInterfaceClassUsedCnt = 0; int RTmethodInterfaceMethodTotalCnt = 0; int RTmethodInterfaceMethodNotUsedCnt = 0; int RTmethodInterfaceMethodUsedCnt = 0; int RTmethodClassesImpldByTotalCnt = 0; int RTmethodInterfaceMonoCnt = 0; int RTmethodInterfacePolyReallyMonoCnt=0; /* look at every method that implments and see if its poly or mono1*/ int RTmethodNoSubsAbstractCnt = 0; for (subs = ci->impldBy; subs != NULL; subs = subs->nextClass) { classinfo * ici = subs->classType; classinfo * isubs = subs->classType; classinfo * iBy; classSetNode * inBy; int impldBycnt; if (isubs->sub == NULL) RTmethodNoSubsAbstractCnt++; if (pClassHeir >= 2) { printf("Interface class: ");fflush(stdout); utf_display(ici->name); printf("\t#Methods=%i",ici->methodscount); } RTmethodInterfaceClassImplementedCnt++; if (ici -> classUsed == USED) {RTmethodInterfaceClassUsedCnt++;} if (pClassHeir >= 2) { printf("\n\t\t\tImplemented by classes:\n"); } impldBycnt = 0; /* get the total impldBy classes Used */ for (inBy = ici->impldBy; inBy != NULL; inBy = inBy->nextClass) { impldBycnt++; RTmethodClassesImpldByTotalCnt++; if (pClassHeir >= 2) { printf("\t\t\t");utf_display(inBy->classType->name); printf("\n"); } if (inBy->classType->classUsed == NOTUSED) panic("printRTInterfaceClasses: class in the implemented list without being used!!!??"); } if (pClassHeir >= 2) { printf("\t\t\tImpld by: %i\n",impldBycnt); } if (impldBycnt== 1) RTmethodInterfaceMonoCnt++; /* if interface class is used */ if (ici -> classUsed != NOTUSED) { if (pClassHeir >= 2) { printf(" cMethods used:\n"); } /* for each interface method implementation that has been used */ for (mm=0; mm< ici->methodscount; mm++) { methodinfo *imi = &(ici->methods[mm]); RTmethodInterfaceMethodTotalCnt++; if (imi->methodUsed != USED) { RTmethodInterfaceMethodNotUsedCnt++; } if (imi->methodUsed == USED) { RTmethodInterfaceMethodUsedCnt++; if (pClassHeirStatsOnly >= 2) { printf("\t\t"); utf_display(ici->name);printf(".");method_display(imi);fflush(stdout); } if (impldBycnt == 1) { classinfo *cii; methodinfo *mii; int i; /* if only 1 implementing class then possibly really mono call */ inBy = ici->impldBy; cii = inBy->classType; mii = class_findmethod(cii, imi->name, imi->descriptor); if (mii == NULL) { /* assume its resolved up the heirarchy and just 1 possiblity so MONO1 */ imi->monoPoly = MONO1; RTmethodInterfacePolyReallyMonoCnt++; } else { if (imi->monoPoly != POLY) panic ("interface monopoly not POLY"); if (mii->monoPoly != POLY) { imi->monoPoly = MONO1; RTmethodInterfacePolyReallyMonoCnt++; } else { imi->monoPoly = POLY; } } } } } if (pClassHeir >= 2) { printf("\n"); } } } if (pClassHeirStatsOnly >= 1) { printf("\n\n >>>>>>>>>>>>>>>>>>>> Interface Statistics Summary: \n"); printf("Classes: Total: %i \tUSED: %i \tIMPLD BY: \t%i \tJUST 1 IMPLD BY: %i \tNOSUB: %i \n", RTmethodInterfaceClassImplementedCnt, RTmethodInterfaceClassUsedCnt,RTmethodClassesImpldByTotalCnt, RTmethodInterfaceMonoCnt, RTmethodNoSubsAbstractCnt); printf("Methods: Total: %i \tNOTUSED: %i \tUSED: \t%i \tPoly that resolves to Mono %i \n", RTmethodInterfaceMethodTotalCnt, RTmethodInterfaceMethodNotUsedCnt,RTmethodInterfaceMethodUsedCnt, RTmethodInterfacePolyReallyMonoCnt); } } /*--------------------------------------------------------------*/ void printRThierarchyInfo(methodinfo *m) { /*-- init for statistics --*/ RTclassHeirNotUsedCnt=0; RTclassHeirUsedCnt=0; RTclassHeirPartUsedCnt=0; RTclassHeirSuperCnt=0; RTmethodNotUsedCnt = 0; RTmethodNotUsedCnt1 = 0; RTmethodNotUsedCnt2 = 0; RTmethodUsedCnt = 0; RTmethodMarkedCnt= 0; /*-- --*/ if (pClassHeirStatsOnly >= 2) { printf("\nRT Class Heirarchy for "); printf("--- start of RT info --------------- after :\n"); if (m != NULL) { utf_display(m->class->name); printf("."); method_display(m); printf("\n"); } } printRTClassHeirarchy(class_java_lang_Object); if (pClassHeirStatsOnly >= 2) { printf("--- end of RT info ---------------\n"); } if (pClassHeirStatsOnly >= 1) { /*-- statistic results --*/ printRTInterfaceClasses(); printf("\n >>>>>>>>>>>>>>>>>>>> Analysed Class Heirarchy Statistics:\n"); printf(" Used \t%i \tclasses\t/ Used \t%i methods \t of USED: %i%% \t of ALL: %i%% \n", RTclassHeirUsedCnt,RTmethodUsedCnt, ((100*RTmethodUsedCnt)/(RTmethodUsedCnt + RTmethodNotUsedCnt2)) , ((100*RTmethodUsedCnt)/ (RTmethodNotUsedCnt + RTmethodUsedCnt + RTmethodMarkedCnt)) ); printf(" Part Used \t%i \tclasses\t/\n",RTclassHeirPartUsedCnt); printf(" Not Used \t%i \tclasses\t/\n\n",RTclassHeirNotUsedCnt); printf(" \t \t \t/ Just Marked \t%i methods\n\n",RTmethodMarkedCnt); printf(" In Not Used \t \tclasses\t/ Not Used \t%i methods\n",RTmethodNotUsedCnt1); printf(" In Used \t \tclasses\t/ Not Used \t%i methods\n",RTmethodNotUsedCnt2); printf(" Total \t%i \tclasses\t/ Total \t%i methods\n\n", RTclassHeirNotUsedCnt + RTclassHeirUsedCnt + RTclassHeirPartUsedCnt, RTmethodNotUsedCnt1 + RTmethodNotUsedCnt2 + RTmethodUsedCnt + RTmethodMarkedCnt ); printf(" Mono vs. Polymorhpic calls:\n"); printf(" Mono calls \t%i \tPoly that resolves to Mono \t%i \tPoly calls \t%i\n\n", RTmethodMono, RTmethodPolyReallyMono, RTmethodPoly); printf(" No Subs: Total=\t%i \tAbstract No Subs= \t%i \tAbstract methods used =\t%i\n", RTmethodNoSubs, RTmethodNoSubsAbstract, RTmethodAbstract); printf(" Inlining possible: \tFINALs %i \tSTATICs %i \t FINAL & STATIC %i \t Class has No Subs %i \n", RTmethodFinal, RTmethodStatic,RTmethodFinalStatic, RTmethodNoSubs); printf(" Code size < 100 \tFINALs %i \tSTATICs %i \t FINAL & STATIC %i \t Class has No Subs %i \n", RTmethodFinal100, RTmethodStatic100,RTmethodFinalStatic100, RTmethodNoSubs100); } }