3bdc4678f5e4467ae9d329bd1f6e7e1c50fe9684
[cacao.git] / src / vm / jit / code.c
1 /* src/vm/jit/code.c - codeinfo struct for representing compiled code
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
28 #include <assert.h>
29 #include <stdint.h>
30
31 #include "arch.h"
32
33 #include "mm/memory.h"
34
35 #include "vm/vm.h"
36
37 #include "vm/jit/code.h"
38 #include "vm/jit/codegen-common.h"
39 #include "vm/jit/patcher-common.h"
40 #include "vm/jit/methodtree.h"
41
42 #include "vmcore/options.h"
43
44
45 /* code_init *******************************************************************
46
47    Initialize the code-subsystem.
48
49 *******************************************************************************/
50
51 void code_init(void)
52 {
53         /* Check if offset of codeinfo.m == 0 (see comment in code.h). */
54
55         if (OFFSET(codeinfo, m) != 0)
56                 vm_abort("code_init: offset of codeinfo.m != 0: %d != 0", OFFSET(codeinfo, m));
57 }
58
59
60 /* code_codeinfo_new ***********************************************************
61
62    Create a new codeinfo for the given method.
63    
64    IN:
65        m................method to create a new codeinfo for
66
67    The following fields are set in codeinfo:
68        m
69        patchers
70
71    RETURN VALUE:
72        a new, initialized codeinfo, or
73            NULL if an exception occurred.
74   
75 *******************************************************************************/
76
77 codeinfo *code_codeinfo_new(methodinfo *m)
78 {
79         codeinfo *code;
80
81         code = NEW(codeinfo);
82
83         code->m = m;
84
85         patcher_list_create(code);
86
87 #if defined(ENABLE_STATISTICS)
88         if (opt_stat)
89                 size_codeinfo += sizeof(codeinfo);
90 #endif
91
92         return code;
93 }
94
95
96 /* code_find_codeinfo_for_pc ***************************************************
97
98    Return the codeinfo for the compilation unit that contains the
99    given PC.
100
101    ARGUMENTS:
102        pc...............machine code position
103
104    RETURN VALUE:
105        the codeinfo * for the given PC
106
107 *******************************************************************************/
108
109 codeinfo *code_find_codeinfo_for_pc(void *pc)
110 {
111         void *pv;
112
113         pv = methodtree_find(pc);
114
115         return code_get_codeinfo_for_pv(pv);
116 }
117
118
119 /* code_find_codeinfo_for_pc ***************************************************
120
121    Return the codeinfo for the compilation unit that contains the
122    given PC. This method does not check the return value and is used
123    by the GC.
124
125    IN:
126        pc...............machine code position
127
128    RETURN VALUE:
129        the codeinfo * for the given PC, or NULL
130
131 *******************************************************************************/
132
133 codeinfo *code_find_codeinfo_for_pc_nocheck(void *pc)
134 {
135         void *pv;
136
137         pv = methodtree_find_nocheck(pc);
138
139         if (pv == NULL)
140                 return NULL;
141
142         return code_get_codeinfo_for_pv(pv);
143 }
144
145
146 /* code_get_methodinfo_for_pv **************************************************
147
148    Return the methodinfo for the given PV.
149
150    IN:
151        pv...............PV
152
153    RETURN VALUE:
154        the methodinfo *
155
156 *******************************************************************************/
157
158 methodinfo *code_get_methodinfo_for_pv(void *pv)
159 {
160         codeinfo *code;
161
162         code = code_get_codeinfo_for_pv(pv);
163
164         /* This is the case for asm_vm_call_method. */
165
166         if (code == NULL)
167                 return NULL;
168
169         return code->m;
170 }
171
172
173 /* code_get_sync_slot_count ****************************************************
174
175    Return the number of stack slots used for storing the synchronized object
176    (and the return value around lock_monitor_exit calls) by the given code.
177    
178    IN:
179        code.............the codeinfo of the code in question
180                             (must be != NULL)
181
182    RETURN VALUE:
183        the number of stack slots used for synchronization
184   
185 *******************************************************************************/
186
187 #if defined(ENABLE_REPLACEMENT)
188 int code_get_sync_slot_count(codeinfo *code)
189 {
190 #ifdef ENABLE_THREADS
191         int count;
192         
193         assert(code);
194
195         if (!checksync)
196                 return 0;
197
198         if (!code_is_synchronized(code))
199                 return 0;
200
201         count = 1;
202
203 #ifdef HAS_4BYTE_STACKSLOT
204         /* long and double need 2 4-byte slots */
205         if (IS_2_WORD_TYPE(code->m->parseddesc->returntype.type))
206                 count++;
207 #endif
208
209 #if defined(__POWERPC__)
210         /* powerpc needs an extra slot */
211         count++;
212 #endif
213
214         return count;
215
216 #else /* !ENABLE_THREADS */
217         
218         return 0;
219
220 #endif /* ENABLE_THREADS */
221 }
222 #endif /* defined(ENABLE_REPLACEMENT) */
223
224
225 /* code_codeinfo_free **********************************************************
226
227    Free the memory used by a codeinfo.
228    
229    IN:
230        code.............the codeinfo to free
231
232 *******************************************************************************/
233
234 void code_codeinfo_free(codeinfo *code)
235 {
236         if (code == NULL)
237                 return;
238
239         if (code->mcode != NULL)
240                 CFREE((void *) (ptrint) code->mcode, code->mcodelength);
241
242         patcher_list_free(code);
243
244 #if defined(ENABLE_REPLACEMENT)
245         replace_free_replacement_points(code);
246 #endif
247
248         FREE(code, codeinfo);
249
250 #if defined(ENABLE_STATISTICS)
251         if (opt_stat)
252                 size_codeinfo -= sizeof(codeinfo);
253 #endif
254 }
255
256
257 /* code_free_code_of_method ****************************************************
258
259    Free all codeinfos of the given method
260    
261    IN:
262        m................the method of which the codeinfos are to be freed
263
264 *******************************************************************************/
265
266 void code_free_code_of_method(methodinfo *m)
267 {
268         codeinfo *nextcode;
269         codeinfo *code;
270
271         if (!m)
272                 return;
273         
274         nextcode = m->code;
275         while (nextcode) {
276                 code = nextcode;
277                 nextcode = code->prev;
278                 code_codeinfo_free(code);
279         }
280
281         m->code = NULL;
282 }
283
284 /*
285  * These are local overrides for various environment variables in Emacs.
286  * Please do not remove this and leave it at the end of the file, where
287  * Emacs will automagically detect them.
288  * ---------------------------------------------------------------------
289  * Local variables:
290  * mode: c
291  * indent-tabs-mode: t
292  * c-basic-offset: 4
293  * tab-width: 4
294  * End:
295  * vim:noexpandtab:sw=4:ts=4:
296  */