7 #include "vm/jit/intrp/intrp.h"
9 #include "md-abi.h" /* required for TRACE_ARGS_NUM */
11 #include "cacao/cacao.h"
12 #include "vm/builtin.h"
13 #include "vm/exceptions.h"
14 #include "vm/loader.h"
15 #include "vm/options.h"
16 #include "vm/jit/codegen.inc.h"
17 #include "vm/jit/methodheader.h"
18 #include "vm/jit/patcher.h"
23 # include "ffcall/avcall/avcall.h"
25 # include "libffi/include/ffi.h"
28 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
29 # ifndef USE_MD_THREAD_STUFF
30 # include "machine-instr.h"
32 # include "threads/native/generic-primitives.h"
36 #if !defined(STORE_ORDER_BARRIER) && !defined(USE_THREADS)
37 #define STORE_ORDER_BARRIER() /* nothing */
41 /* threading macros */
44 # define SET_IP(p) ({ip=(p); NEXT_P0;})
45 # define NEXT_INST (*IP)
46 # define INC_IP(const_inc) ({ ip+=(const_inc);})
49 # define NEXT_P2 ({goto **(ip++);})
50 # define EXEC(XT) ({goto *(XT);})
52 #define NEXT ({DEF_CA NEXT_P1; NEXT_P2;})
53 #define IPTOS NEXT_INST
55 #if defined(USE_spTOS)
62 /* conversion on fetch */
65 #define SUPER_END vm_count_block(IP)
68 #define vm_uncount_block(_ip) /* nothing */
71 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
73 #define global_sp (*(Cell **)&(THREADINFO->_global_sp))
75 #else /* defined(USE_THREADS) && defined(NATIVE_THREADS) */
77 #define MAX_STACK_SIZE 128*1024
78 static char stack[MAX_STACK_SIZE];
80 static Cell *_global_sp = (Cell *)(stack+MAX_STACK_SIZE);
81 #define global_sp _global_sp
83 #endif /* defined(USE_THREADS) && defined(NATIVE_THREADS) */
85 #define CLEAR_global_sp (global_sp=NULL)
88 #define THROW0 goto throw
89 #define THROW(_ball) \
92 *exceptionptr = (stacktrace_inline_##_ball(NULL, (u1 *) fp, (functionptr) IP, (functionptr) IP)); \
97 #define CHECK_NULL_PTR(ptr) \
99 if ((ptr) == NULL) { \
100 THROW(nullpointerexception); \
104 #define CHECK_OUT_OF_BOUNDS(_array, _idx) \
106 if (length_array(_array) <= (u4) (_idx)) { \
108 *exceptionptr = stacktrace_inline_arrayindexoutofboundsexception(NULL, (u1 *) fp, (functionptr) IP, (functionptr) IP, _idx); \
114 #define CHECK_ZERO_DIVISOR(_divisor) \
115 { if (_divisor == 0) \
116 THROW(arithmeticexception); \
119 #define access_local_int(_offset) \
120 ( *(Cell*)(((u1 *)fp) + (_offset)) )
122 #define access_local_ref(_offset) \
123 ( *(void **)(((u1 *)fp) + (_offset)) )
125 #define access_local_cell(_offset) \
126 ( *(Cell *)(((u1 *)fp) + (_offset)) )
129 /* !! alignment bug */
130 #define access_local_long(_offset) \
131 ( *(s8 *)(((u1 *)fp) + (_offset)) )
134 #define length_array(array) \
135 ( ((java_arrayheader*)(array))->size )
137 #define access_array_int(array, index) \
138 ((((java_intarray*)(array))->data)[index])
140 #define access_array_long(array, index) \
141 ((((java_longarray*)(array))->data)[index])
143 #define access_array_char(array, index) \
144 ((((java_chararray*)(array))->data)[index])
146 #define access_array_short(array, index) \
147 ((((java_shortarray*)(array))->data)[index])
149 #define access_array_byte(array, index) \
150 ((((java_bytearray*)(array))->data)[index])
152 #define access_array_addr(array, index) \
153 ((((java_objectarray*)(array))->data)[index])
155 #define MAXLOCALS(stub) (((Cell *)stub)[1])
158 #define CLEARSTACK(_start, _end) \
159 do {Cell *__start=(_start); MSET(__start,0,u1,(_end)-__start); } while (0)
161 #define CLEARSTACK(_start, _end)
166 ffi_type *cacaotype2ffitype(s4 cacaotype)
170 return &ffi_type_uint;
172 return &ffi_type_sint64;
174 return &ffi_type_float;
176 return &ffi_type_double;
178 return &ffi_type_pointer;
180 return &ffi_type_void;
188 /* call jni function */
189 static Cell *nativecall(functionptr f, methodinfo *m, Cell *sp, Inst *ra, Cell *fp, u1 *addrcif)
205 switch (md->returntype.type) {
207 endsp = sp - 1 + md->paramslots;
208 av_start_int(alist, f, endsp);
211 endsp = sp - 2 + md->paramslots;
212 av_start_longlong(alist, f, endsp);
215 endsp = sp - 1 + md->paramslots;
216 av_start_float(alist, f, endsp);
219 endsp = sp - 2 + md->paramslots;
220 av_start_double(alist, f, endsp);
223 endsp = sp - 1 + md->paramslots;
224 av_start_ptr(alist, f, void *, endsp);
227 endsp = sp + md->paramslots;
228 av_start_void(alist, f);
234 av_ptr(alist, JNIEnv *, &env);
236 if (m->flags & ACC_STATIC)
237 av_ptr(alist, classinfo *, m->class);
239 for (i = 0, p = sp + md->paramslots; i < md->paramcount; i++) {
240 switch (md->paramtypes[i].type) {
247 av_longlong(alist, *(s8 *)p);
251 av_float(alist, *(float *) p);
255 av_double(alist, *(double *) p);
259 av_ptr(alist, void *, *(void **) p);
268 /* create stackframe info structure */
270 codegen_start_native_call(&s, (u1 *) m->entrypoint,
276 codegen_finish_native_call(&s);
282 methoddesc *md = m->parseddesc;
284 void *values[md->paramcount + 2];
285 void **pvalues = values;
296 pcif = (ffi_cif *) addrcif;
298 /* pass env pointer */
300 penv = (JNIEnv *) &env;
303 /* for static methods, pass class pointer */
305 if (m->flags & ACC_STATIC) {
306 *pvalues++ = &m->class;
309 /* pass parameter to native function */
311 for (i = 0, p = sp + md->paramslots; i < md->paramcount; i++) {
312 if (IS_2_WORD_TYPE(md->paramtypes[i].type))
320 /* calculate position of return value */
322 if (md->returntype.type == TYPE_VOID)
323 endsp = sp + md->paramslots;
325 endsp = sp - (IS_2_WORD_TYPE(md->returntype.type) ? 2 : 1) + md->paramslots;
329 /* create stackframe info structure */
331 codegen_start_native_call((u1 *) (((ptrint ) &s) + sizeof(s)),
332 (u1 *) (ptrint) m->entrypoint,
333 (u1 *) fp, (u1 *) ra);
335 ffi_call(pcif, FFI_FN(f), endsp, values);
337 codegen_finish_native_call((u1 *) (((ptrint) &s) + sizeof(s)));
346 Inst *builtin_throw(Inst *ip, java_objectheader *o, Cell *fp, Cell **new_spp, Cell **new_fpp)
351 s4 exceptiontablelength;
354 /* for a description of the stack see IRETURN in java.vmg */
356 functionptr f = codegen_findmethod((functionptr) (ip-1));
358 /* get methodinfo pointer from method header */
359 methodinfo *m = *(methodinfo **) (((u1 *) f) + MethodPointer);
361 framesize = (*((s4 *) (((u1 *) f) + FrameSize)));
362 ex = (exceptionentry *) (((u1 *) f) + ExTableStart);
363 exceptiontablelength = *((s4 *) (((u1 *) f) + ExTableSize));
365 builtin_trace_exception(o, m, ip, 1);
367 for (i = 0; i < exceptiontablelength; i++) {
374 if (!load_class_bootstrap(c))
382 if (ip-1 >= (Inst *) ex->startpc && ip-1 < (Inst *) ex->endpc &&
383 (c == NULL || builtin_instanceof(o, c))) {
384 *new_spp = (Cell *)(((u1 *)fp) - framesize - SIZEOF_VOID_P);
386 return (Inst *) (ex->handlerpc);
390 ip = (Inst *)access_local_cell(-framesize - SIZEOF_VOID_P);
391 fp = (Cell *)access_local_cell(-framesize);
401 #define NAME(_x) if (vm_debug) {fprintf(vm_out, "%lx: %-20s, ", (long)(ip-1), _x); fprintf(vm_out,"fp=%p, sp=%p", fp, sp);}
406 #define LABEL(_inst) I_##_inst:
407 #define INST_ADDR(_inst) (&&I_##_inst)
408 #define LABEL2(_inst)
412 engine(Inst *ip0, Cell * sp, Cell * fp)
415 IF_spTOS(Cell spTOS);
416 static Inst labels[] = {
417 #include "java-labels.i"
421 fprintf(vm_out,"entering engine(%p,%p,%p)\n",ip0,sp,fp);
427 /* I don't have a clue where these things come from,
428 but I've put them in macros.h for the moment */
429 IF_spTOS(spTOS = sp[0]);
439 /* true on success, false on exception */
440 static bool asm_calljavafunction_intern(methodinfo *m,
441 void *arg1, void *arg2, void *arg3, void *arg4)
443 java_objectheader *retval;
444 Cell *sp = global_sp;
446 functionptr entrypoint;
453 /* XXX ugly hack: thread's run() needs 5 arguments */
454 assert(md->paramcount < 6);
456 if (md->paramcount > 0)
458 if (md->paramcount > 1)
460 if (md->paramcount > 2)
462 if (md->paramcount > 3)
464 if (md->paramcount > 4)
467 entrypoint = createcalljavafunction(m);
469 retval = engine((Inst *) entrypoint, sp, NULL);
471 /* XXX remove the method from the method table */
473 if (retval != NULL) {
474 (void)builtin_throw_exception(retval);
481 s4 asm_calljavafunction_int(methodinfo *m,
482 void *arg1, void *arg2, void *arg3, void *arg4)
484 assert(m->parseddesc->returntype.type == TYPE_INT);
485 if (asm_calljavafunction_intern(m, arg1, arg2, arg3, arg4))
486 return (s4)(*global_sp++);
491 java_objectheader *asm_calljavafunction(methodinfo *m,
492 void *arg1, void *arg2, void *arg3, void *arg4)
494 if (asm_calljavafunction_intern(m, arg1, arg2, arg3, arg4)) {
495 if (m->parseddesc->returntype.type == TYPE_ADR)
496 return (java_objectheader *)(*global_sp++);
498 assert(m->parseddesc->returntype.type == TYPE_VOID);
505 /* true on success, false on exception */
506 static bool jni_invoke_java_intern(methodinfo *m, u4 count, u4 size,
507 jni_callblock *callblock)
509 java_objectheader *retval;
510 Cell *sp = global_sp;
512 functionptr entrypoint;
517 for (i = 0; i < count; i++) {
518 switch (callblock[i].itemtype) {
522 *(--sp) = callblock[i].item;
527 *((u8 *) sp) = callblock[i].item;
532 entrypoint = createcalljavafunction(m);
534 retval = engine((Inst *) entrypoint, sp, NULL);
536 /* XXX remove the method from the method table */
538 if (retval != NULL) {
539 (void)builtin_throw_exception(retval);
546 java_objectheader *asm_calljavafunction2(methodinfo *m, u4 count, u4 size,
547 jni_callblock *callblock)
549 java_objectheader *retval = NULL;
550 if (jni_invoke_java_intern(m, count, size, callblock)) {
551 if (m->parseddesc->returntype.type == TYPE_ADR)
552 retval = (java_objectheader *)*global_sp++;
554 assert(m->parseddesc->returntype.type == TYPE_VOID);
560 s4 asm_calljavafunction2int(methodinfo *m, u4 count, u4 size,
561 jni_callblock *callblock)
565 if (jni_invoke_java_intern(m, count, size, callblock)) {
566 if (m->parseddesc->returntype.type == TYPE_INT)
567 retval = *global_sp++;
569 assert(m->parseddesc->returntype.type == TYPE_VOID);
575 s8 asm_calljavafunction2long(methodinfo *m, u4 count, u4 size,
576 jni_callblock *callblock)
579 assert(m->parseddesc->returntype.type == TYPE_LNG);
580 if (jni_invoke_java_intern(m, count, size, callblock)) {
581 retval = *(s8 *)global_sp;
588 float asm_calljavafunction2float(methodinfo *m, u4 count, u4 size,
589 jni_callblock *callblock)
592 assert(m->parseddesc->returntype.type == TYPE_FLT);
593 if (jni_invoke_java_intern(m, count, size, callblock)) {
594 retval = *(float *)global_sp;
601 double asm_calljavafunction2double(methodinfo *m, u4 count, u4 size,
602 jni_callblock *callblock)
605 assert(m->parseddesc->returntype.type == TYPE_DBL);
606 if (jni_invoke_java_intern(m, count, size, callblock)) {
607 retval = *(double *)global_sp;
615 * These are local overrides for various environment variables in Emacs.
616 * Please do not remove this and leave it at the end of the file, where
617 * Emacs will automagically detect them.
618 * ---------------------------------------------------------------------
621 * indent-tabs-mode: t