* src/vm/jit/intrp/asmpart.c (intrp_asm_abstractmethoderror): Added.
[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, 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: Edwin Steiner
31
32    $Id: asmpart.c 5812 2006-10-20 14:22:23Z 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 #include "vm/jit/dseg.h"
54
55
56 static bool intrp_asm_vm_call_method_intern(methodinfo *m, s4 vmargscount,
57                                                                                         vm_arg *vmargs)
58 {
59         java_objectheader *retval;
60         Cell              *sp;
61         s4                 i;
62         u1                *entrypoint;
63
64         sp = global_sp;
65         CLEAR_global_sp;
66
67         assert(sp != NULL);
68
69         for (i = 0; i < vmargscount; i++) {
70                 switch (vmargs[i].type) {
71                 case TYPE_INT:
72                 case TYPE_FLT:
73                 case TYPE_ADR:
74                         *(--sp) = (Cell) vmargs[i].data.l;
75                         break;
76                 case TYPE_LNG:
77                 case TYPE_DBL:
78                         sp -= 2;
79                         *((u8 *) sp) = vmargs[i].data.l;
80                         break;
81                 }
82         }
83
84         entrypoint = createcalljavafunction(m);
85
86         retval = engine((Inst *) entrypoint, sp, NULL);
87
88         /* XXX remove the method from the method table */
89
90         if (retval != NULL) {
91                 (void)builtin_throw_exception(retval);
92                 return false;
93         }
94         else
95                 return true;
96 }
97
98
99 java_objectheader *intrp_asm_vm_call_method(methodinfo *m, s4 vmargscount,
100                                                                                         vm_arg *vmargs)
101 {
102         java_objectheader *retval = NULL;
103
104         if (intrp_asm_vm_call_method_intern(m, vmargscount, vmargs)) {
105                 if (m->parseddesc->returntype.type == TYPE_ADR)
106                         retval = (java_objectheader *)*global_sp++;
107                 else
108                         assert(m->parseddesc->returntype.type == TYPE_VOID);
109                 return retval;
110         } else
111                 return NULL;
112 }
113
114
115 s4 intrp_asm_vm_call_method_int(methodinfo *m, s4 vmargscount, vm_arg *vmargs)
116 {
117         s4 retval = 0;
118
119         if (intrp_asm_vm_call_method_intern(m, vmargscount, vmargs)) {
120                 if (m->parseddesc->returntype.type == TYPE_INT)
121                         retval = *global_sp++;
122                 else
123                         assert(m->parseddesc->returntype.type == TYPE_VOID);
124                 return retval;
125         } else
126                 return 0;
127 }
128
129
130 s8 intrp_asm_vm_call_method_long(methodinfo *m, s4 vmargscount, vm_arg *vmargs)
131 {
132         s8 retval;
133
134         assert(m->parseddesc->returntype.type == TYPE_LNG);
135
136         if (intrp_asm_vm_call_method_intern(m, vmargscount, vmargs)) {
137                 retval = *(s8 *)global_sp;
138                 global_sp += 2;
139                 return retval;
140         } else
141                 return 0;
142 }
143
144
145 float intrp_asm_vm_call_method_float(methodinfo *m, s4 vmargscount,
146                                                                          vm_arg *vmargs)
147 {
148         float retval;
149
150         assert(m->parseddesc->returntype.type == TYPE_FLT);
151
152         if (intrp_asm_vm_call_method_intern(m, vmargscount, vmargs)) {
153                 retval = *(float *)global_sp;
154                 global_sp += 1;
155                 return retval;
156         } else
157                 return 0.0;
158 }
159
160
161 double intrp_asm_vm_call_method_double(methodinfo *m, s4 vmargscount,
162                                                                            vm_arg *vmargs)
163 {
164         double retval;
165
166         assert(m->parseddesc->returntype.type == TYPE_DBL);
167
168         if (intrp_asm_vm_call_method_intern(m, vmargscount, vmargs)) {
169                 retval = *(double *)global_sp;
170                 global_sp += 2;
171                 return retval;
172         } else
173                 return 0.0;
174 }
175
176
177 Inst *intrp_asm_handle_exception(Inst *ip, java_objectheader *o, Cell *fp, Cell **new_spp, Cell **new_fpp)
178 {
179         classinfo            *c;
180         classref_or_classinfo cr;
181         s4                    framesize;
182         s4                    issync;
183         dseg_exception_entry *ex;
184         s4                    exceptiontablelength;
185         s4                    i;
186
187   /* for a description of the stack see IRETURN in java.vmg */
188
189   for (; fp != NULL; ) {
190           u1 *f = codegen_get_pv_from_pc((u1 *) (ip - 1));
191
192           /* get methodinfo pointer from method header */
193
194           codeinfo *code = *((codeinfo **) ((u1 *)f + CodeinfoPointer));
195           methodinfo *m = code->m;
196
197           framesize            = *((s4 *)             (((u1 *) f) + FrameSize));
198           issync               = *((s4 *)             (((u1 *) f) + IsSync));
199           ex                   =   (dseg_exception_entry *) 
200                                                                                                   (((u1 *) f) + ExTableStart);
201           exceptiontablelength = *((s4 *)             (((u1 *) f) + ExTableSize));
202
203 #if !defined(NDEBUG)
204           if (opt_verbose || opt_verbosecall || opt_verboseexception)
205                   builtin_trace_exception(o, m, ip, 1);
206 #endif
207
208           for (i = 0; i < exceptiontablelength; i++) {
209                   ex--;
210
211                   cr = ex->catchtype;
212
213                   if (cr.any == NULL) {
214                           /* catch all */
215                           c = NULL;
216                   }
217                   else {
218                           if (IS_CLASSREF(cr)) {
219                                   /* The exception class reference is unresolved. */
220                                   /* We have to do _eager_ resolving here. While the class of */
221                                   /* the exception object is guaranteed to be loaded, it may  */
222                                   /* well have been loaded by a different loader than the     */
223                                   /* defining loader of m's class, which is the one we must   */
224                                   /* use to resolve the catch class. Thus lazy resolving      */
225                                   /* might fail, even if the result of the resolution would   */
226                                   /* be an already loaded class.                              */
227
228                                   /* The resolving may involve Java code, so we need a usable */
229                                   /* global_sp. XXX is this a correct value for global_sp?    */
230
231                                   global_sp = (Cell *)(((u1 *)fp) - framesize - SIZEOF_VOID_P);
232
233                                   c = resolve_classref_eager(cr.ref);
234
235                                   CLEAR_global_sp;
236
237                                   if (c == NULL) {
238                                           /* Exception resolving the exception class, argh! */
239                                           /* XXX how to report that error? */
240                                           assert(0);
241                                   }
242
243                                   /* Ok, we resolved it. Enter it in the table, so we don't */
244                                   /* have to do this again.                                 */
245                                   /* XXX this write should be atomic. Is it?                */
246
247                                   ex->catchtype.cls = c;
248                           }
249                           else {
250                                   c = cr.cls;
251                                 
252                                   /* If the class is not linked, the exception object cannot */
253                                   /* be an instance of it.                                   */
254                                   if (!(c->state & CLASS_LINKED))
255                                           continue;
256                           }
257                   }
258
259                   if (ip-1 >= (Inst *) ex->startpc && ip-1 < (Inst *) ex->endpc &&
260                           (c == NULL || builtin_instanceof(o, c))) 
261                   {
262                           *new_spp = (Cell *)(((u1 *)fp) - framesize - SIZEOF_VOID_P);
263                           *new_fpp = fp;
264                           return (Inst *) (ex->handlerpc);
265                   }
266           }
267
268 #if defined(ENABLE_THREADS)
269           /* is this method synchronized? */
270
271           if (issync) {
272                   java_objectheader *syncobj;
273
274                   /* get synchronization object */
275
276                   if (m->flags & ACC_STATIC) {
277                           syncobj = (java_objectheader *) m->class;
278                   }
279                   else {
280                           syncobj = (java_objectheader *) access_local_cell(-framesize + SIZEOF_VOID_P);
281                   }
282
283                   assert(syncobj != NULL);
284
285                   lock_monitor_exit(syncobj);
286           }
287 #endif /* defined(ENABLE_THREADS) */
288
289           /* unwind stack frame */
290
291           ip = (Inst *)access_local_cell(-framesize - SIZEOF_VOID_P);
292           fp = (Cell *)access_local_cell(-framesize);
293   }
294
295   return NULL; 
296 }
297
298
299 void intrp_asm_abstractmethoderror(void)
300 {
301         vm_abort("intrp_asm_abstractmethoderror: IMPLEMENT ME!");
302 }
303
304
305 void intrp_asm_getclassvalues_atomic(vftbl_t *super, vftbl_t *sub, castinfo *out)
306 {
307         s4 sbv, sdv, sv;
308
309 #if defined(ENABLE_THREADS)
310         compiler_lock();
311 #endif
312
313         sbv = super->baseval;
314         sdv = super->diffval;
315         sv  = sub->baseval;
316
317 #if defined(ENABLE_THREADS)
318         compiler_unlock();
319 #endif
320
321         out->super_baseval = sbv;
322         out->super_diffval = sdv;
323         out->sub_baseval   = sv;
324 }
325
326
327 /*
328  * These are local overrides for various environment variables in Emacs.
329  * Please do not remove this and leave it at the end of the file, where
330  * Emacs will automagically detect them.
331  * ---------------------------------------------------------------------
332  * Local variables:
333  * mode: c
334  * indent-tabs-mode: t
335  * c-basic-offset: 4
336  * tab-width: 4
337  * End:
338  * vim:noexpandtab:sw=4:ts=4:
339  */