-/* src/vm/finalizer.c - finalizer linked list and thread
+/* src/vm/vm.c - VM startup and shutdown functions
Copyright (C) 1996-2005, 2006 R. Grafl, A. Krall, C. Kruegel,
C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
Authors: Christian Thalinger
- Changes:
+ Changes: Martin Platter
- $Id: finalizer.c 4357 2006-01-22 23:33:38Z twisti $
+ $Id: vm.c 4357 2006-01-22 23:33:38Z twisti $
*/
#include "native/jni.h"
#include "native/native.h"
-#if defined(USE_THREADS)
-# if defined(NATIVE_THREADS)
-# include "threads/native/threads.h"
-# else
-# include "threads/green/threads.h"
-# include "threads/green/locks.h"
-# endif
+#if defined(ENABLE_THREADS)
+# include "threads/native/threads.h"
#endif
+#include "toolbox/util.h"
#include "vm/classcache.h"
#include "vm/exceptions.h"
#include "vm/finalizer.h"
#include "vm/signallocal.h"
#include "vm/stringlocal.h"
#include "vm/suck.h"
+#include "vm/vm.h"
+#include "vm/jit/jit.h"
#include "vm/jit/asmpart.h"
+
+#include "vm/jit/recompile.h"
+
#include "vm/jit/profile/profile.h"
+#include "vm/rt-timing.h"
+
+#if defined(ENABLE_JVMTI)
+#include "native/jvmti/cacaodbg.h"
+#endif
/* Invocation API variables ***************************************************/
-JavaVM *_Jv_jvm; /* denotes a Java VM */
+_Jv_JavaVM *_Jv_jvm; /* denotes a Java VM */
_Jv_JNIEnv *_Jv_env; /* pointer to native method interface */
u1 *intrp_main_stack = NULL;
#endif
-void **stackbottom = NULL;
-
char *mainstring = NULL;
classinfo *mainclass = NULL;
/* define heap sizes **********************************************************/
-#define HEAP_MAXSIZE 64 * 1024 * 1024 /* default 64MB */
-#define HEAP_STARTSIZE 2 * 1024 * 1024 /* default 2MB */
-#define STACK_SIZE 128 * 1024 /* default 128kB */
+#define HEAP_MAXSIZE 128 * 1024 * 1024 /* default 128MB */
+#define HEAP_STARTSIZE 2 * 1024 * 1024 /* default 2MB */
+#define STACK_SIZE 64 * 1024 /* default 64kB */
/* define command line options ************************************************/
OPT_HELP,
OPT_X,
+ OPT_ESA,
+ OPT_DSA,
+
/* Java non-standard options */
OPT_JIT,
OPT_BOOTCLASSPATH_A,
OPT_BOOTCLASSPATH_P,
+ OPT_GLIBJ,
+
OPT_PROF,
OPT_PROF_OPTION,
OPT_VERBOSE1,
OPT_NOIEEE,
OPT_SOFTNULL,
- OPT_TIME,
#if defined(ENABLE_STATISTICS)
+ OPT_TIME,
OPT_STAT,
#endif
OPT_SIGNATURE,
OPT_SHOW,
OPT_ALL,
- OPT_OLOOP,
- OPT_INLINING,
- OPT_VERBOSETC,
+#if defined(ENABLE_VERIFIER)
OPT_NOVERIFY,
- OPT_LIBERALUTF,
+#if defined(TYPECHECK_VERBOSE)
+ OPT_VERBOSETC,
+#endif
+#endif /* defined(ENABLE_VERIFIER) */
OPT_EAGER,
/* optimization options */
+#if defined(ENABLE_LOOP)
+ OPT_OLOOP,
+#endif
+
#if defined(ENABLE_IFCONV)
OPT_IFCONV,
#endif
OPT_LSRA,
#endif
+#if defined(ENABLE_INLINING)
+ OPT_INLINING,
+#endif
+
#if defined(ENABLE_INTRP)
/* interpreter options */
#ifdef ENABLE_JVMTI
OPT_DEBUG,
+ OPT_XRUNJDWP,
+ OPT_NOAGENT,
OPT_AGENTLIB,
OPT_AGENTPATH,
#endif
{ "d64", false, OPT_D64 },
{ "client", false, OPT_IGNORE },
{ "server", false, OPT_IGNORE },
+ { "jvm", false, OPT_IGNORE },
{ "hotspot", false, OPT_IGNORE },
{ "classpath", true, OPT_CLASSPATH },
{ "?", false, OPT_HELP },
{ "X", false, OPT_X },
+ { "esa", false, OPT_ESA },
+ { "enablesystemassertions", false, OPT_ESA },
+ { "dsa", false, OPT_DSA },
+ { "disablesystemassertions", false, OPT_DSA },
+
{ "noasyncgc", false, OPT_IGNORE },
+#if defined(ENABLE_VERIFIER)
{ "noverify", false, OPT_NOVERIFY },
- { "liberalutf", false, OPT_LIBERALUTF },
+#endif
{ "v", false, OPT_VERBOSE1 },
{ "verbose:", true, OPT_VERBOSE },
-#ifdef TYPECHECK_VERBOSE
+#if defined(ENABLE_VERIFIER) && defined(TYPECHECK_VERBOSE)
{ "verbosetc", false, OPT_VERBOSETC },
#endif
#if defined(__ALPHA__)
{ "noieee", false, OPT_NOIEEE },
#endif
{ "softnull", false, OPT_SOFTNULL },
- { "time", false, OPT_TIME },
#if defined(ENABLE_STATISTICS)
+ { "time", false, OPT_TIME },
{ "stat", false, OPT_STAT },
#endif
{ "log", true, OPT_LOG },
{ "eager", false, OPT_EAGER },
{ "sig", true, OPT_SIGNATURE },
{ "all", false, OPT_ALL },
+#if defined(ENABLE_LOOP)
{ "oloop", false, OPT_OLOOP },
+#endif
#if defined(ENABLE_IFCONV)
{ "ifconv", false, OPT_IFCONV },
#endif
{ "Xbootclasspath:", true, OPT_BOOTCLASSPATH },
{ "Xbootclasspath/a:", true, OPT_BOOTCLASSPATH_A },
{ "Xbootclasspath/p:", true, OPT_BOOTCLASSPATH_P },
+ { "Xglibj:", true, OPT_GLIBJ },
+
#ifdef ENABLE_JVMTI
{ "Xdebug", false, OPT_DEBUG },
+ { "Xnoagent", false, OPT_NOAGENT },
+ { "Xrunjdwp", true, OPT_XRUNJDWP },
#endif
+
{ "Xms", true, OPT_MS },
{ "ms", true, OPT_MS },
{ "Xmx", true, OPT_MX },
/* keep these at the end of the list */
+#if defined(ENABLE_INLINING)
{ "i", true, OPT_INLINING },
+#endif
{ "m", true, OPT_METHOD },
{ "s", true, OPT_SHOW },
{
puts("Usage: cacao [-options] classname [arguments]");
puts(" (to run a class file)");
- puts(" cacao [-options] -jar jarfile [arguments]");
+ puts(" or cacao [-options] -jar jarfile [arguments]");
puts(" (to run a standalone jar file)\n");
puts("Java options:");
puts(" -d64 use 64-bit data model if available");
puts(" -client compatibility (currently ignored)");
puts(" -server compatibility (currently ignored)");
+ puts(" -jvm compatibility (currently ignored)");
puts(" -hotspot compatibility (currently ignored)\n");
puts(" -cp <path> specify a path to look for classes");
puts(" -fullversion print jpackage-compatible product version and exit");
puts(" -showversion print product version and continue");
puts(" -help, -? print this help message");
- puts(" -X print help on non-standard Java options\n");
+ puts(" -X print help on non-standard Java options");
+ puts(" -esa | -enablesystemassertions");
+ puts(" enable system assertions");
+ puts(" -dsa | -disablesystemassertions");
+ puts(" disable system assertions");
+ puts("");
#ifdef ENABLE_JVMTI
puts(" -agentlib:<agent-lib-name>=<options> library to load containg JVMTI agent");
+ puts (" for jdwp help use: -agentlib:jdwp=help");
puts(" -agentpath:<path-to-agent>=<options> path to library containg JVMTI agent");
#endif
- puts("CACAO options:\n");
+ puts("CACAO options:");
puts(" -v write state-information");
- puts(" -verbose[:call|exception]enable specific verbose output");
+ puts(" -verbose[:call|exception|jit]");
+ puts(" enable specific verbose output");
#ifdef TYPECHECK_VERBOSE
puts(" -verbosetc write debug messages while typechecking");
#endif
#if defined(__ALPHA__)
puts(" -noieee don't use ieee compliant arithmetic");
#endif
+#if defined(ENABLE_VERIFIER)
puts(" -noverify don't verify classfiles");
- puts(" -liberalutf don't warn about overlong UTF-8 sequences");
+#endif
puts(" -softnull use software nullpointer check");
- puts(" -time measure the runtime");
#if defined(ENABLE_STATISTICS)
+ puts(" -time measure the runtime");
puts(" -stat detailed compiler statistics");
#endif
puts(" -log logfile specify a name for the logfile");
puts(" -c(heck)b(ounds) don't check array bounds");
puts(" s(ync) don't check for synchronization");
- puts(" -oloop optimize array accesses in loops");
+#if defined(ENABLE_LOOP)
+ puts(" -oloop optimize array accesses in loops");
+#endif
puts(" -l don't start the class after loading");
puts(" -eager perform eager class loading and linking");
puts(" -all compile all methods, no execution");
puts(" -m compile only a specific method");
puts(" -sig specify signature for a specific method");
- puts(" -s(how)a(ssembler) show disassembled listing");
- puts(" c(onstants) show the constant pool");
- puts(" d(atasegment) show data segment listing");
- puts(" e(xceptionstubs) show disassembled exception stubs (only with -sa)");
- puts(" i(ntermediate) show intermediate representation");
- puts(" m(ethods) show class fields and methods");
- puts(" n(ative) show disassembled native stubs");
- puts(" u(tf) show the utf - hash");
+ puts(" -s(how)... show...");
+ puts(" c(onstants) the constant pool");
+ puts(" m(ethods) class fields and methods");
+ puts(" u(tf) the utf - hash");
+ puts(" i(ntermediate) intermediate representation");
+#if defined(ENABLE_DISASSEMBLER)
+ puts(" a(ssembler) disassembled listing");
+ 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 n(line) activate inlining");
puts(" v(irtual) inline virtual methods (uses/turns rt option on)");
puts(" e(exception) inline methods with exceptions");
puts(" p(aramopt) optimize argument renaming");
puts(" o(utsiders) inline methods of foreign classes");
+#endif /* defined(ENABLE_INLINING) */
#if defined(ENABLE_IFCONV)
puts(" -ifconv use if-conversion");
#endif
puts(" value is appended to the bootstrap class path");
puts(" -Xbootclasspath/p:<zip/jar files and directories separated by :>");
puts(" value is prepended to the bootstrap class path");
- puts(" -Xms<size> set the initial size of the heap (default: 2MB)");
- puts(" -Xmx<size> set the maximum size of the heap (default: 64MB)");
- puts(" -Xss<size> set the thread stack size (default: 128kB)");
+ puts(" -Xglibj:<zip/jar files and directories separated by :>");
+ puts(" value is used as Java core library, but the");
+ puts(" hardcoded VM interface classes are prepended");
+ printf(" -Xms<size> set the initial size of the heap (default: %dMB)\n", HEAP_STARTSIZE / 1024 / 1024);
+ printf(" -Xmx<size> set the maximum size of the heap (default: %dMB)\n", HEAP_MAXSIZE / 1024 / 1024);
+ printf(" -Xss<size> set the thread stack size (default: %dkB)\n", STACK_SIZE / 1024);
puts(" -Xprof[:bb] collect and print profiling data");
#if defined(ENABLE_JVMTI)
- puts(" -Xdebug<transport> enable remote debugging");
+ /* -Xdebug option depend on gnu classpath JDWP options. options:
+ transport=dt_socket,address=<hostname:port>,server=(y|n),suspend(y|n) */
+ puts(" -Xdebug enable remote debugging\n");
+ puts(" -Xrunjdwp transport=[dt_socket|...],address=<hostname:port>,server=[y|n],suspend=[y|n]\n");
+ puts(" enable remote debugging\n");
#endif
/* exit with error code */
*******************************************************************************/
-static void version(void)
+static void version(bool opt_exit)
{
puts("java version \""JAVA_VERSION"\"");
puts("CACAO version "VERSION"");
puts("Configure/Build options:\n");
puts(" ./configure: "VERSION_CONFIGURE_ARGS"");
+#if defined(__VERSION__)
puts(" CC : "VERSION_CC" ("__VERSION__")");
- puts(" CFLAGS : "VERSION_CFLAGS"");
+#else
+ puts(" CC : "VERSION_CC"");
+#endif
+ puts(" CFLAGS : "VERSION_CFLAGS"\n");
+
+ puts("Default variables:\n");
+ printf(" maximum heap size : %d\n", HEAP_MAXSIZE);
+ printf(" initial heap size : %d\n", HEAP_STARTSIZE);
+ printf(" stack size : %d\n", STACK_SIZE);
+ puts(" java.boot.class.path: "CACAO_VM_ZIP":"CLASSPATH_GLIBJ_ZIP"");
+ puts(" java.library.path : "CLASSPATH_LIBRARY_PATH"\n");
+
+ 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", bootclasspath);
+
+ /* exit normally, if requested */
+
+ if (opt_exit)
+ exit(0);
}
{
char *cp;
s4 cplen;
- u4 heapmaxsize;
- u4 heapstartsize;
s4 opt;
s4 i, j, k;
+ bool opt_version;
+ bool opt_exit;
+
+#if defined(ENABLE_JVMTI)
+ lt_dlhandle handle;
+ char *libname, *agentarg;
+ bool jdwp,agentbypath;
+ jdwp = agentbypath = false;
+#endif
/* check the JNI version requested */
if (vms > 0)
return false;
+ /* set the VM starttime */
+
+ _Jv_jvm->starttime = util_current_time_millis();
/* get stuff from the environment *****************************************/
strcpy(bootclasspath, cp);
} else {
- cplen = strlen(CACAO_VM_ZIP_PATH) +
+ cplen = strlen(CACAO_VM_ZIP) +
strlen(":") +
- strlen(CLASSPATH_GLIBJ_ZIP_PATH) +
+ strlen(CLASSPATH_GLIBJ_ZIP) +
strlen("0");
bootclasspath = MNEW(char, cplen);
- strcat(bootclasspath, CACAO_VM_ZIP_PATH);
+ strcat(bootclasspath, CACAO_VM_ZIP);
strcat(bootclasspath, ":");
- strcat(bootclasspath, CLASSPATH_GLIBJ_ZIP_PATH);
+ strcat(bootclasspath, CLASSPATH_GLIBJ_ZIP);
}
-
/* set the classpath */
cp = getenv("CLASSPATH");
/* interpret the options **************************************************/
-
- checknull = false;
- opt_noieee = false;
- heapmaxsize = HEAP_MAXSIZE;
- heapstartsize = HEAP_STARTSIZE;
- opt_stacksize = STACK_SIZE;
+ opt_version = false;
+ opt_exit = false;
+
+ checknull = 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 properties before commandline handling */
throw_cacao_exception_exit(string_java_lang_InternalError,
"Unable to init properties");
+ /* add some default properties */
+
+ properties_add("java.endorsed.dirs", ""CACAO_PREFIX"/jre/lib/endorsed");
+
+
/* iterate over all passed options */
while ((opt = options_get(opts, vm_args)) != OPT_DONE) {
if (opt_arg[j] == '=') {
opt_arg[j] = '\0';
properties_add(opt_arg, opt_arg + j + 1);
- goto didit;
+ goto opt_d_done;
}
}
/* if no '=' is given, just create an empty property */
properties_add(opt_arg, "");
-
- didit:
+
+ opt_d_done:
break;
case OPT_BOOTCLASSPATH:
/* Forget default bootclasspath and set the argument as
new boot classpath. */
+
MFREE(bootclasspath, char, strlen(bootclasspath));
bootclasspath = MNEW(char, strlen(opt_arg) + strlen("0"));
case OPT_BOOTCLASSPATH_A:
/* append to end of bootclasspath */
+
cplen = strlen(bootclasspath);
bootclasspath = MREALLOC(bootclasspath,
case OPT_BOOTCLASSPATH_P:
/* prepend in front of bootclasspath */
+
cp = bootclasspath;
cplen = strlen(cp);
MFREE(cp, char, cplen);
break;
+ case OPT_GLIBJ:
+ /* use as Java core library, but prepend VM interface classes */
+
+ MFREE(bootclasspath, char, strlen(bootclasspath));
+
+ cplen = strlen(CACAO_VM_ZIP) +
+ strlen(":") +
+ strlen(opt_arg) +
+ strlen("0");
+
+ bootclasspath = MNEW(char, cplen);
+
+ strcpy(bootclasspath, CACAO_VM_ZIP);
+ strcat(bootclasspath, ":");
+ strcat(bootclasspath, opt_arg);
+ break;
+
#if defined(ENABLE_JVMTI)
case OPT_DEBUG:
- dbg = true;
- transport = opt_arg;
+ /* this option exists only for compatibility reasons */
+ break;
+ case OPT_NOAGENT:
+ /* I don't know yet what Xnoagent should do. This is only for
+ compatiblity with eclipse - motse */
+ break;
+ case OPT_XRUNJDWP:
+ agentbypath=jvmti=jdwp=true;
+ i = strlen(opt_arg)+33;
+ agentarg = MNEW(char,i);
+ /* XXX how can I get the <prefix>/lib directory ? */
+ snprintf(agentarg,i,"/usr/local/cacao/lib/libjdwp.so=%s",&opt_arg[1]);
break;
-
case OPT_AGENTPATH:
+ agentbypath = true;
case OPT_AGENTLIB:
- set_jvmti_phase(JVMTI_PHASE_ONLOAD);
- agentload(opt_arg);
- set_jvmti_phase(JVMTI_PHASE_PRIMORDIAL);
+ jvmti=true;
+ agentarg = opt_arg;
break;
#endif
j = atoi(opt_arg);
if (opt == OPT_MX)
- heapmaxsize = j;
+ opt_heapmaxsize = j;
else if (opt == OPT_MS)
- heapstartsize = j;
+ opt_heapstartsize = j;
else
opt_stacksize = j;
}
opt_verboseexception = true;
break;
-#ifdef TYPECHECK_VERBOSE
+#if defined(ENABLE_VERIFIER) && defined(TYPECHECK_VERBOSE)
case OPT_VERBOSETC:
- typecheckverbose = true;
+ opt_typecheckverbose = true;
break;
#endif
case OPT_VERSION:
- version();
- exit(0);
+ opt_version = true;
+ opt_exit = true;
break;
case OPT_FULLVERSION:
break;
case OPT_SHOWVERSION:
- version();
+ opt_version = true;
break;
case OPT_NOIEEE:
opt_noieee = true;
break;
+#if defined(ENABLE_VERIFIER)
case OPT_NOVERIFY:
opt_verify = false;
break;
-
- case OPT_LIBERALUTF:
- opt_liberalutf = true;
- break;
+#endif
case OPT_SOFTNULL:
checknull = true;
break;
+#if defined(ENABLE_STATISTICS)
case OPT_TIME:
- getcompilingtime = true;
- getloadingtime = true;
+ opt_getcompilingtime = true;
+ opt_getloadingtime = true;
break;
-#if defined(ENABLE_STATISTICS)
case OPT_STAT:
opt_stat = true;
break;
case OPT_SHOW: /* Display options */
for (j = 0; j < strlen(opt_arg); j++) {
switch (opt_arg[j]) {
- case 'a':
- opt_showdisassemble = true;
- compileverbose = true;
- break;
case 'c':
showconstantpool = true;
break;
- case 'd':
- opt_showddatasegment = true;
+
+ case 'u':
+ showutf = true;
break;
- case 'e':
- opt_showexceptionstubs = true;
+
+ case 'm':
+ showmethods = true;
break;
+
case 'i':
opt_showintermediate = true;
compileverbose = true;
break;
- case 'm':
- showmethods = true;
+
+#if defined(ENABLE_DISASSEMBLER)
+ case 'a':
+ opt_showdisassemble = true;
+ compileverbose = true;
+ break;
+
+ case 'e':
+ opt_showexceptionstubs = true;
break;
+
case 'n':
opt_shownativestub = true;
break;
- case 'u':
- showutf = true;
+#endif
+
+ case 'd':
+ opt_showddatasegment = true;
break;
+
default:
usage();
}
}
break;
+#if defined(ENABLE_LOOP)
case OPT_OLOOP:
opt_loops = true;
break;
+#endif
+#if defined(ENABLE_INLINING)
case OPT_INLINING:
for (j = 0; j < strlen(opt_arg); j++) {
switch (opt_arg[j]) {
}
}
break;
+#endif /* defined(ENABLE_INLINING) */
#if defined(ENABLE_IFCONV)
case OPT_IFCONV:
Xusage();
break;
+ case OPT_ESA:
+ _Jv_jvm->Java_java_lang_VMClassLoader_defaultAssertionStatus = true;
+ break;
+
+ case OPT_DSA:
+ _Jv_jvm->Java_java_lang_VMClassLoader_defaultAssertionStatus = false;
+ break;
+
case OPT_PROF_OPTION:
/* use <= to get the last \0 too */
}
+ /* Now we have all options handled and we can print the version
+ information. */
+
+ if (opt_version)
+ version(opt_exit);
+
+
/* get the main class *****************************************************/
if (opt_index < vm_args->nOptions) {
mainstring = vm_args->options[opt_index++].optionString;
- if (opt_jar == true) {
+ /* Put the jar file into the classpath (if any). */
- /* prepend the jar file to the classpath (if any) */
+ if (opt_jar == true) {
+ /* free old classpath */
- if (opt_jar == true) {
- /* put jarfile in classpath */
+ MFREE(classpath, char, strlen(classpath));
- cp = classpath;
+ /* put jarfile into classpath */
- classpath = MNEW(char, strlen(mainstring) + strlen(":") +
- strlen(classpath) + strlen("0"));
+ classpath = MNEW(char, strlen(mainstring) + strlen("0"));
- strcpy(classpath, mainstring);
- strcat(classpath, ":");
- strcat(classpath, cp);
+ strcpy(classpath, mainstring);
- MFREE(cp, char, strlen(cp));
-
- } else {
- /* replace .'s with /'s in classname */
+ } else {
+ /* replace .'s with /'s in classname */
- for (i = strlen(mainstring) - 1; i >= 0; i--)
- if (mainstring[i] == '.')
- mainstring[i] = '/';
- }
+ 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);
+ jvmti_agentload(agentarg, agentbypath, &handle, &libname);
+ if (jdwp) MFREE(agentarg,char,strlen(agentarg));
+ jvmti_set_phase(JVMTI_PHASE_PRIMORDIAL);
+ }
+
+#endif
+
/* initialize this JVM ****************************************************/
/* initialize the garbage collector */
- gc_init(heapmaxsize, heapstartsize);
+ gc_init(opt_heapmaxsize, opt_heapstartsize);
#if defined(ENABLE_INTRP)
/* Allocate main thread stack on the Java heap. */
}
#endif
-#if defined(USE_THREADS)
-#if defined(NATIVE_THREADS)
+#if defined(ENABLE_THREADS)
threads_preinit();
#endif
- initLocks();
-#endif
/* initialize the string hashtable stuff: lock (must be done
_after_ threads_preinit) */
/* initialize the loader subsystems (must be done _after_
classcache_init) */
- if (!loader_init((u1 *) stackbottom))
+ if (!loader_init())
throw_main_exception_exit();
if (!linker_init())
if (!builtin_init())
throw_main_exception_exit();
-#if defined(USE_THREADS)
- if (!threads_init((u1 *) stackbottom))
+ /* Initialize the JNI subsystem (must be done _before_
+ threads_init, as threads_init can call JNI methods
+ (e.g. NewGlobalRef). */
+
+ if (!jni_init())
+ throw_main_exception_exit();
+
+#if defined(ENABLE_THREADS)
+ if (!threads_init())
throw_main_exception_exit();
#endif
if (!initialize_class(class_java_lang_System))
throw_main_exception_exit();
- /* JNI init creates a Java object (this means running Java code) */
+#if defined(ENABLE_PROFILING)
+ /* initialize profiling */
- if (!jni_init())
+ if (!profile_init())
throw_main_exception_exit();
+#endif
- /* initialize profiling */
+#if defined(ENABLE_THREADS)
+ /* initialize recompilation */
- if (!profile_init())
+ if (!recompile_init())
throw_main_exception_exit();
-#if defined(USE_THREADS)
/* finally, start the finalizer thread */
if (!finalizer_start_thread())
throw_main_exception_exit();
+ /* start the recompilation thread (must be done before the
+ profiling thread) */
+
+ if (!recompile_start_thread())
+ throw_main_exception_exit();
+
+# if defined(ENABLE_PROFILING)
/* start the profile sampling thread */
-/* if (!profile_start_thread()) */
-/* throw_main_exception_exit(); */
+ if (opt_prof)
+ if (!profile_start_thread())
+ throw_main_exception_exit();
+# endif
+#endif
+
+#if defined(ENABLE_JVMTI)
+ 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 */
s4 vm_destroy(JavaVM *vm)
{
-#if defined(USE_THREADS)
-#if defined(NATIVE_THREADS)
- joinAllThreads();
-#else
- killThread(currentThread);
-#endif
+#if defined(ENABLE_THREADS)
+ threads_join_all_threads();
#endif
/* everything's ok */
assert(class_java_lang_System->state & CLASS_LOADED);
#if defined(ENABLE_JVMTI)
- set_jvmti_phase(JVMTI_PHASE_DEAD);
- agentunload();
+ if (jvmti || (dbgcom!=NULL)) {
+ jvmti_set_phase(JVMTI_PHASE_DEAD);
+ if (jvmti) jvmti_agentunload();
+ }
#endif
if (!link_class(class_java_lang_System))
class_java_lang_Object,
true);
- if (!m)
+ if (m == NULL)
throw_main_exception_exit();
/* call the exit function with passed exit status */
- ASM_CALLJAVAFUNCTION(m, (void *) (ptrint) status, NULL, NULL, NULL);
-
- /* this should never happen */
+ (void) vm_call_method(m, NULL, status);
- if (*exceptionptr)
- throw_exception_exit();
+ /* If we had an exception, just ignore the exception and exit with
+ the proper code. */
- throw_cacao_exception_exit(string_java_lang_InternalError,
- "System.exit(I)V returned without exception");
+ vm_shutdown(status);
}
void vm_shutdown(s4 status)
{
-#if defined(ENABLE_JVMTI)
- agentunload();
+ if (opt_verbose
+#if defined(ENABLE_STATISTICS)
+ || opt_getcompilingtime || opt_stat
#endif
-
- if (opt_verbose || getcompilingtime || opt_stat) {
+ )
+ {
log_text("CACAO terminated by shutdown");
dolog("Exit status: %d\n", (s4) status);
+
}
+#if defined(ENABLE_JVMTI)
+ /* terminate cacaodbgserver */
+ if (dbgcom!=NULL) {
+ pthread_mutex_lock(&dbgcomlock);
+ dbgcom->running=1;
+ pthread_mutex_unlock(&dbgcomlock);
+ jvmti_cacaodbgserver_quit();
+ }
+#endif
+
exit(status);
}
if (showutf)
utf_show();
+# if defined(ENABLE_PROFILING)
if (opt_prof)
profile_printstats();
+# endif
+#endif /* !defined(NDEBUG) */
+
+#if defined(ENABLE_RT_TIMING)
+ rt_timing_print_time_stats(stderr);
#endif
-#if defined(USE_THREADS) && !defined(NATIVE_THREADS)
- clear_thread_flags(); /* restores standard file descriptor
- flags */
+#if defined(ENABLE_CYCLES_STATS)
+ builtin_print_cycles_stats(stderr);
+ stacktrace_print_cycles_stats(stderr);
#endif
- if (opt_verbose || getcompilingtime || opt_stat) {
+ if (opt_verbose
+#if defined(ENABLE_STATISTICS)
+ || opt_getcompilingtime || opt_stat
+#endif
+ )
+ {
log_text("CACAO terminated");
#if defined(ENABLE_STATISTICS)
mem_usagelog(1);
- if (getcompilingtime)
+ if (opt_getcompilingtime)
print_times();
-#endif
+#endif /* defined(ENABLE_STATISTICS) */
}
/* vm_print_profile(stderr);*/
}
+/* vm_abort ********************************************************************
+
+ Prints an error message and aborts the VM.
+
+*******************************************************************************/
+
+void vm_abort(const char *text, ...)
+{
+ va_list ap;
+
+ /* print the log message */
+
+ log_start();
+
+ va_start(ap, text);
+ log_vprint(text, ap);
+ va_end(ap);
+
+ log_finish();
+
+ /* now abort the VM */
+
+ abort();
+}
+
+
+/* vm_vmargs_from_valist *******************************************************
+
+ XXX
+
+*******************************************************************************/
+
+static void vm_vmargs_from_valist(methodinfo *m, java_objectheader *o,
+ vm_arg *vmargs, va_list ap)
+{
+ typedesc *paramtypes;
+ s4 i;
+
+ paramtypes = m->parseddesc->paramtypes;
+
+ /* if method is non-static fill first block and skip `this' pointer */
+
+ i = 0;
+
+ if (o != NULL) {
+ /* the `this' pointer */
+ vmargs[0].type = TYPE_ADR;
+ vmargs[0].data.l = (u8) (ptrint) o;
+
+ paramtypes++;
+ i++;
+ }
+
+ for (; i < m->parseddesc->paramcount; i++, paramtypes++) {
+ switch (paramtypes->decltype) {
+ /* primitive types */
+ case PRIMITIVETYPE_BOOLEAN:
+ case PRIMITIVETYPE_BYTE:
+ case PRIMITIVETYPE_CHAR:
+ case PRIMITIVETYPE_SHORT:
+ case PRIMITIVETYPE_INT:
+ vmargs[i].type = TYPE_INT;
+ vmargs[i].data.l = (s8) va_arg(ap, s4);
+ break;
+
+ case PRIMITIVETYPE_LONG:
+ vmargs[i].type = TYPE_LNG;
+ vmargs[i].data.l = (s8) va_arg(ap, s8);
+ break;
+
+ case PRIMITIVETYPE_FLOAT:
+ vmargs[i].type = TYPE_FLT;
+#if defined(__ALPHA__)
+ /* this keeps the assembler function much simpler */
+
+ vmargs[i].data.d = (jdouble) va_arg(ap, jdouble);
+#else
+ vmargs[i].data.f = (jfloat) va_arg(ap, jdouble);
+#endif
+ break;
+
+ case PRIMITIVETYPE_DOUBLE:
+ vmargs[i].type = TYPE_DBL;
+ vmargs[i].data.d = (jdouble) va_arg(ap, jdouble);
+ break;
+
+ case TYPE_ADR:
+ vmargs[i].type = TYPE_ADR;
+ vmargs[i].data.l = (u8) (ptrint) va_arg(ap, void*);
+ break;
+ }
+ }
+}
+
+
+/* vm_vmargs_from_jvalue *******************************************************
+
+ XXX
+
+*******************************************************************************/
+
+static void vm_vmargs_from_jvalue(methodinfo *m, java_objectheader *o,
+ vm_arg *vmargs, jvalue *args)
+{
+ typedesc *paramtypes;
+ s4 i;
+ s4 j;
+
+ paramtypes = m->parseddesc->paramtypes;
+
+ /* if method is non-static fill first block and skip `this' pointer */
+
+ i = 0;
+
+ if (o != NULL) {
+ /* the `this' pointer */
+ vmargs[0].type = TYPE_ADR;
+ vmargs[0].data.l = (u8) (ptrint) o;
+
+ paramtypes++;
+ i++;
+ }
+
+ for (j = 0; i < m->parseddesc->paramcount; i++, j++, paramtypes++) {
+ switch (paramtypes->decltype) {
+ /* primitive types */
+ case PRIMITIVETYPE_BOOLEAN:
+ case PRIMITIVETYPE_BYTE:
+ case PRIMITIVETYPE_CHAR:
+ case PRIMITIVETYPE_SHORT:
+ case PRIMITIVETYPE_INT:
+ vmargs[i].type = TYPE_INT;
+ vmargs[i].data.l = (s8) args[j].i;
+ break;
+
+ case PRIMITIVETYPE_LONG:
+ vmargs[i].type = TYPE_LNG;
+ vmargs[i].data.l = (s8) args[j].j;
+ break;
+
+ case PRIMITIVETYPE_FLOAT:
+ vmargs[i].type = TYPE_FLT;
+#if defined(__ALPHA__)
+ /* this keeps the assembler function much simpler */
+
+ vmargs[i].data.d = (jdouble) args[j].f;
+#else
+ vmargs[i].data.f = args[j].f;
+#endif
+ break;
+
+ case PRIMITIVETYPE_DOUBLE:
+ vmargs[i].type = TYPE_DBL;
+ vmargs[i].data.d = args[j].d;
+ break;
+
+ case TYPE_ADR:
+ vmargs[i].type = TYPE_ADR;
+ vmargs[i].data.l = (u8) (ptrint) args[j].l;
+ break;
+ }
+ }
+}
+
+
+/* vm_call_method **************************************************************
+
+ Calls a Java method with a variable number of arguments and returns
+ an address.
+
+*******************************************************************************/
+
+java_objectheader *vm_call_method(methodinfo *m, java_objectheader *o, ...)
+{
+ va_list ap;
+ java_objectheader *ro;
+
+ va_start(ap, o);
+ ro = vm_call_method_valist(m, o, ap);
+ va_end(ap);
+
+ return ro;
+}
+
+
+/* vm_call_method_valist *******************************************************
+
+ Calls a Java method with a variable number of arguments, passed via
+ a va_list, and returns an address.
+
+*******************************************************************************/
+
+java_objectheader *vm_call_method_valist(methodinfo *m, java_objectheader *o,
+ va_list ap)
+{
+ s4 vmargscount;
+ vm_arg *vmargs;
+ java_objectheader *ro;
+ s4 dumpsize;
+
+ /* mark start of dump memory area */
+
+ dumpsize = dump_size();
+
+ /* get number of Java method arguments */
+
+ vmargscount = m->parseddesc->paramcount;
+
+ /* allocate vm_arg array */
+
+ vmargs = DMNEW(vm_arg, vmargscount);
+
+ /* fill the vm_arg array from a va_list */
+
+ vm_vmargs_from_valist(m, o, vmargs, ap);
+
+ /* call the Java method */
+
+ ro = vm_call_method_vmarg(m, vmargscount, vmargs);
+
+ /* release dump area */
+
+ dump_release(dumpsize);
+
+ return ro;
+}
+
+
+/* vm_call_method_jvalue *******************************************************
+
+ Calls a Java method with a variable number of arguments, passed via
+ a jvalue array, and returns an address.
+
+*******************************************************************************/
+
+java_objectheader *vm_call_method_jvalue(methodinfo *m, java_objectheader *o,
+ jvalue *args)
+{
+ s4 vmargscount;
+ vm_arg *vmargs;
+ java_objectheader *ro;
+ s4 dumpsize;
+
+ /* mark start of dump memory area */
+
+ dumpsize = dump_size();
+
+ /* get number of Java method arguments */
+
+ vmargscount = m->parseddesc->paramcount;
+
+ /* allocate vm_arg array */
+
+ vmargs = DMNEW(vm_arg, vmargscount);
+
+ /* fill the vm_arg array from a va_list */
+
+ vm_vmargs_from_jvalue(m, o, vmargs, args);
+
+ /* call the Java method */
+
+ ro = vm_call_method_vmarg(m, vmargscount, vmargs);
+
+ /* release dump area */
+
+ dump_release(dumpsize);
+
+ return ro;
+}
+
+
+/* vm_call_method_vmarg ********************************************************
+
+ Calls a Java method with a variable number of arguments, passed via
+ a vm_arg array, and returns an address.
+
+*******************************************************************************/
+
+java_objectheader *vm_call_method_vmarg(methodinfo *m, s4 vmargscount,
+ vm_arg *vmargs)
+{
+ java_objectheader *o;
+
+#if defined(ENABLE_JIT)
+# if defined(ENABLE_INTRP)
+ if (opt_intrp)
+ o = intrp_asm_vm_call_method(m, vmargscount, vmargs);
+ else
+# endif
+ o = asm_vm_call_method(m, vmargscount, vmargs);
+#else
+ o = intrp_asm_vm_call_method(m, vmargscount, vmargs);
+#endif
+
+ return o;
+}
+
+
+/* vm_call_method_int **********************************************************
+
+ Calls a Java method with a variable number of arguments and returns
+ an integer (s4).
+
+*******************************************************************************/
+
+s4 vm_call_method_int(methodinfo *m, java_objectheader *o, ...)
+{
+ va_list ap;
+ s4 i;
+
+ va_start(ap, o);
+ i = vm_call_method_int_valist(m, o, ap);
+ va_end(ap);
+
+ return i;
+}
+
+
+/* vm_call_method_int_valist ***************************************************
+
+ Calls a Java method with a variable number of arguments, passed via
+ a va_list, and returns an integer (s4).
+
+*******************************************************************************/
+
+s4 vm_call_method_int_valist(methodinfo *m, java_objectheader *o, va_list ap)
+{
+ s4 vmargscount;
+ vm_arg *vmargs;
+ s4 i;
+ s4 dumpsize;
+
+ /* mark start of dump memory area */
+
+ dumpsize = dump_size();
+
+ /* get number of Java method arguments */
+
+ vmargscount = m->parseddesc->paramcount;
+
+ /* allocate vm_arg array */
+
+ vmargs = DMNEW(vm_arg, vmargscount);
+
+ /* fill the vm_arg array from a va_list */
+
+ vm_vmargs_from_valist(m, o, vmargs, ap);
+
+ /* call the Java method */
+
+ i = vm_call_method_int_vmarg(m, vmargscount, vmargs);
+
+ /* release dump area */
+
+ dump_release(dumpsize);
+
+ return i;
+}
+
+
+/* vm_call_method_int_jvalue ***************************************************
+
+ Calls a Java method with a variable number of arguments, passed via
+ a jvalue array, and returns an integer (s4).
+
+*******************************************************************************/
+
+s4 vm_call_method_int_jvalue(methodinfo *m, java_objectheader *o, jvalue *args)
+{
+ s4 vmargscount;
+ vm_arg *vmargs;
+ s4 i;
+ s4 dumpsize;
+
+ /* mark start of dump memory area */
+
+ dumpsize = dump_size();
+
+ /* get number of Java method arguments */
+
+ vmargscount = m->parseddesc->paramcount;
+
+ /* allocate vm_arg array */
+
+ vmargs = DMNEW(vm_arg, vmargscount);
+
+ /* fill the vm_arg array from a va_list */
+
+ vm_vmargs_from_jvalue(m, o, vmargs, args);
+
+ /* call the Java method */
+
+ i = vm_call_method_int_vmarg(m, vmargscount, vmargs);
+
+ /* release dump area */
+
+ dump_release(dumpsize);
+
+ return i;
+}
+
+
+/* vm_call_method_int_vmarg ****************************************************
+
+ Calls a Java method with a variable number of arguments, passed via
+ a vm_arg array, and returns an integer (s4).
+
+*******************************************************************************/
+
+s4 vm_call_method_int_vmarg(methodinfo *m, s4 vmargscount, vm_arg *vmargs)
+{
+ s4 i;
+
+#if defined(ENABLE_JIT)
+# if defined(ENABLE_INTRP)
+ if (opt_intrp)
+ i = intrp_asm_vm_call_method_int(m, vmargscount, vmargs);
+ else
+# endif
+ i = asm_vm_call_method_int(m, vmargscount, vmargs);
+#else
+ i = intrp_asm_vm_call_method_int(m, vmargscount, vmargs);
+#endif
+
+ return i;
+}
+
+
+/* vm_call_method_long *********************************************************
+
+ Calls a Java method with a variable number of arguments and returns
+ a long (s8).
+
+*******************************************************************************/
+
+s8 vm_call_method_long(methodinfo *m, java_objectheader *o, ...)
+{
+ va_list ap;
+ s8 l;
+
+ va_start(ap, o);
+ l = vm_call_method_long_valist(m, o, ap);
+ va_end(ap);
+
+ return l;
+}
+
+
+/* vm_call_method_long_valist **************************************************
+
+ Calls a Java method with a variable number of arguments, passed via
+ a va_list, and returns a long (s8).
+
+*******************************************************************************/
+
+s8 vm_call_method_long_valist(methodinfo *m, java_objectheader *o, va_list ap)
+{
+ s4 vmargscount;
+ vm_arg *vmargs;
+ s8 l;
+ s4 dumpsize;
+
+ /* mark start of dump memory area */
+
+ dumpsize = dump_size();
+
+ /* get number of Java method arguments */
+
+ vmargscount = m->parseddesc->paramcount;
+
+ /* allocate vm_arg array */
+
+ vmargs = DMNEW(vm_arg, vmargscount);
+
+ /* fill the vm_arg array from a va_list */
+
+ vm_vmargs_from_valist(m, o, vmargs, ap);
+
+ /* call the Java method */
+
+ l = vm_call_method_long_vmarg(m, vmargscount, vmargs);
+
+ /* release dump area */
+
+ dump_release(dumpsize);
+
+ return l;
+}
+
+
+/* vm_call_method_long_jvalue **************************************************
+
+ Calls a Java method with a variable number of arguments, passed via
+ a jvalue array, and returns a long (s8).
+
+*******************************************************************************/
+
+s8 vm_call_method_long_jvalue(methodinfo *m, java_objectheader *o, jvalue *args)
+{
+ s4 vmargscount;
+ vm_arg *vmargs;
+ s8 l;
+ s4 dumpsize;
+
+ /* mark start of dump memory area */
+
+ dumpsize = dump_size();
+
+ /* get number of Java method arguments */
+
+ vmargscount = m->parseddesc->paramcount;
+
+ /* allocate vm_arg array */
+
+ vmargs = DMNEW(vm_arg, vmargscount);
+
+ /* fill the vm_arg array from a va_list */
+
+ vm_vmargs_from_jvalue(m, o, vmargs, args);
+
+ /* call the Java method */
+
+ l = vm_call_method_long_vmarg(m, vmargscount, vmargs);
+
+ /* release dump area */
+
+ dump_release(dumpsize);
+
+ return l;
+}
+
+
+/* vm_call_method_long_vmarg ***************************************************
+
+ Calls a Java method with a variable number of arguments, passed via
+ a vm_arg array, and returns a long (s8).
+
+*******************************************************************************/
+
+s8 vm_call_method_long_vmarg(methodinfo *m, s4 vmargscount, vm_arg *vmargs)
+{
+ s8 l;
+
+#if defined(ENABLE_JIT)
+# if defined(ENABLE_INTRP)
+ if (opt_intrp)
+ l = intrp_asm_vm_call_method_long(m, vmargscount, vmargs);
+ else
+# endif
+ l = asm_vm_call_method_long(m, vmargscount, vmargs);
+#else
+ l = intrp_asm_vm_call_method_long(m, vmargscount, vmargs);
+#endif
+
+ return l;
+}
+
+
+/* vm_call_method_float ********************************************************
+
+ Calls a Java method with a variable number of arguments and returns
+ an float.
+
+*******************************************************************************/
+
+float vm_call_method_float(methodinfo *m, java_objectheader *o, ...)
+{
+ va_list ap;
+ float f;
+
+ va_start(ap, o);
+ f = vm_call_method_float_valist(m, o, ap);
+ va_end(ap);
+
+ return f;
+}
+
+
+/* vm_call_method_float_valist *************************************************
+
+ Calls a Java method with a variable number of arguments, passed via
+ a va_list, and returns a float.
+
+*******************************************************************************/
+
+float vm_call_method_float_valist(methodinfo *m, java_objectheader *o,
+ va_list ap)
+{
+ s4 vmargscount;
+ vm_arg *vmargs;
+ float f;
+ s4 dumpsize;
+
+ /* mark start of dump memory area */
+
+ dumpsize = dump_size();
+
+ /* get number of Java method arguments */
+
+ vmargscount = m->parseddesc->paramcount;
+
+ /* allocate vm_arg array */
+
+ vmargs = DMNEW(vm_arg, vmargscount);
+
+ /* fill the vm_arg array from a va_list */
+
+ vm_vmargs_from_valist(m, o, vmargs, ap);
+
+ /* call the Java method */
+
+ f = vm_call_method_float_vmarg(m, vmargscount, vmargs);
+
+ /* release dump area */
+
+ dump_release(dumpsize);
+
+ return f;
+}
+
+
+/* vm_call_method_float_jvalue *************************************************
+
+ Calls a Java method with a variable number of arguments, passed via
+ a jvalue array, and returns a float.
+
+*******************************************************************************/
+
+float vm_call_method_float_jvalue(methodinfo *m, java_objectheader *o,
+ jvalue *args)
+{
+ s4 vmargscount;
+ vm_arg *vmargs;
+ float f;
+ s4 dumpsize;
+
+ /* mark start of dump memory area */
+
+ dumpsize = dump_size();
+
+ /* get number of Java method arguments */
+
+ vmargscount = m->parseddesc->paramcount;
+
+ /* allocate vm_arg array */
+
+ vmargs = DMNEW(vm_arg, vmargscount);
+
+ /* fill the vm_arg array from a va_list */
+
+ vm_vmargs_from_jvalue(m, o, vmargs, args);
+
+ /* call the Java method */
+
+ f = vm_call_method_float_vmarg(m, vmargscount, vmargs);
+
+ /* release dump area */
+
+ dump_release(dumpsize);
+
+ return f;
+}
+
+
+/* vm_call_method_float_vmarg **************************************************
+
+ Calls a Java method with a variable number of arguments and returns
+ an float.
+
+*******************************************************************************/
+
+float vm_call_method_float_vmarg(methodinfo *m, s4 vmargscount, vm_arg *vmargs)
+{
+ float f;
+
+#if defined(ENABLE_JIT)
+# if defined(ENABLE_INTRP)
+ if (opt_intrp)
+ f = intrp_asm_vm_call_method_float(m, vmargscount, vmargs);
+ else
+# endif
+ f = asm_vm_call_method_float(m, vmargscount, vmargs);
+#else
+ f = intrp_asm_vm_call_method_float(m, vmargscount, vmargs);
+#endif
+
+ return f;
+}
+
+
+/* vm_call_method_double *******************************************************
+
+ Calls a Java method with a variable number of arguments and returns
+ a double.
+
+*******************************************************************************/
+
+double vm_call_method_double(methodinfo *m, java_objectheader *o, ...)
+{
+ va_list ap;
+ double d;
+
+ va_start(ap, o);
+ d = vm_call_method_double_valist(m, o, ap);
+ va_end(ap);
+
+ return d;
+}
+
+
+/* vm_call_method_double_valist ************************************************
+
+ Calls a Java method with a variable number of arguments, passed via
+ a va_list, and returns a double.
+
+*******************************************************************************/
+
+double vm_call_method_double_valist(methodinfo *m, java_objectheader *o,
+ va_list ap)
+{
+ s4 vmargscount;
+ vm_arg *vmargs;
+ double d;
+ s4 dumpsize;
+
+ /* mark start of dump memory area */
+
+ dumpsize = dump_size();
+
+ /* get number of Java method arguments */
+
+ vmargscount = m->parseddesc->paramcount;
+
+ /* allocate vm_arg array */
+
+ vmargs = DMNEW(vm_arg, vmargscount);
+
+ /* fill the vm_arg array from a va_list */
+
+ vm_vmargs_from_valist(m, o, vmargs, ap);
+
+ /* call the Java method */
+
+ d = vm_call_method_double_vmarg(m, vmargscount, vmargs);
+
+ /* release dump area */
+
+ dump_release(dumpsize);
+
+ return d;
+}
+
+
+/* vm_call_method_double_jvalue ************************************************
+
+ Calls a Java method with a variable number of arguments, passed via
+ a jvalue array, and returns a double.
+
+*******************************************************************************/
+
+double vm_call_method_double_jvalue(methodinfo *m, java_objectheader *o,
+ jvalue *args)
+{
+ s4 vmargscount;
+ vm_arg *vmargs;
+ double d;
+ s4 dumpsize;
+
+ /* mark start of dump memory area */
+
+ dumpsize = dump_size();
+
+ /* get number of Java method arguments */
+
+ vmargscount = m->parseddesc->paramcount;
+
+ /* allocate vm_arg array */
+
+ vmargs = DMNEW(vm_arg, vmargscount);
+
+ /* fill the vm_arg array from a va_list */
+
+ vm_vmargs_from_jvalue(m, o, vmargs, args);
+
+ /* call the Java method */
+
+ d = vm_call_method_double_vmarg(m, vmargscount, vmargs);
+
+ /* release dump area */
+
+ dump_release(dumpsize);
+
+ return d;
+}
+
+
+/* vm_call_method_double_vmarg *************************************************
+
+ Calls a Java method with a variable number of arguments and returns
+ a double.
+
+*******************************************************************************/
+
+double vm_call_method_double_vmarg(methodinfo *m, s4 vmargscount,
+ vm_arg *vmargs)
+{
+ double d;
+
+#if defined(ENABLE_JIT)
+# if defined(ENABLE_INTRP)
+ if (opt_intrp)
+ d = intrp_asm_vm_call_method_double(m, vmargscount, vmargs);
+ else
+# endif
+ d = asm_vm_call_method_double(m, vmargscount, vmargs);
+#else
+ d = intrp_asm_vm_call_method_double(m, vmargscount, vmargs);
+#endif
+
+ return d;
+}
+
+
/*
* These are local overrides for various environment variables in Emacs.
* Please do not remove this and leave it at the end of the file, where