* Removed all Id tags.
[cacao.git] / src / vm / jit / intrp / asmpart.c
index 86eefd5b57a1b2309f321420d1ff9f768ca1bee7..1d886a5352158e742c1b0f7d4fad50422b68410c 100644 (file)
@@ -1,9 +1,9 @@
-/* src/vm/jit/intrp/asmpart.S - Java-C interface functions for Interpreter
+/* 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.
+   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+   02110-1301, USA.
 
-   Contact: cacao@complang.tuwien.ac.at
+*/
 
-   Authors: Andreas Krall
-            Reinhard Grafl
 
-   Changes: Joseph Wenninger
-            Christian Thalinger
+#include "config.h"
 
-   $Id: asmpart.c 3176 2005-09-14 08:51:23Z twisti $
+#include <assert.h>
 
-*/
+#include "vm/types.h"
 
+#include "arch.h"
 
-#include "config.h"
+#if defined(ENABLE_THREADS)
+# include "threads/native/threads.h"
+#else
+# include "threads/none/threads.h"
+#endif
 
-#include "vm/jit/intrp/arch.h"
-#include "vm/jit/intrp/types.h"
+#include "vm/builtin.h"
+#include "vm/exceptions.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"
 
-/* this is required to link cacao with intrp */
-threadcritnode asm_criticalsections = { NULL, NULL, NULL };
+#if defined(ENABLE_VMLOG)
+#include <vmlog_cacao.h>
+#endif
 
 
-void asm_getclassvalues_atomic(vftbl_t *super, vftbl_t *sub, castinfo *out)
+static bool intrp_asm_vm_call_method_intern(methodinfo *m, s4 vmargscount,
+                                                                                       vm_arg *vmargs)
 {
-       s4 sbv, sdv, sv;
+       java_objectheader *retval;
+       Cell              *sp;
+       s4                 i;
+       u1                *entrypoint;
 
-#if defined(USE_THREADS)
-#if defined(NATIVE_THREADS)
-       compiler_lock();
-#else
-       intsDisable();
+       sp = global_sp;
+       CLEAR_global_sp;
+
+       assert(sp != NULL);
+
+       for (i = 0; i < vmargscount; i++) {
+               switch (vmargs[i].type) {
+               case TYPE_INT:
+               case TYPE_FLT:
+               case TYPE_ADR:
+                       *(--sp) = (Cell) vmargs[i].data.l;
+                       break;
+               case TYPE_LNG:
+               case TYPE_DBL:
+                       sp -= 2;
+                       *((u8 *) sp) = vmargs[i].data.l;
+                       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 *intrp_asm_vm_call_method(methodinfo *m, s4 vmargscount,
+                                                                                       vm_arg *vmargs)
+{
+       java_objectheader *retval = NULL;
+
+       if (intrp_asm_vm_call_method_intern(m, vmargscount, vmargs)) {
+               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 intrp_asm_vm_call_method_int(methodinfo *m, s4 vmargscount, vm_arg *vmargs)
+{
+       s4 retval = 0;
+
+       if (intrp_asm_vm_call_method_intern(m, vmargscount, vmargs)) {
+               if (m->parseddesc->returntype.type == TYPE_INT)
+                       retval = *global_sp++;
+               else
+                       assert(m->parseddesc->returntype.type == TYPE_VOID);
+               return retval;
+       } else
+               return 0;
+}
+
+
+s8 intrp_asm_vm_call_method_long(methodinfo *m, s4 vmargscount, vm_arg *vmargs)
+{
+       s8 retval;
+
+       assert(m->parseddesc->returntype.type == TYPE_LNG);
+
+       if (intrp_asm_vm_call_method_intern(m, vmargscount, vmargs)) {
+               retval = *(s8 *)global_sp;
+               global_sp += 2;
+               return retval;
+       } else
+               return 0;
+}
+
+
+float intrp_asm_vm_call_method_float(methodinfo *m, s4 vmargscount,
+                                                                        vm_arg *vmargs)
+{
+       float retval;
+
+       assert(m->parseddesc->returntype.type == TYPE_FLT);
+
+       if (intrp_asm_vm_call_method_intern(m, vmargscount, vmargs)) {
+               retval = *(float *)global_sp;
+               global_sp += 1;
+               return retval;
+       } else
+               return 0.0;
+}
+
+
+double intrp_asm_vm_call_method_double(methodinfo *m, s4 vmargscount,
+                                                                          vm_arg *vmargs)
+{
+       double retval;
+
+       assert(m->parseddesc->returntype.type == TYPE_DBL);
+
+       if (intrp_asm_vm_call_method_intern(m, vmargscount, vmargs)) {
+               retval = *(double *)global_sp;
+               global_sp += 2;
+               return retval;
+       } else
+               return 0.0;
+}
+
+
+Inst *intrp_asm_handle_exception(Inst *ip, java_objectheader *o, Cell *fp, Cell **new_spp, Cell **new_fpp)
+{
+       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_get_pv_from_pc((u1 *) (ip - 1));
+
+         /* get methodinfo pointer from method header */
+
+         codeinfo *code = *((codeinfo **) ((u1 *)f + CodeinfoPointer));
+         methodinfo *m = code->m;
+
+         framesize            = *((s4 *)             (((u1 *) f) + FrameSize));
+         issync               = *((s4 *)             (((u1 *) f) + IsSync));
+         ex                   =   (dseg_exception_entry *) 
+                                                                                                 (((u1 *) f) + ExTableStart);
+         exceptiontablelength = *((s4 *)             (((u1 *) f) + ExTableSize));
+
+#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--;
+
+                 cr = ex->catchtype;
+
+                 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))) 
+                 {
+#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);
+  }
+
+  return NULL; 
+}
+
+
+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;
+
+       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;
@@ -88,4 +347,5 @@ void 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:
  */