5aba6908a69c62665d82a2ece41eb88d87e80e58
[cacao.git] / src / vm / jit / intrp / engine.c
1 /* src/vm/jit/intrp/engine.c - #included by engine1.c and engine2.c
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    $Id: engine.c 7366 2007-02-15 19:48:11Z twisti $
26 */
27
28
29 /* #define VM_DEBUG */
30
31 #include "config.h"
32
33 #include <assert.h>
34
35 #include "vm/types.h"
36
37 #include "arch.h"
38
39 #include "vm/jit/intrp/intrp.h"
40
41 #include "md-abi.h"                           /* required for TRACE_ARGS_NUM */
42
43 #include "mm/memory.h"
44
45 #if defined(ENABLE_THREADS)
46 # include "threads/native/threads.h"
47 #else
48 # include "threads/none/threads.h"
49 #endif
50
51 #include "vm/builtin.h"
52 #include "vm/exceptions.h"
53
54 #include "vm/jit/methodheader.h"
55 #include "vm/jit/patcher.h"
56 #include "vm/jit/stacktrace.h"
57
58 #include "vmcore/loader.h"
59 #include "vmcore/options.h"
60
61
62 #if defined(ENABLE_THREADS)
63 # ifndef USE_FAKE_ATOMIC_INSTRUCTIONS
64 #  include "machine-instr.h"
65 # else
66 #  include "threads/native/generic-primitives.h"
67 # endif
68 #endif
69
70 #if !defined(STORE_ORDER_BARRIER) && !defined(ENABLE_THREADS)
71 #define STORE_ORDER_BARRIER() /* nothing */
72 #endif
73
74
75 /* threading macros */
76 #define GCC_PR15242_WORKAROUND
77 #ifdef GCC_PR15242_WORKAROUND
78 #  define NEXT_P1_5
79 #  define DO_GOTO goto before_goto
80 #else
81 #  define NEXT_P1_5
82 #  define DO_GOTO goto *ip[-1]
83 #endif
84
85 #  define NEXT_P0
86 #  define IP            (ip)
87 #  define SET_IP(p)     do {ip=(p); NEXT_P0;} while (0)
88 #  define NEXT_INST     (*IP)
89 #  define INC_IP(const_inc)     do { ip+=(const_inc);} while (0)
90 #  define DEF_CA
91 #  define NEXT_P1       (ip++)
92 #  define NEXT_P2   do {NEXT_P1_5; DO_GOTO;} while(0)
93
94 #define NEXT ({DEF_CA NEXT_P1; NEXT_P2;})
95 #define IPTOS NEXT_INST
96
97 #if defined(__POWERPC__) || defined(__POWERPC64__) || defined(__SPARC__)
98 # define USE_spTOS
99 #endif
100
101 #if defined(USE_spTOS)
102 #define IF_spTOS(x) x
103 #else
104 #define IF_spTOS(x)
105 #define spTOS (sp[0])
106 #endif
107
108 #if defined(__I386__)
109 /* works with gcc-2.95.4 20011002 (Debian prerelease) without static supers */
110 #define SPREG /* __asm__("%esi") */
111 #define TOSREG /* __asm__("%ecx") */
112 #elif defined(__X86_64__)
113 /* works with gcc-4.0.2 (Debian 4.0.2-2) */
114 #define SPREG /* __asm__("%r15") */
115 #define TOSREG
116 #else
117 #define SPREG
118 #define TOSREG
119 #endif
120
121
122 /* conversion on fetch */
123
124 #ifdef VM_PROFILING
125 #define SUPER_END  vm_count_block(IP)
126 #else
127 #define SUPER_END
128 #define vm_uncount_block(_ip)   /* nothing */
129 #endif
130
131
132 #define THROW0       goto throw
133 #if 1
134 #define THROW(_ball) do { \
135                        __asm__(""); /* work around gcc PR 25285 */ \
136                        goto *throw_##_ball; \
137                      } while (0)
138 #else
139 #define THROW(_ball) do { \
140                        goto throw_##_ball##1; \
141                      } while (0)
142 #endif
143
144 #define THROWCODE(_ball) \
145     throw_##_ball##1: \
146         global_sp = sp; \
147         *exceptionptr = (stacktrace_inline_##_ball(NULL, (u1 *) fp, (u1 *) IP, (u1 *) IP)); \
148         CLEAR_global_sp; \
149         THROW0;
150
151 #define CHECK_NULL_PTR(ptr) \
152     { \
153         if ((ptr) == NULL) { \
154             THROW(nullpointerexception); \
155             } \
156         }
157
158 #define THROW_CLASSCASTEXCEPTION(o) \
159     { \
160                 classcastexception_object = o; \
161         THROW(classcastexception); \
162         }
163
164 #define CHECK_OUT_OF_BOUNDS(_array, _idx)              \
165         {                                            \
166           if (length_array(_array) <= (u4) (_idx)) { \
167                 arrayindexoutofbounds_index = (_idx); \
168                                 THROW(arrayindexoutofboundsexception); \
169           } \
170         }
171
172 #define CHECK_ZERO_DIVISOR(_divisor) \
173   { if (_divisor == 0) \
174       THROW(arithmeticexception); \
175   } 
176
177 #if 0
178 /* !! alignment bug */
179 #define access_local_long(_offset) \
180         ( *(s8 *)(((u1 *)fp) + (_offset)) )
181 #endif
182
183 #define length_array(array)                          \
184         ( ((java_arrayheader*)(array))->size )
185
186 #define access_array_int(array, index)               \
187         ((((java_intarray*)(array))->data)[index])
188
189 #define access_array_long(array, index)               \
190         ((((java_longarray*)(array))->data)[index])
191
192 #define access_array_char(array, index)               \
193         ((((java_chararray*)(array))->data)[index])
194
195 #define access_array_short(array, index)               \
196         ((((java_shortarray*)(array))->data)[index])
197
198 #define access_array_byte(array, index)               \
199         ((((java_bytearray*)(array))->data)[index])
200
201 #define access_array_addr(array, index)               \
202         ((((java_objectarray*)(array))->data)[index])
203
204 #define access_array_float(array, index)               \
205         ((((java_floatarray*)(array))->data)[index])
206
207 /* (see createcompilerstub in codegen.c) */
208 #define FRAMESIZE(stub) (((Cell *)stub)[1])
209
210 #if 0
211 #define CLEARSTACK(_start, _end) \
212          do {Cell *__start=(_start); MSET(__start,0,u1,(_end)-__start); } while (0)
213 #else
214 #define CLEARSTACK(_start, _end)
215 #endif
216
217
218 #ifdef VM_DEBUG
219 #define NAME(_x) if (vm_debug) {fprintf(vm_out, "%lx: %-20s, ", (long)(ip-1), _x); fprintf(vm_out,"fp=%p, sp=%p", fp, sp);}
220 #else
221 #define NAME(_x)
222 #endif
223
224 #define LABEL2(name) J_##name: __asm__("");
225 #define LABEL3(name) K_##name: __asm__("");
226
227
228 java_objectheader *
229 engine(Inst *ip0, Cell * sp0, Cell * fp)
230 {
231   Inst *ip;
232   register Cell *sp SPREG = sp0;
233   /* Inst ca1; XXX unused? */ /* code address; this is the next dispatched instruction */
234   IF_spTOS(register Cell spTOS TOSREG;)
235   static Inst   labels[] = {
236 #define INST_ADDR(_inst) (&&I_##_inst)
237 #include <java-labels.i>
238 #undef INST_ADDR
239           NULL,
240 #define INST_ADDR(_inst) (&&J_##_inst)
241 #include <java-labels.i>
242 #undef INST_ADDR
243 #define INST_ADDR(_inst) (&&K_##_inst)
244 #include <java-labels.i>
245 #undef INST_ADDR
246     (Label)&&after_last,
247     (Label)&&before_goto,
248     (Label)&&after_goto,
249 #define INST_ADDR(_inst) (&&H_##_inst)
250 #include <java-labels.i>
251 #undef INST_ADDR
252   };
253   /* local variables for the various throw codes; this helps make
254          potentially throwing instructions relocatable (instead of a
255          non-relocatable direct jump, they perform an indirect jump) */
256   Label throw_arithmeticexception            = &&throw_arithmeticexception1;
257   Label throw_arrayindexoutofboundsexception = &&throw_arrayindexoutofboundsexception1;
258   Label throw_classcastexception                         = &&throw_classcastexception1;  
259   Label throw_nullpointerexception                   = &&throw_nullpointerexception1;
260   Label throw_arraystoreexception            = &&throw_arraystoreexception1;
261   java_objectheader *classcastexception_object = NULL;
262   s4 arrayindexoutofbounds_index = 0; /* pass the index to the throw code */
263
264   if (vm_debug)
265       fprintf(vm_out,"entering engine(%p,%p,%p)\n",ip0,sp,fp);
266   if (ip0 == NULL) {
267     return (java_objectheader *)labels;
268   }
269
270   if (0) {
271   before_goto:
272           goto *ip[-1];
273   after_goto:
274           /* ensure that gcc does not constant-propagate the contents of
275                  these variables and thus undo our relocatability work */
276           throw_arithmeticexception = 0;
277           throw_arrayindexoutofboundsexception = 0;
278           throw_classcastexception = 0;
279           throw_nullpointerexception = 0;
280           throw_arraystoreexception = 0;
281
282       /* the actual codes jumped to through the ...exception variables */
283           THROWCODE(arithmeticexception);
284           THROWCODE(nullpointerexception);
285           THROWCODE(arraystoreexception);
286
287   throw_classcastexception1:
288           global_sp = sp;
289           *exceptionptr = stacktrace_inline_classcastexception(NULL, (u1 *) fp, (u1 *) IP, (u1 *) IP, classcastexception_object);
290           CLEAR_global_sp;
291           THROW0;
292
293   throw_arrayindexoutofboundsexception1:
294           global_sp = sp;
295           *exceptionptr = stacktrace_inline_arrayindexoutofboundsexception(NULL, (u1 *) fp, (u1 *) IP, (u1 *) IP, arrayindexoutofbounds_index);
296           CLEAR_global_sp;
297           THROW0;
298   }
299
300   /* I don't have a clue where these things come from,
301      but I've put them in macros.h for the moment */
302   IF_spTOS(spTOS = sp[0]);
303
304   SET_IP(ip0);
305   NEXT;
306
307 #define INST_ADDR(_inst) (&&I_##_inst)
308 #include <java-vm.i>
309 #undef NAME
310  after_last: return NULL;
311 }
312
313
314 /*
315  * These are local overrides for various environment variables in Emacs.
316  * Please do not remove this and leave it at the end of the file, where
317  * Emacs will automagically detect them.
318  * ---------------------------------------------------------------------
319  * Local variables:
320  * mode: c
321  * indent-tabs-mode: t
322  * c-basic-offset: 4
323  * tab-width: 4
324  * End:
325  * vim:noexpandtab:sw=4:ts=4:
326  */