* Updated header: Added 2006. Changed address of FSF. Changed email
[cacao.git] / src / vm / jit / inline / parseRTstats.c
1 /* sr/cvm/jit/inline/parseRTstats.c -
2
3    Copyright (C) 1996-2005, 2006 R. Grafl, A. Krall, C. Kruegel,
4    C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
5    E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
6    J. Wenninger, Institut f. Computersprachen - TU Wien
7
8    This file is part of CACAO.
9
10    This program is free software; you can redistribute it and/or
11    modify it under the terms of the GNU General Public License as
12    published by the Free Software Foundation; either version 2, or (at
13    your option) any later version.
14
15    This program is distributed in the hope that it will be useful, but
16    WITHOUT ANY WARRANTY; without even the implied warranty of
17    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
18    General Public License for more details.
19
20    You should have received a copy of the GNU General Public License
21    along with this program; if not, write to the Free Software
22    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
23    02110-1301, USA.
24
25    Contact: cacao@cacaojvm.org
26
27    Authors: Carolyn Oates
28
29    Changes: Christian Thalinger
30
31    $Id: parseRTstats.c 4357 2006-01-22 23:33:38Z twisti $
32
33 */
34
35 #include <stdio.h>
36
37 #include "config.h"
38 #include "toolbox/list.h"
39 #include "vm/class.h"
40 #include "vm/loader.h"
41 #include "vm/options.h"
42 #include "vm/statistics.h"
43 #include "vm/jit/inline/parseRT.h"
44 #include "vm/jit/inline/parseRTstats.h"
45 #include "vm/jit/inline/parseRTprint.h"
46
47
48 int pClassHeirStatsOnly = 2;
49 int pClassHeir = 2;
50
51 /*--- Statistics ---------------------------------------------------------*/
52
53 int unRTclassHeirCnt=0;
54 int unRTmethodCnt = 0;
55
56 /*-----*/
57 int RTclassHeirNotUsedCnt=0; 
58 int RTclassHeirUsedCnt=0;    
59 int RTclassHeirPartUsedCnt=0;
60 int RTclassHeirSuperCnt=0;
61
62 int RTmethodNotUsedCnt = 0;
63 int RTmethodNotUsedCnt1= 0;
64 int RTmethodNotUsedCnt2= 0;
65 int RTmethodUsedCnt = 0;
66 int RTmethodMarkedCnt= 0;
67
68 /* What might be inlined of the Used Methods */
69 int RTmethodFinal  = 0;
70 int RTmethodStatic = 0;
71 int RTmethodFinalStatic = 0;
72 int RTmethodNoSubs = 0;
73
74 int RTmethodMono; 
75 int RTmethodPossiblePoly;
76 int RTmethodPolyReallyMono;
77 int RTmethodPoly;
78
79 int RTmethodFinal100  = 0;
80 int RTmethodStatic100 = 0;
81 int RTmethodFinalStatic100 = 0;
82 int RTmethodNoSubs100 = 0;
83
84 #define MAXCODLEN 10
85
86 int RTmethodNoSubsAbstract = 0;
87 int RTmethod1Used  = 0;
88
89 int RTmethodAbstract = 0;
90
91 int subRedefsCnt =0;
92 int subRedefsCntUsed =0;
93
94
95
96 /*--------------------------------------------------------------*/
97 void printCallgraph (list *rtaWorkList)
98
99     int i = 1;
100     rtaNode    *rta;
101     methodinfo *rt_meth;  
102
103 #if defined(ENABLE_STATISTICS)
104  printf("-*-*-*-*- RTA Callgraph Worklist:<%i>\n",count_methods_marked_used);
105 #endif
106
107    for (rta =list_first(rtaWorkList);
108          rta != NULL;
109          rta =list_next(rtaWorkList,rta))
110         {
111          rt_meth = rta->method;
112
113          printf("  (%i): ",i++); 
114          method_println(rt_meth);
115         }
116
117  printf("\n\n");
118
119 }
120 /*--------------------------------------------------------------*/
121 /*--------------------------------------------------------------*/
122 /*--------------------------------------------------------------*/
123 int subdefd(methodinfo *meth) {
124     classinfo *subs;
125     methodinfo *submeth;
126
127         printf("subdefd for:");
128         method_println(meth);
129
130     if (  (meth->flags & ACC_STATIC) && (meth->flags & ACC_FINAL ) )  
131         printf("\n\n\nPossible Poly call for FINAL or STATIC\n\n\n");
132
133     if ((meth->class->sub == NULL)  && (!(meth->flags & ACC_ABSTRACT )) ) { 
134                 return 0;
135         }
136     if (meth->flags & ACC_ABSTRACT ) ; /*printf("AB\n"); fflush(stdout); */
137
138         printf("sub exist for:");method_println(meth);
139
140     for (subs = meth->class->sub;subs != NULL;subs = subs->nextsub) {
141                 submeth = class_findmethod_approx(subs, meth->name, meth->descriptor); 
142                 if (submeth != NULL) {
143                         subRedefsCnt++;
144                         if (submeth->methodUsed == USED) {
145                                 subRedefsCntUsed++;
146                                 /*return 1;*/
147                         }
148                         else {
149                                 if (subdefd(submeth) > 0)
150                                         ; /*return 1;*/
151                         }
152                 }
153         }
154     if (subRedefsCntUsed > 0) return 1;
155     return 0;
156 }
157
158 /*--------------------------------------------------------------*/
159 #define CLASSINFO(cls,txt)  { \
160   printf(txt); fflush(stdout); \
161     printf(" <c%i>(depth=%i) ",cls->classUsed,cls->index); \
162     printf("\tbase/diff =%3d/%3d\t", \
163                                    cls->vftbl->baseval, \
164                                    cls->vftbl->diffval); \
165   utf_display(cls->name); printf("\n"); fflush(stdout); } 
166
167 /*--------------------------------------------------------------*/
168
169 void printRTClassHeirarchy2(classinfo  *class) {
170 classinfo  *s;
171   methodinfo *meth;
172   int m;
173
174   if (class == NULL) {return;}
175   CLASSINFO(class,"CLASS: ");
176   for (s = class->super.cls; s != NULL; s = s->super.cls) {
177     CLASSINFO(s,"SUPER:: ");
178     }
179
180   printf("METHODs: "); fflush(stdout);
181
182   for (m=0; m < class->methodscount; m++) {
183     meth = &class->methods[m];
184     printf("(%i) ",m);
185     METHINFOx(meth);
186     }
187   printf("---------------------------\n");fflush(stdout);
188
189     if (class->sub != NULL) printf("SUBS:\n:");
190     else printf("NO SUBS\n");
191     fflush(stdout);
192
193     for (s = class->sub; s != NULL; s = s->nextsub) {
194                 printRTClassHeirarchy2(s);
195                 printf("---------------------------\n");fflush(stdout);
196         }
197 }
198
199 void printRTClassHeirarchy(classinfo  *class) {
200   
201         classinfo  *subs;
202         methodinfo *meth;
203         int m,cnt;
204
205         if (class == NULL) {return;}
206     /* Class Name */
207     if (class->classUsed == NOTUSED) {
208                 RTclassHeirNotUsedCnt++;
209                 RTmethodNotUsedCnt = RTmethodNotUsedCnt + class->methodscount;
210                 RTmethodNotUsedCnt1 = RTmethodNotUsedCnt1 + class->methodscount;
211                 for (m=0; m < class->methodscount; m++) {
212                         meth = &class->methods[m];
213                         if (meth->methodUsed == USED) {
214                                 if (pClassHeirStatsOnly >= 2) {
215                                         printf("\nMETHOD marked used in CLASS marked NOTUSED: \n\t"); 
216                                         method_println(meth);
217                                         printf("<%i>\n\t",meth->methodUsed);
218                                         fflush(stdout);
219                                         printf("\nMETHOD marked used in CLASS marked NOTUSED\n\n\n\n"); 
220                                 }
221                         }       
222                         else {
223                                 printf(" UNUSED METHOD "); fflush(stdout);
224                                 method_println(meth);
225                         }
226                 }       
227         }
228
229     if (class->classUsed != NOTUSED) {
230         if (pClassHeirStatsOnly >= 2) {
231                         printf("\nClass: "); 
232                         utf_display(class->name);    
233                         printf(" <%i> (depth=%i) ",class->classUsed,class->index);
234
235                         printf("\tbase/diff =%3d/%3d\n",
236                                    class->vftbl->baseval,
237                                    class->vftbl->diffval);
238                 }
239
240         if (class->classUsed == PARTUSED) {
241             if (pClassHeirStatsOnly >= 2) {
242                                 printf("\tClass not instanciated - but  methods/fields resolved to this class' code (static,inits,fields,super)\n");
243                         }
244                         RTclassHeirPartUsedCnt++;
245             }   
246         else {
247                         if (pClassHeirStatsOnly >= 2) {
248                 printf("\n");
249                         }
250                         RTclassHeirUsedCnt++;
251                 }
252
253
254                 /* Print methods used */
255                 cnt=0;
256         for (m=0; m < class->methodscount; m++) {
257
258             meth = &class->methods[m];
259                 
260                         if (meth->methodUsed == NOTUSED)        RTmethodNotUsedCnt2++; 
261                         if (meth->methodUsed == MARKED)   RTmethodMarkedCnt++;
262                         if (meth->methodUsed == USED) {
263                                 RTmethodUsedCnt++;
264                                 if (  (meth->flags & ACC_FINAL ) && (!(meth->flags & ACC_STATIC)) ) { 
265                                         RTmethodFinal++;
266                                         if (meth->jcodelength < MAXCODLEN)  RTmethodFinal100++;
267                                 }
268
269                                 if (  (meth->flags & ACC_STATIC) && (!(meth->flags & ACC_FINAL )) ) { 
270                                         RTmethodStatic++;
271                                         if (meth->jcodelength < MAXCODLEN)  RTmethodStatic100++;
272                                 }
273
274                                 if (  (meth->flags & ACC_STATIC) && (meth->flags & ACC_FINAL ) ) { 
275                                         RTmethodFinalStatic++;
276                                         if (meth->jcodelength < MAXCODLEN)  RTmethodFinalStatic100++;
277                                 }
278
279                                 if ((! ((meth->flags & ACC_FINAL ) && (meth->flags & ACC_STATIC)) ) 
280                                         && ((meth->class->sub == NULL)  && (!(meth->flags & ACC_ABSTRACT)) ))    {
281                                         RTmethodNoSubs++;
282                                         if (meth->jcodelength < MAXCODLEN)  RTmethodNoSubs100++;
283                                 }
284
285                                 if ((! ((meth->flags & ACC_FINAL ) && (meth->flags & ACC_STATIC)) ) 
286                                         && ((meth->class->sub == NULL)  &&   (meth->flags & ACC_ABSTRACT)  ))    RTmethodNoSubsAbstract++;
287
288                                 if (meth->flags & ACC_ABSTRACT) RTmethodAbstract++;
289                                                         
290                                 if (meth->monoPoly == MONO) RTmethodMono++;
291                                 if (meth->monoPoly == POLY) {
292                                         RTmethodPossiblePoly++;
293                                         subRedefsCnt = 0;
294                                         subRedefsCntUsed = 0;
295                                         if (meth->flags & ACC_ABSTRACT ) {
296                                                 if (pClassHeirStatsOnly >= 2) {
297                                                         printf("STATS: abstract_method=");
298                                                         method_println(meth);
299                                                 }
300                                         }
301                                         else    {
302                                                 if (subdefd(meth) == 0) {
303                                                         meth->monoPoly = MONO1;
304                                                         RTmethodPolyReallyMono++;
305                                                 }                       
306                                                 else    {
307                                                         RTmethodPoly++;
308                                                         meth->subRedefs = subRedefsCnt;
309                                                         meth->subRedefsUsed = subRedefsCntUsed;
310                                                 }
311                                         }
312                                 }
313
314                                 if (pClassHeirStatsOnly >= 2) {
315                                         if (cnt == 0) {
316                                                 printf("bMethods used:\n");
317                                         }
318                                         cnt++;
319                                         printf("\t");
320                                         method_println(meth);
321                                         printf("\t\t");
322                                         if (meth->monoPoly != MONO) printf("\t\tRedefs used/total<%i/%i>\n", meth->subRedefsUsed, meth->subRedefs);
323                                 }
324                         }
325                 }
326                 if (pClassHeirStatsOnly >= 2) {
327                         if (cnt > 0) {
328                                 if (class->classUsed == PARTUSED)
329                                   printf("> %i of %i methods (part)used\n",cnt, class->methodscount);
330                                 if (class->classUsed == USED)
331                                   printf("> %i of %i methods used\n",cnt, class->methodscount);
332                                 }
333                 }
334         }
335
336     for (subs = class->sub; subs != NULL; subs = subs->nextsub) {
337                 printRTClassHeirarchy(subs);
338         }
339 }
340 /*--------------------------------------------------------------*/
341 void printRTInterfaceClasses() {
342         int mm;
343         classinfo *ci = class_java_lang_Object;
344         classSetNode *subs;
345
346         int RTmethodInterfaceClassImplementedCnt        = 0;
347         int RTmethodInterfaceClassUsedCnt               = 0;
348
349         int RTmethodInterfaceMethodTotalCnt             = 0;
350         int RTmethodInterfaceMethodNotUsedCnt   = 0;
351         int RTmethodInterfaceMethodUsedCnt              = 0;
352
353         int RTmethodClassesImpldByTotalCnt              = 0;
354
355         int RTmethodInterfaceMonoCnt                    = 0;
356         int RTmethodInterfacePolyReallyMonoCnt=0;  /* look at every method that implments and see if its poly or mono1*/
357
358         int RTmethodNoSubsAbstractCnt = 0;
359
360         for (subs = ci->impldBy; subs != NULL; subs = subs->nextClass) {
361         classinfo * ici = subs->classType;
362                 classinfo * isubs = subs->classType;
363                 classSetNode * inBy;
364                 int impldBycnt;
365
366                 if (isubs->sub == NULL) RTmethodNoSubsAbstractCnt++;
367                 if (pClassHeir >= 2) {
368                         printf("Interface class: ");fflush(stdout);
369                 utf_display(ici->name); printf("\t#Methods=%i",ici->methodscount);
370                 }
371                 RTmethodInterfaceClassImplementedCnt++;
372                 if (ici -> classUsed == USED)     {RTmethodInterfaceClassUsedCnt++;}
373                 if (pClassHeir >= 2) {
374                         printf("\n\t\t\tImplemented by classes:\n");
375                 }
376                 impldBycnt = 0;
377                 /* get the total impldBy classes Used */
378                 for (inBy = ici->impldBy; inBy != NULL; inBy = inBy->nextClass) {
379                         impldBycnt++;
380                         RTmethodClassesImpldByTotalCnt++;
381                         if (pClassHeir >= 2) {
382                                 printf("\t\t\t");utf_display(inBy->classType->name);
383                                 printf("\n");
384                         }
385                         if (inBy->classType->classUsed == NOTUSED) 
386                                 printf("\n\n\nprintRTInterfaceClasses: class in the implemented list without being used!!!??\n\n\n");
387                         fflush(stdout);
388                 }
389                 if (pClassHeir >= 2) {
390                         printf("\t\t\tImpld by: %i\n",impldBycnt);
391                 }
392                 if (impldBycnt== 1) RTmethodInterfaceMonoCnt++;
393
394         /* if interface class is used */
395         if (ici -> classUsed != NOTUSED) {
396                         if (pClassHeir >= 2) {
397                         printf("    cMethods used:\n");
398                         }
399
400                         /* for each interface method implementation that has been used */
401                         for (mm=0; mm< ici->methodscount; mm++) {
402                                 methodinfo *imi = &(ici->methods[mm]);
403                                 RTmethodInterfaceMethodTotalCnt++;
404                                 if  (imi->methodUsed != USED) {
405                                         RTmethodInterfaceMethodNotUsedCnt++;
406                                 }
407                                 if  (imi->methodUsed == USED) {
408                                         RTmethodInterfaceMethodUsedCnt++;
409                                         if (pClassHeirStatsOnly >= 2) {
410                                                 printf("\t\t"); 
411                                                 method_println(imi);
412                                         }
413                                         if (impldBycnt == 1) {
414                                                 classinfo  *cii;
415                                                 methodinfo *mii;
416
417                                                 /* if only 1 implementing class then possibly really mono call */
418                                         inBy = ici->impldBy;
419                                                 cii = inBy->classType;
420                                                 
421                                                 mii = class_findmethod(cii, imi->name, imi->descriptor); 
422                                                 if (mii == NULL) {
423                                                         /* assume its resolved up the heirarchy and just 1 possiblity so MONO1 */
424                                                         imi->monoPoly = MONO1;
425                                                         RTmethodInterfacePolyReallyMonoCnt++;
426                                                 }
427                                                 else    {
428                                                         /**if (imi->monoPoly != POLY) 
429                                                                 printf("\n\n\ninterface monopoly not POLY\n\n\n");
430                                                         **/
431                                                         if (mii->monoPoly != POLY) {
432                                                                 imi->monoPoly = MONO1;
433                                                                 RTmethodInterfacePolyReallyMonoCnt++;
434                                                         }
435                                                         else    {
436                                                                 imi->monoPoly = POLY;
437                                                         }
438                                                 }
439                                         }
440                                 }
441                         }
442                         if (pClassHeir >= 2) {
443                                 printf("\n");
444                         }
445                 }
446         }
447         if (pClassHeirStatsOnly >= 1) {
448                 printf("\n\n  >>>>>>>>>>>>>>>>>>>>  Interface Statistics Summary: \n");
449                 printf("Classes:  Total:   %i \tUSED:      %i \tIMPLD BY:   \t%i \tJUST 1 IMPLD BY:  %i \tNOSUB:     %i \n",
450                            RTmethodInterfaceClassImplementedCnt,
451                            RTmethodInterfaceClassUsedCnt,RTmethodClassesImpldByTotalCnt, RTmethodInterfaceMonoCnt,
452                            RTmethodNoSubsAbstractCnt);
453                 printf("Methods:  Total:   %i \tNOTUSED:   %i  \tUSED:      \t%i \tPoly that resolves to Mono  %i \n",
454                            RTmethodInterfaceMethodTotalCnt,
455                            RTmethodInterfaceMethodNotUsedCnt,RTmethodInterfaceMethodUsedCnt, RTmethodInterfacePolyReallyMonoCnt);
456         }
457 }
458
459 /*--------------------------------------------------------------*/
460
461
462
463 /*--------------------------------------------------------------*/
464 /*--------------------------------------------------------------*/
465
466 void printRThierarchyInfo(methodinfo *m) {
467
468         /*-- init for statistics --*/
469         RTclassHeirNotUsedCnt=0; 
470         RTclassHeirUsedCnt=0;    
471         RTclassHeirPartUsedCnt=0;   
472         RTclassHeirSuperCnt=0;   
473         RTmethodNotUsedCnt = 0; 
474         RTmethodNotUsedCnt1 = 0; 
475         RTmethodNotUsedCnt2 = 0;  
476         RTmethodUsedCnt = 0;   
477         RTmethodMarkedCnt= 0;  
478
479
480 printf("RT Heirarchy:------------\n"); fflush(stdout);
481         /*-- --*/
482                 printf("\nRT Class Hierarchy for ");
483                 if (m != NULL) {
484                         method_println(m);
485                         printf("\n");
486                         }
487                 else {  
488                      printf(" called with NULL method\n"); 
489                      return;
490                      }
491         /**printRTClassHeirarchy(class_java_lang_Object); **/
492         printRTClassHeirarchy(m->class);
493         printf("--- end  of RT info ---------------\n");
494
495         if (pClassHeirStatsOnly >= 10) {
496                 /*--  statistic results --*/
497                 if (opt_rt)
498                 printRTInterfaceClasses();
499         
500                 printf("\n  >>>>>>>>>>>>>>>>>>>>  Analysed Class Hierarchy Statistics:\n"); 
501                 printf(" Used            \t%i \tclasses\t/ Used       \t%i methods \t of USED: %i%% \t  of ALL: %i%% \n",
502                            RTclassHeirUsedCnt,RTmethodUsedCnt,
503                            ((100*RTmethodUsedCnt)/(RTmethodUsedCnt + RTmethodNotUsedCnt2)) ,
504                            ((100*RTmethodUsedCnt)/ (RTmethodNotUsedCnt    + RTmethodUsedCnt    + RTmethodMarkedCnt)) );
505                 printf(" Part Used       \t%i \tclasses\t/\n",RTclassHeirPartUsedCnt); 
506                 printf(" Not Used        \t%i \tclasses\t/\n\n",RTclassHeirNotUsedCnt); 
507                 printf("                 \t    \t       \t/ Just Marked \t%i methods\n\n",RTmethodMarkedCnt); 
508                 printf(" In Not Used     \t    \tclasses\t/ Not Used    \t%i methods\n",RTmethodNotUsedCnt1); 
509                 printf(" In Used         \t    \tclasses\t/ Not Used    \t%i methods\n",RTmethodNotUsedCnt2);
510                 printf(" Total           \t%i \tclasses\t/ Total       \t%i methods\n\n",
511                            RTclassHeirNotUsedCnt + RTclassHeirUsedCnt + RTclassHeirPartUsedCnt,  
512                            RTmethodNotUsedCnt1 + RTmethodNotUsedCnt2    + RTmethodUsedCnt    + RTmethodMarkedCnt ); 
513
514                 printf(" Mono vs. Polymorphic calls:\n");
515                 printf(" Mono calls     \t%i   \tPoly that resolves to Mono \t%i \tPoly calls     \t%i\n\n",
516                            RTmethodMono, RTmethodPolyReallyMono, RTmethodPoly);
517
518                 printf(" No Subs: Total=\t%i   \tAbstract No Subs=           \t%i \tAbstract methods used =\t%i\n",
519                            RTmethodNoSubs, RTmethodNoSubsAbstract, RTmethodAbstract);
520
521                 printf(" Inlining possible:  \tFINALs %i \tSTATICs %i \t FINAL & STATIC %i \t Class has No Subs %i \n",
522                            RTmethodFinal, RTmethodStatic,RTmethodFinalStatic,  RTmethodNoSubs);
523                 printf("    Code size < 100  \tFINALs %i \tSTATICs %i \t FINAL & STATIC %i \t Class has No Subs %i \n",
524                            RTmethodFinal100, RTmethodStatic100,RTmethodFinalStatic100,  RTmethodNoSubs100);
525         }
526 }
527
528
529 /*--------------------------------------------------------------*/
530
531 /*
532  * These are local overrides for various environment variables in Emacs.
533  * Please do not remove this and leave it at the end of the file, where
534  * Emacs will automagically detect them.
535  * ---------------------------------------------------------------------
536  * Local variables:
537  * mode: c
538  * indent-tabs-mode: t
539  * c-basic-offset: 4
540  * tab-width: 4
541  * End:
542  */
543