bc5cd42bd0ea18c8337f2297d30fbb05b422fe9c
[cacao.git] / src / vm / jit / intrp / asmpart.c
1 /* src/vm/jit/intrp/asmpart.c - Java-C interface functions for Interpreter
2
3    Copyright (C) 1996-2005 R. Grafl, A. Krall, C. Kruegel, C. Oates,
4    R. Obermaisser, M. Platter, M. Probst, S. Ring, E. Steiner,
5    C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich, J. Wenninger,
6    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., 59 Temple Place - Suite 330, Boston, MA
23    02111-1307, USA.
24
25    Contact: cacao@complang.tuwien.ac.at
26
27    Authors: Christian Thalinger
28             Anton Ertl
29
30    Changes:
31
32    $Id: asmpart.c 4340 2006-01-22 19:55:52Z twisti $
33
34 */
35
36
37 #include "config.h"
38
39 #include <assert.h>
40
41 #include "vm/types.h"
42
43 #include "arch.h"
44
45 #include "vm/builtin.h"
46 #include "vm/class.h"
47 #include "vm/exceptions.h"
48 #include "vm/loader.h"
49 #include "vm/options.h"
50 #include "vm/jit/asmpart.h"
51 #include "vm/jit/methodheader.h"
52 #include "vm/jit/intrp/intrp.h"
53
54
55 /* true on success, false on exception */
56
57 static bool intrp_asm_calljavafunction_intern(methodinfo *m,
58                                                                                           void *arg1, void *arg2,
59                                                                                           void *arg3, void *arg4)
60 {
61         java_objectheader *retval;
62         Cell              *sp;
63         methoddesc        *md;
64         u1                *entrypoint;
65
66         sp = global_sp;
67         md = m->parseddesc;
68
69         CLEAR_global_sp;
70         assert(sp != NULL);
71
72         /* XXX ugly hack: thread's run() needs 5 arguments */
73         assert(md->paramcount < 6);
74
75         if (md->paramcount > 0)
76                 *--sp=(Cell)arg1;
77         if (md->paramcount > 1)
78                 *--sp=(Cell)arg2;
79         if (md->paramcount > 2)
80                 *--sp=(Cell)arg3;
81         if (md->paramcount > 3)
82                 *--sp=(Cell)arg4;
83         if (md->paramcount > 4)
84                 *--sp=(Cell) 0;
85
86         entrypoint = createcalljavafunction(m);
87
88         retval = engine((Inst *) entrypoint, sp, NULL);
89
90         /* XXX remove the method from the method table */
91
92         if (retval != NULL) {
93                 (void) builtin_throw_exception(retval);
94                 return false;
95         }
96         else 
97                 return true;
98 }
99
100
101 java_objectheader *intrp_asm_calljavafunction(methodinfo *m,
102                                                                                           void *arg1, void *arg2,
103                                                                                           void *arg3, void *arg4)
104 {
105         if (intrp_asm_calljavafunction_intern(m, arg1, arg2, arg3, arg4)) {
106                 if (m->parseddesc->returntype.type == TYPE_ADR)
107                         return (java_objectheader *)(*global_sp++);
108                 else {
109                         assert(m->parseddesc->returntype.type == TYPE_VOID);
110                         return NULL;
111                 }
112         } else
113                 return NULL;
114 }
115
116
117 s4 intrp_asm_calljavafunction_int(methodinfo *m, void *arg1, void *arg2,
118                                                                   void *arg3, void *arg4)
119 {
120         assert(m->parseddesc->returntype.type == TYPE_INT);
121
122         if (intrp_asm_calljavafunction_intern(m, arg1, arg2, arg3, arg4))
123                 return (s4) (*global_sp++);
124         else
125                 return 0;
126 }
127
128
129 /* true on success, false on exception */
130 static bool jni_invoke_java_intern(methodinfo *m, u4 count, u4 size,
131                                                                    jni_callblock *callblock)
132 {
133         java_objectheader *retval;
134         Cell              *sp;
135         s4                 i;
136         u1                *entrypoint;
137
138         sp = global_sp;
139         CLEAR_global_sp;
140
141         assert(sp != NULL);
142
143         for (i = 0; i < count; i++) {
144                 switch (callblock[i].itemtype) {
145                 case TYPE_INT:
146                 case TYPE_FLT:
147                 case TYPE_ADR:
148                         *(--sp) = callblock[i].item;
149                         break;
150                 case TYPE_LNG:
151                 case TYPE_DBL:
152                         sp -= 2;
153                         *((u8 *) sp) = callblock[i].item;
154                         break;
155                 }
156         }
157
158         entrypoint = createcalljavafunction(m);
159
160         retval = engine((Inst *) entrypoint, sp, NULL);
161
162         /* XXX remove the method from the method table */
163
164         if (retval != NULL) {
165                 (void)builtin_throw_exception(retval);
166                 return false;
167         }
168         else
169                 return true;
170 }
171
172
173 java_objectheader *intrp_asm_calljavafunction2(methodinfo *m, u4 count, u4 size,
174                                                                                            jni_callblock *callblock)
175 {
176         java_objectheader *retval = NULL;
177
178         if (jni_invoke_java_intern(m, count, size, callblock)) {
179                 if (m->parseddesc->returntype.type == TYPE_ADR)
180                         retval = (java_objectheader *)*global_sp++;
181                 else
182                         assert(m->parseddesc->returntype.type == TYPE_VOID);
183                 return retval;
184         } else
185                 return NULL;
186 }
187
188
189 s4 intrp_asm_calljavafunction2int(methodinfo *m, u4 count, u4 size,
190                                                                   jni_callblock *callblock)
191 {
192         s4 retval=0;
193
194         if (jni_invoke_java_intern(m, count, size, callblock)) {
195                 if (m->parseddesc->returntype.type == TYPE_INT)
196                         retval = *global_sp++;
197                 else
198                         assert(m->parseddesc->returntype.type == TYPE_VOID);
199                 return retval;
200         } else
201                 return 0;
202 }
203
204
205 s8 intrp_asm_calljavafunction2long(methodinfo *m, u4 count, u4 size,
206                                                                    jni_callblock *callblock)
207 {
208         s8 retval;
209
210         assert(m->parseddesc->returntype.type == TYPE_LNG);
211
212         if (jni_invoke_java_intern(m, count, size, callblock)) {
213                 retval = *(s8 *)global_sp;
214                 global_sp += 2;
215                 return retval;
216         } else
217                 return 0;
218 }
219
220
221 float intrp_asm_calljavafunction2float(methodinfo *m, u4 count, u4 size,
222                                                                            jni_callblock *callblock)
223 {
224         float retval;
225
226         assert(m->parseddesc->returntype.type == TYPE_FLT);
227
228         if (jni_invoke_java_intern(m, count, size, callblock)) {
229                 retval = *(float *)global_sp;
230                 global_sp += 1;
231                 return retval;
232         } else
233                 return 0.0;
234 }
235
236
237 double intrp_asm_calljavafunction2double(methodinfo *m, u4 count, u4 size,
238                                                                                  jni_callblock *callblock)
239 {
240         double retval;
241
242         assert(m->parseddesc->returntype.type == TYPE_DBL);
243
244         if (jni_invoke_java_intern(m, count, size, callblock)) {
245                 retval = *(double *)global_sp;
246                 global_sp += 2;
247                 return retval;
248         } else
249                 return 0.0;
250 }
251
252
253 Inst *intrp_asm_handle_exception(Inst *ip, java_objectheader *o, Cell *fp, Cell **new_spp, Cell **new_fpp)
254 {
255         classinfo      *c;
256         s4              framesize;
257         exceptionentry *ex;
258         s4              exceptiontablelength;
259         s4              i;
260
261   /* for a description of the stack see IRETURN in java.vmg */
262
263   for (; fp != NULL; ) {
264           u1 *f = codegen_findmethod((u1 *) (ip - 1));
265
266           /* get methodinfo pointer from method header */
267
268           methodinfo *m = *(methodinfo **) (((u1 *) f) + MethodPointer);
269
270           framesize = (*((s4 *) (((u1 *) f) + FrameSize)));
271           ex = (exceptionentry *) (((u1 *) f) + ExTableStart);
272           exceptiontablelength = *((s4 *) (((u1 *) f) + ExTableSize));
273
274           if (opt_verbose || runverbose || opt_verboseexception)
275                   builtin_trace_exception(o, m, ip, 1);
276
277           for (i = 0; i < exceptiontablelength; i++) {
278                   ex--;
279                   c = ex->catchtype.cls;
280
281                   if (c != NULL) {
282                           if (!(c->state & CLASS_LOADED))
283                                   /* XXX fix me! */
284                                   if (!load_class_bootstrap(c->name))
285                                           assert(0);
286
287                           if (!(c->state & CLASS_LINKED))
288                                   if (!link_class(c))
289                                           assert(0);
290                   }
291
292                   if (ip-1 >= (Inst *) ex->startpc && ip-1 < (Inst *) ex->endpc &&
293                           (c == NULL || builtin_instanceof(o, c))) {
294                           *new_spp = (Cell *)(((u1 *)fp) - framesize - SIZEOF_VOID_P);
295                           *new_fpp = fp;
296                           return (Inst *) (ex->handlerpc);
297                   }
298           }
299
300           ip = (Inst *)access_local_cell(-framesize - SIZEOF_VOID_P);
301           fp = (Cell *)access_local_cell(-framesize);
302   }
303
304   return NULL; 
305 }
306
307
308 void intrp_asm_getclassvalues_atomic(vftbl_t *super, vftbl_t *sub, castinfo *out)
309 {
310         s4 sbv, sdv, sv;
311
312 #if defined(USE_THREADS)
313 #if defined(NATIVE_THREADS)
314         compiler_lock();
315 #else
316         intsDisable();
317 #endif
318 #endif
319
320         sbv = super->baseval;
321         sdv = super->diffval;
322         sv  = sub->baseval;
323
324 #if defined(USE_THREADS)
325 #if defined(NATIVE_THREADS)
326         compiler_unlock();
327 #else
328         intsRestore();
329 #endif
330 #endif
331
332         out->super_baseval = sbv;
333         out->super_diffval = sdv;
334         out->sub_baseval   = sv;
335 }
336
337
338 /*
339  * These are local overrides for various environment variables in Emacs.
340  * Please do not remove this and leave it at the end of the file, where
341  * Emacs will automagically detect them.
342  * ---------------------------------------------------------------------
343  * Local variables:
344  * mode: c
345  * indent-tabs-mode: t
346  * c-basic-offset: 4
347  * tab-width: 4
348  * End:
349  */