* Dynamic superinstructions added.
[cacao.git] / src / vm / jit / intrp / asmpart.c
index 1f3bd2b49017846d4aeb202ae2731d3bdb1c698c..c4c6786e2454edc61f016d30fc59d7e91586fdaa 100644 (file)
 
    Contact: cacao@complang.tuwien.ac.at
 
-   Authors: Andreas Krall
-            Reinhard Grafl
-
-   Changes: Joseph Wenninger
-            Christian Thalinger
+   Authors: Christian Thalinger
             Anton Ertl
 
-   $Id: asmpart.c 3231 2005-09-19 14:09:18Z twisti $
+   Changes:
+
+   $Id: asmpart.c 3895 2005-12-07 16:03:37Z anton $
 
 */
 
 
+#include <assert.h>
+
 #include "config.h"
 #include "vm/types.h"
 
 #include "arch.h"
 
+#include "vm/builtin.h"
+#include "vm/class.h"
+#include "vm/exceptions.h"
 #include "vm/jit/asmpart.h"
+#include "vm/jit/methodheader.h"
+#include "vm/jit/intrp/intrp.h"
 
 
 /* this is required to link cacao with intrp */
 threadcritnode asm_criticalsections = { NULL, NULL, NULL };
 
 
+/* true on success, false on exception */
+static bool asm_calljavafunction_intern(methodinfo *m, void *arg1, void *arg2,
+                                                                               void *arg3, void *arg4)
+{
+       java_objectheader *retval;
+       Cell *sp = global_sp;
+       methoddesc *md;
+       functionptr entrypoint;
+
+       md = m->parseddesc;
+
+       CLEAR_global_sp;
+       assert(sp != NULL);
+
+       /* XXX ugly hack: thread's run() needs 5 arguments */
+       assert(md->paramcount < 6);
+
+       if (md->paramcount > 0)
+               *--sp=(Cell)arg1;
+       if (md->paramcount > 1)
+               *--sp=(Cell)arg2;
+       if (md->paramcount > 2)
+               *--sp=(Cell)arg3;
+       if (md->paramcount > 3)
+               *--sp=(Cell)arg4;
+       if (md->paramcount > 4)
+               *--sp=(Cell) 0;
+
+       entrypoint = createcalljavafunction(m);
+
+       retval = engine((Inst *) entrypoint, sp, NULL);
+
+       /* XXX remove the method from the method table */
+
+       if (retval != NULL) {
+               (void) builtin_throw_exception(retval);
+               return false;
+       }
+       else 
+               return true;
+}
+
+
+s4 asm_calljavafunction_int(methodinfo *m, void *arg1, void *arg2,
+                                                       void *arg3, void *arg4)
+{
+       assert(m->parseddesc->returntype.type == TYPE_INT);
+
+       if (asm_calljavafunction_intern(m, arg1, arg2, arg3, arg4))
+               return (s4)(*global_sp++);
+       else
+               return 0;
+}
+
+
+java_objectheader *asm_calljavafunction(methodinfo *m, void *arg1, void *arg2,
+                                                                               void *arg3, void *arg4)
+{
+       if (asm_calljavafunction_intern(m, arg1, arg2, arg3, arg4)) {
+               if (m->parseddesc->returntype.type == TYPE_ADR)
+                       return (java_objectheader *)(*global_sp++);
+               else {
+                       assert(m->parseddesc->returntype.type == TYPE_VOID);
+                       return NULL;
+               }
+       } else
+               return NULL;
+}
+
+
+/* true on success, false on exception */
+static bool jni_invoke_java_intern(methodinfo *m, u4 count, u4 size,
+                                                                  jni_callblock *callblock)
+{
+       java_objectheader *retval;
+       Cell *sp = global_sp;
+       s4 i;
+       functionptr entrypoint;
+
+       CLEAR_global_sp;
+       assert(sp != NULL);
+
+       for (i = 0; i < count; i++) {
+               switch (callblock[i].itemtype) {
+               case TYPE_INT:
+               case TYPE_FLT:
+               case TYPE_ADR:
+                       *(--sp) = callblock[i].item;
+                       break;
+               case TYPE_LNG:
+               case TYPE_DBL:
+                       sp -= 2;
+                       *((u8 *) sp) = callblock[i].item;
+                       break;
+               }
+       }
+
+       entrypoint = createcalljavafunction(m);
+
+       retval = engine((Inst *) entrypoint, sp, NULL);
+
+       /* XXX remove the method from the method table */
+
+       if (retval != NULL) {
+               (void)builtin_throw_exception(retval);
+               return false;
+       }
+       else
+               return true;
+}
+
+
+java_objectheader *asm_calljavafunction2(methodinfo *m, u4 count, u4 size,
+                                         jni_callblock *callblock)
+{
+       java_objectheader *retval = NULL;
+       if (jni_invoke_java_intern(m, count, size, callblock)) {
+               if (m->parseddesc->returntype.type == TYPE_ADR)
+                       retval = (java_objectheader *)*global_sp++;
+               else
+                       assert(m->parseddesc->returntype.type == TYPE_VOID);
+               return retval;
+       } else
+               return NULL;
+}
+
+
+s4 asm_calljavafunction2int(methodinfo *m, u4 count, u4 size,
+                            jni_callblock *callblock)
+{
+       s4 retval=0;
+
+       if (jni_invoke_java_intern(m, count, size, callblock)) {
+               if (m->parseddesc->returntype.type == TYPE_INT)
+                       retval = *global_sp++;
+               else
+                       assert(m->parseddesc->returntype.type == TYPE_VOID);
+               return retval;
+       } else
+               return 0;
+}
+
+
+s8 asm_calljavafunction2long(methodinfo *m, u4 count, u4 size,
+                             jni_callblock *callblock)
+{
+       s8 retval;
+
+       assert(m->parseddesc->returntype.type == TYPE_LNG);
+
+       if (jni_invoke_java_intern(m, count, size, callblock)) {
+               retval = *(s8 *)global_sp;
+               global_sp += 2;
+               return retval;
+       } else
+               return 0;
+}
+
+
+float asm_calljavafunction2float(methodinfo *m, u4 count, u4 size,
+                                                                jni_callblock *callblock)
+{
+       float retval;
+
+       assert(m->parseddesc->returntype.type == TYPE_FLT);
+
+       if (jni_invoke_java_intern(m, count, size, callblock)) {
+               retval = *(float *)global_sp;
+               global_sp += 1;
+               return retval;
+       } else
+               return 0.0;
+}
+
+
+double asm_calljavafunction2double(methodinfo *m, u4 count, u4 size,
+                                   jni_callblock *callblock)
+{
+       double retval;
+
+       assert(m->parseddesc->returntype.type == TYPE_DBL);
+
+       if (jni_invoke_java_intern(m, count, size, callblock)) {
+               retval = *(double *)global_sp;
+               global_sp += 2;
+               return retval;
+       } else
+               return 0.0;
+}
+
+
+Inst *asm_handle_exception(Inst *ip, java_objectheader *o, Cell *fp, Cell **new_spp, Cell **new_fpp)
+{
+       classinfo      *c;
+       s4              framesize;
+       exceptionentry *ex;
+       s4              exceptiontablelength;
+       s4              i;
+
+  /* for a description of the stack see IRETURN in java.vmg */
+
+  for (; fp != NULL; ) {
+         u1 *f = codegen_findmethod((u1 *) (ip - 1));
+
+         /* get methodinfo pointer from method header */
+
+         methodinfo *m = *(methodinfo **) (((u1 *) f) + MethodPointer);
+
+         framesize = (*((s4 *) (((u1 *) f) + FrameSize)));
+         ex = (exceptionentry *) (((u1 *) f) + ExTableStart);
+         exceptiontablelength = *((s4 *) (((u1 *) f) + ExTableSize));
+
+         builtin_trace_exception(o, m, ip, 1);
+
+         for (i = 0; i < exceptiontablelength; i++) {
+                 ex--;
+                 c = ex->catchtype.cls;
+
+                 if (c != NULL) {
+                         if (!(c->state & CLASS_LOADED))
+                                 /* XXX fix me! */
+                                 if (!load_class_bootstrap(c->name))
+                                         assert(0);
+
+                         if (!(c->state & CLASS_LINKED))
+                                 if (!link_class(c))
+                                         assert(0);
+                 }
+
+                 if (ip-1 >= (Inst *) ex->startpc && ip-1 < (Inst *) ex->endpc &&
+                         (c == NULL || builtin_instanceof(o, c))) {
+                         *new_spp = (Cell *)(((u1 *)fp) - framesize - SIZEOF_VOID_P);
+                         *new_fpp = fp;
+                         return (Inst *) (ex->handlerpc);
+                 }
+         }
+
+         ip = (Inst *)access_local_cell(-framesize - SIZEOF_VOID_P);
+         fp = (Cell *)access_local_cell(-framesize);
+  }
+
+  return NULL; 
+}
+
+
 void asm_getclassvalues_atomic(vftbl_t *super, vftbl_t *sub, castinfo *out)
 {
        s4 sbv, sdv, sv;