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