* configure.ac (ENABLE_RT_TIMING): Added.
[cacao.git] / src / vm / vm.c
index 0b9118c2606c16b6c50f2fad88c8f1fa70e3e98d..dcb460d42eb3a790419d2f511011f34387eeb8ae 100644 (file)
@@ -41,6 +41,7 @@
 #include "vm/types.h"
 
 #include "mm/boehm.h"
+#include "mm/memory.h"
 #include "native/jni.h"
 #include "native/native.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/profile/profile.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 */
 
 
@@ -105,14 +111,43 @@ bool startit = true;
 /* define command line options ************************************************/
 
 enum {
+       /* Java options */
+
+       OPT_JAR,
+
+       OPT_D32,
+       OPT_D64,
+
        OPT_CLASSPATH,
        OPT_D,
+
+       OPT_VERBOSE,
+
+       OPT_VERSION,
+       OPT_SHOWVERSION,
+       OPT_FULLVERSION,
+
+       OPT_HELP,
+       OPT_X,
+
+       /* Java non-standard options */
+
+       OPT_JIT,
+       OPT_INTRP,
+
+       OPT_BOOTCLASSPATH,
+       OPT_BOOTCLASSPATH_A,
+       OPT_BOOTCLASSPATH_P,
+
+       OPT_PROF,
+       OPT_PROF_OPTION,
+
        OPT_MS,
        OPT_MX,
+
+       /* CACAO options */
+
        OPT_VERBOSE1,
-       OPT_VERBOSE,
-       OPT_VERBOSESPECIFIC,
-       OPT_VERBOSECALL,
        OPT_NOIEEE,
        OPT_SOFTNULL,
        OPT_TIME,
@@ -134,7 +169,6 @@ enum {
        OPT_VERBOSETC,
        OPT_NOVERIFY,
        OPT_LIBERALUTF,
-       OPT_VERBOSEEXCEPTION,
        OPT_EAGER,
 
        /* optimization options */
@@ -147,23 +181,6 @@ enum {
        OPT_LSRA,
 #endif
 
-       OPT_JAR,
-       OPT_BOOTCLASSPATH,
-       OPT_BOOTCLASSPATH_A,
-       OPT_BOOTCLASSPATH_P,
-       OPT_VERSION,
-       OPT_SHOWVERSION,
-       OPT_FULLVERSION,
-
-       OPT_HELP,
-       OPT_X,
-
-       OPT_JIT,
-       OPT_INTRP,
-
-       OPT_PROF,
-       OPT_PROF_OPTION,
-
 #if defined(ENABLE_INTRP)
        /* interpreter options */
 
@@ -178,6 +195,8 @@ enum {
 
 #ifdef ENABLE_JVMTI
        OPT_DEBUG,
+       OPT_XRUNJDWP,
+       OPT_NOAGENT,
        OPT_AGENTLIB,
        OPT_AGENTPATH,
 #endif
@@ -187,17 +206,32 @@ enum {
 
 
 opt_struct opts[] = {
+       /* Java options */
+
+       { "jar",               false, OPT_JAR },
+
+       { "d32",               false, OPT_D32 },
+       { "d64",               false, OPT_D64 },
+       { "client",            false, OPT_IGNORE },
+       { "server",            false, OPT_IGNORE },
+       { "hotspot",           false, OPT_IGNORE },
+
        { "classpath",         true,  OPT_CLASSPATH },
        { "cp",                true,  OPT_CLASSPATH },
        { "D",                 true,  OPT_D },
+       { "version",           false, OPT_VERSION },
+       { "showversion",       false, OPT_SHOWVERSION },
+       { "fullversion",       false, OPT_FULLVERSION },
+       { "help",              false, OPT_HELP },
+       { "?",                 false, OPT_HELP },
+       { "X",                 false, OPT_X },
+
        { "noasyncgc",         false, OPT_IGNORE },
        { "noverify",          false, OPT_NOVERIFY },
        { "liberalutf",        false, OPT_LIBERALUTF },
        { "v",                 false, OPT_VERBOSE1 },
-       { "verbose",           false, OPT_VERBOSE },
-       { "verbose:",          true,  OPT_VERBOSESPECIFIC },
-       { "verbosecall",       false, OPT_VERBOSECALL },
-       { "verboseexception",  false, OPT_VERBOSEEXCEPTION },
+       { "verbose:",          true,  OPT_VERBOSE },
+
 #ifdef TYPECHECK_VERBOSE
        { "verbosetc",         false, OPT_VERBOSETC },
 #endif
@@ -222,12 +256,6 @@ opt_struct opts[] = {
 #if defined(ENABLE_LSRA)
        { "lsra",              false, OPT_LSRA },
 #endif
-       { "jar",               false, OPT_JAR },
-       { "version",           false, OPT_VERSION },
-       { "showversion",       false, OPT_SHOWVERSION },
-       { "fullversion",       false, OPT_FULLVERSION },
-       { "help",              false, OPT_HELP },
-       { "?",                 false, OPT_HELP },
 
 #if defined(ENABLE_INTRP)
        /* interpreter options */
@@ -245,9 +273,8 @@ opt_struct opts[] = {
        { "agentpath:",        true,  OPT_AGENTPATH },
 #endif
 
-       /* X options */
+       /* Java non-standard options */
 
-       { "X",                 false, OPT_X },
        { "Xjit",              false, OPT_JIT },
        { "Xint",              false, OPT_INTRP },
        { "Xbootclasspath:",   true,  OPT_BOOTCLASSPATH },
@@ -255,15 +282,17 @@ opt_struct opts[] = {
        { "Xbootclasspath/p:", true,  OPT_BOOTCLASSPATH_P },
 #ifdef ENABLE_JVMTI
        { "Xdebug",            false, OPT_DEBUG },
+       { "Xnoagent",          false, OPT_NOAGENT },
+       { "Xrunjdwp",          true,  OPT_XRUNJDWP },
 #endif 
        { "Xms",               true,  OPT_MS },
-       { "Xmx",               true,  OPT_MX },
-       { "Xprof:",            true,  OPT_PROF_OPTION },
-       { "Xprof",             false, OPT_PROF },
-       { "Xss",               true,  OPT_SS },
        { "ms",                true,  OPT_MS },
+       { "Xmx",               true,  OPT_MX },
        { "mx",                true,  OPT_MX },
+       { "Xss",               true,  OPT_SS },
        { "ss",                true,  OPT_SS },
+       { "Xprof:",            true,  OPT_PROF_OPTION },
+       { "Xprof",             false, OPT_PROF },
 
        /* keep these at the end of the list */
 
@@ -283,73 +312,76 @@ opt_struct opts[] = {
 
 void usage(void)
 {
-       printf("Usage: cacao [-options] classname [arguments]\n");
-       printf("               (to run a class file)\n");
-       printf("       cacao [-options] -jar jarfile [arguments]\n");
-       printf("               (to run a standalone jar file)\n\n");
-
-       printf("Java options:\n");
-       printf("    -cp <path>               specify a path to look for classes\n");
-       printf("    -classpath <path>        specify a path to look for classes\n");
-       printf("    -D<name>=<value>         add an entry to the property list\n");
-       printf("    -verbose[:class|gc|jni]  enable specific verbose output\n");
-       printf("    -version                 print product version and exit\n");
-       printf("    -fullversion             print jpackage-compatible product version and exit\n");
-       printf("    -showversion             print product version and continue\n");
-       printf("    -help, -?                print this help message\n");
-       printf("    -X                       print help on non-standard Java options\n\n");
+       puts("Usage: cacao [-options] classname [arguments]");
+       puts("               (to run a class file)");
+       puts("   or  cacao [-options] -jar jarfile [arguments]");
+       puts("               (to run a standalone jar file)\n");
+
+       puts("Java options:");
+       puts("    -d32                     use 32-bit data model if available");
+       puts("    -d64                     use 64-bit data model if available");
+       puts("    -client                  compatibility (currently ignored)");
+       puts("    -server                  compatibility (currently ignored)");
+       puts("    -hotspot                 compatibility (currently ignored)\n");
+
+       puts("    -cp <path>               specify a path to look for classes");
+       puts("    -classpath <path>        specify a path to look for classes");
+       puts("    -D<name>=<value>         add an entry to the property list");
+       puts("    -verbose[:class|gc|jni]  enable specific verbose output");
+       puts("    -version                 print product version and exit");
+       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");
 
 #ifdef ENABLE_JVMTI
-       printf("    -agentlib:<agent-lib-name>=<options>  library to load containg JVMTI agent\n");
-       printf("    -agentpath:<path-to-agent>=<options>  path to library containg JVMTI agent\n");
+       puts("    -agentlib:<agent-lib-name>=<options>  library to load containg JVMTI agent");
+       puts("    -agentpath:<path-to-agent>=<options>  path to library containg JVMTI agent");
 #endif
 
-       printf("CACAO options:\n");
-       printf("    -v                       write state-information\n");
-       printf("    -verbose                 write more information\n");
-       printf("    -verbosegc               write message for each GC\n");
-       printf("    -verbosecall             write message for each call\n");
-       printf("    -verboseexception        write message for each step of stack unwinding\n");
+       puts("CACAO options:\n");
+       puts("    -v                       write state-information");
+       puts("    -verbose[:call|exception]enable specific verbose output");
 #ifdef TYPECHECK_VERBOSE
-       printf("    -verbosetc               write debug messages while typechecking\n");
+       puts("    -verbosetc               write debug messages while typechecking");
 #endif
 #if defined(__ALPHA__)
-       printf("    -noieee                  don't use ieee compliant arithmetic\n");
+       puts("    -noieee                  don't use ieee compliant arithmetic");
 #endif
-       printf("    -noverify                don't verify classfiles\n");
-       printf("    -liberalutf              don't warn about overlong UTF-8 sequences\n");
-       printf("    -softnull                use software nullpointer check\n");
-       printf("    -time                    measure the runtime\n");
+       puts("    -noverify                don't verify classfiles");
+       puts("    -liberalutf              don't warn about overlong UTF-8 sequences");
+       puts("    -softnull                use software nullpointer check");
+       puts("    -time                    measure the runtime");
 #if defined(ENABLE_STATISTICS)
-       printf("    -stat                    detailed compiler statistics\n");
+       puts("    -stat                    detailed compiler statistics");
 #endif
-       printf("    -log logfile             specify a name for the logfile\n");
-       printf("    -c(heck)b(ounds)         don't check array bounds\n");
-       printf("            s(ync)           don't check for synchronization\n");
-       printf("    -oloop                   optimize array accesses in loops\n"); 
-       printf("    -l                       don't start the class after loading\n");
-       printf("    -eager                   perform eager class loading and linking\n");
-       printf("    -all                     compile all methods, no execution\n");
-       printf("    -m                       compile only a specific method\n");
-       printf("    -sig                     specify signature for a specific method\n");
-       printf("    -s(how)a(ssembler)       show disassembled listing\n");
-       printf("           c(onstants)       show the constant pool\n");
-       printf("           d(atasegment)     show data segment listing\n");
-       printf("           e(xceptionstubs)  show disassembled exception stubs (only with -sa)\n");
-       printf("           i(ntermediate)    show intermediate representation\n");
-       printf("           m(ethods)         show class fields and methods\n");
-       printf("           n(ative)          show disassembled native stubs\n");
-       printf("           u(tf)             show the utf - hash\n");
-       printf("    -i     n(line)           activate inlining\n");
-       printf("           v(irtual)         inline virtual methods (uses/turns rt option on)\n");
-       printf("           e(exception)      inline methods with exceptions\n");
-       printf("           p(aramopt)        optimize argument renaming\n");
-       printf("           o(utsiders)       inline methods of foreign classes\n");
+       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"); 
+       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("    -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");
 #if defined(ENABLE_IFCONV)
-       printf("    -ifconv                  use if-conversion\n");
+       puts("    -ifconv                  use if-conversion");
 #endif
 #if defined(ENABLE_LSRA)
-       printf("    -lsra                    use linear scan register allocation\n");
+       puts("    -lsra                    use linear scan register allocation");
 #endif
 
        /* exit with error code */
@@ -361,23 +393,27 @@ void usage(void)
 static void Xusage(void)
 {
 #if defined(ENABLE_JIT)
-       printf("    -Xjit             JIT mode execution (default)\n");
+       puts("    -Xjit                    JIT mode execution (default)");
 #endif
 #if defined(ENABLE_INTRP)
-       printf("    -Xint             interpreter mode execution\n");
+       puts("    -Xint                    interpreter mode execution");
 #endif
-       printf("    -Xbootclasspath:<zip/jar files and directories separated by :>\n");
-    printf("                      value is set as bootstrap class path\n");
-       printf("    -Xbootclasspath/a:<zip/jar files and directories separated by :>\n");
-       printf("                      value is appended to the bootstrap class path\n");
-       printf("    -Xbootclasspath/p:<zip/jar files and directories separated by :>\n");
-       printf("                      value is prepended to the bootstrap class path\n");
-       printf("    -Xms<size>        set the initial size of the heap (default: 2MB)\n");
-       printf("    -Xmx<size>        set the maximum size of the heap (default: 64MB)\n");
-       printf("    -Xss<size>        set the thread stack size (default: 128kB)\n");
-       printf("    -Xprof[:bb]       collect and print profiling data\n");
+       puts("    -Xbootclasspath:<zip/jar files and directories separated by :>");
+    puts("                             value is set as bootstrap class path");
+       puts("    -Xbootclasspath/a:<zip/jar files and directories separated by :>");
+       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("    -Xprof[:bb]              collect and print profiling data");
 #if defined(ENABLE_JVMTI)
-       printf("    -Xdebug<transport> enable remote debugging\n");
+    /* -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 */
@@ -394,23 +430,32 @@ static void Xusage(void)
 
 static void version(void)
 {
-       printf("java version \""JAVA_VERSION"\"\n");
-       printf("CACAO version "VERSION"\n");
-
-       printf("Copyright (C) 1996-2005, 2006 R. Grafl, A. Krall, C. Kruegel,\n");
-       printf("C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,\n");
-       printf("E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,\n");
-       printf("J. Wenninger, Institut f. Computersprachen - TU Wien\n\n");
-
-       printf("This program is free software; you can redistribute it and/or\n");
-       printf("modify it under the terms of the GNU General Public License as\n");
-       printf("published by the Free Software Foundation; either version 2, or (at\n");
-       printf("your option) any later version.\n\n");
-
-       printf("This program is distributed in the hope that it will be useful, but\n");
-       printf("WITHOUT ANY WARRANTY; without even the implied warranty of\n");
-       printf("MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n");
-       printf("General Public License for more details.\n");
+       puts("java version \""JAVA_VERSION"\"");
+       puts("CACAO version "VERSION"");
+
+       puts("Copyright (C) 1996-2005, 2006 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("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.\n");
+
+       puts("Configure/Build options:\n");
+       puts("  ./configure: "VERSION_CONFIGURE_ARGS"");
+#if defined(__VERSION__)
+       puts("  CC         : "VERSION_CC" ("__VERSION__")");
+#else
+       puts("  CC         : "VERSION_CC"");
+#endif
+       puts("  CFLAGS     : "VERSION_CFLAGS"");
 }
 
 
@@ -423,7 +468,7 @@ static void version(void)
 
 static void fullversion(void)
 {
-       printf("java full version \"cacao-"JAVA_VERSION"\"\n");
+       puts("java full version \"cacao-"JAVA_VERSION"\"");
 
        /* exit normally */
 
@@ -470,6 +515,7 @@ bool vm_create(JavaVMInitArgs *vm_args)
        nogc_init(HEAP_MAXSIZE, HEAP_STARTSIZE);
 #endif
 
+
        /* set the bootclasspath */
 
        cp = getenv("BOOTCLASSPATH");
@@ -514,6 +560,15 @@ bool vm_create(JavaVMInitArgs *vm_args)
        heapstartsize = HEAP_STARTSIZE;
        opt_stacksize = STACK_SIZE;
 
+
+#if defined(ENABLE_JVMTI)
+       /* initialize JVMTI related  **********************************************/
+       jvmtibrkpt.brk=NULL;
+       jvmtibrkpt.num=0;
+       jvmtibrkpt.size=0;
+       jdwp = jvmti = dbgprocess = false;
+#endif
+
        /* initialize properties before commandline handling */
 
        if (!properties_init())
@@ -527,6 +582,48 @@ bool vm_create(JavaVMInitArgs *vm_args)
                case OPT_IGNORE:
                        break;
                        
+               case OPT_JAR:
+                       opt_jar = true;
+                       break;
+
+               case OPT_D32:
+#if SIZEOF_VOID_P == 8
+                       puts("Running a 32-bit JVM is not supported on this platform.");
+                       exit(1);
+#endif
+                       break;
+
+               case OPT_D64:
+#if SIZEOF_VOID_P == 4
+                       puts("Running a 64-bit JVM is not supported on this platform.");
+                       exit(1);
+#endif
+                       break;
+
+               case OPT_CLASSPATH:
+                       /* forget old classpath and set the argument as new classpath */
+                       MFREE(classpath, char, strlen(classpath));
+
+                       classpath = MNEW(char, strlen(opt_arg) + strlen("0"));
+                       strcpy(classpath, opt_arg);
+                       break;
+
+               case OPT_D:
+                       for (j = 0; j < strlen(opt_arg); j++) {
+                               if (opt_arg[j] == '=') {
+                                       opt_arg[j] = '\0';
+                                       properties_add(opt_arg, opt_arg + j + 1);
+                                       goto didit;
+                               }
+                       }
+
+                       /* if no '=' is given, just create an empty property */
+
+                       properties_add(opt_arg, "");
+                                       
+               didit:
+                       break;
+
                case OPT_BOOTCLASSPATH:
                        /* Forget default bootclasspath and set the argument as
                           new boot classpath. */
@@ -565,48 +662,44 @@ bool vm_create(JavaVMInitArgs *vm_args)
                        MFREE(cp, char, cplen);
                        break;
 
-               case OPT_CLASSPATH:
-                       /* forget old classpath and set the argument as new classpath */
-                       MFREE(classpath, char, strlen(classpath));
-
-                       classpath = MNEW(char, strlen(opt_arg) + strlen("0"));
-                       strcpy(classpath, opt_arg);
-                       break;
-
-               case OPT_JAR:
-                       opt_jar = true;
-                       break;
-
 #if defined(ENABLE_JVMTI)
                case OPT_DEBUG:
-                       dbg = true;
+                       jdwp=true;
+                       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:
                        transport = opt_arg;
+                       j=0;
+                       while (transport[j]!='=') j++;
+                       j++;
+                       while (j<strlen(transport)) {
+                               if (strncmp("suspend=",&transport[j],8)==0) {
+                                       if ((j+8)>=strlen(transport) || 
+                                               (transport[j+8]!= 'y' && transport[j+8]!= 'n')) {
+                                               printf("bad Xrunjdwp option: -Xrunjdwp%s\n",transport);
+                                               usage();
+                                               break;
+                                       }
+                                       else {
+                                               suspend = transport[j+8] == 'y';
+                                               break;
+                                       }
+                               }
+                               while (transport[j]!=',') j++;
+                               j++;
+                       }
+                       
                        break;
-
                case OPT_AGENTPATH:
                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
                        
-               case OPT_D:
-                       for (j = 0; j < strlen(opt_arg); j++) {
-                               if (opt_arg[j] == '=') {
-                                       opt_arg[j] = '\0';
-                                       properties_add(opt_arg, opt_arg + j + 1);
-                                       goto didit;
-                               }
-                       }
-
-                       /* if no '=' is given, just create an empty property */
-
-                       properties_add(opt_arg, "");
-                                       
-               didit:
-                       break;
-
                case OPT_MX:
                case OPT_MS:
                case OPT_SS:
@@ -637,14 +730,6 @@ bool vm_create(JavaVMInitArgs *vm_args)
                        break;
 
                case OPT_VERBOSE:
-                       opt_verbose = true;
-                       loadverbose = true;
-                       linkverbose = true;
-                       initverbose = true;
-                       compileverbose = true;
-                       break;
-
-               case OPT_VERBOSESPECIFIC:
                        if (strcmp("class", opt_arg) == 0)
                                opt_verboseclass = true;
 
@@ -653,10 +738,19 @@ bool vm_create(JavaVMInitArgs *vm_args)
 
                        else if (strcmp("jni", opt_arg) == 0)
                                opt_verbosejni = true;
-                       break;
 
-               case OPT_VERBOSEEXCEPTION:
-                       opt_verboseexception = true;
+                       else if (strcmp("call", opt_arg) == 0)
+                               opt_verbosecall = true;
+
+                       else if (strcmp("jit", opt_arg) == 0) {
+                               opt_verbose = true;
+                               loadverbose = true;
+                               linkverbose = true;
+                               initverbose = true;
+                               compileverbose = true;
+                       }
+                       else if (strcmp("exception", opt_arg) == 0)
+                               opt_verboseexception = true;
                        break;
 
 #ifdef TYPECHECK_VERBOSE
@@ -665,10 +759,6 @@ bool vm_create(JavaVMInitArgs *vm_args)
                        break;
 #endif
                                
-               case OPT_VERBOSECALL:
-                       runverbose = true;
-                       break;
-
                case OPT_VERSION:
                        version();
                        exit(0);
@@ -918,34 +1008,43 @@ bool vm_create(JavaVMInitArgs *vm_args)
        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)
+       /* The fork has to occure before threads a created because threads  are 
+          not forked correctly (see man pthread_atfork). Varibale dbgprocess 
+          stores information whether this is the debugger or debuggee process. */
+       if (jvmti || jdwp) {
+               set_jvmti_phase(JVMTI_PHASE_ONLOAD);
+               dbgprocess = cacaodbgfork();
+       }
+
+       if (dbgprocess && jvmti) { /* is this the parent/debugger process ? */
+               agentload(agentarg);
+               set_jvmti_phase(JVMTI_PHASE_PRIMORDIAL);
+       }
+#endif
+
 
        /* initialize this JVM ****************************************************/
 
@@ -956,10 +1055,10 @@ bool vm_create(JavaVMInitArgs *vm_args)
        gc_init(heapmaxsize, heapstartsize);
 
 #if defined(ENABLE_INTRP)
-       /* allocate main thread stack */
+       /* Allocate main thread stack on the Java heap. */
 
        if (opt_intrp) {
-               intrp_main_stack = (u1 *) alloca(opt_stacksize);
+               intrp_main_stack = GCMNEW(u1, opt_stacksize);
                MSET(intrp_main_stack, 0, u1, opt_stacksize);
        }
 #endif
@@ -1071,11 +1170,13 @@ bool vm_create(JavaVMInitArgs *vm_args)
        if (!jni_init())
                throw_main_exception_exit();
 
+#if defined(ENABLE_PROFILING)
        /* initialize profiling */
 
        if (!profile_init())
                throw_main_exception_exit();
-               
+#endif
+
 #if defined(USE_THREADS)
        /* finally, start the finalizer thread */
 
@@ -1142,8 +1243,10 @@ void vm_exit(s4 status)
        assert(class_java_lang_System->state & CLASS_LOADED);
 
 #if defined(ENABLE_JVMTI)
-       set_jvmti_phase(JVMTI_PHASE_DEAD);
-       agentunload();
+       if (dbgprocess) {
+               set_jvmti_phase(JVMTI_PHASE_DEAD);
+               if (jvmti) agentunload();
+       }
 #endif
 
        if (!link_class(class_java_lang_System))
@@ -1157,20 +1260,17 @@ void vm_exit(s4 status)
                                                                 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);
+       (void) vm_call_method(m, NULL, status);
 
-       /* this should never happen */
+       /* If we had an exception, just ignore the exception and exit with
+          the proper code. */
 
-       if (*exceptionptr)
-               throw_exception_exit();
-
-       throw_cacao_exception_exit(string_java_lang_InternalError,
-                                                          "System.exit(I)V returned without exception");
+       vm_shutdown(status);
 }
 
 
@@ -1184,9 +1284,12 @@ void vm_exit(s4 status)
 void vm_shutdown(s4 status)
 {
 #if defined(ENABLE_JVMTI)
-       agentunload();
+       if (dbgprocess) {
+               set_jvmti_phase(JVMTI_PHASE_DEAD);
+               if (jvmti) agentunload();
+               ipcrm();
+       }
 #endif
-
        if (opt_verbose || getcompilingtime || opt_stat) {
                log_text("CACAO terminated by shutdown");
                dolog("Exit status: %d\n", (s4) status);
@@ -1208,6 +1311,12 @@ void vm_shutdown(s4 status)
 
 void vm_exit_handler(void)
 {
+#if defined(ENABLE_JVMTI)
+       if (jvmti && jdwp) set_jvmti_phase(JVMTI_PHASE_DEAD);
+       if (jvmti) agentunload();
+       ipcrm();
+#endif
+
 #if !defined(NDEBUG)
        if (showmethods)
                class_showmethods(mainclass);
@@ -1218,8 +1327,10 @@ void vm_exit_handler(void)
        if (showutf)
                utf_show();
 
+# if defined(ENABLE_PROFILING)
        if (opt_prof)
                profile_printstats();
+# endif
 #endif
 
 #if defined(USE_THREADS) && !defined(NATIVE_THREADS)
@@ -1227,6 +1338,10 @@ void vm_exit_handler(void)
                                       flags */
 #endif
 
+#if defined(ENABLE_RT_TIMING)
+       jit_print_time_stats(stderr);
+#endif
+
        if (opt_verbose || getcompilingtime || opt_stat) {
                log_text("CACAO terminated");
 
@@ -1248,6 +1363,803 @@ void vm_exit_handler(void)
 }
 
 
+/* 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 = (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 = (s8) va_arg(ap, s4);
+                       break;
+
+               case PRIMITIVETYPE_LONG:
+                       vmargs[i].type = TYPE_LNG;
+                       vmargs[i].data = (s8) va_arg(ap, s8);
+                       break;
+
+               case PRIMITIVETYPE_FLOAT:
+                       vmargs[i].type = TYPE_FLT;
+#if defined(__ALPHA__)
+                       /* this keeps the assembler function much simpler */
+
+                       *((jdouble *) (&vmargs[i].data)) = (jdouble) va_arg(ap, jdouble);
+#else
+                       *((jfloat *) (&vmargs[i].data)) = (jfloat) va_arg(ap, jdouble);
+#endif
+                       break;
+
+               case PRIMITIVETYPE_DOUBLE:
+                       vmargs[i].type = TYPE_DBL;
+                       *((jdouble *) (&vmargs[i].data)) = (jdouble) va_arg(ap, jdouble);
+                       break;
+
+               case TYPE_ADR: 
+                       vmargs[i].type = TYPE_ADR;
+                       vmargs[i].data = (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 = (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 = (s8) args[j].i;
+                       break;
+
+               case PRIMITIVETYPE_LONG:
+                       vmargs[i].type = TYPE_LNG;
+                       vmargs[i].data = (s8) args[j].j;
+                       break;
+
+               case PRIMITIVETYPE_FLOAT:
+                       vmargs[i].type = TYPE_FLT;
+#if defined(__ALPHA__)
+                       /* this keeps the assembler function much simpler */
+
+                       *((jdouble *) (&vmargs[i].data)) = (jdouble) args[j].f;
+#else
+                       *((jfloat *) (&vmargs[i].data)) = args[j].f;
+#endif
+                       break;
+
+               case PRIMITIVETYPE_DOUBLE:
+                       vmargs[i].type = TYPE_DBL;
+                       *((jdouble *) (&vmargs[i].data)) = args[j].d;
+                       break;
+
+               case TYPE_ADR: 
+                       vmargs[i].type = TYPE_ADR;
+                       vmargs[i].data = (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