* Removed all Id tags.
[cacao.git] / src / vm / jit / intrp / asmpart.c
index 59a35fa18a17ee2e0fd8d6fe39eed7840aef46ee..1d886a5352158e742c1b0f7d4fad50422b68410c 100644 (file)
@@ -1,9 +1,9 @@
 /* src/vm/jit/intrp/asmpart.c - Java-C interface functions for Interpreter
 
-   Copyright (C) 1996-2005 R. Grafl, A. Krall, C. Kruegel, C. Oates,
-   R. Obermaisser, M. Platter, M. Probst, S. Ring, E. Steiner,
-   C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich, J. Wenninger,
-   Institut f. Computersprachen - TU Wien
+   Copyright (C) 1996-2005, 2006, 2007 R. Grafl, A. Krall, C. Kruegel,
+   C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
+   E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
+   J. Wenninger, Institut f. Computersprachen - TU Wien
 
    This file is part of CACAO.
 
 
    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
-   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
-   02111-1307, USA.
-
-   Contact: cacao@complang.tuwien.ac.at
-
-   Authors: Christian Thalinger
-            Anton Ertl
-
-   Changes:
-
-   $Id: asmpart.c 4329 2006-01-20 13:40:25Z twisti $
+   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+   02110-1301, USA.
 
 */
 
 
 #include "arch.h"
 
+#if defined(ENABLE_THREADS)
+# include "threads/native/threads.h"
+#else
+# include "threads/none/threads.h"
+#endif
+
 #include "vm/builtin.h"
-#include "vm/class.h"
 #include "vm/exceptions.h"
-#include "vm/options.h"
+
 #include "vm/jit/asmpart.h"
 #include "vm/jit/methodheader.h"
 #include "vm/jit/intrp/intrp.h"
+#include "vm/jit/dseg.h"
 
+#include "vmcore/class.h"
+#include "vmcore/linker.h"
+#include "vmcore/loader.h"
+#include "vmcore/options.h"
 
