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