X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=src%2Fcacao%2Fcacao.c;h=183ba52a8707a5caaeeae4497a2ddf78d726a670;hb=ad92477479aeed17382996ab43a7ca0dfab2ba93;hp=706da745a4802d49e0d01595d9a0a7a24027851c;hpb=c5fa1c7dccde6effeac76c0b9388d3bb9a980ded;p=cacao.git diff --git a/src/cacao/cacao.c b/src/cacao/cacao.c index 706da745a..183ba52a8 100644 --- a/src/cacao/cacao.c +++ b/src/cacao/cacao.c @@ -1,9 +1,9 @@ /* src/cacao/cacao.c - contains main() of cacao - Copyright (C) 1996-2005 R. Grafl, A. Krall, C. Kruegel, C. Oates, - R. Obermaisser, M. Platter, M. Probst, S. Ring, E. Steiner, - C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich, J. Wenninger, - Institut f. Computersprachen - TU Wien + Copyright (C) 1996-2005, 2006 R. Grafl, A. Krall, C. Kruegel, + C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring, + E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich, + J. Wenninger, J. Wenninger, Institut f. Computersprachen - TU Wien This file is part of CACAO. @@ -19,10 +19,10 @@ You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - 02111-1307, USA. + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + 02110-1301, USA. - Contact: cacao@complang.tuwien.ac.at + Contact: cacao@cacaojvm.org Authors: Reinhard Grafl @@ -37,28 +37,46 @@ - Calling the class loader - Running the main method - $Id: cacao.c 2148 2005-03-30 16:49:40Z twisti $ + $Id: cacao.c 4357 2006-01-22 23:33:38Z twisti $ */ +#include "config.h" + +#include #include #include -#include "config.h" +#include "vm/types.h" + #include "cacao/cacao.h" #include "mm/boehm.h" #include "mm/memory.h" #include "native/jni.h" #include "native/native.h" + +#if defined(ENABLE_JVMTI) +#include "native/jvmti/jvmti.h" +#include "native/jvmti/dbg.h" +#include +#include +#include +#endif + #include "toolbox/logging.h" +#include "vm/classcache.h" #include "vm/exceptions.h" +#include "vm/finalizer.h" #include "vm/global.h" +#include "vm/initialize.h" #include "vm/loader.h" #include "vm/options.h" +#include "vm/properties.h" +#include "vm/signallocal.h" #include "vm/statistics.h" #include "vm/stringlocal.h" -#include "vm/tables.h" +#include "vm/suck.h" #include "vm/jit/asmpart.h" #include "vm/jit/jit.h" @@ -69,8 +87,19 @@ /* define heap sizes **********************************************************/ -#define HEAP_MAXSIZE 64 * 1024 * 1024; /* default 64MB */ -#define HEAP_STARTSIZE 2 * 1024 * 1024; /* default 2MB */ +#define HEAP_MAXSIZE 64 * 1024 * 1024 /* default 64MB */ +#define HEAP_STARTSIZE 2 * 1024 * 1024 /* default 2MB */ +#define STACK_SIZE 128 * 1024 /* default 128kB */ + +#if defined(ENABLE_INTRP) +u1 *intrp_main_stack; +#endif + + +/* CACAO related stuff ********************************************************/ + +bool cacao_initializing; +bool cacao_exiting; /* Invocation API variables ***************************************************/ @@ -81,11 +110,6 @@ JNIEnv *env; /* pointer to native method interface */ JDK1_1InitArgs vm_args; /* JDK 1.1 VM initialization arguments */ -bool cacao_initializing; - -char *bootclasspath; /* contains the boot classpath */ -char *classpath; /* contains the classpath */ - char *mainstring; static classinfo *mainclass; @@ -96,72 +120,96 @@ void **stackbottom = 0; /* define command line options ************************************************/ -#define OPT_CLASSPATH 2 -#define OPT_D 3 -#define OPT_MS 4 -#define OPT_MX 5 -#define OPT_VERBOSE1 6 -#define OPT_VERBOSE 7 -#define OPT_VERBOSEGC 8 -#define OPT_VERBOSECALL 9 -#define OPT_NOIEEE 10 -#define OPT_SOFTNULL 11 -#define OPT_TIME 12 - -#if defined(STATISTICS) -#define OPT_STAT 13 -#endif /* defined(STATISTICS) */ - -#define OPT_LOG 14 -#define OPT_CHECK 15 -#define OPT_LOAD 16 -#define OPT_METHOD 17 -#define OPT_SIGNATURE 18 -#define OPT_SHOW 19 -#define OPT_ALL 20 -#define OPT_OLOOP 24 -#define OPT_INLINING 25 +enum { + OPT_CLASSPATH, + OPT_D, + OPT_MS, + OPT_MX, + OPT_VERBOSE1, + OPT_VERBOSE, + OPT_VERBOSESPECIFIC, + OPT_VERBOSECALL, + OPT_NOIEEE, + OPT_SOFTNULL, + OPT_TIME, + +#if defined(ENABLE_STATISTICS) + OPT_STAT, +#endif + + OPT_LOG, + OPT_CHECK, + OPT_LOAD, + OPT_METHOD, + OPT_SIGNATURE, + OPT_SHOW, + OPT_ALL, + OPT_OLOOP, + OPT_INLINING, #define STATIC_ANALYSIS #if defined(STATIC_ANALYSIS) -# define OPT_RT 26 -# define OPT_XTA 27 -# define OPT_VTA 28 -#endif /* defined(STATIC_ANALYSIS) */ + OPT_RT, + OPT_XTA, + OPT_VTA, +#endif -#define OPT_VERBOSETC 29 -#define OPT_NOVERIFY 30 -#define OPT_LIBERALUTF 31 -#define OPT_VERBOSEEXCEPTION 32 -#define OPT_EAGER 33 + OPT_VERBOSETC, + OPT_NOVERIFY, + OPT_LIBERALUTF, + OPT_VERBOSEEXCEPTION, + OPT_EAGER, -#if defined(LSRA) -# define OPT_LSRA 34 -#endif /* defined(LSRA) */ +#if defined(ENABLE_LSRA) + OPT_LSRA, +#endif + + OPT_JAR, + OPT_BOOTCLASSPATH, + OPT_BOOTCLASSPATH_A, + OPT_BOOTCLASSPATH_P, + OPT_VERSION, + OPT_SHOWVERSION, + OPT_FULLVERSION, + + OPT_HELP, + OPT_X, -#define OPT_JAR 35 -#define OPT_BOOTCLASSPATH 36 -#define OPT_BOOTCLASSPATH_A 37 -#define OPT_BOOTCLASSPATH_P 38 -#define OPT_VERSION 39 + OPT_JIT, + OPT_INTRP, + +#if defined(ENABLE_INTRP) + /* interpreter options */ + + OPT_NO_DYNAMIC, + OPT_NO_REPLICATION, + OPT_NO_QUICKSUPER, + OPT_STATIC_SUPERS, + OPT_TRACE, +#endif + + OPT_SS, + +#ifdef ENABLE_JVMTI + OPT_DEBUG, + OPT_AGENTLIB, + OPT_AGENTPATH, +#endif + + DUMMY +}; opt_struct opts[] = { { "classpath", true, OPT_CLASSPATH }, { "cp", true, OPT_CLASSPATH }, { "D", true, OPT_D }, - { "Xms", true, OPT_MS }, - { "Xmx", true, OPT_MX }, - { "ms", true, OPT_MS }, - { "mx", true, OPT_MX }, { "noasyncgc", false, OPT_IGNORE }, { "noverify", false, OPT_NOVERIFY }, { "liberalutf", false, OPT_LIBERALUTF }, - { "oss", true, OPT_IGNORE }, - { "ss", true, OPT_IGNORE }, { "v", false, OPT_VERBOSE1 }, { "verbose", false, OPT_VERBOSE }, - { "verbosegc", false, OPT_VERBOSEGC }, + { "verbose:", true, OPT_VERBOSESPECIFIC }, { "verbosecall", false, OPT_VERBOSECALL }, { "verboseexception", false, OPT_VERBOSEEXCEPTION }, #ifdef TYPECHECK_VERBOSE @@ -172,106 +220,180 @@ opt_struct opts[] = { #endif { "softnull", false, OPT_SOFTNULL }, { "time", false, OPT_TIME }, -#if defined(STATISTICS) +#if defined(ENABLE_STATISTICS) { "stat", false, OPT_STAT }, #endif { "log", true, OPT_LOG }, { "c", true, OPT_CHECK }, { "l", false, OPT_LOAD }, - { "eager", false, OPT_EAGER }, - { "m", true, OPT_METHOD }, + { "eager", false, OPT_EAGER }, { "sig", true, OPT_SIGNATURE }, - { "s", true, OPT_SHOW }, { "all", false, OPT_ALL }, { "oloop", false, OPT_OLOOP }, - { "i", true, OPT_INLINING }, #ifdef STATIC_ANALYSIS { "rt", false, OPT_RT }, { "xta", false, OPT_XTA }, { "vta", false, OPT_VTA }, #endif -#ifdef LSRA +#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 */ + + { "trace", false, OPT_TRACE }, + { "static-supers", true, OPT_STATIC_SUPERS }, + { "no-dynamic", false, OPT_NO_DYNAMIC }, + { "no-replication", false, OPT_NO_REPLICATION }, + { "no-quicksuper", false, OPT_NO_QUICKSUPER }, +#endif + + /* JVMTI Agent Command Line Options */ +#ifdef ENABLE_JVMTI + { "agentlib:", true, OPT_AGENTLIB }, + { "agentpath:", true, OPT_AGENTPATH }, +#endif + + /* X options */ + + { "X", false, OPT_X }, + { "Xjit", false, OPT_JIT }, + { "Xint", false, OPT_INTRP }, { "Xbootclasspath:", true, OPT_BOOTCLASSPATH }, { "Xbootclasspath/a:", true, OPT_BOOTCLASSPATH_A }, { "Xbootclasspath/p:", true, OPT_BOOTCLASSPATH_P }, - { "version", false, OPT_VERSION }, +#ifdef ENABLE_JVMTI + { "Xdebug", false, OPT_DEBUG }, +#endif + { "Xms", true, OPT_MS }, + { "Xmx", true, OPT_MX }, + { "Xss", true, OPT_SS }, + { "ms", true, OPT_MS }, + { "mx", true, OPT_MX }, + { "ss", true, OPT_SS }, + + /* keep these at the end of the list */ + + { "i", true, OPT_INLINING }, + { "m", true, OPT_METHOD }, + { "s", true, OPT_SHOW }, + { NULL, false, 0 } }; -/******************** interne Function: print_usage ************************ +/* usage *********************************************************************** -Prints the correct usage syntax to stdout. + Prints the correct usage syntax to stdout. -***************************************************************************/ +*******************************************************************************/ -static void usage() +static void usage(void) { - printf("Usage: cacao [options] classname [program arguments]\n\n"); + 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("Options:\n"); + printf("Java options:\n"); printf(" -cp specify a path to look for classes\n"); printf(" -classpath specify a path to look for classes\n"); - printf(" -jar jarfile execute a jar file\n"); printf(" -D= add an entry to the property list\n"); - printf(" -Xmx[kK|mM] specify the size for the heap\n"); - printf(" -Xms[kK|mM] specify the initial size for the heap\n"); - printf(" -mx[kK|mM] specify the size for the heap\n"); - printf(" -ms[kK|mM] specify the initial size for the heap\n"); - printf(" -Xbootclasspath: set search path for bootstrap classes and resources\n"); - printf(" -Xbootclasspath/a: append to end of bootstrap class path\n"); - printf(" -Xbootclasspath/p: prepend in front of bootstrap class path\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"); + 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"); + +#ifdef ENABLE_JVMTI + printf(" -agentlib:= library to load containg JVMTI agent\n"); + printf(" -agentpath:= path to library containg JVMTI agent\n"); +#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"); #ifdef TYPECHECK_VERBOSE - printf(" -verbosetc ........... write debug messages while typechecking\n"); + printf(" -verbosetc write debug messages while typechecking\n"); #endif - printf(" -version print product version and exit\n"); #if defined(__ALPHA__) - printf(" -noieee .............. don't use ieee compliant arithmetic\n"); + printf(" -noieee don't use ieee compliant arithmetic\n"); #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"); -#if defined(STATISTICS) - printf(" -stat ................ detailed compiler statistics\n"); + 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"); +#if defined(ENABLE_STATISTICS) + printf(" -stat detailed compiler statistics\n"); #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(" i(ntermediate). show intermediate representation\n"); - printf(" m(ethods)...... show class fields and methods\n"); - printf(" u(tf) ......... show the utf - hash\n"); - printf(" -i n ............. activate inlining\n"); - printf(" v ............. inline virtual methods\n"); - printf(" uses/turns rt option on\n"); - printf(" e ............. inline methods with exceptions\n"); - printf(" p ............. optimize argument renaming\n"); - printf(" o ............. inline methods of foreign classes\n"); + 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"); #ifdef STATIC_ANALYSIS - printf(" -rt .................. use rapid type analysis\n"); - printf(" -xta ................. use x type analysis\n"); - printf(" -vta ................. use variable type analysis\n"); + printf(" -rt use rapid type analysis\n"); + printf(" -xta use x type analysis\n"); + printf(" -vta use variable type analysis\n"); +#endif +#if defined(ENABLE_LSRA) + printf(" -lsra use linear scan register allocation\n"); +#endif + + /* exit with error code */ + + exit(1); +} + + +static void Xusage(void) +{ +#if defined(ENABLE_JIT) + printf(" -Xjit JIT mode execution (default)\n"); #endif -#ifdef LSRA - printf(" -lsra ................ use linear scan register allocation\n"); +#if defined(ENABLE_INTRP) + printf(" -Xint interpreter mode execution\n"); #endif + printf(" -Xbootclasspath:\n"); + printf(" value is set as bootstrap class path\n"); + printf(" -Xbootclasspath/a:\n"); + printf(" value is appended to the bootstrap class path\n"); + printf(" -Xbootclasspath/p:\n"); + printf(" value is prepended to the bootstrap class path\n"); + printf(" -Xms set the initial size of the heap (default: 2MB)\n"); + printf(" -Xmx set the maximum size of the heap (default: 64MB)\n"); + printf(" -Xss set the thread stack size (default: 128kB)\n"); +#if defined(ENABLE_JVMTI) + printf(" -Xdebug enable remote debugging\n"); +#endif /* exit with error code */ @@ -281,13 +403,45 @@ static void usage() /* version ********************************************************************* - Only prints cacao version information and exits. + Only prints cacao version information. + +*******************************************************************************/ + +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"); +} + + +/* fullversion ***************************************************************** + + Prints a Sun compatible version information (required e.g. by + jpackage, www.jpackage.org). *******************************************************************************/ -static void version() +static void fullversion(void) { - printf("cacao "VERSION"\n"); + printf("java full version \"cacao-"JAVA_VERSION"\"\n"); + + /* exit normally */ + exit(0); } @@ -296,140 +450,186 @@ static void version() void typecheck_print_statistics(FILE *file); #endif +/* setup_debugger_process ***************************************************** + Helper function to start JDWP threads -/* getmainclassfromjar ************************************************************ +*******************************************************************************/ +#if defined(ENABLE_JVMTI) + +static void setup_debugger_process(char* transport) { + java_objectheader *o; + methodinfo *m; + java_lang_String *s; - gets the name of the main class form a jar's manifest file + /* new gnu.classpath.jdwp.Jdwp() */ + mainclass = + load_class_from_sysloader(utf_new_char("gnu.classpath.jdwp.Jdwp")); + if (!mainclass) + throw_main_exception_exit(); -**********************************************************************************/ + o = builtin_new(mainclass); -char *getmainclassnamefromjar(JNIEnv *env, char *mainstring) -{ - jclass class; - jmethodID mid; - jobject obj; - - class = (*env)->FindClass(env, "java/util/jar/JarFile"); - if (class == NULL) { - log_text("unable to find java.util.jar.JarFile"); + if (!o) throw_main_exception_exit(); - } - mid = (*env)->GetMethodID(NULL, class, "","(Ljava/lang/String;)V"); - if (mid == NULL) { - log_text("unable to find constructor in java.util.jar.JarFile"); - cacao_exit(1); - } + m = class_resolveclassmethod(mainclass, + utf_init, + utf_java_lang_String__void, + class_java_lang_Object, + true); + if (!m) + throw_main_exception_exit(); - /* open jarfile */ - obj = (*env)->NewObject(NULL,class,mid,((*env)->NewStringUTF(NULL,(char*)mainstring))); - if ((*env)->ExceptionOccurred(NULL) != NULL) { - (*env)->ExceptionDescribe(NULL); - cacao_exit(1); - } + ASM_CALLJAVAFUNCTION(m, o, NULL, NULL, NULL); + + /* configure(transport,NULL) */ + m = class_resolveclassmethod( + mainclass, utf_new_char("configure"), + utf_new_char("(Ljava/lang/String;Ljava/lang/Thread;)V"), + class_java_lang_Object, + false); + + + s = javastring_new_char(transport); + + ASM_CALLJAVAFUNCTION(m, o, s, NULL, NULL); + + if (!m) + throw_main_exception_exit(); + + /* _doInitialization */ + m = class_resolveclassmethod(mainclass, + utf_new_char("_doInitialization"), + utf_new_char("()V"), + mainclass, + false); - mid = (*env)->GetMethodID(NULL, class, "getManifest","()Ljava/util/jar/Manifest;"); - if (mid == NULL) { - log_text("unable to find getMainfest method"); - cacao_exit(1); - } + if (!m) + throw_main_exception_exit(); + + ASM_CALLJAVAFUNCTION(m, o, NULL, NULL, NULL); +} +#endif + + +/* getmainclassfromjar ********************************************************* + + Gets the name of the main class form a JAR's manifest file. + +*******************************************************************************/ + +static char *getmainclassnamefromjar(char *mainstring) +{ + classinfo *c; + java_objectheader *o; + methodinfo *m; + java_lang_String *s; + + c = load_class_from_sysloader(utf_new_char("java/util/jar/JarFile")); + + if (!c) + throw_main_exception_exit(); + + /* create JarFile object */ + + o = builtin_new(c); + + if (!o) + throw_main_exception_exit(); + + + m = class_resolveclassmethod(c, + utf_init, + utf_java_lang_String__void, + class_java_lang_Object, + true); + + if (!m) + throw_main_exception_exit(); + + s = javastring_new_char(mainstring); + + ASM_CALLJAVAFUNCTION(m, o, s, NULL, NULL); + + if (*exceptionptr) + throw_main_exception_exit(); /* get manifest object */ - obj = (*env)->CallObjectMethod(NULL,obj,mid); - if ((*env)->ExceptionOccurred(NULL) != NULL) { - (*env)->ExceptionDescribe(NULL); - cacao_exit(1); - } - mid = (*env)->GetMethodID(NULL, (jclass)((java_objectheader*) obj)->vftbl->class, "getMainAttributes","()Ljava/util/jar/Attributes;"); - if (mid == NULL) { - log_text("unable to find getMainAttributes method"); + m = class_resolveclassmethod(c, + utf_new_char("getManifest"), + utf_new_char("()Ljava/util/jar/Manifest;"), + class_java_lang_Object, + true); + + if (!m) + throw_main_exception_exit(); + + ASM_CALLJAVAFUNCTION_ADR(o, m, o, NULL, NULL, NULL); + + if (!o) { + fprintf(stderr, "Could not get manifest from %s (invalid or corrupt jarfile?)\n", mainstring); cacao_exit(1); } + /* get Main Attributes */ - obj = (*env)->CallObjectMethod(NULL,obj,mid); - if ((*env)->ExceptionOccurred(NULL) != NULL) { - (*env)->ExceptionDescribe(NULL); - cacao_exit(1); - } + m = class_resolveclassmethod(o->vftbl->class, + utf_new_char("getMainAttributes"), + utf_new_char("()Ljava/util/jar/Attributes;"), + class_java_lang_Object, + true); - mid = (*env)->GetMethodID(NULL, (jclass)((java_objectheader*) obj)->vftbl->class, "getValue","(Ljava/lang/String;)Ljava/lang/String;"); - if (mid == NULL) { - log_text("unable to find getValue method"); - cacao_exit(1); - } + if (!m) + throw_main_exception_exit(); - /* get property Main-Class */ - obj = (*env)->CallObjectMethod(NULL,obj,mid,(*env)->NewStringUTF(NULL,"Main-Class")); - if ((*env)->ExceptionOccurred(NULL) != NULL) { - (*env)->ExceptionDescribe(NULL); + ASM_CALLJAVAFUNCTION_ADR(o, m, o, NULL, NULL, NULL); + + if (!o) { + fprintf(stderr, "Could not get main attributes from %s (invalid or corrupt jarfile?)\n", mainstring); cacao_exit(1); } - - return javastring_tochar((java_objectheader *) obj); -} -/* - * void exit_handler(void) - * ----------------------- - * The exit_handler function is called upon program termination to shutdown - * the various subsystems and release the resources allocated to the VM. - */ -void exit_handler(void) -{ - /********************* Print debug tables ************************/ - - if (showmethods) class_showmethods(mainclass); - if (showconstantpool) class_showconstantpool(mainclass); - if (showutf) utf_show(); - -#if defined(USE_THREADS) && !defined(NATIVE_THREADS) - clear_thread_flags(); /* restores standard file descriptor - flags */ -#endif + /* get property Main-Class */ - /************************ Free all resources *******************/ + m = class_resolveclassmethod(o->vftbl->class, + utf_new_char("getValue"), + utf_new_char("(Ljava/lang/String;)Ljava/lang/String;"), + class_java_lang_Object, + true); - loader_close(); - tables_close(); + if (!m) + throw_main_exception_exit(); - MFREE(classpath, u1, strlen(classpath)); + s = javastring_new_char("Main-Class"); - if (opt_verbose || getcompilingtime || opt_stat) { - log_text("CACAO terminated"); + ASM_CALLJAVAFUNCTION_ADR(o, m, o, s, NULL, NULL); -#if defined(STATISTICS) - if (opt_stat) { - print_stats(); -#ifdef TYPECHECK_STATISTICS - typecheck_print_statistics(get_logfile()); -#endif - } + if (!o) + throw_main_exception_exit(); - if (getcompilingtime) - print_times(); - mem_usagelog(1); -#endif - } + return javastring_tochar(o); } -/************************** Function: main ******************************* +void exit_handler(void); + + +/* main ************************************************************************ The main program. -**************************************************************************/ +*******************************************************************************/ int main(int argc, char **argv) { s4 i, j; void *dummy; - /********** interne (nur fuer main relevante Optionen) **************/ + /* local variables ********************************************************/ char logfilename[200] = ""; u4 heapmaxsize; @@ -440,6 +640,12 @@ int main(int argc, char **argv) char *specificmethodname = NULL; char *specificsignature = NULL; bool jar = false; +#if defined(ENABLE_JVMTI) + bool dbg = false; + char *transport; + int waitval; +#endif + #if defined(USE_THREADS) && !defined(NATIVE_THREADS) stackbottom = &dummy; @@ -449,46 +655,48 @@ int main(int argc, char **argv) throw_cacao_exception_exit(string_java_lang_InternalError, "Unable to register exit_handler"); + /* initialize global variables */ + + cacao_exiting = false; + /************ Collect info from the environment ************************/ +#if defined(DISABLE_GC) + nogc_init(HEAP_MAXSIZE, HEAP_STARTSIZE); +#endif + /* set the bootclasspath */ cp = getenv("BOOTCLASSPATH"); + if (cp) { - bootclasspath = MNEW(char, strlen(cp) + 1); + bootclasspath = MNEW(char, strlen(cp) + strlen("0")); strcpy(bootclasspath, cp); } else { -#if !defined(WITH_EXTERNAL_CLASSPATH) - cplen = strlen(CACAO_INSTALL_PREFIX) + strlen(CACAO_RT_JAR_PATH); + cplen = strlen(CACAO_VM_ZIP_PATH) + + strlen(":") + + strlen(CLASSPATH_GLIBJ_ZIP_PATH) + + strlen("0"); - bootclasspath = MNEW(char, cplen + 1); - strcpy(bootclasspath, CACAO_INSTALL_PREFIX); - strcat(bootclasspath, CACAO_RT_JAR_PATH); -#else - cplen = strlen(CACAO_INSTALL_PREFIX) + strlen(CACAO_VM_ZIP_PATH) + - strlen(EXTERNAL_CLASSPATH_PREFIX) + strlen(CLASSPATH_GLIBJ_ZIP_PATH); - - bootclasspath = MNEW(char, cplen + 1 + 1); - strcpy(bootclasspath, CACAO_INSTALL_PREFIX); + bootclasspath = MNEW(char, cplen); strcat(bootclasspath, CACAO_VM_ZIP_PATH); strcat(bootclasspath, ":"); - strcat(bootclasspath, EXTERNAL_CLASSPATH_PREFIX); strcat(bootclasspath, CLASSPATH_GLIBJ_ZIP_PATH); -#endif } /* set the classpath */ cp = getenv("CLASSPATH"); + if (cp) { - classpath = MNEW(char, strlen(cp) + 1); + classpath = MNEW(char, strlen(cp) + strlen("0")); strcat(classpath, cp); } else { - classpath = MNEW(char, 2); + classpath = MNEW(char, strlen(".") + strlen("0")); strcpy(classpath, "."); } @@ -500,7 +708,13 @@ int main(int argc, char **argv) heapmaxsize = HEAP_MAXSIZE; heapstartsize = HEAP_STARTSIZE; + opt_stacksize = STACK_SIZE; + + /* initialize properties before commandline handling */ + if (!properties_init()) + throw_cacao_exception_exit(string_java_lang_InternalError, + "Unable to init properties"); while ((i = get_opt(argc, argv, opts)) != OPT_DONE) { switch (i) { @@ -512,7 +726,7 @@ int main(int argc, char **argv) /* classpath. */ MFREE(bootclasspath, char, strlen(bootclasspath)); - bootclasspath = MNEW(char, strlen(opt_arg) + 1); + bootclasspath = MNEW(char, strlen(opt_arg) + strlen("0")); strcpy(bootclasspath, opt_arg); break; @@ -523,7 +737,8 @@ int main(int argc, char **argv) bootclasspath = MREALLOC(bootclasspath, char, cplen, - cplen + 1 + strlen(opt_arg) + 1); + cplen + strlen(":") + + strlen(opt_arg) + strlen("0")); strcat(bootclasspath, ":"); strcat(bootclasspath, opt_arg); @@ -534,7 +749,8 @@ int main(int argc, char **argv) cp = bootclasspath; cplen = strlen(cp); - bootclasspath = MNEW(char, strlen(opt_arg) + 1 + cplen + 1); + bootclasspath = MNEW(char, strlen(opt_arg) + strlen(":") + + cplen + strlen("0")); strcpy(bootclasspath, opt_arg); strcat(bootclasspath, ":"); @@ -547,33 +763,50 @@ int main(int argc, char **argv) /* forget old classpath and set the argument as new classpath */ MFREE(classpath, char, strlen(classpath)); - classpath = MNEW(char, strlen(opt_arg) + 1); + classpath = MNEW(char, strlen(opt_arg) + strlen("0")); strcpy(classpath, opt_arg); break; case OPT_JAR: jar = true; break; + +#if defined(ENABLE_JVMTI) + case OPT_DEBUG: + dbg = true; + transport = opt_arg; + break; + + case OPT_AGENTPATH: + case OPT_AGENTLIB: + set_jvmti_phase(JVMTI_PHASE_ONLOAD); + agentload(opt_arg); + set_jvmti_phase(JVMTI_PHASE_PRIMORDIAL); + break; +#endif case OPT_D: { for (j = 0; j < strlen(opt_arg); j++) { if (opt_arg[j] == '=') { opt_arg[j] = '\0'; - create_property(opt_arg, opt_arg + j + 1); + properties_add(opt_arg, opt_arg + j + 1); goto didit; } } /* if no '=' is given, just create an empty property */ - create_property(opt_arg, ""); + + properties_add(opt_arg, ""); - didit: ; + didit: + ; } break; - case OPT_MS: case OPT_MX: + case OPT_MS: + case OPT_SS: { char c; c = opt_arg[strlen(opt_arg) - 1]; @@ -584,10 +817,15 @@ int main(int argc, char **argv) } else if (c == 'm' || c == 'M') { j = 1024 * 1024 * atoi(opt_arg); - } else j = atoi(opt_arg); + } else + j = atoi(opt_arg); - if (i == OPT_MX) heapmaxsize = j; - else heapstartsize = j; + if (i == OPT_MX) + heapmaxsize = j; + else if (i == OPT_MS) + heapstartsize = j; + else + opt_stacksize = j; } break; @@ -603,12 +841,19 @@ int main(int argc, char **argv) compileverbose = true; break; - case OPT_VERBOSEEXCEPTION: - verboseexception = true; + case OPT_VERBOSESPECIFIC: + if (strcmp("class", opt_arg) == 0) + opt_verboseclass = true; + + else if (strcmp("gc", opt_arg) == 0) + opt_verbosegc = true; + + else if (strcmp("jni", opt_arg) == 0) + opt_verbosejni = true; break; - case OPT_VERBOSEGC: - collectverbose = true; + case OPT_VERBOSEEXCEPTION: + opt_verboseexception = true; break; #ifdef TYPECHECK_VERBOSE @@ -622,6 +867,15 @@ int main(int argc, char **argv) break; case OPT_VERSION: + version(); + exit(0); + break; + + case OPT_FULLVERSION: + fullversion(); + break; + + case OPT_SHOWVERSION: version(); break; @@ -646,7 +900,7 @@ int main(int argc, char **argv) getloadingtime = true; break; -#if defined(STATISTICS) +#if defined(ENABLE_STATISTICS) case OPT_STAT: opt_stat = true; break; @@ -700,22 +954,28 @@ int main(int argc, char **argv) for (j = 0; j < strlen(opt_arg); j++) { switch (opt_arg[j]) { case 'a': - showdisassemble = true; + opt_showdisassemble = true; compileverbose = true; break; case 'c': showconstantpool = true; break; case 'd': - showddatasegment = true; + opt_showddatasegment = true; + break; + case 'e': + opt_showexceptionstubs = true; break; case 'i': - showintermediate = true; + opt_showintermediate = true; compileverbose = true; break; case 'm': showmethods = true; break; + case 'n': + opt_shownativestub = true; + break; case 'u': showutf = true; break; @@ -734,12 +994,7 @@ int main(int argc, char **argv) switch (opt_arg[j]) { case 'n': /* define in options.h; Used in main.c, jit.c & inline.c */ -#ifdef INAFTERMAIN - useinliningm = true; - useinlining = false; -#else - useinlining = true; -#endif + /* inlining is currently deactivated */ break; case 'v': inlinevirtuals = true; @@ -776,15 +1031,58 @@ int main(int argc, char **argv) break; #endif -#ifdef LSRA +#if defined(ENABLE_LSRA) case OPT_LSRA: -#if defined(__I386__) || defined(__ALPHA__) || defined (__X86_64__) || defined(__POWERPC__) opt_lsra = true; + break; +#endif + + case OPT_HELP: + usage(); + break; + + case OPT_X: + Xusage(); + break; + + case OPT_JIT: +#if defined(ENABLE_JIT) + opt_jit = true; #else - printf("LSRA not available for this architecture\n"); - opt_lsra = false; + printf("-Xjit option not enabled.\n"); + exit(1); #endif break; + + case OPT_INTRP: +#if defined(ENABLE_INTRP) + opt_intrp = true; +#else + printf("-Xint option not enabled.\n"); + exit(1); +#endif + break; + +#if defined(ENABLE_INTRP) + case OPT_STATIC_SUPERS: + opt_static_supers = atoi(opt_arg); + break; + + case OPT_NO_DYNAMIC: + opt_no_dynamic = true; + break; + + case OPT_NO_REPLICATION: + opt_no_replication = true; + break; + + case OPT_NO_QUICKSUPER: + opt_no_quicksuper = true; + break; + + case OPT_TRACE: + vm_debug = true; + break; #endif default: @@ -800,16 +1098,22 @@ int main(int argc, char **argv) /* transform dots into slashes in the class name */ mainstring = argv[opt_ind++]; + if (!jar) { /* do not mangle jar filename */ + for (i = strlen(mainstring) - 1; i >= 0; i--) { if (mainstring[i] == '.') mainstring[i] = '/'; } } else { /* put jarfile in classpath */ + cp = classpath; - classpath = MNEW(char, strlen(mainstring) + 1 + strlen(classpath) + 1); + + classpath = MNEW(char, strlen(mainstring) + strlen(":") + + strlen(classpath) + strlen("0")); + strcpy(classpath, mainstring); strcat(classpath, ":"); strcat(classpath, cp); @@ -841,36 +1145,98 @@ int main(int argc, char **argv) JNI_CreateJavaVM(&jvm, &env, &vm_args); +#if defined(ENABLE_JVMTI) + set_jvmti_phase(JVMTI_PHASE_START); +#endif /* initialize the garbage collector */ gc_init(heapmaxsize, heapstartsize); - tables_init(); +#if defined(ENABLE_INTRP) + /* allocate main thread stack */ - /* initialize the loader with bootclasspath */ - - suck_init(bootclasspath); + if (opt_intrp) { + intrp_main_stack = (u1 *) alloca(opt_stacksize); + MSET(intrp_main_stack, 0, u1, opt_stacksize); + } +#endif cacao_initializing = true; #if defined(USE_THREADS) #if defined(NATIVE_THREADS) - initThreadsEarly(); + threads_preinit(); #endif initLocks(); #endif + /* initialize the string hashtable stuff: lock (must be done + _after_ threads_preinit) */ + + if (!string_init()) + throw_main_exception_exit(); + + /* initialize the utf8 hashtable stuff: lock, often used utf8 + strings (must be done _after_ threads_preinit) */ + + if (!utf8_init()) + throw_main_exception_exit(); + + /* initialize the classcache hashtable stuff: lock, hashtable + (must be done _after_ threads_preinit) */ + + if (!classcache_init()) + throw_main_exception_exit(); + + /* initialize the loader with bootclasspath (must be done _after_ + thread_preinit) */ + + if (!suck_init()) + throw_main_exception_exit(); + + suck_add_from_property("java.endorsed.dirs"); + suck_add(bootclasspath); + + /* initialize the memory subsystem (must be done _after_ + threads_preinit) */ + + if (!memory_init()) + throw_main_exception_exit(); + + /* initialize the finalizer stuff: lock, linked list (must be done + _after_ threads_preinit) */ + + if (!finalizer_init()) + throw_main_exception_exit(); + /* install architecture dependent signal handler used for exceptions */ - init_exceptions(); - /* initializes jit compiler and codegen stuff */ + signal_init(); + + /* initialize the codegen subsystems */ + + codegen_init(); + + /* initializes jit compiler */ + jit_init(); - /* initialize some cacao subsystems */ + /* machine dependent initialization */ + +#if defined(ENABLE_JIT) +# if defined(ENABLE_INTRP) + if (opt_intrp) + intrp_md_init(); + else +# endif + md_init(); +#else + intrp_md_init(); +#endif - utf8_init(); - class_init_foo(); + /* initialize the loader subsystems (must be done _after_ + classcache_init) */ if (!loader_init((u1 *) &dummy)) throw_main_exception_exit(); @@ -884,27 +1250,40 @@ int main(int argc, char **argv) if (!exceptions_init()) throw_main_exception_exit(); + if (!builtin_init()) + throw_main_exception_exit(); + #if defined(USE_THREADS) - initThreads((u1 *) &dummy); + if (!threads_init((u1 *) &dummy)) + throw_main_exception_exit(); #endif - *threadrootmethod = NULL; + /* That's important, otherwise we get into trouble, if the Runtime + static initializer is called before (circular dependency. This + is with classpath 0.09. Another important thing is, that this + has to happen after initThreads!!! */ + + if (!initialize_class(class_java_lang_System)) + throw_main_exception_exit(); - /*That's important, otherwise we get into trouble, if the Runtime static - initializer is called before (circular dependency. This is with - classpath 0.09. Another important thing is, that this has to happen - after initThreads!!! */ + /* JNI init creates a Java object (this means running Java code) */ - if (!class_init(class_java_lang_System)) + if (!jni_init()) throw_main_exception_exit(); +#if defined(USE_THREADS) + /* finally, start the finalizer thread */ + + if (!finalizer_start_thread()) + throw_main_exception_exit(); +#endif + cacao_initializing = false; /* start worker routines **************************************************/ if (startit) { - classinfo *cl; /* java/lang/ClassLoader */ classinfo *mainclass; /* java/lang/Class */ methodinfo *m; java_objectarray *a; @@ -916,35 +1295,13 @@ int main(int argc, char **argv) if (jar) { /* open jar file with java.util.jar.JarFile */ - mainstring = getmainclassnamefromjar((JNIEnv *) &env, mainstring); + mainstring = getmainclassnamefromjar(mainstring); } - /* get system classloader */ - - m = class_resolveclassmethod(class_java_lang_ClassLoader, - utf_new_char("getSystemClassLoader"), - utf_new_char("()Ljava/lang/ClassLoader;"), - class_java_lang_Object, - false); - - cl = (classinfo *) asm_calljavafunction(m, NULL, NULL, NULL, NULL); - - /* get `loadClass' method */ - - m = class_resolveclassmethod(cl->header.vftbl->class, - utf_loadClass, - utf_java_lang_String__java_lang_Class, - class_java_lang_Object, - false); - /* load the main class */ - mainclass = - (classinfo *) asm_calljavafunction(m, - cl, - javastring_new_char(mainstring), - NULL, - NULL); + if (!(mainclass = load_class_from_sysloader(utf_new_char(mainstring)))) + throw_main_exception_exit(); /* error loading class, clear exceptionptr for new exception */ @@ -957,6 +1314,9 @@ int main(int argc, char **argv) throw_main_exception_exit(); } + if (!link_class(mainclass)) + throw_main_exception_exit(); + /* find the `main' method of the main class */ m = class_resolveclassmethod(mainclass, @@ -965,9 +1325,13 @@ int main(int argc, char **argv) class_java_lang_Object, false); + if (*exceptionptr) { + throw_main_exception_exit(); + } + /* there is no main method or it isn't static */ - if (*exceptionptr || !m || !(m->flags & ACC_STATIC)) { + if (!m || !(m->flags & ACC_STATIC)) { *exceptionptr = NULL; *exceptionptr = @@ -990,13 +1354,60 @@ int main(int argc, char **argv) #endif /*class_showmethods(currentThread->group->header.vftbl->class); */ - *threadrootmethod = m; +#if defined(ENABLE_JVMTI) && defined(NATIVE_THREADS) + if(dbg) { + debuggee = fork(); + if (debuggee == (-1)) { + log_text("fork error"); + exit(1); + } else { + if (debuggee == 0) { + /* child: allow helper process to trace us */ + if (TRACEME != 0) exit(0); + + /* give parent/helper debugger process control */ + kill(0, SIGTRAP); /* do we need this at this stage ? */ + + /* continue with normal startup */ + + } else { + + /* parent/helper debugger process */ + wait(&waitval); + remotedbgjvmtienv = new_jvmtienv(); + /* set eventcallbacks */ + if (JVMTI_ERROR_NONE == + remotedbgjvmtienv-> + SetEventCallbacks(remotedbgjvmtienv, + &jvmti_jdwp_EventCallbacks, + sizeof(jvmti_jdwp_EventCallbacks))){ + log_text("unable to setup event callbacks"); + cacao_exit(1); + } + + /* setup listening process (JDWP) */ + setup_debugger_process(transport); + + /* start to be debugged program */ + CONT(debuggee); + + /* exit debugger process - todo: cleanup */ + joinAllThreads(); + cacao_exit(0); + } + } + } + else + debuggee= -1; + +#endif /* here we go... */ - asm_calljavafunction(m, a, NULL, NULL, NULL); + ASM_CALLJAVAFUNCTION(m, a, NULL, NULL, NULL); /* exception occurred? */ + if (*exceptionptr) { throw_main_exception(); status = 1; @@ -1024,33 +1435,65 @@ int main(int argc, char **argv) methodinfo *m; u4 slot; s4 i; + classcache_name_entry *nmen; + classcache_class_entry *clsen; - /* create all classes found in the classpath */ + /* create all classes found in the bootclasspath */ /* XXX currently only works with zip/jar's */ - create_all_classes(); - - /* load and link all classes */ - for (slot = 0; slot < class_hash.size; slot++) { - c = class_hash.ptr[slot]; - - while (c) { - if (!c->loaded) - if (!load_class_bootstrap(c)) - throw_main_exception_exit(); - - if (!c->linked) - if (!link_class(c)) - throw_main_exception_exit(); - - /* compile all class methods */ - for (i = 0; i < c->methodscount; i++) { - m = &(c->methods[i]); - if (m->jcode) { - (void) jit_compile(m); + + loader_load_all_classes(); + + /* link all classes */ + + for (slot = 0; slot < hashtable_classcache.size; slot++) { + nmen = (classcache_name_entry *) hashtable_classcache.ptr[slot]; + + for (; nmen; nmen = nmen->hashlink) { + /* iterate over all class entries */ + + for (clsen = nmen->classes; clsen; clsen = clsen->next) { + c = clsen->classobj; + + if (!c) + continue; + + if (!(c->state & CLASS_LINKED)) { + if (!link_class(c)) { + fprintf(stderr, "Error linking: "); + utf_fprint_classname(stderr, c->name); + fprintf(stderr, "\n"); + + /* print out exception and cause */ + + exceptions_print_exception(*exceptionptr); + + /* goto next class */ + + continue; + } } - } - c = c->hashlink; + /* compile all class methods */ + + for (i = 0; i < c->methodscount; i++) { + m = &(c->methods[i]); + + if (m->jcode) { + if (!jit_compile(m)) { + fprintf(stderr, "Error compiling: "); + utf_fprint_classname(stderr, c->name); + fprintf(stderr, "."); + utf_fprint(stderr, m->name); + utf_fprint(stderr, m->descriptor); + fprintf(stderr, "\n"); + + /* print out exception and cause */ + + exceptions_print_exception(*exceptionptr); + } + } + } + } } } } @@ -1062,9 +1505,8 @@ int main(int argc, char **argv) methodinfo *m; /* create, load and link the main class */ - mainclass = class_new(utf_new_char(mainstring)); - if (!load_class_bootstrap(mainclass)) + if (!(mainclass = load_class_bootstrap(utf_new_char(mainstring)))) throw_main_exception_exit(); if (!link_class(mainclass)) @@ -1117,14 +1559,21 @@ void cacao_exit(s4 status) { methodinfo *m; - /* class should already be loaded, but who knows... */ + assert(class_java_lang_System); + assert(class_java_lang_System->state & CLASS_LOADED); - if (!load_class_bootstrap(class_java_lang_System)) - throw_main_exception_exit(); +#if defined(ENABLE_JVMTI) + set_jvmti_phase(JVMTI_PHASE_DEAD); + agentunload(); +#endif if (!link_class(class_java_lang_System)) throw_main_exception_exit(); + /* signal that we are exiting */ + + cacao_exiting = true; + /* call java.lang.System.exit(I)V */ m = class_resolveclassmethod(class_java_lang_System, @@ -1142,7 +1591,7 @@ void cacao_exit(s4 status) /* not sure if permanant or temp restriction */ if (inlinevirtuals) inlineoutsiders = false; - asm_calljavafunction(m, (void *) (ptrint) status, NULL, NULL, NULL); + ASM_CALLJAVAFUNCTION(m, (void *) (ptrint) status, NULL, NULL, NULL); /* this should never happen */ @@ -1163,6 +1612,11 @@ void cacao_exit(s4 status) void cacao_shutdown(s4 status) { + +#if defined(ENABLE_JVMTI) + agentunload(); +#endif + if (opt_verbose || getcompilingtime || opt_stat) { log_text("CACAO terminated by shutdown"); dolog("Exit status: %d\n", (s4) status); @@ -1172,6 +1626,57 @@ void cacao_shutdown(s4 status) } +/* exit_handler **************************************************************** + + The exit_handler function is called upon program termination. + + ATTENTION: Don't free system resources here! Some threads may still + be running as this is called from VMRuntime.exit(). The OS does the + cleanup for us. + +*******************************************************************************/ + +void exit_handler(void) +{ + /********************* Print debug tables ************************/ + +#if !defined(NDEBUG) + if (showmethods) + class_showmethods(mainclass); + + if (showconstantpool) + class_showconstantpool(mainclass); + + if (showutf) + utf_show(); +#endif + +#if defined(USE_THREADS) && !defined(NATIVE_THREADS) + clear_thread_flags(); /* restores standard file descriptor + flags */ +#endif + + if (opt_verbose || getcompilingtime || opt_stat) { + log_text("CACAO terminated"); + +#if defined(ENABLE_STATISTICS) + if (opt_stat) { + print_stats(); +#ifdef TYPECHECK_STATISTICS + typecheck_print_statistics(get_logfile()); +#endif + } + + mem_usagelog(1); + + if (getcompilingtime) + print_times(); +#endif + } + /* vm_print_profile(stderr);*/ +} + + /* * 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