/* 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.
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
- Calling the class loader
- Running the main method
- $Id: cacao.c 2211 2005-04-04 10:39:36Z christian $
+ $Id: cacao.c 4357 2006-01-22 23:33:38Z twisti $
*/
+#include "config.h"
+
#include <assert.h>
#include <stdlib.h>
#include <string.h>
-#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 <sys/types.h>
+#include <signal.h>
+#include <sys/wait.h>
+#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/classcache.h"
+#include "vm/suck.h"
#include "vm/jit/asmpart.h"
#include "vm/jit/jit.h"
/* 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 ***************************************************/
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;
/* 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
+
+ OPT_VERBOSETC,
+ OPT_NOVERIFY,
+ OPT_LIBERALUTF,
+ OPT_VERBOSEEXCEPTION,
+ OPT_EAGER,
+
+#if defined(ENABLE_LSRA)
+ OPT_LSRA,
+#endif
-#define OPT_VERBOSETC 29
-#define OPT_NOVERIFY 30
-#define OPT_LIBERALUTF 31
-#define OPT_VERBOSEEXCEPTION 32
-#define OPT_EAGER 33
+ OPT_JAR,
+ OPT_BOOTCLASSPATH,
+ OPT_BOOTCLASSPATH_A,
+ OPT_BOOTCLASSPATH_P,
+ OPT_VERSION,
+ OPT_SHOWVERSION,
+ OPT_FULLVERSION,
-#if defined(LSRA)
-# define OPT_LSRA 34
-#endif /* defined(LSRA) */
+ 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
#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 <path> specify a path to look for classes\n");
printf(" -classpath <path> specify a path to look for classes\n");
- printf(" -jar jarfile execute a jar file\n");
printf(" -D<name>=<value> add an entry to the property list\n");
- printf(" -Xmx<size>[kK|mM] specify the size for the heap\n");
- printf(" -Xms<size>[kK|mM] specify the initial size for the heap\n");
- printf(" -mx<size>[kK|mM] specify the size for the heap\n");
- printf(" -ms<size>[kK|mM] specify the initial size for the heap\n");
- printf(" -Xbootclasspath:<path> set search path for bootstrap classes and resources\n");
- printf(" -Xbootclasspath/a:<path> append to end of bootstrap class path\n");
- printf(" -Xbootclasspath/p:<path> 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:<agent-lib-name>=<options> library to load containg JVMTI agent\n");
+ printf(" -agentpath:<path-to-agent>=<options> 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:<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");
+#if defined(ENABLE_JVMTI)
+ printf(" -Xdebug<transport> enable remote debugging\n");
+#endif
/* exit with error code */
/* version *********************************************************************
- Only prints cacao version information and exits.
+ Only prints cacao version information.
*******************************************************************************/
-static void version()
+static void version(void)
{
- printf("cacao "VERSION"\n");
+ 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 fullversion(void)
+{
+ printf("java full version \"cacao-"JAVA_VERSION"\"\n");
+
+ /* exit normally */
+
exit(0);
}
void typecheck_print_statistics(FILE *file);
#endif
+/* setup_debugger_process *****************************************************
+ Helper function to start JDWP threads
-/* getmainclassfromjar ************************************************************
+*******************************************************************************/
+#if defined(ENABLE_JVMTI)
- gets the name of the main class form a jar's manifest file
+static void setup_debugger_process(char* transport) {
+ java_objectheader *o;
+ methodinfo *m;
+ java_lang_String *s;
-**********************************************************************************/
+ /* new gnu.classpath.jdwp.Jdwp() */
+ mainclass =
+ load_class_from_sysloader(utf_new_char("gnu.classpath.jdwp.Jdwp"));
+ if (!mainclass)
+ throw_main_exception_exit();
-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");
+ o = builtin_new(mainclass);
+
+ if (!o)
throw_main_exception_exit();
- }
- mid = (*env)->GetMethodID(NULL, class, "<init>","(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;
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;
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);
-
- 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);
+ cplen = strlen(CACAO_VM_ZIP_PATH) +
+ strlen(":") +
+ strlen(CLASSPATH_GLIBJ_ZIP_PATH) +
+ strlen("0");
- 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, ".");
}
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) {
/* 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;
bootclasspath = MREALLOC(bootclasspath,
char,
cplen,
- cplen + 1 + strlen(opt_arg) + 1);
+ cplen + strlen(":") +
+ strlen(opt_arg) + strlen("0"));
strcat(bootclasspath, ":");
strcat(bootclasspath, opt_arg);
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, ":");
/* 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];
} 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;
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
break;
case OPT_VERSION:
+ version();
+ exit(0);
+ break;
+
+ case OPT_FULLVERSION:
+ fullversion();
+ break;
+
+ case OPT_SHOWVERSION:
version();
break;
getloadingtime = true;
break;
-#if defined(STATISTICS)
+#if defined(ENABLE_STATISTICS)
case OPT_STAT:
opt_stat = true;
break;
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;
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;
break;
#endif
-#ifdef LSRA
+#if defined(ENABLE_LSRA)
case OPT_LSRA:
-/* #if defined(__I386__) || defined(__ALPHA__) || defined (__X86_64__) || defined(__POWERPC__) */
opt_lsra = true;
-/* #else */
-/* printf("LSRA not available for this architecture\n"); */
-/* opt_lsra = false; */
-/* #endif */
+ break;
+#endif
+
+ case OPT_HELP:
+ usage();
+ break;
+
+ case OPT_X:
+ Xusage();
+ break;
+
+ case OPT_JIT:
+#if defined(ENABLE_JIT)
+ opt_jit = true;
+#else
+ 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
/* 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);
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 */
- utf8_init();
+#if defined(ENABLE_JIT)
+# if defined(ENABLE_INTRP)
+ if (opt_intrp)
+ intrp_md_init();
+ else
+# endif
+ md_init();
+#else
+ intrp_md_init();
+#endif
+
+ /* initialize the loader subsystems (must be done _after_
+ classcache_init) */
if (!loader_init((u1 *) &dummy))
throw_main_exception_exit();
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!!! */
+ /* 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();
+ /* JNI init creates a Java object (this means running Java code) */
+
+ 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;
if (jar) {
/* open jar file with java.util.jar.JarFile */
- mainstring = getmainclassnamefromjar((JNIEnv *) &env, mainstring);
+ mainstring = getmainclassnamefromjar(mainstring);
}
/* load the main class */
- if (!load_class_from_sysloader(utf_new_char(mainstring),&mainclass))
+ if (!(mainclass = load_class_from_sysloader(utf_new_char(mainstring))))
throw_main_exception_exit();
/* error loading class, clear exceptionptr for new exception */
throw_main_exception_exit();
}
+ if (!link_class(mainclass))
+ throw_main_exception_exit();
+
/* find the `main' method of the main class */
m = class_resolveclassmethod(mainclass,
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 =
#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;
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();
+
+ loader_load_all_classes();
/* link all classes */
- for (slot = 0; slot < classcache_hash.size; slot++) {
- nmen = (classcache_name_entry *) classcache_hash.ptr[slot];
- for (; nmen; nmen=nmen->hashlink) {
+
+ 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;
- assert(c);
- assert(c->loaded);
- /*utf_fprint_classname(stderr,c->name);fprintf(stderr,"\n");*/
+ 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 */
- if (!c->linked)
- if (!link_class(c))
- throw_main_exception_exit();
+ exceptions_print_exception(*exceptionptr);
+
+ /* goto next class */
+
+ continue;
+ }
+ }
/* compile all class methods */
+
for (i = 0; i < c->methodscount; i++) {
m = &(c->methods[i]);
+
if (m->jcode) {
- /*fprintf(stderr," compiling:");utf_fprint(stderr,m->name);fprintf(stderr,"\n");*/
- (void) jit_compile(m);
+ 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);
+ }
}
}
}
methodinfo *m;
/* create, load and link the main class */
- if (!load_class_bootstrap(utf_new_char(mainstring), &mainclass))
+
+ if (!(mainclass = load_class_bootstrap(utf_new_char(mainstring))))
throw_main_exception_exit();
if (!link_class(mainclass))
{
methodinfo *m;
-
assert(class_java_lang_System);
- assert(class_java_lang_System->loaded);
+ assert(class_java_lang_System->state & CLASS_LOADED);
+
+#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,
/* 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 */
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);
}
+/* 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