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