/* src/vm/vm.c - VM startup and shutdown functions
- 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
+ Copyright (C) 1996-2005, 2006, 2007, 2008
+ CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
This file is part of CACAO.
#include "vm/jit/abi-asm.h"
+#include "mm/codememory.h"
#include "mm/gc-common.h"
#include "mm/memory.h"
#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 */
#include "native/vm/nativevm.h"
-#include "threads/threads-common.h"
+#include "threads/lock-common.h"
+#include "threads/mutex.h"
+#include "threads/threadlist.h"
+#include "threads/thread.h"
#include "toolbox/logging.h"
+#include "vm/array.h"
+
+#if defined(ENABLE_ASSERTION)
+#include "vm/assertion.h"
+#endif
+
#include "vm/builtin.h"
#include "vm/exceptions.h"
#include "vm/finalizer.h"
#include "vm/stringlocal.h"
#include "vm/vm.h"
-#include "vm/jit/jit.h"
-#include "vm/jit/md.h"
+#include "vm/jit/argument.h"
#include "vm/jit/asmpart.h"
+#include "vm/jit/code.h"
+
+#if defined(ENABLE_DISASSEMBLER)
+# include "vm/jit/disass.h"
+#endif
+
+#include "vm/jit/jit.h"
+#include "vm/jit/methodtree.h"
#if defined(ENABLE_PROFILING)
# include "vm/jit/optimizing/profile.h"
#include "vm/jit/optimizing/recompile.h"
+#if defined(ENABLE_PYTHON)
+# include "vm/jit/python.h"
+#endif
+
+#include "vm/jit/trap.h"
+
#include "vmcore/classcache.h"
#include "vmcore/options.h"
#include "vmcore/statistics.h"
#include "vmcore/suck.h"
+#include "vmcore/system.h"
#if defined(ENABLE_JVMTI)
# include "native/jvmti/cacaodbg.h"
s4 vms = 0; /* number of VMs created */
bool vm_initializing = false;
-bool vm_exiting = false;
+bool vm_created = false;
+bool vm_exiting = false;
char *mainstring = NULL;
classinfo *mainclass = NULL;
OPT_EA,
OPT_DA,
+ OPT_EA_NOARG,
+ OPT_DA_NOARG,
+
OPT_ESA,
OPT_DSA,
OPT_LSRA,
#endif
-#if defined(ENABLE_INLINING)
- OPT_INLINING,
-#if !defined(NDEBUG)
- OPT_INLINE_LOG,
-#endif
-#if defined(ENABLE_INLINING_DEBUG)
- OPT_INLINE_DEBUG_ALL,
- OPT_INLINE_DEBUG_END,
- OPT_INLINE_DEBUG_MIN,
- OPT_INLINE_DEBUG_MAX,
-#endif /* defined(ENABLE_INLINING_DEBUG) */
-#endif /* defined(ENABLE_INLINING) */
-
#if defined(ENABLE_INTRP)
/* interpreter options */
{ "ea:", true, OPT_EA },
{ "da:", true, OPT_DA },
- { "ea", false, OPT_EA },
- { "da", false, OPT_DA },
+ { "ea", false, OPT_EA_NOARG },
+ { "da", false, OPT_DA_NOARG },
+
+ { "enableassertions:", true, OPT_EA },
+ { "disableassertions:", true, OPT_DA },
+ { "enableassertions", false, OPT_EA_NOARG },
+ { "disableassertions", false, OPT_DA_NOARG },
{ "esa", false, OPT_ESA },
{ "enablesystemassertions", false, OPT_ESA },
#if defined(ENABLE_IFCONV)
{ "ifconv", false, OPT_IFCONV },
#endif
-#if defined(ENABLE_LSRA) || defined(ENABLE_SSA)
+#if defined(ENABLE_LSRA)
{ "lsra", false, OPT_LSRA },
#endif
+#if defined(ENABLE_SSA)
+ { "lsra", true, OPT_LSRA },
+#endif
#if defined(ENABLE_INTRP)
/* interpreter options */
{ "Xprof", false, OPT_PROF },
#endif
- /* inlining options */
-
-#if defined(ENABLE_INLINING)
-#if defined(ENABLE_INLINING_DEBUG)
- { "ia", false, OPT_INLINE_DEBUG_ALL },
- { "ii", true, OPT_INLINE_DEBUG_MIN },
- { "im", true, OPT_INLINE_DEBUG_MAX },
- { "ie", true, OPT_INLINE_DEBUG_END },
-#endif /* defined(ENABLE_INLINING_DEBUG) */
-#if !defined(NDEBUG)
- { "il", false, OPT_INLINE_LOG },
-#endif
- { "i", false, OPT_INLINING },
-#endif /* defined(ENABLE_INLINING) */
-
/* keep these at the end of the list */
#if !defined(NDEBUG)
#endif
puts(" (d)atasegment data segment listing");
-#if defined(ENABLE_INLINING)
- puts(" -i activate inlining");
-#if !defined(NDEBUG)
- puts(" -il log inlining");
-#endif
-#if defined(ENABLE_INLINING_DEBUG)
- puts(" -ia use inlining for all methods");
- puts(" -ii <size> set minimum size for inlined result");
- puts(" -im <size> set maximum size for inlined result");
- puts(" -ie <number> stop inlining after the given number of roots");
-#endif /* defined(ENABLE_INLINING_DEBUG) */
-#endif /* defined(ENABLE_INLINING) */
-
#if defined(ENABLE_IFCONV)
puts(" -ifconv use if-conversion");
#endif
puts(" -lsra use linear scan register allocation");
#endif
#if defined(ENABLE_SSA)
- puts(" -lsra use linear scan register allocation (with SSA)");
+ puts(" -lsra:... use linear scan register allocation (with SSA)");
+ puts(" (d)ead code elimination");
+ puts(" (c)opy propagation");
#endif
#if defined(ENABLE_DEBUG_FILTER)
puts(" -XXfi <regex> begin of dynamic scope for verbosecall filter");
static void version(bool opt_exit)
{
puts("java version \""JAVA_VERSION"\"");
- puts("CACAO version "VERSION"");
-
- puts("Copyright (C) 1996-2005, 2006, 2007 R. Grafl, A. Krall, C. Kruegel,");
- puts("C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,");
- puts("E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,");
- puts("J. Wenninger, Institut f. Computersprachen - TU Wien\n");
+ puts("CACAO version "VERSION"\n");
- puts("This program is free software; you can redistribute it and/or");
- puts("modify it under the terms of the GNU General Public License as");
- puts("published by the Free Software Foundation; either version 2, or (at");
- puts("your option) any later version.\n");
-
- puts("This program is distributed in the hope that it will be useful, but");
- puts("WITHOUT ANY WARRANTY; without even the implied warranty of");
- puts("MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU");
- puts("General Public License for more details.");
+ puts("Copyright (C) 1996-2005, 2006, 2007, 2008");
+ puts("CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO");
+ puts("This is free software; see the source for copying conditions. There is NO");
+ puts("warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.");
/* exit normally, if requested */
printf(" initial heap size : %d\n", HEAP_STARTSIZE);
printf(" stack size : %d\n", STACK_SIZE);
-#if defined(WITH_JRE_LAYOUT)
+#if defined(ENABLE_JRE_LAYOUT)
/* When we're building with JRE-layout, the default paths are the
same as the runtime paths. */
#else
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;
jdwp = agentbypath = false;
#endif
-#if defined(ENABLE_VMLOG)
- vmlog_cacao_init(vm_args);
-#endif
-
#if defined(ENABLE_JNI)
/* Check the JNI version requested. */
/* First of all, parse the -XX options. */
+#if defined(ENABLE_VMLOG)
+ vmlog_cacao_init_options();
+#endif
+
options_xx(vm_args);
+#if defined(ENABLE_VMLOG)
+ vmlog_cacao_init();
+#endif
+
/* We need to check if the actual size of a java.lang.Class object
is smaller or equal than the assumption made in
src/vmcore/class.h. */
break;
#endif
-#if defined(ENABLE_INLINING)
-#if defined(ENABLE_INLINING_DEBUG)
- case OPT_INLINE_DEBUG_ALL:
- opt_inline_debug_all = true;
- break;
- case OPT_INLINE_DEBUG_END:
- opt_inline_debug_end_counter = atoi(opt_arg);
- break;
- case OPT_INLINE_DEBUG_MIN:
- opt_inline_debug_min_size = atoi(opt_arg);
- break;
- case OPT_INLINE_DEBUG_MAX:
- opt_inline_debug_max_size = atoi(opt_arg);
- break;
-#endif /* defined(ENABLE_INLINING_DEBUG) */
-#if !defined(NDEBUG)
- case OPT_INLINE_LOG:
- opt_inline_debug_log = true;
- break;
-#endif /* !defined(NDEBUG) */
-
- case OPT_INLINING:
- opt_inlining = true;
- break;
-#endif /* defined(ENABLE_INLINING) */
-
#if defined(ENABLE_IFCONV)
case OPT_IFCONV:
opt_ifconv = true;
break;
#endif
-#if defined(ENABLE_LSRA) || defined(ENABLE_SSA)
+#if defined(ENABLE_LSRA)
case OPT_LSRA:
opt_lsra = true;
break;
#endif
+#if defined(ENABLE_SSA)
+ case OPT_LSRA:
+ opt_lsra = true;
+ for (i = 0; i < strlen(opt_arg); i++) {
+ switch (opt_arg[i]) {
+ case 'c':
+ opt_ssa_cp = true;
+ break;
+
+ case 'd':
+ opt_ssa_dce = true;
+ break;
+
+ case ':':
+ break;
+
+ default:
+ usage();
+ }
+ }
+ break;
+#endif
case OPT_HELP:
usage();
break;
case OPT_EA:
- /* currently ignored */
+#if defined(ENABLE_ASSERTION)
+ assertion_ea_da(opt_arg, true);
+#endif
break;
case OPT_DA:
- /* currently ignored */
+#if defined(ENABLE_ASSERTION)
+ assertion_ea_da(opt_arg, false);
+#endif
+ break;
+
+ case OPT_EA_NOARG:
+#if defined(ENABLE_ASSERTION)
+ assertion_user_enabled = true;
+#endif
+ break;
+
+ case OPT_DA_NOARG:
+#if defined(ENABLE_ASSERTION)
+ assertion_user_enabled = false;
+#endif
break;
case OPT_ESA:
- _Jv_jvm->Java_java_lang_VMClassLoader_defaultAssertionStatus = true;
+#if defined(ENABLE_ASSERTION)
+ assertion_system_enabled = true;
+#endif
break;
case OPT_DSA:
- _Jv_jvm->Java_java_lang_VMClassLoader_defaultAssertionStatus = false;
+#if defined(ENABLE_ASSERTION)
+ assertion_system_enabled = false;
+#endif
break;
#if defined(ENABLE_PROFILING)
gc_init(opt_heapmaxsize, opt_heapstartsize);
#if defined(ENABLE_THREADS)
+ /* BEFORE: threads_preinit */
+
+ threadlist_init();
+
/* AFTER: gc_init (directly after, as this initializes the
stopworldlock lock */
threads_preinit();
+ lock_init();
+ critical_init();
#endif
/* install architecture dependent signal handlers */
/* AFTER: threads_preinit */
- if (!utf8_init())
- vm_abort("vm_create: utf8_init failed");
+ utf8_init();
/* AFTER: thread_preinit */
if (!classcache_init())
vm_abort("vm_create: classcache_init failed");
- /* initialize the memory subsystem (must be done _after_
- threads_preinit) */
+ /* Initialize the code memory management. */
+ /* AFTER: threads_preinit */
- if (!memory_init())
- vm_abort("vm_create: memory_init failed");
+ codememory_init();
/* initialize the finalizer stuff (must be done _after_
threads_preinit) */
if (!finalizer_init())
vm_abort("vm_create: finalizer_init failed");
- /* initialize the codegen subsystems */
-
- codegen_init();
-
- /* initializes jit compiler */
+ /* Initialize the JIT compiler. */
jit_init();
+ code_init();
+ methodtree_init();
- /* machine dependent initialization */
-
-#if defined(ENABLE_JIT)
-# if defined(ENABLE_INTRP)
- if (opt_intrp)
- intrp_md_init();
- else
-# endif
- md_init();
-#else
- intrp_md_init();
+#if defined(ENABLE_PYTHON)
+ pythonpass_init();
#endif
/* BEFORE: loader_preinit */
/* AFTER: loader_init, linker_init */
primitive_postinit();
+ method_init();
- exceptions_init();
+#if defined(ENABLE_JIT)
+ trap_init();
+#endif
if (!builtin_init())
vm_abort("vm_create: builtin_init failed");
/* Register the native methods implemented in the VM. */
/* BEFORE: threads_init */
- if (!nativevm_preinit())
- vm_abort("vm_create: nativevm_preinit failed");
+ nativevm_preinit();
#if defined(ENABLE_JNI)
/* Initialize the JNI subsystem (must be done _before_
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
+
+ /* Iinitialize some important system classes. */
+ /* BEFORE: threads_init */
+
+ initialize_init();
+
#if defined(ENABLE_THREADS)
- if (!threads_init())
- vm_abort("vm_create: threads_init failed");
+ threads_init();
#endif
/* Initialize the native VM subsystem. */
/* AFTER: threads_init (at least for SUN's classes) */
- if (!nativevm_init())
- vm_abort("vm_create: nativevm_init failed");
+ nativevm_init();
#if defined(ENABLE_PROFILING)
/* initialize profiling */
}
#endif
- /* increment the number of VMs */
+ /* Increment the number of VMs. */
vms++;
- /* initialization is done */
+ /* Initialization is done, VM is created.. */
+ vm_created = true;
vm_initializing = false;
-#if !defined(NDEBUG)
/* Print the VM configuration after all stuff is set and the VM is
initialized. */
if (opt_PrintConfig)
vm_printconfig();
-#endif
/* everything's ok */
s4 oalength;
utf *u;
java_handle_t *s;
- s4 status;
- s4 i;
+ int status;
+ int i;
+
+#if defined(ENABLE_THREADS)
+ threadobject *t;
+#endif
#if !defined(NDEBUG)
if (compileall) {
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
status = 1;
}
- /* unload the JavaVM */
+#if defined(ENABLE_THREADS)
+ /* Detach the main thread so that it appears to have ended when
+ the application's main method exits. */
+
+ t = thread_get_current();
+
+ if (!threads_detach_thread(t))
+ vm_abort("vm_run: Could not detach main thread.");
+#endif
+
+ /* Destroy the JavaVM. */
(void) vm_destroy(vm);
- /* and exit */
+ /* And exit. */
vm_exit(status);
}
*******************************************************************************/
-s4 vm_destroy(JavaVM *vm)
+int vm_destroy(JavaVM *vm)
{
#if defined(ENABLE_THREADS)
+ /* Create a a trivial new Java waiter thread called
+ "DestroyJavaVM". */
+
+ JavaVMAttachArgs args;
+
+ args.name = "DestroyJavaVM";
+ args.group = NULL;
+
+ if (!threads_attach_current_thread(&args, false))
+ return 1;
+
+ /* Wait until we are the last non-daemon thread. */
+
threads_join_all_threads();
#endif
- /* everything's ok */
+ /* VM is gone. */
+
+ vm_created = false;
+
+ /* Everything is ok. */
return 0;
}
#if defined(ENABLE_JVMTI)
/* terminate cacaodbgserver */
if (dbgcom!=NULL) {
- pthread_mutex_lock(&dbgcomlock);
+ mutex_lock(&dbgcomlock);
dbgcom->running=1;
- pthread_mutex_unlock(&dbgcomlock);
+ mutex_unlock(&dbgcomlock);
jvmti_cacaodbgserver_quit();
}
#endif
Prints an error message and aborts the VM.
+ IN:
+ text ... error message to print
+
*******************************************************************************/
void vm_abort(const char *text, ...)
{
va_list ap;
- /* print the log message */
+ /* Print the log message. */
+
+ log_start();
+
+ va_start(ap, text);
+ log_vprint(text, ap);
+ va_end(ap);
+
+ log_finish();
+
+ /* Now abort the VM. */
+
+ system_abort();
+}
+
+
+/* vm_abort_errnum *************************************************************
+
+ Prints an error message, appends ":" plus the strerror-message of
+ errnum and aborts the VM.
+
+ IN:
+ errnum ... error number
+ text ..... error message to print
+
+*******************************************************************************/
+
+void vm_abort_errnum(int errnum, const char *text, ...)
+{
+ va_list ap;
+
+ /* Print the log message. */
log_start();
log_vprint(text, ap);
va_end(ap);
+ /* Print the strerror-message of errnum. */
+
+ log_print(": %s", system_strerror(errnum));
+
log_finish();
- /* now abort the VM */
+ /* Now abort the VM. */
- abort();
+ system_abort();
+}
+
+
+/* vm_abort_errno **************************************************************
+
+ Equal to vm_abort_errnum, but uses errno to get the error number.
+
+ IN:
+ text ... error message to print
+
+*******************************************************************************/
+
+void vm_abort_errno(const char *text, ...)
+{
+ va_list ap;
+
+ va_start(ap, text);
+ vm_abort_errnum(errno, text, ap);
+ va_end(ap);
+}
+
+
+/* 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...");
}
o = vm_call_method(m, o, s);
if (o == NULL) {
- exceptions_print_stacktrace();
+ fprintf(stderr, "Failed to load Main-Class manifest attribute from\n");
+ fprintf(stderr, "%s\n", mainstring);
return NULL;
}
#endif /* !defined(NDEBUG) */
-/* vm_array_store_int **********************************************************
-
- Helper function to store an integer into the argument array, taking
- care of architecture specific issues.
-
-*******************************************************************************/
-
-static void vm_array_store_int(uint64_t *array, paramdesc *pd, int32_t value)
-{
- int32_t index;
-
- if (!pd->inmemory) {
- index = pd->index;
- array[index] = (int64_t) value;
- }
- else {
- index = ARG_CNT + pd->index;
-#if SIZEOF_VOID_P == 8
- array[index] = (int64_t) value;
-#else
-# if WORDS_BIGENDIAN == 1
- array[index] = ((int64_t) value) << 32;
-# else
- array[index] = (int64_t) value;
-# endif
-#endif
- }
-}
-
-
-/* vm_array_store_lng **********************************************************
-
- Helper function to store a long into the argument array, taking
- care of architecture specific issues.
-
-*******************************************************************************/
-
-static void vm_array_store_lng(uint64_t *array, paramdesc *pd, int64_t value)
-{
- int32_t index;
-
-#if SIZEOF_VOID_P == 8
- if (!pd->inmemory)
- index = pd->index;
- else
- index = ARG_CNT + pd->index;
-
- array[index] = value;
-#else
- if (!pd->inmemory) {
- /* move low and high 32-bits into it's own argument slot */
-
- index = GET_LOW_REG(pd->index);
- array[index] = value & 0x00000000ffffffff;
-
- index = GET_HIGH_REG(pd->index);
- array[index] = value >> 32;
- }
- else {
- index = ARG_CNT + pd->index;
- array[index] = value;
- }
-#endif
-}
-
-
-/* vm_array_store_flt **********************************************************
-
- Helper function to store a float into the argument array, taking
- care of architecture specific issues.
-
-*******************************************************************************/
-
-static void vm_array_store_flt(uint64_t *array, paramdesc *pd, uint64_t value)
-{
- int32_t index;
-
- if (!pd->inmemory) {
-#if defined(SUPPORT_PASS_FLOATARGS_IN_INTREGS)
- index = pd->index;
-#else
- index = INT_ARG_CNT + pd->index;
-#endif
-#if WORDS_BIGENDIAN == 1 && !defined(__POWERPC__) && !defined(__POWERPC64__) && !defined(__S390__)
- array[index] = value >> 32;
-#else
- array[index] = value;
-#endif
- }
- else {
- index = ARG_CNT + pd->index;
-#if defined(__SPARC_64__)
- array[index] = value >> 32;
-#else
- array[index] = value;
-#endif
- }
-}
-
-
-/* vm_array_store_dbl **********************************************************
-
- Helper function to store a double into the argument array, taking
- care of architecture specific issues.
-
-*******************************************************************************/
-
-static void vm_array_store_dbl(uint64_t *array, paramdesc *pd, uint64_t value)
-{
- int32_t index;
-
- if (!pd->inmemory) {
-#if SIZEOF_VOID_P != 8 && defined(SUPPORT_PASS_FLOATARGS_IN_INTREGS)
- index = GET_LOW_REG(pd->index);
- array[index] = value & 0x00000000ffffffff;
-
- index = GET_HIGH_REG(pd->index);
- array[index] = value >> 32;
-#else
- index = INT_ARG_CNT + pd->index;
- array[index] = value;
-#endif
- }
- else {
- index = ARG_CNT + pd->index;
- array[index] = value;
- }
-}
-
-
-/* vm_array_store_adr **********************************************************
-
- Helper function to store an address into the argument array, taking
- care of architecture specific issues.
-
-*******************************************************************************/
-
-static void vm_array_store_adr(uint64_t *array, paramdesc *pd, void *value)
-{
- int32_t index;
-
- if (!pd->inmemory) {
-#if defined(HAS_ADDRESS_REGISTER_FILE)
- /* When the architecture has address registers, place them
- after integer and float registers. */
-
- index = INT_ARG_CNT + FLT_ARG_CNT + pd->index;
-#else
- index = pd->index;
-#endif
- array[index] = (uint64_t) (intptr_t) value;
- }
- else {
- index = ARG_CNT + pd->index;
-#if SIZEOF_VOID_P == 8
- array[index] = (uint64_t) (intptr_t) value;
-#else
-# if WORDS_BIGENDIAN == 1
- array[index] = ((uint64_t) (intptr_t) value) << 32;
-# else
- array[index] = (uint64_t) (intptr_t) value;
-# endif
-#endif
- }
-}
-
-
-/* vm_array_from_valist ********************************************************
-
- XXX
-
-*******************************************************************************/
-
-uint64_t *vm_array_from_valist(methodinfo *m, java_handle_t *o, va_list ap)
-{
- methoddesc *md;
- paramdesc *pd;
- typedesc *td;
- uint64_t *array;
- int32_t i;
- imm_union value;
-
- /* get the descriptors */
-
- md = m->parseddesc;
- pd = md->params;
- td = md->paramtypes;
-
- /* allocate argument array */
-
- array = DMNEW(uint64_t, INT_ARG_CNT + FLT_ARG_CNT + md->memuse);
-
- /* if method is non-static fill first block and skip `this' pointer */
-
- i = 0;
-
- if (o != NULL) {
- /* the `this' pointer */
- vm_array_store_adr(array, pd, o);
-
- pd++;
- td++;
- i++;
- }
-
- for (; i < md->paramcount; i++, pd++, td++) {
- switch (td->type) {
- case TYPE_INT:
- value.i = va_arg(ap, int32_t);
- vm_array_store_int(array, pd, value.i);
- break;
-
- case TYPE_LNG:
- value.l = va_arg(ap, int64_t);
- vm_array_store_lng(array, pd, value.l);
- break;
-
- case TYPE_FLT:
-#if defined(__ALPHA__) || defined(__POWERPC__) || defined(__POWERPC64__)
- /* This is required to load the correct float value in
- assembler code. */
-
- value.d = (double) va_arg(ap, double);
-#else
- value.f = (float) va_arg(ap, double);
-#endif
- vm_array_store_flt(array, pd, value.l);
- break;
-
- case TYPE_DBL:
- value.d = va_arg(ap, double);
- vm_array_store_dbl(array, pd, value.l);
- break;
-
- case TYPE_ADR:
- value.a = va_arg(ap, void*);
- vm_array_store_adr(array, pd, value.a);
- break;
- }
- }
-
- return array;
-}
-
+/* vm_call_array ***************************************************************
-/* vm_array_from_jvalue ********************************************************
+ Calls a Java method with a variable number of arguments, passed via
+ an argument array.
- XXX
+ ATTENTION: This function has to be used outside the nativeworld.
*******************************************************************************/
-static uint64_t *vm_array_from_jvalue(methodinfo *m, java_handle_t *o,
- const jvalue *args)
-{
- methoddesc *md;
- paramdesc *pd;
- typedesc *td;
- uint64_t *array;
- int32_t i;
- int32_t j;
-
- /* get the descriptors */
-
- md = m->parseddesc;
- pd = md->params;
- td = md->paramtypes;
-
- /* allocate argument array */
-
-#if defined(HAS_ADDRESS_REGISTER_FILE)
- array = DMNEW(uint64_t, INT_ARG_CNT + FLT_ARG_CNT + ADR_ARG_CNT + md->memuse);
-#else
- array = DMNEW(uint64_t, INT_ARG_CNT + FLT_ARG_CNT + md->memuse);
-#endif
-
- /* if method is non-static fill first block and skip `this' pointer */
-
- i = 0;
-
- if (o != NULL) {
- /* the `this' pointer */
- vm_array_store_adr(array, pd, o);
-
- pd++;
- td++;
- i++;
- }
-
- for (j = 0; i < md->paramcount; i++, j++, pd++, td++) {
- switch (td->decltype) {
- case TYPE_INT:
- vm_array_store_int(array, pd, args[j].i);
- break;
-
- case TYPE_LNG:
- vm_array_store_lng(array, pd, args[j].j);
- break;
-
- case TYPE_FLT:
- vm_array_store_flt(array, pd, args[j].j);
- break;
-
- case TYPE_DBL:
- vm_array_store_dbl(array, pd, args[j].j);
- break;
-
- case TYPE_ADR:
- vm_array_store_adr(array, pd, args[j].l);
- break;
- }
- }
-
- return array;
+#define VM_CALL_ARRAY(name, type) \
+static type vm_call##name##_array(methodinfo *m, uint64_t *array) \
+{ \
+ methoddesc *md; \
+ void *pv; \
+ type value; \
+ \
+ assert(m->code != NULL); \
+ \
+ md = m->parseddesc; \
+ pv = m->code->entrypoint; \
+ \
+ STATISTICS(count_calls_native_to_java++); \
+ \
+ value = asm_vm_call_method##name(pv, array, md->memuse); \
+ \
+ return value; \
}
-
-/* vm_array_from_objectarray ***************************************************
-
- XXX
-
-*******************************************************************************/
-
-uint64_t *vm_array_from_objectarray(methodinfo *m, java_handle_t *o,
- java_handle_objectarray_t *params)
+static java_handle_t *vm_call_array(methodinfo *m, uint64_t *array)
{
methoddesc *md;
- paramdesc *pd;
- typedesc *td;
- uint64_t *array;
- java_handle_t *param;
- classinfo *c;
- int type;
- int32_t i;
- int32_t j;
- imm_union value;
+ void *pv;
+ java_object_t *o;
- /* get the descriptors */
+ assert(m->code != NULL);
md = m->parseddesc;
- pd = md->params;
- td = md->paramtypes;
-
- /* allocate argument array */
-
- array = DMNEW(uint64_t, INT_ARG_CNT + FLT_ARG_CNT + md->memuse);
-
- /* if method is non-static fill first block and skip `this' pointer */
-
- i = 0;
-
- if (o != NULL) {
- /* this pointer */
- vm_array_store_adr(array, pd, o);
+ pv = m->code->entrypoint;
- pd++;
- td++;
- i++;
- }
-
- for (j = 0; i < md->paramcount; i++, j++, pd++, td++) {
- LLNI_objectarray_element_get(params, j, param);
-
- switch (td->type) {
- case TYPE_INT:
- if (param == NULL) {
- exceptions_throw_illegalargumentexception();
- return NULL;
- }
-
- /* convert the value according to its declared type */
-
- LLNI_class_get(param, c);
- type = primitive_type_get_by_wrapperclass(c);
-
- switch (td->decltype) {
- case PRIMITIVETYPE_BOOLEAN:
- switch (type) {
- case PRIMITIVETYPE_BOOLEAN:
- /* This type is OK. */
- break;
- default:
- exceptions_throw_illegalargumentexception();
- return NULL;
- }
- break;
-
- case PRIMITIVETYPE_BYTE:
- switch (type) {
- case PRIMITIVETYPE_BYTE:
- /* This type is OK. */
- break;
- default:
- exceptions_throw_illegalargumentexception();
- return NULL;
- }
- break;
-
- case PRIMITIVETYPE_CHAR:
- switch (type) {
- case PRIMITIVETYPE_CHAR:
- /* This type is OK. */
- break;
- default:
- exceptions_throw_illegalargumentexception();
- return NULL;
- }
- break;
+ STATISTICS(count_calls_native_to_java++);
- case PRIMITIVETYPE_SHORT:
- switch (type) {
- case PRIMITIVETYPE_BYTE:
- case PRIMITIVETYPE_SHORT:
- /* These types are OK. */
- break;
- default:
- exceptions_throw_illegalargumentexception();
- return NULL;
- }
- break;
-
- case PRIMITIVETYPE_INT:
- switch (type) {
- case PRIMITIVETYPE_BYTE:
- case PRIMITIVETYPE_SHORT:
- case PRIMITIVETYPE_INT:
- /* These types are OK. */
- break;
- default:
- exceptions_throw_illegalargumentexception();
- return NULL;
- }
- break;
-
- default:
- vm_abort("vm_array_from_objectarray: invalid type %d",
- td->decltype);
- }
+ o = asm_vm_call_method(pv, array, md->memuse);
- value = primitive_unbox(param);
- vm_array_store_int(array, pd, value.i);
- break;
+ if (md->returntype.type == TYPE_VOID)
+ o = NULL;
- case TYPE_LNG:
- if (param == NULL) {
- exceptions_throw_illegalargumentexception();
- return NULL;
- }
-
- LLNI_class_get(param, c);
- type = primitive_type_get_by_wrapperclass(c);
-
- assert(td->decltype == PRIMITIVETYPE_LONG);
-
- switch (type) {
- case PRIMITIVETYPE_BYTE:
- case PRIMITIVETYPE_SHORT:
- case PRIMITIVETYPE_INT:
- case PRIMITIVETYPE_LONG:
- /* These types are OK. */
- break;
- default:
- exceptions_throw_illegalargumentexception();
- return NULL;
- }
-
- value = primitive_unbox(param);
- vm_array_store_lng(array, pd, value.l);
- break;
-
- case TYPE_FLT:
- if (param == NULL) {
- exceptions_throw_illegalargumentexception();
- return NULL;
- }
-
- LLNI_class_get(param, c);
- type = primitive_type_get_by_wrapperclass(c);
-
- assert(td->decltype == PRIMITIVETYPE_FLOAT);
-
- switch (type) {
- case PRIMITIVETYPE_FLOAT:
- /* This type is OK. */
- break;
- default:
- exceptions_throw_illegalargumentexception();
- return NULL;
- }
-
- value = primitive_unbox(param);
- vm_array_store_flt(array, pd, value.l);
- break;
-
- case TYPE_DBL:
- if (param == NULL) {
- exceptions_throw_illegalargumentexception();
- return NULL;
- }
-
- LLNI_class_get(param, c);
- type = primitive_type_get_by_wrapperclass(c);
-
- assert(td->decltype == PRIMITIVETYPE_DOUBLE);
-
- switch (type) {
- case PRIMITIVETYPE_FLOAT:
- case PRIMITIVETYPE_DOUBLE:
- /* These types are OK. */
- break;
- default:
- exceptions_throw_illegalargumentexception();
- return NULL;
- }
-
- value = primitive_unbox(param);
- vm_array_store_dbl(array, pd, value.l);
- break;
-
- case TYPE_ADR:
- if (!resolve_class_from_typedesc(td, true, true, &c))
- return NULL;
-
- if (param != NULL) {
- if (td->arraydim > 0) {
- if (!builtin_arrayinstanceof(param, c)) {
- exceptions_throw_illegalargumentexception();
- return NULL;
- }
- }
- else {
- if (!builtin_instanceof(param, c)) {
- exceptions_throw_illegalargumentexception();
- return NULL;
- }
- }
- }
-
- vm_array_store_adr(array, pd, param);
- break;
-
- default:
- vm_abort("vm_array_from_objectarray: invalid type %d", td->type);
- }
- }
-
- return array;
+ return LLNI_WRAP(o);
}
+VM_CALL_ARRAY(_int, int32_t)
+VM_CALL_ARRAY(_long, int64_t)
+VM_CALL_ARRAY(_float, float)
+VM_CALL_ARRAY(_double, double)
+
/* vm_call_method **************************************************************
type vm_call_method##name##_valist(methodinfo *m, java_handle_t *o, \
va_list ap) \
{ \
- int32_t dumpsize; \
uint64_t *array; \
type value; \
+ int32_t dumpmarker; \
+ \
+ if (m->code == NULL) \
+ if (!jit_compile(m)) \
+ return 0; \
\
- dumpsize = dump_size(); \
- array = vm_array_from_valist(m, o, ap); \
+ THREAD_NATIVEWORLD_EXIT; \
+ DMARKER; \
+ \
+ array = argument_vmarray_from_valist(m, o, ap); \
value = vm_call##name##_array(m, array); \
- dump_release(dumpsize); \
+ \
+ DRELEASE; \
+ THREAD_NATIVEWORLD_ENTER; \
\
return value; \
}
type vm_call_method##name##_jvalue(methodinfo *m, java_handle_t *o, \
const jvalue *args) \
{ \
- int32_t dumpsize; \
uint64_t *array; \
type value; \
+ int32_t dumpmarker; \
+ \
+ if (m->code == NULL) \
+ if (!jit_compile(m)) \
+ return 0; \
+ \
+ THREAD_NATIVEWORLD_EXIT; \
+ DMARKER; \
\
- dumpsize = dump_size(); \
- array = vm_array_from_jvalue(m, o, args); \
+ array = argument_vmarray_from_jvalue(m, o, args); \
value = vm_call##name##_array(m, array); \
- dump_release(dumpsize); \
+ \
+ DRELEASE; \
+ THREAD_NATIVEWORLD_ENTER; \
\
return value; \
}
VM_CALL_METHOD_JVALUE(_double, double)
-/* vm_call_array ***************************************************************
+/* vm_call_method_objectarray **************************************************
- Calls a Java method with a variable number of arguments, passed via
- an argument array.
+ Calls a Java method with a variable number if arguments, passed via
+ an objectarray of boxed values. Returns a boxed value.
*******************************************************************************/
-#define VM_CALL_ARRAY(name, type) \
-type vm_call##name##_array(methodinfo *m, uint64_t *array) \
-{ \
- methoddesc *md; \
- void *pv; \
- type value; \
- \
- md = m->parseddesc; \
- \
- if (m->code == NULL) \
- if (!jit_compile(m)) \
- return 0; \
- \
- pv = m->code->entrypoint; \
- \
- STATISTICS(count_calls_native_to_java++); \
- \
- value = asm_vm_call_method##name(pv, array, md->memuse); \
- \
- return value; \
-}
+java_handle_t *vm_call_method_objectarray(methodinfo *m, java_handle_t *o,
+ java_handle_objectarray_t *params)
+{
+ uint64_t *array;
+ java_handle_t *xptr;
+ java_handle_t *ro;
+ imm_union value;
+ int32_t dumpmarker;
-VM_CALL_ARRAY(, java_handle_t *)
-VM_CALL_ARRAY(_int, int32_t)
-VM_CALL_ARRAY(_long, int64_t)
-VM_CALL_ARRAY(_float, float)
-VM_CALL_ARRAY(_double, double)
+ /* Prevent compiler warnings. */
+
+ ro = NULL;
+
+ /* compile methods which are not yet compiled */
+
+ if (m->code == NULL)
+ if (!jit_compile(m))
+ return NULL;
+
+ /* leave the nativeworld */
+
+ THREAD_NATIVEWORLD_EXIT;
+
+ /* mark start of dump memory area */
+
+ DMARKER;
+
+ /* Fill the argument array from a object-array. */
+
+ array = argument_vmarray_from_objectarray(m, o, params);
+
+ if (array == NULL) {
+ /* release dump area */
+
+ DRELEASE;
+
+ /* enter the nativeworld again */
+
+ THREAD_NATIVEWORLD_ENTER;
+
+ exceptions_throw_illegalargumentexception();
+
+ return NULL;
+ }
+
+ switch (m->parseddesc->returntype.decltype) {
+ case PRIMITIVETYPE_VOID:
+ value.a = vm_call_array(m, array);
+ break;
+
+ case PRIMITIVETYPE_BOOLEAN:
+ case PRIMITIVETYPE_BYTE:
+ case PRIMITIVETYPE_CHAR:
+ case PRIMITIVETYPE_SHORT:
+ case PRIMITIVETYPE_INT:
+ value.i = vm_call_int_array(m, array);
+ break;
+
+ case PRIMITIVETYPE_LONG:
+ value.l = vm_call_long_array(m, array);
+ break;
+
+ case PRIMITIVETYPE_FLOAT:
+ value.f = vm_call_float_array(m, array);
+ break;
+
+ case PRIMITIVETYPE_DOUBLE:
+ value.d = vm_call_double_array(m, array);
+ break;
+
+ case TYPE_ADR:
+ ro = vm_call_array(m, array);
+ break;
+
+ default:
+ vm_abort("vm_call_method_objectarray: invalid return type %d", m->parseddesc->returntype.decltype);
+ }
+
+ /* release dump area */
+
+ DRELEASE;
+
+ /* 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) {
+ /* clear exception pointer, we are calling JIT code again */
+
+ exceptions_clear_exception();
+
+ exceptions_throw_invocationtargetexception(xptr);
+ }
+
+ return ro;
+}
/*