* src/vm/jit/exceptiontable.c: New file.
[cacao.git] / src / vm / vm.c
index a1d3ee144a60f17412d8940e0dc20e31dc5a6ba1..2a9b9cbc8bf0d20f56e34c34007065eff2436624 100644 (file)
@@ -44,6 +44,7 @@
 
 #include "native/jni.h"
 #include "native/llni.h"
+#include "native/localref.h"
 #include "native/native.h"
 
 #include "native/include/java_lang_Object.h"             /* required by j.l.C */
@@ -62,6 +63,7 @@
 
 #include "toolbox/logging.h"
 
+#include "vm/array.h"
 #include "vm/builtin.h"
 #include "vm/exceptions.h"
 #include "vm/finalizer.h"
 
 #include "vm/jit/argument.h"
 #include "vm/jit/asmpart.h"
+
+#if defined(ENABLE_DISASSEMBLER)
+# include "vm/jit/disass.h"
+#endif
+
 #include "vm/jit/jit.h"
 #include "vm/jit/md.h"
 
@@ -736,16 +743,6 @@ bool vm_createjvm(JavaVM **p_vm, void **p_env, void *vm_args)
        if (!vm_create(_vm_args))
                goto error;
 
-#if defined(ENABLE_JNI)
-       /* setup the local ref table (must be created after vm_create) */
-
-       /* XXX this one will never get freed for the main thread;
-          call localref_table_destroy() if you want to do it! */
-
-       if (!localref_table_init())
-               goto error;
-#endif
-
        /* now return the values */
 
        *p_vm  = (JavaVM *) vm;
@@ -1555,6 +1552,14 @@ bool vm_create(JavaVMInitArgs *vm_args)
                vm_abort("vm_create: jni_init failed");
 #endif
 
+#if defined(ENABLE_JNI) || defined(ENABLE_HANDLES)
+       /* Initialize the local reference table for the main thread. */
+       /* BEFORE: threads_init */
+
+       if (!localref_table_init())
+               vm_abort("vm_create: localref_table_init failed");
+#endif
+
 #if defined(ENABLE_THREADS)
        if (!threads_init())
                vm_abort("vm_create: threads_init failed");
@@ -1758,7 +1763,7 @@ void vm_run(JavaVM *vm, JavaVMInitArgs *vm_args)
                u = utf_new_char(vm_args->options[opt_index + i].optionString);
                s = javastring_new(u);
 
-               LLNI_objectarray_element_set(oa, i, s);
+               array_objectarray_element_set(oa, i, s);
        }
 
 #ifdef TYPEINFO_DEBUG_TEST
@@ -1994,6 +1999,55 @@ void vm_abort(const char *text, ...)
 }
 
 
