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