1f988b702a17348fb05af75bd0bdb7520f49452f
[cacao.git] / src / vm / jit / optimizing / profile.c
1 /* src/vm/jit/optimizing/profile.c - runtime profiling
2
3    Copyright (C) 1996-2005, 2006, 2007 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, 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    $Id: profile.c 7952 2007-05-23 17:53:13Z twisti $
26
27 */
28
29
30 #include "config.h"
31
32 #include <assert.h>
33 #include <stdlib.h>
34
35 #include "vm/types.h"
36
37 #include "mm/memory.h"
38
39 #include "threads/threads-common.h"
40
41 #include "vm/builtin.h"
42 #include "vm/stringlocal.h"
43
44 #include "vm/jit/jit.h"
45 #include "vm/jit/methodheader.h"
46 #include "vm/jit/optimizing/recompile.h"
47
48 #include "vmcore/class.h"
49 #include "vmcore/classcache.h"
50 #include "vmcore/method.h"
51 #include "vmcore/options.h"
52
53
54 /* profile_init ****************************************************************
55
56    Initializes the profile global lock.
57
58 *******************************************************************************/
59
60 bool profile_init(void)
61 {
62         /* everything's ok */
63
64         return true;
65 }
66
67
68 /* profile_thread **************************************************************
69
70    XXX
71
72 *******************************************************************************/
73
74 static s4 runs = 0;
75 static s4 hits = 0;
76 static s4 misses = 0;
77
78 #if defined(ENABLE_THREADS)
79 static void profile_thread(void)
80 {
81         threadobject *t;
82         s4            nanos;
83         u1           *pc;
84         u1           *pv;
85         methodinfo   *m;
86         codeinfo     *code;
87
88         while (true) {
89                 /* sleep thread for 0.5-1.0 ms */
90
91                 nanos = 500 + (int) (500.0 * (rand() / (RAND_MAX + 1.0)));
92 /*              fprintf(stderr, "%d\n", nanos); */
93
94                 threads_sleep(0, nanos);
95                 runs++;
96
97                 /* lock the threads lists */
98
99                 threads_list_lock();
100
101                 /* iterate over all started threads */
102
103                 for (t = threads_list_first(); t != NULL; t = threads_list_next(t)) {
104                         /* is this a Java thread? */
105
106                         if (!(t->flags & THREAD_FLAG_JAVA))
107                                 continue;
108
109                         /* send SIGUSR2 to thread to get the current PC */
110                         /* XXX write a threads-function for that */
111
112                         pthread_kill(t->tid, SIGUSR2);
113
114                         /* the thread object now contains the current thread PC */
115
116                         pc = t->pc;
117
118                         /* get the PV for the current PC */
119
120                         pv = codegen_get_pv_from_pc_nocheck(pc);
121
122                         /* get methodinfo pointer from data segment */
123
124                         if (pv == NULL) {
125                                 misses++;
126                         }
127                         else {
128                                 code = *((codeinfo **) (pv + CodeinfoPointer));
129
130                                 /* For asm_vm_call_method the codeinfo pointer is NULL
131                                    (which is also in the method tree). */
132
133                                 if (code != NULL) {
134                                         m = code->m;
135
136                                         /* native methods are never recompiled */
137
138                                         if (!(m->flags & ACC_NATIVE)) {
139                                                 /* increase the method incovation counter */
140
141                                                 code->frequency++;
142                                                 hits++;
143
144                                                 if (code->frequency > 500) {
145                                                         /* clear frequency count before
146                                                            recompilation */
147
148                                                         code->frequency = 0;
149
150                                                         /* add this method to the method list and
151                                                            start recompilation */
152
153                                                         recompile_queue_method(m);
154                                                 }
155                                         }
156                                 }
157                         }
158                 }
159
160                 /* unlock the threads lists */
161
162                 threads_list_unlock();
163         }
164 }
165 #endif
166
167
168 /* profile_start_thread ********************************************************
169
170    Starts the profile sampling thread.
171
172 *******************************************************************************/
173
174 #if defined(ENABLE_THREADS)
175 bool profile_start_thread(void)
176 {
177         utf *name;
178
179         name = utf_new_char("Profiling Sampler");
180
181         if (!threads_thread_start_internal(name, profile_thread))
182                 return false;
183
184         /* everything's ok */
185
186         return true;
187 }
188 #endif
189
190
191 /* profile_printstats **********************************************************
192
193    Prints profiling statistics gathered during runtime.
194
195 *******************************************************************************/
196
197 #if !defined(NDEBUG)
198 void profile_printstats(void)
199 {
200         list_t                 *l;
201         list_method_entry      *lme;
202         list_method_entry      *tlme;
203         classinfo              *c;
204         methodinfo             *m;
205         codeinfo               *code;
206         u4                      slot;
207         classcache_name_entry  *nmen;
208         classcache_class_entry *clsen;
209         s4                      i;
210         s4                      j;
211         u4                      frequency;
212         s8                      cycles;
213
214         frequency = 0;
215         cycles    = 0;
216
217         /* create new method list */
218
219         l = list_create(OFFSET(list_method_entry, linkage));
220
221         /* iterate through all classes and methods */
222
223         for (slot = 0; slot < hashtable_classcache.size; slot++) {
224                 nmen = (classcache_name_entry *) hashtable_classcache.ptr[slot];
225
226                 for (; nmen; nmen = nmen->hashlink) {
227                         /* iterate over all class entries */
228
229                         for (clsen = nmen->classes; clsen; clsen = clsen->next) {
230                                 c = clsen->classobj;
231
232                                 if (c == NULL)
233                                         continue;
234
235                                 /* interate over all class methods */
236
237                                 for (i = 0; i < c->methodscount; i++) {
238                                         m = &(c->methods[i]);
239
240                                         code = m->code;
241
242                                         /* was this method actually called? */
243
244                                         if ((code != NULL) && (code->frequency > 0)) {
245                                                 /* add to overall stats */
246
247                                                 frequency += code->frequency;
248                                                 cycles    += code->cycles;
249
250                                                 /* create new list entry */
251
252                                                 lme = NEW(list_method_entry);
253                                                 lme->m = m;
254
255                                                 /* sort the new entry into the list */
256                                                 
257                                                 if ((tlme = list_first(l)) == NULL) {
258                                                         list_add_first(l, lme);
259                                                 }
260                                                 else {
261                                                         for (; tlme != NULL; tlme = list_next(l, tlme)) {
262                                                                 /* check the frequency */
263
264                                                                 if (code->frequency > tlme->m->code->frequency) {
265                                                                         list_add_before(l, tlme, lme);
266                                                                         break;
267                                                                 }
268                                                         }
269
270                                                         /* if we are at the end of the list, add
271                                                            it as last entry */
272
273                                                         if (tlme == NULL)
274                                                                 list_add_last(l, lme);
275                                                 }
276                                         }
277                                 }
278                         }
279                 }
280         }
281
282         /* print all methods sorted */
283
284         printf(" frequency     ratio         cycles     ratio   method name\n");
285         printf("----------- --------- -------------- --------- -------------\n");
286
287         /* now iterate through the list and print it */
288
289         for (lme = list_first(l); lme != NULL; lme = list_next(l, lme)) {
290                 /* get method of the list element */
291
292                 m = lme->m;
293
294                 code = m->code;
295
296                 printf("%10d   %.5f   %12ld   %.5f   ",
297                            code->frequency,
298                            (double) code->frequency / (double) frequency,
299                            (long) code->cycles,
300                            (double) code->cycles / (double) cycles);
301
302                 method_println(m);
303
304                 /* print basic block frequencies */
305
306                 if (opt_prof_bb) {
307                         for (j = 0; j < code->basicblockcount; j++)
308                                 printf("                                                    L%03d: %10d\n",
309                                            j, code->bbfrequency[j]);
310                 }
311         }
312
313         printf("-----------           -------------- \n");
314         printf("%10d             %12ld\n", frequency, (long) cycles);
315
316         printf("\nruns  : %10d\n", runs);
317         printf("hits  : %10d\n", hits);
318         printf("misses: %10d\n", misses);
319 }
320 #endif /* !defined(NDEBUG) */
321
322
323 /*
324  * These are local overrides for various environment variables in Emacs.
325  * Please do not remove this and leave it at the end of the file, where
326  * Emacs will automagically detect them.
327  * ---------------------------------------------------------------------
328  * Local variables:
329  * mode: c
330  * indent-tabs-mode: t
331  * c-basic-offset: 4
332  * tab-width: 4
333  * End:
334  */