* src/vm/jit/jit.c (jit_compile_intern): Perform inlining if
[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_COUNTDOWN  0x02  /* count down hits            */
105 #define RPLPOINT_FLAG_ACTIVE     0x08  /* trap is active             */
106
107
108 #if !defined(NDEBUG)
109 #define RPLPOINT_CHECK(type)     , RPLPOINT_TYPE_##type
110 #define RPLPOINT_CHECK_BB(bptr)  , (bptr)->type
111 #else
112 #define RPLPOINT_CHECK(type)
113 #define RPLPOINT_CHECK_BB(bptr)
114 #endif
115
116
117 /* An `rplpoint` represents a replacement point in a compiled method  */
118
119 struct rplpoint {
120         u1          *pc;           /* machine code PC of this point       */
121         methodinfo  *method;       /* source method this point is in      */
122         rplpoint    *parent;       /* rplpoint of the inlined body        */ /* XXX unify with code */
123         rplalloc    *regalloc;     /* pointer to register index table     */
124         s4           id;           /* id of the rplpoint within method    */
125         s4           callsize;     /* size of call code in bytes          */
126         unsigned int regalloccount:20; /* number of local allocations     */
127         unsigned int type:4;           /* RPLPOINT_TYPE_... constant      */
128         unsigned int flags:8;          /* OR of RPLPOINT_... constants    */
129 };
130
131
132 union replace_val_t {
133         s4                 i;
134         s8                 l;
135         ptrint             p;
136         struct {
137                 u4 lo;
138                 u4 hi;
139         }                  words;
140         float              f;
141         double             d;
142         java_objectheader *a;
143 };
144
145
146 /* An `executionsstate` represents the state of a thread as it reached */
147 /* an replacement point or is about to enter one.                      */
148
149 struct executionstate_t {
150         u1           *pc;                               /* program counter */
151         u1           *sp;                   /* stack pointer within method */
152         u1           *pv;                   /* procedure value. NULL means */
153                                             /* search the AVL tree         */
154
155         ptrint        intregs[INT_REG_CNT];             /* register values */
156         double        fltregs[FLT_REG_CNT];             /* register values */
157
158         codeinfo     *code;            /* codeinfo corresponding to the pv */
159 };
160
161
162 struct sourceframe_t {
163         sourceframe_t *down;           /* source frame down the call chain */
164
165         methodinfo    *method;                  /* method this frame is in */
166         s4             id;
167         s4             type;
168
169         /* values */
170         replace_val_t  instance;
171
172         replace_val_t *javastack;                  /* values of stack vars */
173         u1            *javastacktype;              /*  types of stack vars */
174         s4             javastackdepth;             /* number of stack vars */
175
176         replace_val_t *javalocals;                 /* values of javalocals */
177         u1            *javalocaltype;              /*  types of javalocals */
178         s4             javalocalcount;             /* number of javalocals */
179
180         replace_val_t *syncslots;
181         s4             syncslotcount; /* XXX do we need more than one? */
182
183         /* mapping info */
184         rplpoint      *fromrp;         /* rplpoint used to read this frame */
185         codeinfo      *fromcode;              /* code this frame was using */
186         rplpoint      *torp;          /* rplpoint this frame was mapped to */
187         codeinfo      *tocode;            /* code this frame was mapped to */
188
189         /* info for native frames */
190         stackframeinfo *sfi;      /* sfi for native frames, otherwise NULL */
191         s4             nativeframesize;    /* size (bytes) of native frame */
192         u1            *nativepc;
193         ptrint         nativesavint[INT_SAV_CNT]; /* XXX temporary */
194         double         nativesavflt[FLT_REG_CNT]; /* XXX temporary */
195 };
196
197 #define REPLACE_IS_NATIVE_FRAME(frame)  ((frame)->sfi != NULL)
198 #define REPLACE_IS_JAVA_FRAME(frame)    ((frame)->sfi == NULL)
199
200
201 struct sourcestate_t {
202         sourceframe_t *frames;    /* list of source frames, from bottom up */
203 };
204
205
206 /* replace_safestack_t *********************************************************
207
208    This struct is used to allocate a safe stack area to be used during the
209    last phase of replacement. It also contains copies of all data needed
210    during this phase. (The data cannot be kept in normal variables, as
211    the C stack may be destroyed during replacement.)
212
213    CAUTION: Do not change the layout of this struct! The assembler code
214             depends on the order of fields. (`stack` must be first,
215                         directly followed by `es`.)
216
217 *******************************************************************************/
218
219 struct replace_safestack_t {
220         u1                stack[REPLACE_SAFESTACK_SIZE];
221         executionstate_t  es;
222         sourcestate_t    *ss;
223         u1               *mem;             /* start of the allocated memory chunk */
224         s4                dumpsize;
225 };
226
227
228 /*** macros for the codegens *******************************************/
229
230 #define REPLACEMENT_POINTS_INIT(cd, jd)                              \
231     if (!replace_create_replacement_points(jd))                      \
232         return false;                                                \
233     (cd)->replacementpoint = (jd)->code->rplpoints;
234
235 #define REPLACEMENT_POINTS_RESET(cd, jd)                             \
236     (cd)->replacementpoint = (jd)->code->rplpoints;
237
238 #define REPLACEMENT_POINT_BLOCK_START(cd, bptr)                      \
239     if ((bptr)->bitflags & BBFLAG_REPLACEMENT)                       \
240         codegen_set_replacement_point((cd) RPLPOINT_CHECK_BB(bptr));
241
242 #define REPLACEMENT_POINT_INLINE_START(cd, iptr)                     \
243     codegen_set_replacement_point(cd RPLPOINT_CHECK(INLINE));
244
245 #define REPLACEMENT_POINT_INLINE_BODY(cd, iptr)                      \
246     codegen_set_replacement_point_notrap(cd RPLPOINT_CHECK(BODY));
247
248 #define REPLACEMENT_POINT_RETURN(cd, iptr)                           \
249     codegen_set_replacement_point(cd RPLPOINT_CHECK(RETURN));
250
251 #define REPLACEMENT_POINT_INVOKE(cd, iptr)                           \
252     codegen_set_replacement_point(cd RPLPOINT_CHECK(CALL));
253
254 #define REPLACEMENT_POINT_INVOKE_RETURN(cd,  iptr)                   \
255     if (iptr->opc != ICMD_BUILTIN)                                   \
256         cd->replacementpoint[-1].callsize = (cd->mcodeptr - cd->mcodebase)\
257                     - (ptrint) cd->replacementpoint[-1].pc;
258
259 #define REPLACEMENT_EMIT_STUBS(jd)                                   \
260     emit_replacement_stubs(jd);
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 void replace_me(rplpoint *rp,executionstate_t *es);
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(codeinfo *code, s4 index, rplpoint *rp,
285                                                                 u1 *savedmcode);
286 #endif
287
288 #endif
289
290 /*
291  * These are local overrides for various environment variables in Emacs.
292  * Please do not remove this and leave it at the end of the file, where
293  * Emacs will automagically detect them.
294  * ---------------------------------------------------------------------
295  * Local variables:
296  * mode: c
297  * indent-tabs-mode: t
298  * c-basic-offset: 4
299  * tab-width: 4
300  * End:
301  * vim:noexpandtab:sw=4:ts=4:
302  */