disasm.c: added support for static profiling (disabled), does not
[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 3979 2005-12-21 16:39:52Z anton $
33
34 */
35
36
37 #include <assert.h>
38
39 #include "config.h"
40 #include "vm/types.h"
41
42 #include "arch.h"
43
44 #include "vm/builtin.h"
45 #include "vm/class.h"
46 #include "vm/exceptions.h"
47 #include "vm/options.h"
48 #include "vm/jit/asmpart.h"
49 #include "vm/jit/methodheader.h"
50 #include "vm/jit/intrp/intrp.h"
51
52
53 /* this is required to link cacao with intrp */
54 threadcritnode asm_criticalsections = { NULL, NULL, NULL };
55
56
57 /* true on success, false on exception */
58 static bool asm_calljavafunction_intern(methodinfo *m, void *arg1, void *arg2,
59                                                                                 void *arg3, void *arg4)
60 {
61         java_objectheader *retval;
62         Cell *sp = global_sp;
63         methoddesc *md;
64         functionptr entrypoint;
65
66         md = m->parseddesc;
67
68         CLEAR_global_sp;
69         assert(sp != NULL);
70
71         /* XXX ugly hack: thread's run() needs 5 arguments */
72         assert(md->paramcount < 6);
73
74         if (md->paramcount > 0)
75                 *--sp=(Cell)arg1;
76         if (md->paramcount > 1)
77                 *--sp=(Cell)arg2;
78         if (md->paramcount > 2)
79                 *--sp=(Cell)arg3;
80         if (md->paramcount > 3)
81                 *--sp=(Cell)arg4;
82         if (md->paramcount > 4)
83                 *--sp=(Cell) 0;
84
85         entrypoint = createcalljavafunction(m);
86
87         retval = engine((Inst *) entrypoint, sp, NULL);
88
89         /* XXX remove the method from the method table */
90
91         if (retval != NULL) {
92                 (void) builtin_throw_exception(retval);
93                 return false;
94         }
95         else 
96                 return true;
97 }
98
99
100 s4 asm_calljavafunction_int(methodinfo *m, void *arg1, void *arg2,
101                                                         void *arg3, void *arg4)
102 {
103         assert(m->parseddesc->returntype.type == TYPE_INT);
104
105         if (asm_calljavafunction_intern(m, arg1, arg2, arg3, arg4))
106                 return (s4)(*global_sp++);
107         else
108                 return 0;
109 }
110
111
112 java_objectheader *asm_calljavafunction(methodinfo *m, void *arg1, void *arg2,
113                                                                                 void *arg3, void *arg4)
114 {
115         if (asm_calljavafunction_intern(m, arg1, arg2, arg3, arg4)) {
116                 if (m->parseddesc->returntype.type == TYPE_ADR)
117                         return (java_objectheader *)(*global_sp++);
118                 else {
119                         assert(m->parseddesc->returntype.type == TYPE_VOID);
120                         return NULL;
121                 }
122         } else
123                 return NULL;
124 }
125
126
127 /* true on success, false on exception */
128 static bool jni_invoke_java_intern(methodinfo *m, u4 count, u4 size,
129                                                                    jni_callblock *callblock)
130 {
131         java_objectheader *retval;
132         Cell *sp = global_sp;
133         s4 i;
134         functionptr entrypoint;
135
136         CLEAR_global_sp;
137         assert(sp != NULL);
138
139         for (i = 0; i < count; i++) {
140                 switch (callblock[i].itemtype) {
141                 case TYPE_INT:
142                 case TYPE_FLT:
143                 case TYPE_ADR:
144                         *(--sp) = callblock[i].item;
145                         break;
146                 case TYPE_LNG:
147                 case TYPE_DBL:
148                         sp -= 2;
149                         *((u8 *) sp) = callblock[i].item;
150                         break;
151                 }
152         }
153
154         entrypoint = createcalljavafunction(m);
155
156         retval = engine((Inst *) entrypoint, sp, NULL);
157
158         /* XXX remove the method from the method table */
159
160         if (retval != NULL) {
161                 (void)builtin_throw_exception(retval);
162                 return false;
163         }
164         else
165                 return true;
166 }
167
168
169 java_objectheader *asm_calljavafunction2(methodinfo *m, u4 count, u4 size,
170                                          jni_callblock *callblock)
171 {
172         java_objectheader *retval = NULL;
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 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 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 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 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 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  */