86ebd5578e0f05bd3e2eae411c8d24701a637cd5
[cacao.git] / src / vm / jit / replace.h
1 /* vm/jit/replace.h - 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
36 #ifndef _REPLACE_H
37 #define _REPLACE_H
38
39 #include "config.h"
40 #include "vm/types.h"
41
42 #if defined(ENABLE_REPLACEMENT)
43
44 /* forward typedefs ***********************************************************/
45
46 typedef struct rplalloc rplalloc;
47 typedef struct rplpoint rplpoint;
48 typedef struct executionstate_t executionstate_t;
49 typedef struct sourcestate_t sourcestate_t;
50 typedef struct sourceframe_t sourceframe_t;
51 typedef struct replace_safestack_t replace_safestack_t;
52 typedef union  replace_val_t replace_val_t;
53
54 #include "arch.h"
55 #include "md-abi.h"
56
57 #include "vm/jit/reg.h"
58 #include "vm/jit/stacktrace.h"
59
60 #include "vmcore/method.h"
61
62
63 /* alignment for the safe stack used during replacement */
64
65 #define REPLACE_STACK_ALIGNMENT  16
66
67 /* the size of the safe stack we use during replacement */
68 /* Must be a multiple of REPLACE_STACK_ALIGNMENT.       */
69
70 #define REPLACE_SAFESTACK_SIZE  16384  /* bytes */
71
72
73 /*** structs *********************************************************/
74
75 #define RPLALLOC_STACK  -1
76 #define RPLALLOC_PARAM  -2
77 #define RPLALLOC_SYNC   -3
78
79 /* `rplalloc` is a compact struct for register allocation info        */
80
81 /* XXX optimize this for space efficiency */
82 struct rplalloc {
83         s4           index;     /* local index, -1 for stack slot         */
84         s4           regoff;    /* register index / stack slot offset     */
85         unsigned int flags:4;   /* OR of (INMEMORY,...)                   */
86         unsigned int type:4;    /* TYPE_... constant                      */
87 };
88
89 #if INMEMORY > 0x08
90 #error value of INMEMORY is too big to fit in rplalloc.flags
91 #endif
92
93
94 /* XXX what to do about overlapping rplpoints? */
95 /* CAUTION: Do not change the numerical values. These are used as     */
96 /*          indices into replace_normalize_type_map.                  */
97 #define RPLPOINT_TYPE_STD     BBTYPE_STD
98 #define RPLPOINT_TYPE_EXH     BBTYPE_EXH
99 #define RPLPOINT_TYPE_SBR     BBTYPE_SBR
100 #define RPLPOINT_TYPE_CALL    3
101 #define RPLPOINT_TYPE_INLINE  4
102 #define RPLPOINT_TYPE_RETURN  5
103 #define RPLPOINT_TYPE_BODY    6
104
105 #define RPLPOINT_FLAG_NOTRAP     0x01  /* rplpoint cannot be trapped */
106 #define RPLPOINT_FLAG_COUNTDOWN  0x02  /* count down hits            */
107 #define RPLPOINT_FLAG_ACTIVE     0x08  /* trap is active             */
108
109
110 #if !defined(NDEBUG)
111 #define RPLPOINT_CHECK(type)     , RPLPOINT_TYPE_##type
112 #define RPLPOINT_CHECK_BB(bptr)  , (bptr)->type
113 #else
114 #define RPLPOINT_CHECK(type)
115 #define RPLPOINT_CHECK_BB(bptr)
116 #endif
117
118
119 /* An `rplpoint` represents a replacement point in a compiled method  */
120
121 struct rplpoint {
122         u1          *pc;           /* machine code PC of this point       */
123         methodinfo  *method;       /* source method this point is in      */
124         rplpoint    *parent;       /* rplpoint of the inlined body        */ /* XXX unify with code */
125         rplalloc    *regalloc;     /* pointer to register index table     */
126         s4           id;           /* id of the rplpoint within method    */
127         s4           callsize;     /* size of call code in bytes          */
128         unsigned int regalloccount:20; /* number of local allocations     */
129         unsigned int type:4;           /* RPLPOINT_TYPE_... constant      */
130         unsigned int flags:8;          /* OR of RPLPOINT_... constants    */
131 };
132
133
134 union replace_val_t {
135         s4                 i;
136         s8                 l;
137         ptrint             p;
138         struct {
139                 u4 lo;
140                 u4 hi;
141         }                  words;
142         float              f;
143         double             d;
144         java_objectheader *a;
145 };
146
147
148 /* An `executionsstate` represents the state of a thread as it reached */
149 /* an replacement point or is about to enter one.                      */
150
151 struct executionstate_t {
152         u1           *pc;                               /* program counter */
153         u1           *sp;                   /* stack pointer within method */
154         u1           *pv;                   /* procedure value. NULL means */
155                                             /* search the AVL tree         */
156
157         ptrint        intregs[INT_REG_CNT];             /* register values */
158         double        fltregs[FLT_REG_CNT];             /* register values */
159
160         codeinfo     *code;            /* codeinfo corresponding to the pv */
161 };
162
163
164 struct sourceframe_t {
165         sourceframe_t *down;           /* source frame down the call chain */
166
167         methodinfo    *method;                  /* method this frame is in */
168         s4             id;
169         s4             type;
170
171         /* values */
172         replace_val_t  instance;
173
174         replace_val_t *javastack;                  /* values of stack vars */
175         u1            *javastacktype;              /*  types of stack vars */
176         s4             javastackdepth;             /* number of stack vars */
177
178         replace_val_t *javalocals;                 /* values of javalocals */
179         u1            *javalocaltype;              /*  types of javalocals */
180         s4             javalocalcount;             /* number of javalocals */
181
182         replace_val_t *syncslots;
183         s4             syncslotcount; /* XXX do we need more than one? */
184
185         /* mapping info */
186         rplpoint      *fromrp;         /* rplpoint used to read this frame */
187         codeinfo      *fromcode;              /* code this frame was using */
188         rplpoint      *torp;          /* rplpoint this frame was mapped to */
189         codeinfo      *tocode;            /* code this frame was mapped to */
190
191         /* info for native frames */
192         stackframeinfo *sfi;      /* sfi for native frames, otherwise NULL */
193         s4             nativeframesize;    /* size (bytes) of native frame */
194         u1            *nativepc;
195         ptrint         nativesavint[INT_SAV_CNT]; /* XXX temporary */
196         double         nativesavflt[FLT_REG_CNT]; /* XXX temporary */
197 };
198
199 #define REPLACE_IS_NATIVE_FRAME(frame)  ((frame)->sfi != NULL)
200 #define REPLACE_IS_JAVA_FRAME(frame)    ((frame)->sfi == NULL)
201
202
203 struct sourcestate_t {
204         sourceframe_t *frames;    /* list of source frames, from bottom up */
205 };
206
207
208 /* replace_safestack_t *********************************************************
209
210    This struct is used to allocate a safe stack area to be used during the
211    last phase of replacement. It also contains copies of all data needed
212    during this phase. (The data cannot be kept in normal variables, as
213    the C stack may be destroyed during replacement.)
214
215    CAUTION: Do not change the layout of this struct! The assembler code
216             depends on the order of fields. (`stack` must be first,
217                         directly followed by `es`.)
218
219 *******************************************************************************/
220
221 struct replace_safestack_t {
222         u1                stack[REPLACE_SAFESTACK_SIZE];
223         executionstate_t  es;
224         sourcestate_t    *ss;
225         u1               *mem;             /* start of the allocated memory chunk */
226         s4                dumpsize;
227 };
228
229
230 /*** macros for the codegens *******************************************/
231
232 #define REPLACEMENT_POINTS_INIT(cd, jd)                              \
233     if (!replace_create_replacement_points(jd))                      \
234         return false;                                                \
235     (cd)->replacementpoint = (jd)->code->rplpoints;
236
237 #define REPLACEMENT_POINTS_RESET(cd, jd)                             \
238     (cd)->replacementpoint = (jd)->code->rplpoints;
239
240 #define REPLACEMENT_POINT_BLOCK_START(cd, bptr)                      \
241     if ((bptr)->bitflags & BBFLAG_REPLACEMENT)                       \
242         codegen_set_replacement_point((cd) RPLPOINT_CHECK_BB(bptr));
243
244 #define REPLACEMENT_POINT_INLINE_START(cd, iptr)                     \
245     codegen_set_replacement_point(cd RPLPOINT_CHECK(INLINE));
246
247 #define REPLACEMENT_POINT_INLINE_BODY(cd, iptr)                      \
248     codegen_set_replacement_point_notrap(cd RPLPOINT_CHECK(BODY));
249
250 #define REPLACEMENT_POINT_RETURN(cd, iptr)                           \
251     codegen_set_replacement_point(cd RPLPOINT_CHECK(RETURN));
252
253 #define REPLACEMENT_POINT_INVOKE(cd, iptr)                           \
254     codegen_set_replacement_point(cd RPLPOINT_CHECK(CALL));
255
256 #define REPLACEMENT_POINT_INVOKE_RETURN(cd,  iptr)                   \
257     if (iptr->opc != ICMD_BUILTIN)                                   \
258         cd->replacementpoint[-1].callsize = (cd->mcodeptr - cd->mcodebase)\
259                     - (ptrint) cd->replacementpoint[-1].pc;
260
261 #define REPLACEMENT_EMIT_STUBS(jd)                                   \
262     emit_replacement_stubs(jd);
263
264 /*** prototypes ********************************************************/
265
266 bool replace_create_replacement_points(jitdata *jd);
267 void replace_free_replacement_points(codeinfo *code);
268
269 void replace_activate_replacement_points(codeinfo *code, bool mappable);
270 void replace_deactivate_replacement_points(codeinfo *code);
271
272 void replace_me(rplpoint *rp,executionstate_t *es);
273
274 #if !defined(NDEBUG)
275 void replace_show_replacement_points(codeinfo *code);
276 void replace_replacement_point_println(rplpoint *rp, int depth);
277 void replace_executionstate_println(executionstate_t *es);
278 void replace_sourcestate_println(sourcestate_t *ss);
279 void replace_sourcestate_println_short(sourcestate_t *ss);
280 void replace_source_frame_println(sourceframe_t *frame);
281 #endif
282
283 /* machine dependent functions (code in ARCH_DIR/md.c) */
284
285 #if defined(ENABLE_JIT)
286 void md_patch_replacement_point(codeinfo *code, s4 index, rplpoint *rp,
287                                                                 u1 *savedmcode);
288 #endif
289
290 #else /* !defined(ENABLE_REPLACEMENT) */
291
292 /*** macros for the codegens (disabled version) ************************/
293
294 #define REPLACEMENT_POINTS_INIT(cd, jd)
295 #define REPLACEMENT_POINTS_RESET(cd, jd)
296 #define REPLACEMENT_POINT_BLOCK_START(cd, bptr)
297 #define REPLACEMENT_POINT_INLINE_START(cd, iptr)
298 #define REPLACEMENT_POINT_INLINE_BODY(cd, iptr)
299 #define REPLACEMENT_POINT_RETURN(cd, iptr)
300 #define REPLACEMENT_POINT_INVOKE(cd, iptr)
301 #define REPLACEMENT_POINT_INVOKE_RETURN(cd, iptr)
302 #define REPLACEMENT_EMIT_STUBS(jd)
303
304 #endif /* defined(ENABLE_REPLACEMENT) */
305
306 #endif
307
308 /*
309  * These are local overrides for various environment variables in Emacs.
310  * Please do not remove this and leave it at the end of the file, where
311  * Emacs will automagically detect them.
312  * ---------------------------------------------------------------------
313  * Local variables:
314  * mode: c
315  * indent-tabs-mode: t
316  * c-basic-offset: 4
317  * tab-width: 4
318  * End:
319  * vim:noexpandtab:sw=4:ts=4:
320  */