/* 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.
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301, USA.
- $Id: vm.c 8404 2007-08-22 21:34:24Z twisti $
-
*/
#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/include/java_lang_String.h" /* required by j.l.C */
-#if defined(WITH_CLASSPATH_SUN)
+#if defined(WITH_JAVA_RUNTIME_LIBRARY_OPENJDK)
# include "native/include/java_nio_ByteBuffer.h" /* required by j.l.CL */
# include "native/include/java_lang_ClassLoader.h" /* required by j.l.C */
#endif
#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/global.h"
#include "vm/initialize.h"
+#include "vm/package.hpp"
#include "vm/primitive.h"
#include "vm/properties.h"
#include "vm/signallocal.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;
+static classinfo *mainclass = NULL;
#if defined(ENABLE_INTRP)
u1 *intrp_main_stack = NULL;
#define HEAP_MAXSIZE 128 * 1024 * 1024 /* default 128MB */
#define HEAP_STARTSIZE 2 * 1024 * 1024 /* default 2MB */
-#define STACK_SIZE 64 * 1024 /* default 64kB */
+#define STACK_SIZE 128 * 1024 /* default 64kB */
/* define command line options ************************************************/
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 */
{ "?", false, OPT_HELP },
{ "X", false, OPT_X },
{ "XX:", true, OPT_XX },
- { "XX", false, OPT_XX },
{ "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)
{
puts(" -v write state-information");
#if !defined(NDEBUG)
- puts(" -verbose[:jit|threads]");
- puts(" enable specific verbose output");
+ puts(" -verbose:jit enable specific verbose output");
puts(" -debug-color colored output for ANSI terms");
#endif
#ifdef TYPECHECK_VERBOSE
#if defined(ENABLE_DISASSEMBLER)
puts(" (a)ssembler disassembled listing");
puts(" n(o)ps show NOPs in disassembler output");
- puts(" (e)xceptionstubs disassembled exception stubs (only with -sa)");
- puts(" (n)ative disassembled native stubs");
#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 */
}
-void vm_printconfig(void)
+static void vm_printconfig(void)
{
puts("Configure/Build options:\n");
puts(" ./configure: "VERSION_CONFIGURE_ARGS"");
printf(" maximum heap size : %d\n", HEAP_MAXSIZE);
printf(" initial heap size : %d\n", HEAP_STARTSIZE);
printf(" stack size : %d\n", STACK_SIZE);
-#if defined(WITH_CLASSPATH_GNU)
- puts(" java.boot.class.path : "CACAO_VM_ZIP":"CLASSPATH_CLASSES"");
+
+#if defined(ENABLE_JRE_LAYOUT)
+ /* When we're building with JRE-layout, the default paths are the
+ same as the runtime paths. */
#else
- puts(" java.boot.class.path : "CLASSPATH_CLASSES"");
+# if defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
+ puts(" gnu.classpath.boot.library.path: "JAVA_RUNTIME_LIBRARY_LIBDIR);
+ puts(" java.boot.class.path : "CACAO_VM_ZIP":"JAVA_RUNTIME_LIBRARY_CLASSES"");
+# elif defined(WITH_JAVA_RUNTIME_LIBRARY_OPENJDK)
+ puts(" sun.boot.library.path : "JAVA_RUNTIME_LIBRARY_LIBDIR);
+ puts(" java.boot.class.path : "JAVA_RUNTIME_LIBRARY_CLASSES);
+# endif
#endif
- puts(" gnu.classpath.boot.library.path: "CLASSPATH_LIBDIR"/classpath\n");
+
+ puts("");
puts("Runtime variables:\n");
printf(" maximum heap size : %d\n", opt_heapmaxsize);
printf(" initial heap size : %d\n", opt_heapstartsize);
printf(" stack size : %d\n", opt_stacksize);
- printf(" java.boot.class.path : %s\n", properties_get("java.boot.class.path"));
- printf(" java.class.path : %s\n", properties_get("java.class.path"));
+#if defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
printf(" gnu.classpath.boot.library.path: %s\n", properties_get("gnu.classpath.boot.library.path"));
+#elif defined(WITH_JAVA_RUNTIME_LIBRARY_OPENJDK)
+ printf(" sun.boot.library.path : %s\n", properties_get("sun.boot.library.path"));
+#endif
+
+ printf(" java.boot.class.path : %s\n", properties_get("java.boot.class.path"));
+ printf(" java.class.path : %s\n", properties_get("java.class.path"));
}
static char *vm_get_mainclass_from_jar(char *mainstring);
#if !defined(NDEBUG)
static void vm_compile_all(void);
-static void vm_compile_method(void);
+static void vm_compile_method(char* mainname);
#endif
if (!vm_create(_vm_args))
goto error;
-#if defined(ENABLE_JNI)
- /* setup the local ref table (must be created after vm_create) */
-
- 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
-
- /* check the JNI version requested */
+#if defined(ENABLE_JNI)
+ /* Check the JNI version requested. */
- switch (vm_args->version) {
- case JNI_VERSION_1_1:
- break;
- case JNI_VERSION_1_2:
- case JNI_VERSION_1_4:
- break;
- default:
+ if (!jni_version_check(vm_args->version))
return false;
- }
+#endif
- /* we only support 1 JVM instance */
+ /* We only support 1 JVM instance. */
if (vms > 0)
return false;
+ /* Install the exit handler. */
+
if (atexit(vm_exit_handler))
vm_abort("atexit failed: %s\n", strerror(errno));
- if (opt_verbose)
- log_text("CACAO started -------------------------------------------------------");
+ /* Set some options. */
+
+ opt_version = false;
+ opt_exit = false;
+
+ opt_noieee = false;
+
+ opt_heapmaxsize = HEAP_MAXSIZE;
+ opt_heapstartsize = HEAP_STARTSIZE;
+ opt_stacksize = STACK_SIZE;
+
+ /* Initialize the properties list before command-line handling.
+ Otherwise -XX:+PrintConfig crashes. */
+
+ properties_init();
+
+ /* 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
_Jv_jvm->starttime = builtin_currenttimemillis();
- /* interpret the options **************************************************/
-
- opt_version = false;
- opt_exit = false;
-
- opt_noieee = false;
-
- opt_heapmaxsize = HEAP_MAXSIZE;
- opt_heapstartsize = HEAP_STARTSIZE;
- opt_stacksize = STACK_SIZE;
-
-
#if defined(ENABLE_JVMTI)
/* initialize JVMTI related **********************************************/
jvmti = false;
#endif
- /* Initialize and fill properties before command-line handling. */
+ /* Fill the properties before command-line handling. */
- properties_init();
properties_set();
/* iterate over all passed options */
initverbose = true;
compileverbose = true;
}
- else if (strcmp("threads", opt_arg) == 0) {
- opt_verbosethreads = true;
- }
#endif
else {
printf("Unknown -verbose option: %s\n", opt_arg);
case 'o':
opt_shownops = true;
break;
-
- case 'e':
- opt_showexceptionstubs = true;
- break;
-
- case 'n':
- opt_shownativestub = true;
- break;
#endif
case 'd':
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
break;
case OPT_XX:
- options_xx(opt_arg);
+ /* Already parsed. */
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)
}
}
- /* get the main class *****************************************************/
-
- if (opt_index < vm_args->nOptions) {
- mainstring = vm_args->options[opt_index++].optionString;
-
- /* Put the jar file into the classpath (if any). */
-
- if (opt_jar == true) {
- /* free old classpath */
-
-/* MFREE(_Jv_classpath, char, strlen(_Jv_classpath)); */
-
- /* put jarfile into classpath */
-
- p = MNEW(char, strlen(mainstring) + strlen("0"));
-
- strcpy(p, mainstring);
-
-#if defined(ENABLE_JAVASE)
- properties_add("java.class.path", p);
-#endif
- }
- else {
- /* replace .'s with /'s in classname */
-
- for (i = strlen(mainstring) - 1; i >= 0; i--)
- if (mainstring[i] == '.')
- mainstring[i] = '/';
- }
- }
-
#if defined(ENABLE_JVMTI)
if (jvmti) {
jvmti_set_phase(JVMTI_PHASE_ONLOAD);
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 */
+ /* Initialize the JIT compiler. */
- codegen_init();
+ jit_init();
+ code_init();
+ methodtree_init();
- /* initializes jit compiler */
+#if defined(ENABLE_PYTHON)
+ pythonpass_init();
+#endif
- jit_init();
+ /* BEFORE: loader_preinit */
- /* machine dependent initialization */
+ Package_initialize();
-#if defined(ENABLE_JIT)
-# if defined(ENABLE_INTRP)
- if (opt_intrp)
- intrp_md_init();
- else
-# endif
- md_init();
-#else
- intrp_md_init();
-#endif
+ /* AFTER: utf8_init, classcache_init */
- /* initialize the loader subsystems (must be done _after_
- classcache_init) */
+ loader_preinit();
+ linker_preinit();
- if (!loader_init())
- vm_abort("vm_create: loader_init failed");
+ /* AFTER: loader_preinit, linker_preinit */
- /* Link some important VM classes. */
- /* AFTER: utf8_init */
+ primitive_init();
- if (!linker_init())
- vm_abort("vm_create: linker_init failed");
+ loader_init();
+ linker_init();
- if (!primitive_init())
- vm_abort("vm_create: primitive_init failed");
+ /* AFTER: loader_init, linker_init */
- if (!exceptions_init())
- vm_abort("vm_create: exceptions_init failed");
+ primitive_postinit();
+ method_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
#if defined(ENABLE_JVMTI)
+# if defined(ENABLE_GC_CACAO)
+ /* XXX this will not work with the new indirection cells for classloaders!!! */
+ assert(0);
+# endif
if (jvmti) {
/* add agent library to native library hashtable */
native_hashtable_library_add(utf_new_char(libname), class_java_lang_Object->classloader, handle);
}
#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;
+ /* Print the VM configuration after all stuff is set and the VM is
+ initialized. */
+
+ if (opt_PrintConfig)
+ vm_printconfig();
+
/* everything's ok */
return true;
void vm_run(JavaVM *vm, JavaVMInitArgs *vm_args)
{
+ char* option;
+ char* mainname;
+ char* p;
utf *mainutf;
classinfo *mainclass;
java_handle_t *e;
s4 oalength;
utf *u;
java_handle_t *s;
- s4 status;
- s4 i;
+ int status;
+ int i;
+
+ // Prevent compiler warnings.
+ oa = NULL;
#if !defined(NDEBUG)
if (compileall) {
vm_compile_all();
return;
}
+#endif
- if (opt_method != NULL) {
- vm_compile_method();
- return;
+ /* Get the main class plus it's arguments. */
+
+ mainname = NULL;
+
+ if (opt_index < vm_args->nOptions) {
+ /* Get main-class argument. */
+
+ mainname = vm_args->options[opt_index].optionString;
+
+ /* If the main class argument is a jar file, put it into the
+ classpath. */
+
+ if (opt_jar == true) {
+ p = MNEW(char, strlen(mainname) + strlen("0"));
+
+ strcpy(p, mainname);
+
+#if defined(ENABLE_JAVASE)
+ properties_add("java.class.path", p);
+#endif
+ }
+ else {
+ /* Replace dots with slashes in the class name. */
+
+ for (i = 0; i < strlen(mainname); i++)
+ if (mainname[i] == '.')
+ mainname[i] = '/';
+ }
+
+ /* Build argument array. Move index to first argument. */
+
+ opt_index++;
+
+ oalength = vm_args->nOptions - opt_index;
+
+ oa = builtin_anewarray(oalength, class_java_lang_String);
+
+ for (i = 0; i < oalength; i++) {
+ option = vm_args->options[opt_index + i].optionString;
+
+ u = utf_new_char(option);
+ s = javastring_new(u);
+
+ array_objectarray_element_set(oa, i, s);
+ }
}
-#endif /* !defined(NDEBUG) */
- /* should we run the main-method? */
+ /* Do we have a main-class argument? */
- if (mainstring == NULL)
+ if (mainname == NULL)
usage();
+#if !defined(NDEBUG)
+ if (opt_method != NULL) {
+ vm_compile_method(mainname);
+ return;
+ }
+#endif
+
/* set return value to OK */
status = 0;
if (opt_jar == true) {
/* open jar file with java.util.jar.JarFile */
- mainstring = vm_get_mainclass_from_jar(mainstring);
+ mainname = vm_get_mainclass_from_jar(mainname);
- if (mainstring == NULL)
+ if (mainname == NULL)
vm_exit(1);
}
/* load the main class */
- mainutf = utf_new_char(mainstring);
+ mainutf = utf_new_char(mainname);
#if defined(ENABLE_JAVAME_CLDC1_1)
mainclass = load_class_bootstrap(mainutf);
vm_exit(1);
}
- /* build argument array */
-
- oalength = vm_args->nOptions - opt_index;
-
- oa = builtin_anewarray(oalength, class_java_lang_String);
-
- for (i = 0; i < oalength; i++) {
- u = utf_new_char(vm_args->options[opt_index + i].optionString);
- s = javastring_new(u);
-
- LLNI_objectarray_element_set(oa, i, s);
- }
-
#ifdef TYPEINFO_DEBUG_TEST
/* test the typeinfo system */
typeinfo_test();
#endif
- /*class_showmethods(currentThread->group->header.vftbl->class); */
#if defined(ENABLE_JVMTI)
jvmti_set_phase(JVMTI_PHASE_LIVE);
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. */
+
+ if (!thread_detach_current_thread())
+ 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 (!thread_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();
log_finish();
- /* now abort the VM */
+ /* Now abort the VM. */
- abort();
+ system_abort();
}
-/* vm_get_mainclass_from_jar ***************************************************
+/* vm_abort_errnum *************************************************************
- Gets the name of the main class from a JAR's manifest file.
+ Prints an error message, appends ":" plus the strerror-message of
+ errnum and aborts the VM.
+
+ IN:
+ errnum ... error number
+ text ..... error message to print
*******************************************************************************/
-static char *vm_get_mainclass_from_jar(char *mainstring)
+void vm_abort_errnum(int errnum, const char *text, ...)
{
- classinfo *c;
- java_handle_t *o;
- methodinfo *m;
- java_handle_t *s;
+ va_list ap;
- c = load_class_from_sysloader(utf_new_char("java/util/jar/JarFile"));
+ /* Print the log message. */
- if (c == NULL) {
- exceptions_print_stacktrace();
- return NULL;
- }
+ log_start();
- /* create JarFile object */
+ va_start(ap, text);
+ log_vprint(text, ap);
+ va_end(ap);
- o = builtin_new(c);
+ /* Print the strerror-message of errnum. */
- if (o == NULL) {
- exceptions_print_stacktrace();
- return NULL;
- }
+ log_print(": %s", system_strerror(errnum));
- m = class_resolveclassmethod(c,
- utf_init,
- utf_java_lang_String__void,
+ log_finish();
+
+ /* Now abort the VM. */
+
+ 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...");
+}
+
+
+/* vm_get_mainclass_from_jar ***************************************************
+
+ Gets the name of the main class from a JAR's manifest file.
+
+*******************************************************************************/
+
+static char *vm_get_mainclass_from_jar(char *mainname)
+{
+ classinfo *c;
+ java_handle_t *o;
+ methodinfo *m;
+ java_handle_t *s;
+
+ c = load_class_from_sysloader(utf_new_char("java/util/jar/JarFile"));
+
+ if (c == NULL) {
+ exceptions_print_stacktrace();
+ return NULL;
+ }
+
+ /* create JarFile object */
+
+ o = builtin_new(c);
+
+ if (o == NULL) {
+ exceptions_print_stacktrace();
+ return NULL;
+ }
+
+ m = class_resolveclassmethod(c,
+ utf_init,
+ utf_java_lang_String__void,
class_java_lang_Object,
true);
return NULL;
}
- s = javastring_new_from_ascii(mainstring);
+ s = javastring_new_from_ascii(mainname);
(void) vm_call_method(m, o, s);
o = vm_call_method(m, o);
if (o == NULL) {
- fprintf(stderr, "Could not get manifest from %s (invalid or corrupt jarfile?)\n", mainstring);
+ fprintf(stderr, "Could not get manifest from %s (invalid or corrupt jarfile?)\n", mainname);
return NULL;
}
/* get Main Attributes */
- m = class_resolveclassmethod(o->vftbl->class,
+ LLNI_class_get(o, c);
+
+ m = class_resolveclassmethod(c,
utf_new_char("getMainAttributes"),
utf_new_char("()Ljava/util/jar/Attributes;"),
class_java_lang_Object,
o = vm_call_method(m, o);
if (o == NULL) {
- fprintf(stderr, "Could not get main attributes from %s (invalid or corrupt jarfile?)\n", mainstring);
+ fprintf(stderr, "Could not get main attributes from %s (invalid or corrupt jarfile?)\n", mainname);
return NULL;
}
/* get property Main-Class */
- m = class_resolveclassmethod(o->vftbl->class,
+ LLNI_class_get(o, c);
+
+ m = class_resolveclassmethod(c,
utf_new_char("getValue"),
utf_new_char("(Ljava/lang/String;)Ljava/lang/String;"),
class_java_lang_Object,
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", mainname);
return NULL;
}
*******************************************************************************/
#if !defined(NDEBUG)
-static void vm_compile_method(void)
+static void vm_compile_method(char* mainname)
{
methodinfo *m;
/* create, load and link the main class */
- mainclass = load_class_bootstrap(utf_new_char(mainstring));
+ mainclass = load_class_bootstrap(utf_new_char(mainname));
if (mainclass == NULL)
exceptions_print_stacktrace();
#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_object_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_object_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_object_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);
-
- 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)
- goto illegal_arg;
-
- /* convert the value according to its declared type */
-
- c = param->vftbl->class;
- type = primitive_type_get_by_wrapperclass(c);
-
- switch (td->decltype) {
- case PRIMITIVETYPE_BOOLEAN:
- switch (type) {
- case PRIMITIVETYPE_BOOLEAN:
- /* This type is OK. */
- break;
- default:
- goto illegal_arg;
- }
- break;
-
- case PRIMITIVETYPE_BYTE:
- switch (type) {
- case PRIMITIVETYPE_BYTE:
- /* This type is OK. */
- break;
- default:
- goto illegal_arg;
- }
- break;
-
- case PRIMITIVETYPE_CHAR:
- switch (type) {
- case PRIMITIVETYPE_CHAR:
- /* This type is OK. */
- break;
- default:
- goto illegal_arg;
- }
- break;
-
- case PRIMITIVETYPE_SHORT:
- switch (type) {
- case PRIMITIVETYPE_BYTE:
- case PRIMITIVETYPE_SHORT:
- /* These types are OK. */
- break;
- default:
- goto illegal_arg;
- }
- break;
-
- case PRIMITIVETYPE_INT:
- switch (type) {
- case PRIMITIVETYPE_BYTE:
- case PRIMITIVETYPE_SHORT:
- case PRIMITIVETYPE_INT:
- /* These types are OK. */
- break;
- default:
- goto illegal_arg;
- }
- break;
-
- default:
- vm_abort("vm_array_from_objectarray: invalid type %d",
- td->decltype);
- }
-
- value = primitive_unbox(param);
- vm_array_store_int(array, pd, value.i);
- break;
-
- case TYPE_LNG:
- if (param == NULL)
- goto illegal_arg;
-
- c = param->vftbl->class;
- 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:
- goto illegal_arg;
- }
+ pv = m->code->entrypoint;
- value = primitive_unbox(param);
- vm_array_store_lng(array, pd, value.l);
- break;
-
- case TYPE_FLT:
- if (param == NULL)
- goto illegal_arg;
-
- c = param->vftbl->class;
- type = primitive_type_get_by_wrapperclass(c);
-
- assert(td->decltype == PRIMITIVETYPE_FLOAT);
-
- switch (type) {
- case PRIMITIVETYPE_FLOAT:
- /* This type is OK. */
- break;
- default:
- goto illegal_arg;
- }
-
- value = primitive_unbox(param);
- vm_array_store_flt(array, pd, value.l);
- break;
-
- case TYPE_DBL:
- if (param == NULL)
- goto illegal_arg;
-
- c = param->vftbl->class;
- 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:
- goto illegal_arg;
- }
-
- 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 false;
-
- if (param != NULL) {
- if (td->arraydim > 0) {
- if (!builtin_arrayinstanceof(param, c))
- goto illegal_arg;
- }
- else {
- if (!builtin_instanceof(param, c))
- goto illegal_arg;
- }
- }
-
- vm_array_store_adr(array, pd, param);
- break;
+ STATISTICS(count_calls_native_to_java++);
- default:
- vm_abort("vm_array_from_objectarray: invalid type %d", td->type);
- }
- }
+ o = asm_vm_call_method(pv, array, md->memuse);
- return array;
+ if (md->returntype.type == TYPE_VOID)
+ o = NULL;
-illegal_arg:
- exceptions_throw_illegalargumentexception();
- return NULL;
+ 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; \
\
- dumpsize = dump_size(); \
- array = vm_array_from_jvalue(m, o, args); \
+ THREAD_NATIVEWORLD_EXIT; \
+ DMARKER; \
+ \
+ 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;
+}
/*
* c-basic-offset: 4
* tab-width: 4
* End:
+ * vim:noexpandtab:sw=4:ts=4:
*/