Merge from subtype.
[cacao.git] / src / vm / jit / intrp / patcher.c
1 /* src/vm/jit/intrp/patcher.c - Interpreter code patching functions
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 #include "vm/types.h"
28
29 #include "mm/memory.h"
30
31 #include "native/native.hpp"
32
33 #include "vm/jit/builtin.hpp"
34 #include "vm/class.hpp"
35 #include "vm/field.hpp"
36 #include "vm/initialize.hpp"
37 #include "vm/options.h"
38 #include "vm/references.h"
39 #include "vm/resolve.hpp"
40
41 #include "vm/jit/asmpart.h"
42 #include "vm/jit/patcher.h"
43
44
45 /* patcher_get_putstatic *******************************************************
46
47    Machine code:
48
49 *******************************************************************************/
50
51 bool intrp_patcher_get_putstatic(u1 *sp)
52 {
53         ptrint            *ip;
54         unresolved_field  *uf;
55         fieldinfo         *fi;
56
57         ip = (ptrint *) sp;
58         uf = (unresolved_field *) ip[2];
59
60         /* get the fieldinfo */
61
62         if (!(fi = resolve_field_eager(uf)))
63                 return false;
64
65         /* check if the field's class is initialized */
66
67         if (!(fi->clazz->state & CLASS_INITIALIZED))
68                 if (!initialize_class(fi->clazz))
69                         return false;
70
71         /* patch the field's address */
72
73         ip[1] = (ptrint) &(fi->value);
74
75         return true;
76 }
77
78
79 /* patcher_get_putstatic_clinit ************************************************
80
81    This patcher is used if we already have the resolved fieldinfo but the
82    class of the field has not been initialized, yet.
83    
84    Machine code:
85
86 *******************************************************************************/
87
88 bool intrp_patcher_get_putstatic_clinit(u1 *sp)
89 {
90         ptrint            *ip;
91         fieldinfo         *fi;
92
93         /* get the fieldinfo */
94
95         ip = (ptrint *) sp;
96         fi = (fieldinfo *) ip[2];
97
98         /* check if the field's class is initialized */
99
100         if (!(fi->clazz->state & CLASS_INITIALIZED))
101                 if (!initialize_class(fi->clazz))
102                         return false;
103
104         /* patch the field's address */
105
106         ip[1] = (ptrint) &(fi->value);
107
108         return true;
109 }
110
111
112 /* patcher_get_putfield ********************************************************
113
114    Machine code:
115
116 *******************************************************************************/
117
118 bool intrp_patcher_get_putfield(u1 *sp)
119 {
120         ptrint            *ip;
121         unresolved_field  *uf;
122         fieldinfo         *fi;
123
124         ip = (ptrint *) sp;
125         uf = (unresolved_field *) ip[2];
126
127         /* get the fieldinfo */
128
129         if (!(fi = resolve_field_eager(uf)))
130                 return false;
131
132         /* patch the field's offset */
133
134         ip[1] = fi->offset;
135
136         return true;
137 }
138
139
140 /* patcher_aconst **************************************************************
141
142    Machine code:
143
144 *******************************************************************************/
145
146 bool intrp_patcher_aconst(u1 *sp)
147 {
148         ptrint            *ip;
149         constant_classref *cr;
150         classinfo         *c;
151
152         ip = (ptrint *) sp;
153         cr = (constant_classref *) ip[2];
154         
155         /* get the classinfo */
156
157         if (!(c = resolve_classref_eager(cr)))
158                 return false;
159
160         /* patch the classinfo pointer */
161
162         ip[1] = (ptrint) c;
163
164         return true;
165 }
166
167
168 /* patcher_builtin_multianewarray **********************************************
169
170    Machine code:
171
172 *******************************************************************************/
173
174 bool intrp_patcher_builtin_multianewarray(u1 *sp)
175 {
176         ptrint            *ip;
177         constant_classref *cr;
178         classinfo         *c;
179
180         ip = (ptrint *) sp;
181         cr = (constant_classref *) ip[3];
182
183         /* get the classinfo */
184
185         if (!(c = resolve_classref_eager(cr)))
186                 return false;
187
188         /* patch the classinfo pointer */
189
190         ip[1] = (ptrint) c;
191
192         return true;
193 }
194
195
196 /* patcher_builtin_arraycheckcast **********************************************
197
198    Machine code:
199
200 *******************************************************************************/
201
202 bool intrp_patcher_builtin_arraycheckcast(u1 *sp)
203 {
204         ptrint            *ip;
205         constant_classref *cr;
206         classinfo         *c;
207
208         ip = (ptrint *) sp;
209         cr = (constant_classref *) ip[2];
210
211         /* get the classinfo */
212
213         if (!(c = resolve_classref_eager(cr)))
214                 return false;
215
216         /* patch the classinfo pointer */
217
218         ip[1] = (ptrint) c;
219
220         return true;
221 }
222
223
224 /* patcher_invokestatic_special ************************************************
225
226    Machine code:
227
228 ******************************************************************************/
229
230 bool intrp_patcher_invokestatic_special(u1 *sp)
231 {
232         ptrint            *ip;
233         unresolved_method *um;
234         methodinfo        *m;
235
236         ip = (ptrint *) sp;
237         um = (unresolved_method *) ip[3];
238
239         /* get the fieldinfo */
240
241         if (!(m = resolve_method_eager(um)))
242                 return false;
243
244         /* patch methodinfo and stubroutine */
245
246         ip[3] = (ptrint) m;
247         ip[1] = (ptrint) m->stubroutine;
248
249         return true;
250 }
251
252
253 /* patcher_invokevirtual *******************************************************
254
255    Machine code:
256
257 *******************************************************************************/
258
259 bool intrp_patcher_invokevirtual(u1 *sp)
260 {
261         ptrint            *ip;
262         unresolved_method *um;
263         methodinfo        *m;
264
265         ip = (ptrint *) sp;
266         um = (unresolved_method *) ip[3];
267
268         /* get the fieldinfo */
269
270         if (!(m = resolve_method_eager(um)))
271                 return false;
272
273         /* patch methodinfo and vftbl index */
274
275         ip[3] = (ptrint) m;
276         ip[1] = (OFFSET(vftbl_t, table[0]) + sizeof(methodptr) * m->vftblindex);
277
278         return true;
279 }
280
281
282 /* patcher_invokeinterface *****************************************************
283
284    Machine code:
285
286 *******************************************************************************/
287
288 bool intrp_patcher_invokeinterface(u1 *sp)
289 {
290         ptrint            *ip;
291         unresolved_method *um;
292         methodinfo        *m;
293
294         ip = (ptrint *) sp;
295         um = (unresolved_method *) ip[4];
296
297         /* get the methodinfo */
298
299         if (!(m = resolve_method_eager(um)))
300                 return false;
301
302         /* patch interfacetable index */
303
304         ip[1] = (OFFSET(vftbl_t, interfacetable[0]) -
305                          sizeof(methodptr*) * m->clazz->index);
306
307         /* patch methodinfo and method offset */
308
309         ip[4] = (ptrint) m;
310         ip[2] = (sizeof(methodptr) * (m - m->clazz->methods));
311
312         return true;
313 }
314
315
316 /* patcher_checkcast_instanceof ************************************************
317
318    Machine code:
319
320 *******************************************************************************/
321
322 bool intrp_patcher_checkcast_instanceof(u1 *sp)
323 {
324         ptrint            *ip;
325         constant_classref *cr;
326         classinfo         *c;
327
328         ip = (ptrint *) sp;
329         cr = (constant_classref *) ip[2];
330
331         /* get the classinfo */
332
333         if (!(c = resolve_classref_eager(cr)))
334                 return false;
335
336         /* patch super class pointer */
337
338         ip[1] = (ptrint) c;
339
340         return true;
341 }
342
343
344 /* patcher_resolve_native ******************************************************
345
346    XXX
347
348 *******************************************************************************/
349
350 bool intrp_patcher_resolve_native(u1 *sp)
351 {
352         ptrint      *ip;
353         methodinfo  *m;
354         functionptr  f;
355
356         ip = (ptrint *) sp;
357         m = (methodinfo *) ip[1];
358
359         /* resolve native function */
360
361         if (!(f = native_resolve_function(m)))
362                 return false;
363
364         /* patch native function pointer */
365
366         ip[2] = (ptrint) f;
367
368         return true;
369 }
370
371
372 /*
373  * These are local overrides for various environment variables in Emacs.
374  * Please do not remove this and leave it at the end of the file, where
375  * Emacs will automagically detect them.
376  * ---------------------------------------------------------------------
377  * Local variables:
378  * mode: c
379  * indent-tabs-mode: t
380  * c-basic-offset: 4
381  * tab-width: 4
382  * End:
383  * vim:noexpandtab:sw=4:ts=4:
384  */