* src/vmcore/statistics.c (vm/jit/code.h): Added for codeinfo.
[cacao.git] / src / vm / jit / optimizing / recompile.c
1 /* src/vm/jit/optimizing/recompile.c - recompilation system
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: cacao.c 4357 2006-01-22 23:33:38Z 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 #if defined(ENABLE_THREADS)
40 # include "threads/threads-common.h"
41
42 # include "threads/native/lock.h"
43 # include "threads/native/threads.h"
44 #endif
45
46 #include "toolbox/list.h"
47
48 #include "vm/builtin.h"
49 #include "vm/exceptions.h"
50 #include "vm/stringlocal.h"
51
52 #include "vm/jit/code.h"
53 #include "vm/jit/jit.h"
54
55 #include "vm/jit/optimizing/recompile.h"
56
57 #include "vmcore/classcache.h"
58
59
60 /* global variables ***********************************************************/
61
62 static threadobject      *thread_recompile;
63 static java_objectheader *lock_thread_recompile;
64 static list              *list_recompile_methods;
65
66
67 /* recompile_init **************************************************************
68
69    Initializes the recompilation system.
70
71 *******************************************************************************/
72
73 bool recompile_init(void)
74 {
75         /* initialize the recompile lock object */
76
77         lock_thread_recompile = NEW(java_objectheader);
78
79         lock_init_object_lock(lock_thread_recompile);
80
81         /* create method list */
82
83         list_recompile_methods = list_create(OFFSET(list_method_entry, linkage));
84
85         /* everything's ok */
86
87         return true;
88 }
89
90
91 /* recompile_replace_vftbl *****************************************************
92
93    XXX
94
95 *******************************************************************************/
96
97 static void recompile_replace_vftbl(methodinfo *m)
98 {
99         codeinfo               *code;
100         codeinfo               *pcode;
101         u4                      slot;
102         classcache_name_entry  *nmen;
103         classcache_class_entry *clsen;
104         classinfo              *c;
105         vftbl_t                *vftbl;
106         s4                      i;
107
108         /* get current and previous codeinfo structure */
109
110         code  = m->code;
111         pcode = code->prev;
112
113         assert(pcode);
114
115         /* iterate over all classes */
116
117         for (slot = 0; slot < hashtable_classcache.size; slot++) {
118                 nmen = (classcache_name_entry *) hashtable_classcache.ptr[slot];
119
120                 for (; nmen; nmen = nmen->hashlink) {
121                         /* iterate over all class entries */
122
123                         for (clsen = nmen->classes; clsen; clsen = clsen->next) {
124                                 c = clsen->classobj;
125
126                                 if (c == NULL)
127                                         continue;
128
129                                 /* Search for entrypoint of the previous codeinfo in
130                                    the vftbl and replace it with the current one. */
131
132                                 vftbl = c->vftbl;
133
134                                 /* Is the class linked? Means, is the vftbl finished? */
135
136                                 if (!(c->state & CLASS_LINKED))
137                                         continue;
138
139                                 /* Does the class have a vftbl? Some internal classes
140                                    (e.g. $NEW$) are linked, but do not have a
141                                    vftbl. */
142
143                                 if (vftbl == NULL)
144                                         continue;
145
146                                 for (i = 0; i < vftbl->vftbllength; i++) {
147                                         if (vftbl->table[i] == pcode->entrypoint) {
148 #if !defined(NDEBUG)
149                                                 printf("replacing vftbl in: ");
150                                                 class_println(c);
151 #endif
152                                                 vftbl->table[i] = code->entrypoint;
153                                         }
154                                 }
155                         }
156                 }
157         }
158 }
159
160
161 /* recompile_thread ************************************************************
162
163    XXX
164
165 *******************************************************************************/
166
167 static void recompile_thread(void)
168 {
169         list_method_entry *lme;
170
171         while (true) {
172                 /* get the lock on the recompile lock object, so we can call wait */
173
174                 lock_monitor_enter(lock_thread_recompile);
175
176                 /* wait forever (0, 0) on that object till we are signaled */
177         
178                 lock_wait_for_object(lock_thread_recompile, 0, 0);
179
180                 /* leave the lock */
181
182                 lock_monitor_exit(lock_thread_recompile);
183
184                 /* get the next method and recompile it */
185
186                 while ((lme = list_first(list_recompile_methods)) != NULL) {
187                         /* recompile this method */
188
189                         if (jit_recompile(lme->m) != NULL) {
190                                 /* replace in vftbl's */
191
192                                 recompile_replace_vftbl(lme->m);
193                         }
194                         else {
195                                 /* XXX what is the right-thing(tm) to do here? */
196
197                                 exceptions_print_current_exception();
198                         }
199
200                         /* remove the compiled method */
201
202                         list_remove(list_recompile_methods, lme);
203
204                         /* free the entry */
205
206                         FREE(lme, list_method_entry);
207                 }
208         }
209 }
210
211
212 /* recompile_start_thread ******************************************************
213
214    Starts the recompilation thread.
215
216 *******************************************************************************/
217
218 bool recompile_start_thread(void)
219 {
220         utf *name;
221
222         name = utf_new_char("Recompiler");
223
224         thread_recompile = threads_create_thread(name);
225
226         if (thread_recompile == NULL)
227                 return false;
228
229         /* actually start the recompilation thread */
230
231         threads_start_thread(thread_recompile, recompile_thread);
232
233         /* everything's ok */
234
235         return true;
236 }
237
238
239 /* recompile_queue_method ******************************************************
240
241    Adds a method to the recompilation list and signal the
242    recompilation thread that there is some work to do.
243
244 *******************************************************************************/
245
246 void recompile_queue_method(methodinfo *m)
247 {
248         list_method_entry *lme;
249
250         /* create a method entry */
251
252         lme = NEW(list_method_entry);
253         lme->m = m;
254
255         /* and add it to the list */
256
257         list_add_last(list_recompile_methods, lme);
258
259         /* get the lock on the recompile lock object, so we can call notify */
260
261         lock_monitor_enter(lock_thread_recompile);
262
263         /* signal the recompiler thread */
264         
265         lock_notify_object(lock_thread_recompile);
266
267         /* leave the lock */
268
269         lock_monitor_exit(lock_thread_recompile);
270 }
271
272
273 /*
274  * These are local overrides for various environment variables in Emacs.
275  * Please do not remove this and leave it at the end of the file, where
276  * Emacs will automagically detect them.
277  * ---------------------------------------------------------------------
278  * Local variables:
279  * mode: c
280  * indent-tabs-mode: t
281  * c-basic-offset: 4
282  * tab-width: 4
283  * End:
284  */