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