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