+/* vm_abort_disassemble ********************************************************
+
+   Prints an error message, disassemble the given code range (if
+   enabled) and aborts the VM.
+
+   IN:
+       pc.......PC to disassemble
+          count....number of instructions to disassemble
+
+*******************************************************************************/
+
+void vm_abort_disassemble(void *pc, int count, const char *text, ...)
+{
+       va_list ap;
+#if defined(ENABLE_DISASSEMBLER)
+       int     i;
+#endif
+
+       /* Print debug message. */
+
+       log_start();
+
+       va_start(ap, text);
+       log_vprint(text, ap);
+       va_end(ap);
+
+       log_finish();
+
+       /* Print the PC. */
+
+#if SIZEOF_VOID_P == 8
+       log_println("PC=0x%016lx", pc);
+#else
+       log_println("PC=0x%08x", pc);
+#endif
+
+#if defined(ENABLE_DISASSEMBLER)
+       log_println("machine instructions at PC:");
+
+       /* Disassemble the given number of instructions. */
+
+       for (i = 0; i < count; i++)
+               pc = disassinstr(pc);
+#endif
+
+       vm_abort("Aborting...");
+}
+
+
 /* vm_get_mainclass_from_jar ***************************************************
 
    Gets the name of the main class from a JAR's manifest file.
@@ -2266,7 +2320,27 @@ static type vm_call##name##_array(methodinfo *m, uint64_t *array) \
        return value;                                                 \
 }
 
-VM_CALL_ARRAY(,        java_handle_t *)
+static java_handle_t *vm_call_array(methodinfo *m, uint64_t *array)
+{
+       methoddesc    *md;
+       void          *pv;
+       java_object_t *o;
+
+       assert(m->code != NULL);
+
+       md = m->parseddesc;
+       pv = m->code->entrypoint;
+
+       STATISTICS(count_calls_native_to_java++);
+
+       o = asm_vm_call_method(pv, array, md->memuse);
+
+       if (md->returntype.type == TYPE_VOID)
+               o = NULL;
+
+       return LLNI_WRAP(o);
+}
+
 VM_CALL_ARRAY(_int,    int32_t)
 VM_CALL_ARRAY(_long,   int64_t)
 VM_CALL_ARRAY(_float,  float)
@@ -2409,12 +2483,7 @@ java_handle_t *vm_call_method_objectarray(methodinfo *m, java_handle_t *o,
 
        array = argument_vmarray_from_objectarray(m, o, params);
 
-       /* The array can be NULL if we don't have any arguments to pass
-          and the architecture does not have any argument registers
-          (e.g. i386).  In that case we additionally check for an
-          exception thrown. */
-
-       if ((array == NULL) && (exceptions_get_exception() != NULL)) {
+       if (array == NULL) {
                /* release dump area */
 
                dump_release(dumpsize);
@@ -2423,13 +2492,14 @@ java_handle_t *vm_call_method_objectarray(methodinfo *m, java_handle_t *o,
 
                THREAD_NATIVEWORLD_ENTER;
 
+               exceptions_throw_illegalargumentexception();
+
                return NULL;
        }
 
        switch (m->parseddesc->returntype.decltype) {
-       case TYPE_VOID:
-               (void) vm_call_array(m, array);
-               ro = NULL;
+       case PRIMITIVETYPE_VOID:
+               value.a = vm_call_array(m, array);
                break;
 
        case PRIMITIVETYPE_BOOLEAN:
@@ -2438,22 +2508,18 @@ java_handle_t *vm_call_method_objectarray(methodinfo *m, java_handle_t *o,
        case PRIMITIVETYPE_SHORT:
        case PRIMITIVETYPE_INT:
                value.i = vm_call_int_array(m, array);
-               ro = primitive_box(m->parseddesc->returntype.decltype, value);
                break;
 
        case PRIMITIVETYPE_LONG:
                value.l = vm_call_long_array(m, array);
-               ro = primitive_box(m->parseddesc->returntype.decltype, value);
                break;
 
        case PRIMITIVETYPE_FLOAT:
                value.f = vm_call_float_array(m, array);
-               ro = primitive_box(m->parseddesc->returntype.decltype, value);
                break;
 
        case PRIMITIVETYPE_DOUBLE:
                value.d = vm_call_double_array(m, array);
-               ro = primitive_box(m->parseddesc->returntype.decltype, value);
                break;
 
        case TYPE_ADR:
@@ -2461,9 +2527,24 @@ java_handle_t *vm_call_method_objectarray(methodinfo *m, java_handle_t *o,
                break;
 
        default:
-               vm_abort("_Jv_jni_invokeNative: invalid return type %d", m->parseddesc->returntype.decltype);
+               vm_abort("vm_call_method_objectarray: invalid return type %d", m->parseddesc->returntype.decltype);
        }
 
+       /* release dump area */
+
+       dump_release(dumpsize);
+
+       /* enter the nativeworld again */
+
+       THREAD_NATIVEWORLD_ENTER;
+
+       /* box the return value if necesarry */
+
+       if (m->parseddesc->returntype.decltype != TYPE_ADR)
+               ro = primitive_box(m->parseddesc->returntype.decltype, value);
+
+       /* check for an exception */
+
        xptr = exceptions_get_exception();
 
        if (xptr != NULL) {
@@ -2474,14 +2555,6 @@ java_handle_t *vm_call_method_objectarray(methodinfo *m, java_handle_t *o,
                exceptions_throw_invocationtargetexception(xptr);
        }
 
-       /* release dump area */
-
-       dump_release(dumpsize);
-
-       /* enter the nativeworld again */
-
-       THREAD_NATIVEWORLD_ENTER;
-
        return ro;
 }