* src/vm/jit/replace.c (replace_create_replacement_points): Don't use
[cacao.git] / src / vm / jit / replace.c
1 /* vm/jit/replace.c - on-stack replacement of methods
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, 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: Edwin Steiner
28
29    Changes:
30
31    $Id$
32
33 */
34
35 #include "config.h"
36 #include "vm/types.h"
37
38 #include <assert.h>
39
40 #include "mm/memory.h"
41 #include "vm/options.h"
42 #include "vm/jit/replace.h"
43
44 /* replace_create_replacement_points *******************************************
45  
46    Create the replacement points for the given code.
47   
48    IN:
49        code.............codeinfo where replacement points should be stored
50                             code->rplpoints must be NULL.
51                                                 code->rplpointcount must be 0.
52            rd...............registerdata containing allocation info.
53   
54    OUT:
55        code->rplpoints.......set to the list of replacement points
56            code->rplpointcount...number of replacement points
57            code->regalloc........list of allocation info
58            code->regalloccount...total length of allocation info list
59            code->globalcount.....number of global allocations at the
60                                  start of code->regalloc
61   
62    RETURN VALUE:
63        true.............everything ok 
64        false............an exception has been thrown
65    
66 *******************************************************************************/
67
68 bool replace_create_replacement_points(codeinfo *code,registerdata *rd)
69 {
70         basicblock *bptr;
71         int count;
72         methodinfo *m;
73         rplpoint *rplpoints;
74         rplpoint *rp;
75         int alloccount;
76         int globalcount;
77         s2 *regalloc;
78         s2 *ra;
79         int i;
80         stackptr sp;
81
82         /* assert that we wont overwrite already allocated data */
83         
84         assert(code);
85         assert(code->m);
86         assert(code->rplpoints == NULL);
87         assert(code->rplpointcount == 0);
88         assert(code->regalloc == NULL);
89         assert(code->regalloccount == 0);
90         assert(code->globalcount == 0);
91
92         /* iterate over the basic block list to find replacement points */
93
94         m = code->m;
95
96         count = 0;
97         alloccount = 0;
98         for (bptr = m->basicblocks; bptr; bptr = bptr->next) {
99                 if (!(bptr->bitflags & BBFLAG_REPLACEMENT))
100                         continue;
101
102                 /* there will be a replacement point at the start of this block */
103                 
104                 count++;
105                 alloccount += bptr->indepth;
106         }
107
108         /* if no points were found, there's nothing to do */
109         
110         if (!count)
111                 return true;
112
113         /* count global register allocations */
114
115         globalcount = m->maxlocals;
116         alloccount += globalcount;
117
118         /* allocate replacement point array and allocation array */
119         
120         rplpoints = MNEW(rplpoint,count);
121         regalloc = MNEW(s2,alloccount);
122         ra = regalloc;
123
124         /* store global register allocations */
125
126         for (i=0; i<m->maxlocals; ++i) {
127 #if defined(ENABLE_INTRP)
128                 if (!opt_intrp) {
129 #endif
130                 *ra++ = rd->locals[i][0].regoff; /* XXX */
131 #if defined(ENABLE_INTRP)
132                 }
133                 else {
134                         *ra++ = 0;
135                 }
136 #endif
137         }
138
139         /* initialize replacement point structs */
140
141         rp = rplpoints;
142         for (bptr = m->basicblocks; bptr; bptr = bptr->next) {
143                 if (!(bptr->bitflags & BBFLAG_REPLACEMENT))
144                         continue;
145
146                 /* there will be a replacement point at the start of this block */
147
148                 rp->pc = NULL;        /* set by codegen */
149                 rp->outcode = NULL;   /* set by codegen */
150                 rp->hashlink = NULL;
151                 rp->code = code;
152                 rp->target = NULL;
153                 rp->regalloc = ra;
154
155                 /* store local allocation info */
156
157                 for (sp = bptr->instack; sp; sp = sp->prev) {
158                         *ra++ = sp->regoff; /* XXX */
159                 }
160
161                 rp->regalloccount = ra - rp->regalloc;
162                 
163                 rp++;
164         }
165
166         /* store the data in the codeinfo */
167
168         code->rplpoints = rplpoints;
169         code->rplpointcount = count;
170         code->regalloc = regalloc;
171         code->regalloccount = alloccount;
172         code->globalcount = globalcount;
173
174         /* everything alright */
175
176         return true;
177 }
178
179 /* replace_free_replacement_points *********************************************
180  
181    Free memory used by replacement points.
182   
183    IN:
184        code.............codeinfo whose replacement points should be freed.
185   
186 *******************************************************************************/
187
188 void replace_free_replacement_points(codeinfo *code)
189 {
190         assert(code);
191
192         if (code->rplpoints)
193                 MFREE(code->rplpoints,rplpoint,code->rplpointcount);
194
195         if (code->regalloc)
196                 MFREE(code->regalloc,s2,code->regalloccount);
197
198         code->rplpoints = NULL;
199         code->rplpointcount = 0;
200         code->regalloc = NULL;
201         code->regalloccount = 0;
202         code->globalcount = 0;
203 }
204
205 /* replace_activate_replacement_point ******************************************
206  
207    Activate a replacement point. When this function returns, the
208    replacement point is "armed", that is each thread reaching this point
209    will be replace to `target`.
210    
211    IN:
212        rp...............replacement point to activate
213            target...........target of replacement
214   
215 *******************************************************************************/
216
217 void replace_activate_replacement_point(rplpoint *rp,rplpoint *target)
218 {
219         rp->target = target;
220         
221 #if defined(__I386__) && defined(ENABLE_JIT)
222         md_patch_replacement_point(rp);
223 #endif
224 }
225
226 /* replace_me ******************************************************************
227  
228    This function is called by asm_replacement_out when a thread reaches
229    a replacement point. `replace_me` must map the execution state to the
230    target replacement point and let execution continue there.
231
232    This function never returns!
233   
234    IN:
235        rp...............replacement point that has been reached
236            es...............executions state read by asm_replacement_out
237   
238 *******************************************************************************/
239
240 void replace_me(rplpoint *rp,executionstate *es)
241 {
242         rplpoint *target;
243         
244         target = rp->target;
245         
246         printf("replace_me(%p,%p)\n",(void*)rp,(void*)es);
247         fflush(stdout);
248
249         replace_replacement_point_println(rp);
250         replace_executionstate_println(es);
251
252         es->pc = rp->target->pc;
253 }
254
255 /* replace_replacement_point_println *******************************************
256  
257    Print replacement point info.
258   
259    IN:
260        rp...............the replacement point to print
261   
262 *******************************************************************************/
263
264 #ifndef NDEBUG
265 void replace_replacement_point_println(rplpoint *rp)
266 {
267         int j;
268
269         if (!rp) {
270                 printf("(rplpoint *)NULL\n");
271                 return;
272         }
273
274         printf("rplpoint %p pc:%p out:%p target:%p allocs:%d = [",
275                         (void*)rp,rp->pc,rp->outcode,(void*)rp->target,
276                         rp->regalloccount);
277
278         for (j=0; j<rp->regalloccount; ++j)
279                 printf(" %02d",rp->regalloc[j]);
280
281         printf("] method:");
282         method_print(rp->code->m);
283
284         printf("\n");
285 }
286 #endif
287
288 /* replace_show_replacement_points *********************************************
289  
290    Print replacement point info.
291   
292    IN:
293        code.............codeinfo whose replacement points should be printed.
294   
295 *******************************************************************************/
296
297 #ifndef NDEBUG
298 void replace_show_replacement_points(codeinfo *code)
299 {
300         int i;
301         rplpoint *rp;
302         
303         if (!code) {
304                 printf("(codeinfo *)NULL\n");
305                 return;
306         }
307
308         printf("\treplacement points: %d\n",code->rplpointcount);
309         printf("\tglobal allocations: %d\n",code->globalcount);
310         printf("\ttotal allocations : %d\n",code->regalloccount);
311         printf("\n");
312
313         for (i=0; i<code->rplpointcount; ++i) {
314                 rp = code->rplpoints + i;
315
316                 assert(rp->code == code);
317                 
318                 replace_replacement_point_println(rp);
319         }
320 }
321 #endif
322
323 /* replace_executionstate_println **********************************************
324  
325    Print execution state
326   
327    IN:
328        es...............the execution state to print
329   
330 *******************************************************************************/
331
332 #ifndef NDEBUG
333 void replace_executionstate_println(executionstate *es)
334 {
335         int i;
336
337         if (!es) {
338                 printf("(executionstate *)NULL\n");
339                 return;
340         }
341
342         printf("executionstate %p:\n",(void*)es);
343         printf("\tpc = %p\n",(void*)es->pc);
344         for (i=0; i<3; ++i) {
345                 printf("\tregs[%2d] = %016llx\n",i,(u8)es->regs[i]);
346         }
347
348         printf("\n");
349 }
350 #endif
351
352 /*
353  * These are local overrides for various environment variables in Emacs.
354  * Please do not remove this and leave it at the end of the file, where
355  * Emacs will automagically detect them.
356  * ---------------------------------------------------------------------
357  * Local variables:
358  * mode: c
359  * indent-tabs-mode: t
360  * c-basic-offset: 4
361  * tab-width: 4
362  * End:
363  * vim:noexpandtab:sw=4:ts=4:
364  */