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