/* jit/parseRTstats.c - Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003 R. Grafl, A. Krall, C. Kruegel, C. Oates, R. Obermaisser, M. Probst, S. Ring, E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, J. Wenninger This file is part of CACAO. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. Contact: cacao@complang.tuwien.ac.at Authors: Carolyn Oates $Id: parseRTstats.c 1235 2004-06-30 19:52:18Z twisti $ */ #include "options.h" #include "jit/parseRT.h" #include "jit/parseRTstats.h" /*--- 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; /*-----------------------------------------------------------------------------------------------*/ 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("----- end of XTA Callgraph Worklist:<%i>\n",methXTAlast); 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 printObjectClassHeirarchyAll() { 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_fetchmethod(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->xta == NULL) { printf("class set never created\n"); } else { if (meth->xta->XTAclassSet == NULL) printf("class set never created\n"); else printSet(meth->xta->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 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; 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; /* if only 1 implementing class then possibly really mono call */ inBy = ici->impldBy; cii = inBy->classType; mii = class_fetchmethod(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 Hierarchy 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) { fflush(stdout); printf("--- end of RT info ---------------\n"); } if (pClassHeirStatsOnly >= 1) { /*-- statistic results --*/ if (opt_rt) printRTInterfaceClasses(); printf("\n >>>>>>>>>>>>>>>>>>>> Analysed Class Hierarchy 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. Polymorphic 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); } } /* * These are local overrides for various environment variables in Emacs. * Please do not remove this and leave it at the end of the file, where * Emacs will automagically detect them. * --------------------------------------------------------------------- * Local variables: * mode: c * indent-tabs-mode: t * c-basic-offset: 4 * tab-width: 4 * End: */