-/* true on success, false on exception */
-
-static bool intrp_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;
-}
-
-
-java_objectheader *intrp_asm_calljavafunction(methodinfo *m,
-                                                                                         void *arg1, void *arg2,
-                                                                                         void *arg3, void *arg4)
-{
-       if (intrp_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;
-}
-
-
-s4 intrp_asm_calljavafunction_int(methodinfo *m, void *arg1, void *arg2,
-                                                                 void *arg3, void *arg4)
-{
-       assert(m->parseddesc->returntype.type == TYPE_INT);
-
-       if (intrp_asm_calljavafunction_intern(m, arg1, arg2, arg3, arg4))
-               return (s4) (*global_sp++);
-       else
-               return 0;
-}
+#if defined(ENABLE_VMLOG)
+#include <vmlog_cacao.h>
+#endif
 
 
-/* true on success, false on exception */
-static bool jni_invoke_java_intern(methodinfo *m, u4 count, u4 size,
-                                                                  jni_callblock *callblock)
+static bool intrp_asm_vm_call_method_intern(methodinfo *m, s4 vmargscount,
+                                                                                       vm_arg *vmargs)
 {
        java_objectheader *retval;
-       Cell *sp = global_sp;
-       s4 i;
-       functionptr entrypoint;
+       Cell              *sp;
+       s4                 i;
+       u1                *entrypoint;
 
+       sp = global_sp;
        CLEAR_global_sp;
+
        assert(sp != NULL);
 
-       for (i = 0; i < count; i++) {
-               switch (callblock[i].itemtype) {
+       for (i = 0; i < vmargscount; i++) {
+               switch (vmargs[i].type) {
                case TYPE_INT:
                case TYPE_FLT:
                case TYPE_ADR:
-                       *(--sp) = callblock[i].item;
+                       *(--sp) = (Cell) vmargs[i].data.l;
                        break;
                case TYPE_LNG:
                case TYPE_DBL:
                        sp -= 2;
-                       *((u8 *) sp) = callblock[i].item;
+                       *((u8 *) sp) = vmargs[i].data.l;
                        break;
                }
        }
@@ -166,12 +100,12 @@ static bool jni_invoke_java_intern(methodinfo *m, u4 count, u4 size,
 }
 
 
-java_objectheader *intrp_asm_calljavafunction2(methodinfo *m, u4 count, u4 size,
-                                                                                          jni_callblock *callblock)
+java_objectheader *intrp_asm_vm_call_method(methodinfo *m, s4 vmargscount,
+                                                                                       vm_arg *vmargs)
 {
        java_objectheader *retval = NULL;
 
-       if (jni_invoke_java_intern(m, count, size, callblock)) {
+       if (intrp_asm_vm_call_method_intern(m, vmargscount, vmargs)) {
                if (m->parseddesc->returntype.type == TYPE_ADR)
                        retval = (java_objectheader *)*global_sp++;
                else
@@ -182,12 +116,11 @@ java_objectheader *intrp_asm_calljavafunction2(methodinfo *m, u4 count, u4 size,
 }
 
 
-s4 intrp_asm_calljavafunction2int(methodinfo *m, u4 count, u4 size,
-                                                                 jni_callblock *callblock)
+s4 intrp_asm_vm_call_method_int(methodinfo *m, s4 vmargscount, vm_arg *vmargs)
 {
-       s4 retval=0;
+       s4 retval = 0;
 
-       if (jni_invoke_java_intern(m, count, size, callblock)) {
+       if (intrp_asm_vm_call_method_intern(m, vmargscount, vmargs)) {
                if (m->parseddesc->returntype.type == TYPE_INT)
                        retval = *global_sp++;
                else
@@ -198,14 +131,13 @@ s4 intrp_asm_calljavafunction2int(methodinfo *m, u4 count, u4 size,
 }
 
 
-s8 intrp_asm_calljavafunction2long(methodinfo *m, u4 count, u4 size,
-                                                                  jni_callblock *callblock)
+s8 intrp_asm_vm_call_method_long(methodinfo *m, s4 vmargscount, vm_arg *vmargs)
 {
        s8 retval;
 
        assert(m->parseddesc->returntype.type == TYPE_LNG);
 
-       if (jni_invoke_java_intern(m, count, size, callblock)) {
+       if (intrp_asm_vm_call_method_intern(m, vmargscount, vmargs)) {
                retval = *(s8 *)global_sp;
                global_sp += 2;
                return retval;
@@ -214,14 +146,14 @@ s8 intrp_asm_calljavafunction2long(methodinfo *m, u4 count, u4 size,
 }
 
 
-float intrp_asm_calljavafunction2float(methodinfo *m, u4 count, u4 size,
-                                                                          jni_callblock *callblock)
+float intrp_asm_vm_call_method_float(methodinfo *m, s4 vmargscount,
+                                                                        vm_arg *vmargs)
 {
        float retval;
 
        assert(m->parseddesc->returntype.type == TYPE_FLT);
 
-       if (jni_invoke_java_intern(m, count, size, callblock)) {
+       if (intrp_asm_vm_call_method_intern(m, vmargscount, vmargs)) {
                retval = *(float *)global_sp;
                global_sp += 1;
                return retval;
@@ -230,14 +162,14 @@ float intrp_asm_calljavafunction2float(methodinfo *m, u4 count, u4 size,
 }
 
 
-double intrp_asm_calljavafunction2double(methodinfo *m, u4 count, u4 size,
-                                                                                jni_callblock *callblock)
+double intrp_asm_vm_call_method_double(methodinfo *m, s4 vmargscount,
+                                                                          vm_arg *vmargs)
 {
        double retval;
 
        assert(m->parseddesc->returntype.type == TYPE_DBL);
 
-       if (jni_invoke_java_intern(m, count, size, callblock)) {
+       if (intrp_asm_vm_call_method_intern(m, vmargscount, vmargs)) {
                retval = *(double *)global_sp;
                global_sp += 2;
                return retval;
@@ -248,51 +180,130 @@ double intrp_asm_calljavafunction2double(methodinfo *m, u4 count, u4 size,
 
 Inst *intrp_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;
+       classinfo            *c;
+       classref_or_classinfo cr;
+       s4                    framesize;
+       s4                    issync;
+       dseg_exception_entry *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));
+         u1 *f = codegen_get_pv_from_pc((u1 *) (ip - 1));
 
          /* get methodinfo pointer from method header */
 
-         methodinfo *m = *(methodinfo **) (((u1 *) f) + MethodPointer);
+         codeinfo *code = *((codeinfo **) ((u1 *)f + CodeinfoPointer));
+         methodinfo *m = code->m;
 
-         framesize = (*((s4 *) (((u1 *) f) + FrameSize)));
-         ex = (exceptionentry *) (((u1 *) f) + ExTableStart);
-         exceptiontablelength = *((s4 *) (((u1 *) f) + ExTableSize));
+         framesize            = *((s4 *)             (((u1 *) f) + FrameSize));
+         issync               = *((s4 *)             (((u1 *) f) + IsSync));
+         ex                   =   (dseg_exception_entry *) 
+                                                                                                 (((u1 *) f) + ExTableStart);
+         exceptiontablelength = *((s4 *)             (((u1 *) f) + ExTableSize));
 
-         if (opt_verbose || runverbose || opt_verboseexception)
+#if !defined(NDEBUG)
+         if (opt_verbose || opt_verbosecall || opt_verboseexception)
                  builtin_trace_exception(o, m, ip, 1);
+#endif
+
+#if defined(ENABLE_VMLOG)
+         vmlog_cacao_throw(o);
+#endif
 
          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);
+                 cr = ex->catchtype;
 
-                         if (!(c->state & CLASS_LINKED))
-                                 if (!link_class(c))
+                 if (cr.any == NULL) {
+                         /* catch all */
+                         c = NULL;
+                 }
+                 else {
+                         if (IS_CLASSREF(cr)) {
+                                 /* The exception class reference is unresolved. */
+                                 /* We have to do _eager_ resolving here. While the class of */
+                                 /* the exception object is guaranteed to be loaded, it may  */
+                                 /* well have been loaded by a different loader than the     */
+                                 /* defining loader of m's class, which is the one we must   */
+                                 /* use to resolve the catch class. Thus lazy resolving      */
+                                 /* might fail, even if the result of the resolution would   */
+                                 /* be an already loaded class.                              */
+
+                                 /* The resolving may involve Java code, so we need a usable */
+                                 /* global_sp. XXX is this a correct value for global_sp?    */
+
+                                 global_sp = (Cell *)(((u1 *)fp) - framesize - SIZEOF_VOID_P);
+
+                                 c = resolve_classref_eager(cr.ref);
+
+                                 CLEAR_global_sp;
+
+                                 if (c == NULL) {
+                                         /* Exception resolving the exception class, argh! */
+                                         /* XXX how to report that error? */
                                          assert(0);
+                                 }
+
+                                 /* Ok, we resolved it. Enter it in the table, so we don't */
+                                 /* have to do this again.                                 */
+                                 /* XXX this write should be atomic. Is it?                */
+
+                                 ex->catchtype.cls = c;
+                         }
+                         else {
+                                 c = cr.cls;
+                               
+                                 /* If the class is not linked, the exception object cannot */
+                                 /* be an instance of it.                                   */
+                                 if (!(c->state & CLASS_LINKED))
+                                         continue;
+                         }
                  }
 
                  if (ip-1 >= (Inst *) ex->startpc && ip-1 < (Inst *) ex->endpc &&
-                         (c == NULL || builtin_instanceof(o, c))) {
+                         (c == NULL || builtin_instanceof(o, c))) 
+                 {
+#if defined(ENABLE_VMLOG)
+                         vmlog_cacao_catch(o);
+#endif
+
                          *new_spp = (Cell *)(((u1 *)fp) - framesize - SIZEOF_VOID_P);
                          *new_fpp = fp;
                          return (Inst *) (ex->handlerpc);
                  }
          }
 
+#if defined(ENABLE_THREADS)
+         /* is this method synchronized? */
+
+         if (issync) {
+                 java_objectheader *syncobj;
+
+                 /* get synchronization object */
+
+                 if (m->flags & ACC_STATIC) {
+                         syncobj = (java_objectheader *) m->class;
+                 }
+                 else {
+                         syncobj = (java_objectheader *) access_local_cell(-framesize + SIZEOF_VOID_P);
+                 }
+
+                 assert(syncobj != NULL);
+
+                 lock_monitor_exit(syncobj);
+         }
+#endif /* defined(ENABLE_THREADS) */
+
+         /* unwind stack frame */
+
+#if defined(ENABLE_VMLOG)
+         vmlog_cacao_unwnd_method(m);
+#endif
+
          ip = (Inst *)access_local_cell(-framesize - SIZEOF_VOID_P);
          fp = (Cell *)access_local_cell(-framesize);
   }
@@ -301,29 +312,23 @@ Inst *intrp_asm_handle_exception(Inst *ip, java_objectheader *o, Cell *fp, Cell
 }
 
 
+void intrp_asm_abstractmethoderror(void)
+{
+       vm_abort("intrp_asm_abstractmethoderror: IMPLEMENT ME!");
+}
+
+
 void intrp_asm_getclassvalues_atomic(vftbl_t *super, vftbl_t *sub, castinfo *out)
 {
        s4 sbv, sdv, sv;
 
-#if defined(USE_THREADS)
-#if defined(NATIVE_THREADS)
-       compiler_lock();
-#else
-       intsDisable();
-#endif
-#endif
+       LOCK_MONITOR_ENTER(linker_classrenumber_lock);
 
        sbv = super->baseval;
        sdv = super->diffval;
        sv  = sub->baseval;
 
-#if defined(USE_THREADS)
-#if defined(NATIVE_THREADS)
-       compiler_unlock();
-#else
-       intsRestore();
-#endif
-#endif
+       LOCK_MONITOR_EXIT(linker_classrenumber_lock);
 
        out->super_baseval = sbv;
        out->super_diffval = sdv;
@@ -342,4 +347,5 @@ void intrp_asm_getclassvalues_atomic(vftbl_t *super, vftbl_t *sub, castinfo *out
  * c-basic-offset: 4
  * tab-width: 4
  * End:
+ * vim:noexpandtab:sw=4:ts=4:
  */