#include "config.h"
#include <assert.h>
+#include <errno.h>
#include <stdlib.h>
+#if defined(WITH_JRE_LAYOUT)
+# include <libgen.h>
+# include <unistd.h>
+#endif
+
#include "vm/types.h"
#include "mm/boehm.h"
#include "vm/vm.h"
#include "vm/jit/jit.h"
#include "vm/jit/asmpart.h"
+
+#include "vm/jit/recompile.h"
+
#include "vm/jit/profile/profile.h"
#include "vm/rt-timing.h"
#include "native/jvmti/cacaodbg.h"
#endif
+
/* Invocation API variables ***************************************************/
_Jv_JavaVM *_Jv_jvm; /* denotes a Java VM */
bool vm_initializing = false;
bool vm_exiting = false;
-#if defined(ENABLE_INTRP)
-u1 *intrp_main_stack = NULL;
-#endif
+char *cacao_prefix = NULL;
+char *cacao_libjvm = NULL;
+char *classpath_libdir = NULL;
-char *mainstring = NULL;
+char *mainstring = NULL;
classinfo *mainclass = NULL;
char *specificmethodname = NULL;
bool startit = true;
+#if defined(ENABLE_INTRP)
+u1 *intrp_main_stack = NULL;
+#endif
+
/* define heap sizes **********************************************************/
/* define command line options ************************************************/
enum {
+ OPT_FOO,
+
/* Java options */
OPT_JAR,
OPT_HELP,
OPT_X,
+ OPT_ESA,
+ OPT_DSA,
+
/* Java non-standard options */
OPT_JIT,
OPT_BOOTCLASSPATH_A,
OPT_BOOTCLASSPATH_P,
+ OPT_GLIBJ,
+
OPT_PROF,
OPT_PROF_OPTION,
OPT_LOG,
OPT_CHECK,
OPT_LOAD,
- OPT_METHOD,
- OPT_SIGNATURE,
OPT_SHOW,
+ OPT_DEBUGCOLOR,
+
+#if !defined(NDEBUG)
OPT_ALL,
+ OPT_METHOD,
+ OPT_SIGNATURE,
+#endif
#if defined(ENABLE_VERIFIER)
OPT_NOVERIFY,
OPT_IFCONV,
#endif
-#if defined(ENABLE_LSRA)
+#if defined(ENABLE_LSRA) || defined(ENABLE_SSA)
OPT_LSRA,
#endif
opt_struct opts[] = {
+ { "foo", false, OPT_FOO },
+
/* Java options */
{ "jar", false, OPT_JAR },
{ "d64", false, OPT_D64 },
{ "client", false, OPT_IGNORE },
{ "server", false, OPT_IGNORE },
+ { "jvm", false, OPT_IGNORE },
{ "hotspot", false, OPT_IGNORE },
{ "classpath", true, OPT_CLASSPATH },
{ "?", false, OPT_HELP },
{ "X", false, OPT_X },
+ { "esa", false, OPT_ESA },
+ { "enablesystemassertions", false, OPT_ESA },
+ { "dsa", false, OPT_DSA },
+ { "disablesystemassertions", false, OPT_DSA },
+
{ "noasyncgc", false, OPT_IGNORE },
#if defined(ENABLE_VERIFIER)
{ "noverify", false, OPT_NOVERIFY },
{ "c", true, OPT_CHECK },
{ "l", false, OPT_LOAD },
{ "eager", false, OPT_EAGER },
- { "sig", true, OPT_SIGNATURE },
+
+#if !defined(NDEBUG)
{ "all", false, OPT_ALL },
+ { "sig", true, OPT_SIGNATURE },
+#endif
+
#if defined(ENABLE_LOOP)
{ "oloop", false, OPT_OLOOP },
#endif
#if defined(ENABLE_IFCONV)
{ "ifconv", false, OPT_IFCONV },
#endif
-#if defined(ENABLE_LSRA)
+#if defined(ENABLE_LSRA) || defined(ENABLE_SSA)
{ "lsra", false, OPT_LSRA },
#endif
{ "Xbootclasspath:", true, OPT_BOOTCLASSPATH },
{ "Xbootclasspath/a:", true, OPT_BOOTCLASSPATH_A },
{ "Xbootclasspath/p:", true, OPT_BOOTCLASSPATH_P },
+ { "Xglibj:", true, OPT_GLIBJ },
+
#ifdef ENABLE_JVMTI
{ "Xdebug", false, OPT_DEBUG },
{ "Xnoagent", false, OPT_NOAGENT },
{ "Xrunjdwp", true, OPT_XRUNJDWP },
#endif
+
{ "Xms", true, OPT_MS },
{ "ms", true, OPT_MS },
{ "Xmx", true, OPT_MX },
#if defined(ENABLE_INLINING)
{ "i", true, OPT_INLINING },
#endif
+
+#if !defined(NDEBUG)
{ "m", true, OPT_METHOD },
+#endif
+
{ "s", true, OPT_SHOW },
+ { "debug-color", false, OPT_DEBUGCOLOR },
{ NULL, false, 0 }
};
puts(" -d64 use 64-bit data model if available");
puts(" -client compatibility (currently ignored)");
puts(" -server compatibility (currently ignored)");
+ puts(" -jvm compatibility (currently ignored)");
puts(" -hotspot compatibility (currently ignored)\n");
puts(" -cp <path> specify a path to look for classes");
puts(" -fullversion print jpackage-compatible product version and exit");
puts(" -showversion print product version and continue");
puts(" -help, -? print this help message");
- puts(" -X print help on non-standard Java options\n");
+ puts(" -X print help on non-standard Java options");
+ puts(" -esa | -enablesystemassertions");
+ puts(" enable system assertions");
+ puts(" -dsa | -disablesystemassertions");
+ puts(" disable system assertions");
+ puts("");
#ifdef ENABLE_JVMTI
puts(" -agentlib:<agent-lib-name>=<options> library to load containg JVMTI agent");
+ puts (" for jdwp help use: -agentlib:jdwp=help");
puts(" -agentpath:<path-to-agent>=<options> path to library containg JVMTI agent");
#endif
- puts("CACAO options:\n");
+ puts("CACAO options:");
puts(" -v write state-information");
- puts(" -verbose[:call|exception]enable specific verbose output");
+ puts(" -verbose[:call|exception|jit]");
+ puts(" enable specific verbose output");
+ puts(" -debug-color colored output for ANSI terms");
#ifdef TYPECHECK_VERBOSE
puts(" -verbosetc write debug messages while typechecking");
#endif
#endif
puts(" -l don't start the class after loading");
puts(" -eager perform eager class loading and linking");
+#if !defined(NDEBUG)
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");
+#endif
+
+ puts(" -s(how)... show...");
+ puts(" c(onstants) the constant pool");
+ puts(" m(ethods) class fields and methods");
+ puts(" u(tf) the utf - hash");
+ puts(" i(ntermediate) intermediate representation");
+#if defined(ENABLE_DISASSEMBLER)
+ puts(" a(ssembler) disassembled listing");
+ puts(" e(xceptionstubs) disassembled exception stubs (only with -sa)");
+ puts(" n(ative) disassembled native stubs");
+#endif
+ puts(" d(atasegment) data segment listing");
#if defined(ENABLE_INLINING)
puts(" -i n(line) activate inlining");
puts(" v(irtual) inline virtual methods (uses/turns rt option on)");
#if defined(ENABLE_LSRA)
puts(" -lsra use linear scan register allocation");
#endif
+#if defined(ENABLE_SSA)
+ puts(" -lsra use linear scan register allocation (with SSA)");
+#endif
/* exit with error code */
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(" -Xglibj:<zip/jar files and directories separated by :>");
+ puts(" value is used as Java core library, but the");
+ puts(" hardcoded VM interface classes are prepended");
printf(" -Xms<size> set the initial size of the heap (default: %dMB)\n", HEAP_STARTSIZE / 1024 / 1024);
printf(" -Xmx<size> set the maximum size of the heap (default: %dMB)\n", HEAP_MAXSIZE / 1024 / 1024);
printf(" -Xss<size> set the thread stack size (default: %dkB)\n", STACK_SIZE / 1024);
#if defined(ENABLE_JVMTI)
/* -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(" -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");
+ puts(" enable remote debugging\n");
#endif
/* exit with error code */
*******************************************************************************/
-static void version(void)
+static void version(bool opt_exit)
{
puts("java version \""JAVA_VERSION"\"");
puts("CACAO version "VERSION"");
puts(" CFLAGS : "VERSION_CFLAGS"\n");
puts("Default variables:\n");
- printf(" maximum heap size : %d\n", HEAP_MAXSIZE);
- printf(" initial heap size : %d\n", HEAP_STARTSIZE);
- printf(" stack size : %d\n", STACK_SIZE);
- puts(" java.boot.class.path: "CACAO_VM_ZIP_PATH":"CLASSPATH_GLIBJ_ZIP_PATH"");
- puts(" java.library.path : "CLASSPATH_LIBRARY_PATH"\n");
+ printf(" maximum heap size : %d\n", HEAP_MAXSIZE);
+ printf(" initial heap size : %d\n", HEAP_STARTSIZE);
+ printf(" stack size : %d\n", STACK_SIZE);
+ puts(" java.boot.class.path : "CACAO_VM_ZIP":"CLASSPATH_GLIBJ_ZIP"");
+ puts(" gnu.classpath.boot.library.path: "CLASSPATH_LIBDIR"/classpath\n");
puts("Runtime variables:\n");
- printf(" maximum heap size : %d\n", opt_heapmaxsize);
- printf(" initial heap size : %d\n", opt_heapstartsize);
- printf(" stack size : %d\n", opt_stacksize);
- printf(" java.boot.class.path: %s\n", bootclasspath);
+ printf(" maximum heap size : %d\n", opt_heapmaxsize);
+ printf(" initial heap size : %d\n", opt_heapstartsize);
+ printf(" stack size : %d\n", opt_stacksize);
+ printf(" java.boot.class.path : %s\n", bootclasspath);
+ printf(" gnu.classpath.boot.library.path: %s\n", classpath_libdir);
+
+ /* exit normally, if requested */
+
+ if (opt_exit)
+ exit(0);
}
}
+/* forward declarations *******************************************************/
+
+static char *vm_get_mainclass_from_jar(char *mainstring);
+#if !defined(NDEBUG)
+static void vm_compile_all(void);
+static void vm_compile_method(void);
+#endif
+
+
/* vm_create *******************************************************************
Creates a JVM. Called by JNI_CreateJavaVM.
bool vm_create(JavaVMInitArgs *vm_args)
{
char *cp;
- s4 cplen;
+ s4 len;
s4 opt;
s4 i, j, k;
-
+ bool opt_version;
+ bool opt_exit;
#if defined(ENABLE_JVMTI)
lt_dlhandle handle;
- char* libname;
- bool agentbypath = false;;
+ char *libname, *agentarg;
+ bool jdwp,agentbypath;
+ jdwp = agentbypath = false;
#endif
-
-
/* check the JNI version requested */
if (vms > 0)
return false;
+ if (atexit(vm_exit_handler))
+ vm_abort("atexit failed: %s\n", strerror(errno));
+
+ if (opt_verbose)
+ log_text("CACAO started -------------------------------------------------------");
+
+ /* set the VM starttime */
+
+ _Jv_jvm->starttime = builtin_currenttimemillis();
/* get stuff from the environment *****************************************/
nogc_init(HEAP_MAXSIZE, HEAP_STARTSIZE);
#endif
+#if defined(WITH_JRE_LAYOUT)
+ /* SUN also uses a buffer of 4096-bytes (strace is your friend). */
+
+ cacao_prefix = MNEW(char, 4096);
+
+ if (readlink("/proc/self/exe", cacao_prefix, 4095) == -1)
+ vm_abort("readlink failed: %s\n", strerror(errno));
+
+ /* get the path of the current executable */
+
+ cacao_prefix = dirname(cacao_prefix);
+
+ if ((strlen(cacao_prefix) + strlen("/..") + strlen("0")) > 4096)
+ vm_abort("libjvm name to long for buffer\n");
+
+ /* concatenate the library name */
+
+ strcat(cacao_prefix, "/..");
+
+ /* now set path to libjvm.so */
+
+ len = strlen(cacao_prefix) + strlen("/lib/libjvm") + strlen("0");
+
+ cacao_libjvm = MNEW(char, len);
+ strcpy(cacao_libjvm, cacao_prefix);
+ strcat(cacao_libjvm, "/lib/libjvm");
+
+ /* and finally set the path to GNU Classpath libraries */
+
+ len = strlen(cacao_prefix) + strlen("/lib/classpath") + strlen("0");
+
+ classpath_libdir = MNEW(char, len);
+ strcpy(classpath_libdir, cacao_prefix);
+ strcat(classpath_libdir, "/lib/classpath");
+#else
+ cacao_prefix = CACAO_PREFIX;
+ cacao_libjvm = CACAO_LIBDIR"/libjvm";
+ classpath_libdir = CLASSPATH_LIBDIR"/classpath";
+#endif
/* set the bootclasspath */
cp = getenv("BOOTCLASSPATH");
- if (cp) {
+ if (cp != NULL) {
bootclasspath = MNEW(char, strlen(cp) + strlen("0"));
strcpy(bootclasspath, cp);
+ }
+ else {
+#if defined(WITH_JRE_LAYOUT)
+ len =
+ strlen(cacao_prefix) +
+ strlen("/share/cacao/vm.zip") +
+ strlen(":") +
+ strlen(cacao_prefix) +
+ strlen("/share/classpath/glibj.zip") +
+ strlen("0");
- } else {
- cplen = strlen(CACAO_VM_ZIP_PATH) +
+ bootclasspath = MNEW(char, len);
+ strcat(bootclasspath, cacao_prefix);
+ strcat(bootclasspath, "/share/cacao/vm.zip");
+ strcat(bootclasspath, ":");
+ strcat(bootclasspath, cacao_prefix);
+ strcat(bootclasspath, "/share/classpath/glibj.zip");
+#else
+ len = strlen(CACAO_VM_ZIP) +
strlen(":") +
- strlen(CLASSPATH_GLIBJ_ZIP_PATH) +
+ strlen(CLASSPATH_GLIBJ_ZIP) +
strlen("0");
- bootclasspath = MNEW(char, cplen);
- strcat(bootclasspath, CACAO_VM_ZIP_PATH);
+ bootclasspath = MNEW(char, len);
+ strcat(bootclasspath, CACAO_VM_ZIP);
strcat(bootclasspath, ":");
- strcat(bootclasspath, CLASSPATH_GLIBJ_ZIP_PATH);
+ strcat(bootclasspath, CLASSPATH_GLIBJ_ZIP);
+#endif
}
-
/* set the classpath */
cp = getenv("CLASSPATH");
- if (cp) {
+ if (cp != NULL) {
classpath = MNEW(char, strlen(cp) + strlen("0"));
strcat(classpath, cp);
-
- } else {
+ }
+ else {
classpath = MNEW(char, strlen(".") + strlen("0"));
strcpy(classpath, ".");
}
/* interpret the options **************************************************/
-
- checknull = false;
- opt_noieee = false;
+
+ opt_version = false;
+ opt_exit = false;
+
+ checknull = false;
+ opt_noieee = false;
opt_heapmaxsize = HEAP_MAXSIZE;
opt_heapstartsize = HEAP_STARTSIZE;
#if defined(ENABLE_JVMTI)
/* initialize JVMTI related **********************************************/
- jdwp = jvmti = false;
+ jvmti = false;
#endif
/* initialize properties before commandline handling */
properties_add("java.endorsed.dirs", ""CACAO_PREFIX"/jre/lib/endorsed");
-
/* iterate over all passed options */
while ((opt = options_get(opts, vm_args)) != OPT_DONE) {
switch (opt) {
+ case OPT_FOO:
+ opt_foo = true;
+ break;
+
case OPT_IGNORE:
break;
if (opt_arg[j] == '=') {
opt_arg[j] = '\0';
properties_add(opt_arg, opt_arg + j + 1);
- goto didit;
+ goto opt_d_done;
}
}
properties_add(opt_arg, "");
- didit:
+ opt_d_done:
break;
case OPT_BOOTCLASSPATH:
/* Forget default bootclasspath and set the argument as
new boot classpath. */
+
MFREE(bootclasspath, char, strlen(bootclasspath));
bootclasspath = MNEW(char, strlen(opt_arg) + strlen("0"));
case OPT_BOOTCLASSPATH_A:
/* append to end of bootclasspath */
- cplen = strlen(bootclasspath);
+
+ len = strlen(bootclasspath);
bootclasspath = MREALLOC(bootclasspath,
char,
- cplen,
- cplen + strlen(":") +
+ len,
+ len + strlen(":") +
strlen(opt_arg) + strlen("0"));
strcat(bootclasspath, ":");
case OPT_BOOTCLASSPATH_P:
/* prepend in front of bootclasspath */
+
cp = bootclasspath;
- cplen = strlen(cp);
+ len = strlen(cp);
bootclasspath = MNEW(char, strlen(opt_arg) + strlen(":") +
- cplen + strlen("0"));
+ len + strlen("0"));
strcpy(bootclasspath, opt_arg);
strcat(bootclasspath, ":");
strcat(bootclasspath, cp);
- MFREE(cp, char, cplen);
+ MFREE(cp, char, len);
+ break;
+
+ case OPT_GLIBJ:
+ /* use as Java core library, but prepend VM interface classes */
+
+ MFREE(bootclasspath, char, strlen(bootclasspath));
+
+ len = strlen(CACAO_VM_ZIP) +
+ strlen(":") +
+ strlen(opt_arg) +
+ strlen("0");
+
+ bootclasspath = MNEW(char, len);
+
+ strcpy(bootclasspath, CACAO_VM_ZIP);
+ strcat(bootclasspath, ":");
+ strcat(bootclasspath, opt_arg);
break;
#if defined(ENABLE_JVMTI)
case OPT_DEBUG:
- jdwp=true;
+ /* this option exists only for compatibility reasons */
break;
+
case OPT_NOAGENT:
/* I don't know yet what Xnoagent should do. This is only for
compatiblity with eclipse - motse */
break;
+
case OPT_XRUNJDWP:
- 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++;
- }
-
+ agentbypath = true;
+ jvmti = true;
+ jdwp = true;
+
+ len =
+ strlen(CACAO_LIBDIR) +
+ strlen("/libjdwp.so=") +
+ strlen(opt_arg) +
+ strlen("0");
+
+ agentarg = MNEW(char, len);
+
+ strcpy(agentarg, CACAO_LIBDIR);
+ strcat(agentarg, "/libjdwp.so=");
+ strcat(agentarg, &opt_arg[1]);
break;
case OPT_AGENTPATH:
agentbypath = true;
+
case OPT_AGENTLIB:
- jvmti=true;
+ jvmti = true;
agentarg = opt_arg;
break;
#endif
else if (strcmp("exception", opt_arg) == 0)
opt_verboseexception = true;
break;
+ case OPT_DEBUGCOLOR:
+ opt_debugcolor = true;
+ break;
#if defined(ENABLE_VERIFIER) && defined(TYPECHECK_VERBOSE)
case OPT_VERBOSETC:
#endif
case OPT_VERSION:
- version();
- exit(0);
+ opt_version = true;
+ opt_exit = true;
break;
case OPT_FULLVERSION:
break;
case OPT_SHOWVERSION:
- version();
+ opt_version = true;
break;
case OPT_NOIEEE:
opt_eager = true;
break;
+#if !defined(NDEBUG)
+ case OPT_ALL:
+ compileall = true;
+ opt_run = false;
+ makeinitializations = false;
+ break;
+
case OPT_METHOD:
opt_run = false;
opt_method = opt_arg;
makeinitializations = false;
break;
-
+
case OPT_SIGNATURE:
opt_signature = opt_arg;
break;
-
- case OPT_ALL:
- compileall = true;
- opt_run = false;
- makeinitializations = false;
- break;
-
+#endif
+
case OPT_SHOW: /* Display options */
for (j = 0; j < strlen(opt_arg); j++) {
switch (opt_arg[j]) {
- case 'a':
- opt_showdisassemble = true;
- compileverbose = true;
- break;
case 'c':
showconstantpool = true;
break;
- case 'd':
- opt_showddatasegment = true;
+
+ case 'u':
+ showutf = true;
break;
- case 'e':
- opt_showexceptionstubs = true;
+
+ case 'm':
+ showmethods = true;
break;
+
case 'i':
opt_showintermediate = true;
compileverbose = true;
break;
- case 'm':
- showmethods = true;
+
+#if defined(ENABLE_DISASSEMBLER)
+ case 'a':
+ opt_showdisassemble = true;
+ compileverbose = true;
+ break;
+
+ case 'e':
+ opt_showexceptionstubs = true;
break;
+
case 'n':
opt_shownativestub = true;
break;
- case 'u':
- showutf = true;
+#endif
+
+ case 'd':
+ opt_showddatasegment = true;
break;
+
default:
usage();
}
break;
#endif
-#if defined(ENABLE_LSRA)
+#if defined(ENABLE_LSRA) || defined(ENABLE_SSA)
case OPT_LSRA:
opt_lsra = true;
break;
Xusage();
break;
+ case OPT_ESA:
+ _Jv_jvm->Java_java_lang_VMClassLoader_defaultAssertionStatus = true;
+ break;
+
+ case OPT_DSA:
+ _Jv_jvm->Java_java_lang_VMClassLoader_defaultAssertionStatus = false;
+ break;
+
case OPT_PROF_OPTION:
/* use <= to get the last \0 too */
case OPT_INTRP:
#if defined(ENABLE_INTRP)
opt_intrp = true;
+#if defined(ENABLE_VERIFIER)
+ /* XXX currently the verifier does not work with the interpreter */
+ opt_verify = false;
+#endif
#else
printf("-Xint option not enabled.\n");
exit(1);
}
+ /* Now we have all options handled and we can print the version
+ information. */
+
+ if (opt_version)
+ version(opt_exit);
+
+
/* get the main class *****************************************************/
if (opt_index < vm_args->nOptions) {
classpath = MNEW(char, strlen(mainstring) + strlen("0"));
strcpy(classpath, mainstring);
-
- } else {
+ }
+ else {
/* replace .'s with /'s in classname */
for (i = strlen(mainstring) - 1; i >= 0; i--)
if (jvmti) {
jvmti_set_phase(JVMTI_PHASE_ONLOAD);
jvmti_agentload(agentarg, agentbypath, &handle, &libname);
+
+ if (jdwp)
+ MFREE(agentarg, char, strlen(agentarg));
+
+ jvmti_set_phase(JVMTI_PHASE_PRIMORDIAL);
}
- jvmti_set_phase(JVMTI_PHASE_PRIMORDIAL);
+
#endif
#endif
#if defined(ENABLE_THREADS)
+ /* initialize recompilation */
+
+ if (!recompile_init())
+ throw_main_exception_exit();
+
/* finally, start the finalizer thread */
if (!finalizer_start_thread())
throw_main_exception_exit();
+ /* start the recompilation thread (must be done before the
+ profiling thread) */
+
+ if (!recompile_start_thread())
+ throw_main_exception_exit();
+
+# if defined(ENABLE_PROFILING)
/* start the profile sampling thread */
-/* if (!profile_start_thread()) */
-/* throw_main_exception_exit(); */
+ if (opt_prof)
+ if (!profile_start_thread())
+ throw_main_exception_exit();
+# endif
#endif
#if defined(ENABLE_JVMTI)
}
+/* vm_run **********************************************************************
+
+ Runs the main-method of the passed class.
+
+*******************************************************************************/
+
+void vm_run(JavaVM *vm, JavaVMInitArgs *vm_args)
+{
+ utf *mainutf;
+ classinfo *mainclass;
+ methodinfo *m;
+ java_objectarray *oa;
+ s4 oalength;
+ utf *u;
+ java_lang_String *s;
+ s4 status;
+ s4 i;
+
+#if !defined(NDEBUG)
+ if (compileall) {
+ vm_compile_all();
+ return;
+ }
+
+ if (opt_method != NULL) {
+ vm_compile_method();
+ return;
+ }
+#endif /* !defined(NDEBUG) */
+
+ /* should we run the main-method? */
+
+ if (mainstring == NULL)
+ usage();
+
+ /* set return value to OK */
+
+ status = 0;
+
+ if (opt_jar == true)
+ /* open jar file with java.util.jar.JarFile */
+ mainstring = vm_get_mainclass_from_jar(mainstring);
+
+ /* load the main class */
+
+ mainutf = utf_new_char(mainstring);
+
+ if (!(mainclass = load_class_from_sysloader(mainutf)))
+ throw_main_exception_exit();
+
+ /* error loading class, clear exceptionptr for new exception */
+
+ if (*exceptionptr || !mainclass) {
+ /* *exceptionptr = NULL; */
+
+ /* *exceptionptr = */
+ /* new_exception_message(string_java_lang_NoClassDefFoundError, */
+ /* mainstring); */
+ throw_main_exception_exit();
+ }
+
+ if (!link_class(mainclass))
+ throw_main_exception_exit();
+
+ /* find the `main' method of the main class */
+
+ m = class_resolveclassmethod(mainclass,
+ utf_new_char("main"),
+ utf_new_char("([Ljava/lang/String;)V"),
+ class_java_lang_Object,
+ false);
+
+ if (*exceptionptr) {
+ throw_main_exception_exit();
+ }
+
+ /* there is no main method or it isn't static */
+
+ if ((m == NULL) || !(m->flags & ACC_STATIC)) {
+ *exceptionptr = NULL;
+
+ *exceptionptr =
+ new_exception_message(string_java_lang_NoSuchMethodError, "main");
+ throw_main_exception_exit();
+ }
+
+ /* build argument array */
+
+ oalength = vm_args->nOptions - opt_index;
+
+ oa = builtin_anewarray(oalength, class_java_lang_String);
+
+ for (i = 0; i < oalength; i++) {
+ u = utf_new_char(vm_args->options[opt_index + i].optionString);
+ s = javastring_new(u);
+
+ oa->data[i] = (java_objectheader *) s;
+ }
+
+#ifdef TYPEINFO_DEBUG_TEST
+ /* test the typeinfo system */
+ typeinfo_test();
+#endif
+ /*class_showmethods(currentThread->group->header.vftbl->class); */
+
+#if defined(ENABLE_JVMTI)
+ jvmti_set_phase(JVMTI_PHASE_LIVE);
+#endif
+
+ /* increase total started thread count */
+
+ _Jv_jvm->total_started_thread_count++;
+
+ /* start the main thread */
+
+ (void) vm_call_method(m, NULL, oa);
+
+ /* exception occurred? */
+
+ if (*exceptionptr) {
+ throw_main_exception();
+ status = 1;
+ }
+
+ /* unload the JavaVM */
+
+ vm_destroy(vm);
+
+ /* and exit */
+
+ vm_exit(status);
+}
+
+
/* vm_destroy ******************************************************************
Unloads a Java VM and reclaims its resources.
{
log_text("CACAO terminated by shutdown");
dolog("Exit status: %d\n", (s4) status);
+
}
+#if defined(ENABLE_JVMTI)
+ /* terminate cacaodbgserver */
+ if (dbgcom!=NULL) {
+ pthread_mutex_lock(&dbgcomlock);
+ dbgcom->running=1;
+ pthread_mutex_unlock(&dbgcomlock);
+ jvmti_cacaodbgserver_quit();
+ }
+#endif
+
exit(status);
}
}
+/* vm_get_mainclass_from_jar ***************************************************
+
+ Gets the name of the main class from a JAR's manifest file.
+
+*******************************************************************************/
+
+static char *vm_get_mainclass_from_jar(char *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 == NULL)
+ throw_main_exception_exit();
+
+ /* create JarFile object */
+
+ o = builtin_new(c);
+
+ if (o == NULL)
+ throw_main_exception_exit();
+
+
+ m = class_resolveclassmethod(c,
+ utf_init,
+ utf_java_lang_String__void,
+ class_java_lang_Object,
+ true);
+
+ if (m == NULL)
+ throw_main_exception_exit();
+
+ s = javastring_new_from_ascii(mainstring);
+
+ (void) vm_call_method(m, o, s);
+
+ if (*exceptionptr)
+ throw_main_exception_exit();
+
+ /* get manifest object */
+
+ m = class_resolveclassmethod(c,
+ utf_new_char("getManifest"),
+ utf_new_char("()Ljava/util/jar/Manifest;"),
+ class_java_lang_Object,
+ true);
+
+ if (m == NULL)
+ throw_main_exception_exit();
+
+ o = vm_call_method(m, o);
+
+ if (o == NULL) {
+ fprintf(stderr, "Could not get manifest from %s (invalid or corrupt jarfile?)\n", mainstring);
+ vm_exit(1);
+ }
+
+
+ /* get Main Attributes */
+
+ m = class_resolveclassmethod(o->vftbl->class,
+ utf_new_char("getMainAttributes"),
+ utf_new_char("()Ljava/util/jar/Attributes;"),
+ class_java_lang_Object,
+ true);
+
+ if (m == NULL)
+ throw_main_exception_exit();
+
+ o = vm_call_method(m, o);
+
+ if (o == NULL) {
+ fprintf(stderr, "Could not get main attributes from %s (invalid or corrupt jarfile?)\n", mainstring);
+ vm_exit(1);
+ }
+
+
+ /* get property Main-Class */
+
+ m = class_resolveclassmethod(o->vftbl->class,
+ utf_new_char("getValue"),
+ utf_new_char("(Ljava/lang/String;)Ljava/lang/String;"),
+ class_java_lang_Object,
+ true);
+
+ if (m == NULL)
+ throw_main_exception_exit();
+
+ s = javastring_new_from_ascii("Main-Class");
+
+ o = vm_call_method(m, o, s);
+
+ if (o == NULL)
+ throw_main_exception_exit();
+
+ return javastring_tochar(o);
+}
+
+
+/* vm_compile_all **************************************************************
+
+ Compile all methods found in the bootclasspath.
+
+*******************************************************************************/
+
+#if !defined(NDEBUG)
+static void vm_compile_all(void)
+{
+ classinfo *c;
+ methodinfo *m;
+ u4 slot;
+ classcache_name_entry *nmen;
+ classcache_class_entry *clsen;
+ s4 i;
+
+ /* create all classes found in the bootclasspath */
+ /* XXX currently only works with zip/jar's */
+
+ 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 == NULL)
+ continue;
+
+ if (!(c->state & CLASS_LINKED)) {
+ if (!link_class(c)) {
+ fprintf(stderr, "Error linking: ");
+ utf_fprint_printable_ascii_classname(stderr, c->name);
+ fprintf(stderr, "\n");
+
+ /* print out exception and cause */
+
+ 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 != NULL) {
+ if (!jit_compile(m)) {
+ fprintf(stderr, "Error compiling: ");
+ utf_fprint_printable_ascii_classname(stderr, c->name);
+ fprintf(stderr, ".");
+ utf_fprint_printable_ascii(stderr, m->name);
+ utf_fprint_printable_ascii(stderr, m->descriptor);
+ fprintf(stderr, "\n");
+
+ /* print out exception and cause */
+
+ exceptions_print_exception(*exceptionptr);
+ }
+ }
+ }
+ }
+ }
+ }
+}
+#endif /* !defined(NDEBUG) */
+
+
+/* vm_compile_method ***********************************************************
+
+ Compile a specific method.
+
+*******************************************************************************/
+
+#if !defined(NDEBUG)
+static void vm_compile_method(void)
+{
+ methodinfo *m;
+
+ /* create, load and link the main class */
+
+ if (!(mainclass = load_class_bootstrap(utf_new_char(mainstring))))
+ throw_main_exception_exit();
+
+ if (!link_class(mainclass))
+ throw_main_exception_exit();
+
+ if (opt_signature != NULL) {
+ m = class_resolveclassmethod(mainclass,
+ utf_new_char(opt_method),
+ utf_new_char(opt_signature),
+ mainclass,
+ false);
+ }
+ else {
+ m = class_resolveclassmethod(mainclass,
+ utf_new_char(opt_method),
+ NULL,
+ mainclass,
+ false);
+ }
+
+ if (m == NULL) {
+ char message[MAXLOGTEXT];
+ sprintf(message, "%s%s", opt_method,
+ opt_signature ? opt_signature : "");
+
+ *exceptionptr =
+ new_exception_message(string_java_lang_NoSuchMethodException,
+ message);
+
+ throw_main_exception_exit();
+ }
+
+ jit_compile(m);
+}
+#endif /* !defined(NDEBUG) */
+
+
/* vm_vmargs_from_valist *******************************************************
XXX