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