* src/vm/jit/x86_64/codegen.c (codegen): Use d for return type checks.
[cacao.git] / src / vm / jit / recompile.c
1 /* src/vm/recompile.c - recompilation system
2
3    Copyright (C) 1996-2005, 2006 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    Contact: cacao@cacaojvm.org
26
27    Authors: Christian Thalinger
28
29    Changes:
30
31    $Id: cacao.c 4357 2006-01-22 23:33:38Z twisti $
32
33 */
34
35
36 #include "config.h"
37
38 #include <assert.h>
39 #include <stdlib.h>
40
41 #include "vm/types.h"
42
43 #include "mm/memory.h"
44 #include "native/jni.h"
45 #include "native/include/java_lang_Thread.h"
46 #include "native/include/java_lang_VMThread.h"
47
48 #if defined(ENABLE_THREADS)
49 # include "threads/native/lock.h"
50 # include "threads/native/threads.h"
51 #endif
52
53 #include "toolbox/list.h"
54 #include "vm/builtin.h"
55 #include "vm/classcache.h"
56 #include "vm/stringlocal.h"
57 #include "vm/jit/recompile.h"
58
59
60 /* global variables ***********************************************************/
61
62 static java_lang_VMThread *recompile_vmthread;
63 static java_objectheader *lock_recompile_thread;
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_recompile_thread = NEW(java_objectheader);
78
79         lock_init_object_lock(lock_recompile_thread);
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_recompile_thread);
175
176                 /* wait forever (0, 0) on that object till we are signaled */
177         
178                 lock_wait_for_object(lock_recompile_thread, 0, 0);
179
180                 /* leave the lock */
181
182                 lock_monitor_exit(lock_recompile_thread);
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                                 throw_exception();
196                         }
197
198                         /* remove the compiled method */
199
200                         list_remove(list_recompile_methods, lme);
201
202                         /* free the entry */
203
204                         FREE(lme, list_method_entry);
205                 }
206         }
207 }
208
209
210 /* recompile_start_thread ******************************************************
211
212    Starts the recompilation thread.
213
214 *******************************************************************************/
215
216 bool recompile_start_thread(void)
217 {
218         java_lang_Thread *t;
219
220         /* create the profile object */
221
222         recompile_vmthread =
223                 (java_lang_VMThread *) builtin_new(class_java_lang_VMThread);
224
225         if (recompile_vmthread == NULL)
226                 return false;
227
228         t = (java_lang_Thread *) builtin_new(class_java_lang_Thread);
229
230         t->vmThread = recompile_vmthread;
231         t->name     = javastring_new_from_ascii("Recompiler");
232         t->daemon   = true;
233         t->priority = 5;
234
235         recompile_vmthread->thread = t;
236
237         /* actually start the recompilation thread */
238
239         threads_start_thread(t, recompile_thread);
240
241         /* everything's ok */
242
243         return true;
244 }
245
246
247 /* recompile_queue_method ******************************************************
248
249    Adds a method to the recompilation list and signal the
250    recompilation thread that there is some work to do.
251
252 *******************************************************************************/
253
254 void recompile_queue_method(methodinfo *m)
255 {
256         list_method_entry *lme;
257
258         /* create a method entry */
259
260         lme = NEW(list_method_entry);
261         lme->m = m;
262
263         /* and add it to the list */
264
265         list_add_last(list_recompile_methods, lme);
266
267         /* get the lock on the recompile lock object, so we can call notify */
268
269         lock_monitor_enter(lock_recompile_thread);
270
271         /* signal the recompiler thread */
272         
273         lock_notify_object(lock_recompile_thread);
274
275         /* leave the lock */
276
277         lock_monitor_exit(lock_recompile_thread);
278 }
279
280
281 /*
282  * These are local overrides for various environment variables in Emacs.
283  * Please do not remove this and leave it at the end of the file, where
284  * Emacs will automagically detect them.
285  * ---------------------------------------------------------------------
286  * Local variables:
287  * mode: c
288  * indent-tabs-mode: t
289  * c-basic-offset: 4
290  * tab-width: 4
291  * End:
292  */