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