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