AC_INIT(cacao, 1.1.0pre, cacao@cacaojvm.org)
- AC_CONFIG_SRCDIR(src/cacao/cacao.c)
+ AC_CONFIG_SRCDIR(src/cacao/cacao.cpp)
AC_CANONICAL_HOST
AC_PREREQ(2.59)
AM_INIT_AUTOMAKE([1.9.0 dist-bzip2 tar-ustar])
dnl Set optimization and debugging for all architectures and systems.
if test x"$CFLAGS" = "x"; then
- OPT_CFLAGS="-O0 -g"
+ OPT_CFLAGS="-g -O0"
else
OPT_CFLAGS=$CFLAGS
fi
if test x"$CXXFLAGS" = "x"; then
- OPT_CXXFLAGS="-O0 -g"
+ OPT_CXXFLAGS="-g -O0"
else
OPT_CXXFLAGS=$CXXFLAGS
fi
JAVA_ARCH="alpha"
;;
- arm | armv4 | armv4tl | armv5b | armv5l )
+ arm | armv4 | armv4tl | armv5b | armv5l | armv5tel | armv5tejl )
ARCH_DIR="arm"
ARCH_FLAGS="-D__ARM__"
JAVA_ARCH="arm"
i386 | i486 | i586 | i686 )
ARCH_DIR="i386"
- ARCH_FLAGS="-D__I386__"
+ ARCH_FLAGS="-m32 -D__I386__"
JAVA_ARCH="i386"
;;
powerpc )
ARCH_DIR="powerpc"
- ARCH_FLAGS="-D__POWERPC__"
+ ARCH_FLAGS="-m32 -D__POWERPC__"
JAVA_ARCH="ppc"
;;
powerpc64 )
ARCH_DIR="powerpc64"
- ARCH_FLAGS="-D__POWERPC64__"
+ ARCH_FLAGS="-m64 -D__POWERPC64__"
JAVA_ARCH="ppc64"
;;
AC_PROG_MAKE_SET
AM_PROG_MKDIR_P
+ AM_CONDITIONAL([WITH_GNU_LD], [test x"$with_gnu_ld" = "xyes"])
+
dnl Checks for header files.
AC_HEADER_DIRENT
AC_HEADER_STDC
AC_CHECK_HEADERS([fcntl.h])
AC_CHECK_HEADERS([libgen.h])
AC_CHECK_HEADERS([netdb.h])
+ AC_CHECK_HEADERS([signal.h])
AC_CHECK_HEADERS([stdint.h])
AC_CHECK_HEADERS([stdio.h])
AC_CHECK_HEADERS([stdlib.h])
dnl Checks for libraries (NOTE: Should be done before function checks,
dnl as some functions may be in libraries we check for).
+ case "${OS_DIR}" in
+ solaris )
+ AC_CHECK_LIB([socket], [gethostname],, [AC_MSG_ERROR(cannot find libsocket)])
+ ;;
+ esac
+
dnl Checks for library functions.
AC_PROG_GCC_TRADITIONAL
AC_TYPE_SIGNAL
AC_CHECK_FUNCS([fprintf])
AC_CHECK_FUNCS([fread])
AC_CHECK_FUNCS([free])
+AC_CHECK_FUNCS([fseek])
AC_CHECK_FUNCS([fstat])
AC_CHECK_FUNCS([fsync])
AC_CHECK_FUNCS([ftruncate])
AC_CHECK_FUNCS([shutdown])
AC_CHECK_FUNCS([socket])
AC_CHECK_FUNCS([stat])
+ AC_CHECK_FUNCS([str2sig])
AC_CHECK_FUNCS([strcat])
AC_CHECK_FUNCS([strchr])
AC_CHECK_FUNCS([strcpy])
AC_CHECK_ENABLE_VERIFIER
AC_CHECK_ENABLE_RT_TIMING
AC_CHECK_ENABLE_CYCLE_STATS
+AC_CHECK_ENABLE_JITCACHE
AC_CHECK_ENABLE_JVMTI
AC_CHECK_ENABLE_THREADS
AC_CHECK_ENABLE_IFCONV
AM_CONDITIONAL([ENABLE_SSA], test x"${ENABLE_SSA}" = "xyes")
AM_CONDITIONAL([ENABLE_ESCAPE], test x"${ENABLE_SSA}" = "xyes")
AM_CONDITIONAL([ENABLE_ESCAPE_CHECK], test x"${ENABLE_SSA}" = "xyes")
+ AM_CONDITIONAL([ENABLE_TLH], test x"${ENABLE_SSA}" = "xyes")
if test x"${ENABLE_SSA}" = "xyes"; then
AC_DEFINE([ENABLE_SSA], 1, [enable lsra with ssa])
AC_DEFINE([ENABLE_ESCAPE], 1, [enable escape analysis with ssa])
AC_DEFINE([ENABLE_ESCAPE_CHECK], 1, [enable generating code to validate escape analysis results])
+ AC_DEFINE([ENABLE_TLH], 1, [enable thread local heap])
ENABLE_LSRA="no"
fi
AM_CONDITIONAL([USE_SCHEDULER], [false])
fi
+ AC_CHECK_ENABLE_OPAGENT
AC_CHECK_ENABLE_ZLIB
AC_SUBST(CACAO_VM_ZIP)
- AC_CHECK_WITH_CACAOH
AC_CHECK_WITH_JAVA_RUNTIME_LIBRARY
dnl Now we check for jre-layout so we can skip some checks that are
AC_CHECK_WITH_JAVA_RUNTIME_LIBRARY_PREFIX
AC_CHECK_WITH_JAVA_RUNTIME_LIBRARY_CLASSES
+ AC_CHECK_WITH_BUILD_JAVA_RUNTIME_LIBRARY_CLASSES
if test x"${ENABLE_JRE_LAYOUT}" = "xno"; then
AC_CHECK_WITH_JAVA_RUNTIME_LIBRARY_LIBDIR
[man/Makefile]
[src/Makefile]
[src/cacao/Makefile]
- [src/cacaoh/Makefile]
[src/classes/Makefile]
[src/fdlibm/Makefile]
[src/mm/Makefile]
[src/vm/jit/i386/darwin/Makefile]
[src/vm/jit/i386/freebsd/Makefile]
[src/vm/jit/i386/linux/Makefile]
+ [src/vm/jit/i386/solaris/Makefile]
[src/vm/jit/intrp/Makefile]
[src/vm/jit/inline/Makefile]
[src/vm/jit/ir/Makefile]
[src/vm/jit/x86_64/Makefile]
[src/vm/jit/x86_64/freebsd/Makefile]
[src/vm/jit/x86_64/linux/Makefile]
- [src/vmcore/Makefile]
+ [src/vm/jit/x86_64/solaris/Makefile]
[tests/Makefile]
[tests/regression/Makefile]
[tests/regression/assertion/Makefile]
# undef Bias
#endif
- #include "mm/gc-common.h"
+ #include "mm/gc.hpp"
#include "mm/memory.h"
#include "native/jni.h"
#include "native/llni.h"
#include "threads/lock-common.h"
- #include "threads/thread.h"
+ #include "threads/thread.hpp"
#include "toolbox/logging.h"
#include "toolbox/util.h"
#include "vm/array.h"
#include "vm/builtin.h"
+ #include "vm/class.h"
#include "vm/cycles-stats.h"
- #include "vm/exceptions.h"
+ #include "vm/exceptions.hpp"
#include "vm/global.h"
+ #include "vm/globals.hpp"
#include "vm/initialize.h"
- #include "vm/primitive.h"
- #include "vm/stringlocal.h"
+ #include "vm/linker.h"
+ #include "vm/loader.h"
+ #include "vm/options.h"
+ #include "vm/primitive.hpp"
+ #include "vm/rt-timing.h"
+ #include "vm/string.hpp"
#include "vm/jit/asmpart.h"
- #include "vm/jit/trace.h"
-
- #include "vmcore/class.h"
- #include "vmcore/linker.h"
- #include "vmcore/loader.h"
- #include "vmcore/options.h"
- #include "vmcore/rt-timing.h"
+ #include "vm/jit/trace.hpp"
#if defined(ENABLE_VMLOG)
#include <vmlog_cacao.h>
}
+/* builtintable_get_by_key *****************************************************
+
+ Returns a key for the given builtintable_entry object which is suitable
+ for retrieving the instance again by calling builtintable_get_by_key.
+
+ The key can be regarded fixed between multiple runs of the JVM.
+
+*******************************************************************************/
+
+s4 builtintable_get_key(builtintable_entry *bte)
+{
+ s4 entries;
+/*
+ int i;
+ entries = sizeof(builtintable_internal) / sizeof(builtintable_entry) - 1;
+ for (i = 0; i < entries; i++)
+ if (&builtintable_internal[i] == bte)
+ return i + 1;
+
+ entries = sizeof(builtintable_automatic) / sizeof(builtintable_entry) - 1;
+ for (i = 0; i < entries; i++)
+ if (&builtintable_automatic[i] == bte)
+ return -i;
+
+ entries = sizeof(builtintable_function) / sizeof(builtintable_entry) - 1;
+ for (i = 0; i < entries; i++)
+ if (&builtintable_function[i] == bte)
+ return -1000 - i;
+*/
+
+ entries = sizeof(builtintable_internal) / sizeof(builtintable_entry) - 1;
+ if (&builtintable_internal[0] <= bte
+ && &builtintable_internal[entries - 1] >= bte)
+ {
+ return (s4) (bte - &builtintable_internal[0]) + 1;
+ }
+
+ entries = sizeof(builtintable_automatic) / sizeof(builtintable_entry) - 1;
+ if (&builtintable_automatic[0] <= bte
+ && &builtintable_automatic[entries - 1] >= bte)
+ {
+ return -(s4) (bte - &builtintable_automatic[0]);
+ }
+
+ entries = sizeof(builtintable_function) / sizeof(builtintable_entry) - 1;
+ if (&builtintable_function[0] <= bte
+ && &builtintable_function[entries - 1] >= bte)
+ {
+ return -1000 - (s4) (bte - &builtintable_function[0]);
+ }
+
+ /* builtintable_entry is not in our tables. */
+ assert (0);
+
+ return 0;
+}
+
+/* builtintable_get_by_key *****************************************************
+
+ Retrieves an entry in the internal and automatic builtin functions tables
+ using a key that was retrived previously with builtintable_get_key()
+
+*******************************************************************************/
+
+builtintable_entry *builtintable_get_by_key(s4 key)
+{
+ /* If key is positive it is the index into builtintable_internal. If it is
+ * negative it is the index into builtintable_automatic. If it is <= -1000
+ * it is the index into builtintable_function.
+ */
+ return (key > 0)
+ ? &builtintable_internal[key - 1]
+ : (key > -1000 ? &builtintable_automatic[-key] : &builtintable_function[-(1000 + key)]);
+}
+
/* builtintable_get_internal ***************************************************
Finds an entry in the builtintable for internal functions and
return o;
}
+ #if defined(ENABLE_ESCAPE_REASON)
+ java_handle_t *builtin_escape_reason_new(classinfo *c) {
+ print_escape_reasons();
+ return builtin_java_new(c);
+ }
+ #endif
+
+ #if defined(ENABLE_TLH)
+ java_handle_t *builtin_tlh_new(classinfo *c)
+ {
+ java_handle_t *o;
+ # if defined(ENABLE_RT_TIMING)
+ struct timespec time_start, time_end;
+ # endif
+ # if defined(ENABLE_CYCLES_STATS)
+ u8 cycles_start, cycles_end;
+ # endif
+
+ RT_TIMING_GET_TIME(time_start);
+ CYCLES_STATS_GET(cycles_start);
+
+ /* is the class loaded */
+
+ assert(c->state & CLASS_LOADED);
+
+ /* check if we can instantiate this class */
+
+ if (c->flags & ACC_ABSTRACT) {
+ exceptions_throw_instantiationerror(c);
+ return NULL;
+ }
+
+ /* is the class linked */
+
+ if (!(c->state & CLASS_LINKED))
+ if (!link_class(c))
+ return NULL;
+
+ if (!(c->state & CLASS_INITIALIZED)) {
+ # if !defined(NDEBUG)
+ if (initverbose)
+ log_message_class("Initialize class (from builtin_new): ", c);
+ # endif
+
+ if (!initialize_class(c))
+ return NULL;
+ }
+
+ /*
+ o = tlh_alloc(&(THREADOBJECT->tlh), c->instancesize);
+ */
+ o = NULL;
+
+ if (o == NULL) {
+ o = heap_alloc(c->instancesize, c->flags & ACC_CLASS_HAS_POINTERS,
+ c->finalizer, true);
+ }
+
+ if (!o)
+ return NULL;
+
+ # if !defined(ENABLE_GC_CACAO) && defined(ENABLE_HANDLES)
+ /* XXX this is only a dirty hack to make Boehm work with handles */
+
+ o = LLNI_WRAP((java_object_t *) o);
+ # endif
+
+ LLNI_vftbl_direct(o) = c->vftbl;
+
+ # if defined(ENABLE_THREADS)
+ lock_init_object_lock(LLNI_DIRECT(o));
+ # endif
+
+ CYCLES_STATS_GET(cycles_end);
+ RT_TIMING_GET_TIME(time_end);
+
+ /*
+ CYCLES_STATS_COUNT(builtin_new,cycles_end - cycles_start);
+ RT_TIMING_TIME_DIFF(time_start, time_end, RT_TIMING_NEW_OBJECT);
+ */
+
+ return o;
+ }
+ #endif
+
/* builtin_java_new ************************************************************
#ifndef _BUILTIN_H
#define _BUILTIN_H
+ #ifdef __cplusplus
+ extern "C" {
+ #endif
+
/* forward typedefs ***********************************************************/
typedef struct builtintable_entry builtintable_entry;
#include "toolbox/logging.h"
- #include "vmcore/utf8.h"
+ #include "vm/descriptor.h"
+ #include "vm/utf8.h"
/* define infinity for floating point numbers */
bool builtin_init(void);
+s4 builtintable_get_key(builtintable_entry *);
+builtintable_entry *builtintable_get_by_key(s4 key);
builtintable_entry *builtintable_get_internal(functionptr fp);
builtintable_entry *builtintable_get_automatic(s4 opcode);
*
* IMPORTANT:
* For each builtin function which is used in a BUILTIN* opcode there
- * must be an entry in the builtin_desc table in jit/jit.c.
+ * must be an entry in the tables in vm/builtintable.inc.
*
* Below each prototype is either the BUILTIN_ macro definition or a
* comment specifiying that this function is not used in BUILTIN*
/* NOT AN OP */
java_handle_t *builtin_java_new(java_handle_t *c);
#define BUILTIN_new (functionptr) builtin_java_new
+
+ #if defined(ENABLE_TLH)
+ #define BUILTIN_tlh_new (functionptr) builtin_tlh_new
+ java_handle_t *builtin_tlh_new(classinfo *c);
+ #endif
+
+ #if defined(ENABLE_ESCAPE_REASON)
+ #define BUILTIN_escape_reason_new (functionptr)builtin_escape_reason_new
+ java_handle_t *builtin_escape_reason_new(classinfo *c);
+ #endif
+
java_object_t *builtin_fast_new(classinfo *c);
#define BUILTIN_FAST_new (functionptr) builtin_fast_new
void builtin_print_cycles_stats(FILE *file);
#endif
+ #ifdef __cplusplus
+ }
+ #endif
+
#endif /* _BUILTIN_H */
--- /dev/null
+ /* src/vm/class.c - class related functions
+
+ Copyright (C) 1996-2005, 2006, 2007, 2008
+ CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
+
+ This file is part of CACAO.
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 2, or (at
+ your option) any later version.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ 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., 51 Franklin Street, Fifth Floor, Boston, MA
+ 02110-1301, USA.
+
+ */
+
+
+ #include "config.h"
+
+ #include <assert.h>
+ #include <stdio.h>
+ #include <stdlib.h>
+ #include <string.h>
+
+ #include "vm/types.h"
+
+ #include "arch.h"
+
+ #include "mm/memory.h"
+
+ #include "native/llni.h"
+
+ #include "threads/lock-common.h"
+
+ #include "toolbox/logging.h"
+
+ #include "vm/array.h"
+ #include "vm/builtin.h"
+ #include "vm/class.h"
+ #include "vm/classcache.h"
+ #include "vm/exceptions.hpp"
+ #include "vm/global.h"
+ #include "vm/globals.hpp"
+ #include "vm/javaobjects.hpp"
++#include "vm/jit/jitcache.h"
+ #include "vm/linker.h"
+ #include "vm/loader.h"
+ #include "vm/options.h"
+ #include "vm/resolve.h"
+
+ #if defined(ENABLE_STATISTICS)
+ # include "vm/statistics.h"
+ #endif
+
+ #include "vm/suck.h"
+ #include "vm/utf8.h"
+
+ #include "vm/jit/asmpart.h"
+
+
+ /* class_set_packagename *******************************************************
+
+ Derive the package name from the class name and store it in the
+ struct.
+
+ An internal package name consists of the package name plus the
+ trailing '/', e.g. "java/lang/".
+
+ For classes in the unnamed package, the package name is set to
+ NULL.
+
+ *******************************************************************************/
+
+ void class_set_packagename(classinfo *c)
+ {
+ char *p;
+ char *start;
+
+ p = UTF_END(c->name) - 1;
+ start = c->name->text;
+
+ if (c->name->text[0] == '[') {
+ /* Set packagename of arrays to the element's package. */
+
+ for (; *start == '['; start++);
+
+ /* Skip the 'L' in arrays of references. */
+
+ if (*start == 'L')
+ start++;
+ }
+
+ /* Search for last '/'. */
+
+ for (; (p > start) && (*p != '/'); --p);
+
+ /* If we found a '/' we set the package name plus the trailing
+ '/'. Otherwise we set the packagename to NULL. */
+
+ if (p > start)
+ c->packagename = utf_new(start, p - start + 1);
+ else
+ c->packagename = NULL;
+ }
+
+
+ /* class_create_classinfo ******************************************************
+
+ Create a new classinfo struct. The class name is set to the given utf *,
+ most other fields are initialized to zero.
+
+ Note: classname may be NULL. In this case a not-yet-named classinfo is
+ created. The name must be filled in later and class_set_packagename
+ must be called after that.
+
+ *******************************************************************************/
+
+ classinfo *class_create_classinfo(utf *classname)
+ {
+ classinfo *c;
+
+ #if defined(ENABLE_STATISTICS)
+ if (opt_stat)
+ size_classinfo += sizeof(classinfo);
+ #endif
+
+ /* we use a safe name for temporarily unnamed classes */
+
+ if (classname == NULL)
+ classname = utf_not_named_yet;
+
+ #if !defined(NDEBUG)
+ if (initverbose)
+ log_message_utf("Creating class: ", classname);
+ #endif
+
+ #if !defined(ENABLE_GC_BOEHM)
+ c = (classinfo *) heap_alloc_uncollectable(sizeof(classinfo));
+ /*c = NEW(classinfo);
+ MZERO(c, classinfo, 1);*/
+ #else
+ c = GCNEW_UNCOLLECTABLE(classinfo, 1);
+ /* GCNEW_UNCOLLECTABLE clears the allocated memory */
+ #endif
+
+ c->name = classname;
+
+ /* Set the header.vftbl of all loaded classes to the one of
+ java.lang.Class, so Java code can use a class as object. */
+
+ if (class_java_lang_Class != NULL)
+ if (class_java_lang_Class->vftbl != NULL)
+ c->object.header.vftbl = class_java_lang_Class->vftbl;
+
+ #if defined(ENABLE_JAVASE)
+ /* check if the class is a reference class and flag it */
+
+ if (classname == utf_java_lang_ref_SoftReference) {
+ c->flags |= ACC_CLASS_REFERENCE_SOFT;
+ }
+ else if (classname == utf_java_lang_ref_WeakReference) {
+ c->flags |= ACC_CLASS_REFERENCE_WEAK;
+ }
+ else if (classname == utf_java_lang_ref_PhantomReference) {
+ c->flags |= ACC_CLASS_REFERENCE_PHANTOM;
+ }
+ #endif
+
+ if (classname != utf_not_named_yet)
+ class_set_packagename(c);
++#if defined (ENABLE_JITCACHE)
++ c->cache_file_fd = 0;
++#endif
+
+ LOCK_INIT_OBJECT_LOCK(&c->object.header);
+
+ return c;
+ }
+
+
+ /* class_postset_header_vftbl **************************************************
+
+ Set the header.vftbl of all classes created before java.lang.Class
+ was linked. This is necessary that Java code can use a class as
+ object.
+
+ *******************************************************************************/
+
+ void class_postset_header_vftbl(void)
+ {
+ classinfo *c;
+ u4 slot;
+ classcache_name_entry *nmen;
+ classcache_class_entry *clsen;
+
+ assert(class_java_lang_Class);
+
+ 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;
+
+ /* now set the the vftbl */
+
+ if (c->object.header.vftbl == NULL)
+ c->object.header.vftbl = class_java_lang_Class->vftbl;
+ }
+ }
+ }
+ }
+
+ /* class_define ****************************************************************
+
+ Calls the loader and defines a class in the VM.
+
+ *******************************************************************************/
+
+ classinfo *class_define(utf *name, classloader_t *cl, int32_t length, uint8_t *data, java_handle_t *pd)
+ {
+ classinfo *c;
+ classinfo *r;
+ classbuffer *cb;
+
+ if (name != NULL) {
+ /* check if this class has already been defined */
+
+ c = classcache_lookup_defined_or_initiated(cl, name);
+
+ if (c != NULL) {
+ exceptions_throw_linkageerror("duplicate class definition: ", c);
+ return NULL;
+ }
+ }
+
+ /* create a new classinfo struct */
+
+ c = class_create_classinfo(name);
+
+ #if defined(ENABLE_STATISTICS)
+ /* measure time */
+
+ if (opt_getloadingtime)
+ loadingtime_start();
+ #endif
+
+ /* build a classbuffer with the given data */
+
+ cb = NEW(classbuffer);
+
+ cb->clazz = c;
+ cb->size = length;
+ cb->data = data;
+ cb->pos = cb->data;
+
+ /* preset the defining classloader */
+
+ c->classloader = cl;
+
+ /* load the class from this buffer */
+
+ r = load_class_from_classbuffer(cb);
+
+ /* free memory */
+
+ FREE(cb, classbuffer);
+
+ #if defined(ENABLE_STATISTICS)
+ /* measure time */
+
+ if (opt_getloadingtime)
+ loadingtime_stop();
+ #endif
+
+ if (r == NULL) {
+ /* If return value is NULL, we had a problem and the class is
+ not loaded. Now free the allocated memory, otherwise we
+ could run into a DOS. */
+
+ class_free(c);
+
+ return NULL;
+ }
+
+ #if defined(ENABLE_JAVASE)
+ # if defined(WITH_JAVA_RUNTIME_LIBRARY_OPENJDK)
+ /* Store the protection domain. */
+
+ c->protectiondomain = pd;
+ # endif
+ #endif
+
+ /* Store the newly defined class in the class cache. This call
+ also checks whether a class of the same name has already been
+ defined by the same defining loader, and if so, replaces the
+ newly created class by the one defined earlier. */
+
+ /* Important: The classinfo given to classcache_store must be
+ fully prepared because another thread may return
+ this pointer after the lookup at to top of this
+ function directly after the class cache lock has
+ been released. */
+
+ c = classcache_store(cl, c, true);
+
+ return c;
+ }
+
+
+ /* class_load_attribute_sourcefile *********************************************
+
+ SourceFile_attribute {
+ u2 attribute_name_index;
+ u4 attribute_length;
+ u2 sourcefile_index;
+ }
+
+ *******************************************************************************/
+
+ static bool class_load_attribute_sourcefile(classbuffer *cb)
+ {
+ classinfo *c;
+ u4 attribute_length;
+ u2 sourcefile_index;
+ utf *sourcefile;
+
+ /* get classinfo */
+
+ c = cb->clazz;
+
+ /* check buffer size */
+
+ if (!suck_check_classbuffer_size(cb, 4 + 2))
+ return false;
+
+ /* check attribute length */
+
+ attribute_length = suck_u4(cb);
+
+ if (attribute_length != 2) {
+ exceptions_throw_classformaterror(c, "Wrong size for VALUE attribute");
+ return false;
+ }
+
+ /* there can be no more than one SourceFile attribute */
+
+ if (c->sourcefile != NULL) {
+ exceptions_throw_classformaterror(c, "Multiple SourceFile attributes");
+ return false;
+ }
+
+ /* get sourcefile */
+
+ sourcefile_index = suck_u2(cb);
+ sourcefile = class_getconstant(c, sourcefile_index, CONSTANT_Utf8);
+
+ if (sourcefile == NULL)
+ return false;
+
+ /* store sourcefile */
+
+ c->sourcefile = sourcefile;
+
+ return true;
+ }
+
+
+ /* class_load_attribute_enclosingmethod ****************************************
+
+ EnclosingMethod_attribute {
+ u2 attribute_name_index;
+ u4 attribute_length;
+ u2 class_index;
+ u2 method_index;
+ }
+
+ *******************************************************************************/
+
+ #if defined(ENABLE_JAVASE)
+ static bool class_load_attribute_enclosingmethod(classbuffer *cb)
+ {
+ classinfo *c;
+ u4 attribute_length;
+ u2 class_index;
+ u2 method_index;
+ classref_or_classinfo cr;
+ constant_nameandtype *cn;
+
+ /* get classinfo */
+
+ c = cb->clazz;
+
+ /* check buffer size */
+
+ if (!suck_check_classbuffer_size(cb, 4 + 2 + 2))
+ return false;
+
+ /* check attribute length */
+
+ attribute_length = suck_u4(cb);
+
+ if (attribute_length != 4) {
+ exceptions_throw_classformaterror(c, "Wrong size for VALUE attribute");
+ return false;
+ }
+
+ /* there can be no more than one EnclosingMethod attribute */
+
+ if (c->enclosingmethod != NULL) {
+ exceptions_throw_classformaterror(c, "Multiple EnclosingMethod attributes");
+ return false;
+ }
+
+ /* get class index */
+
+ class_index = suck_u2(cb);
+ cr.ref = innerclass_getconstant(c, class_index, CONSTANT_Class);
+
+ /* get method index */
+
+ method_index = suck_u2(cb);
+ cn = innerclass_getconstant(c, method_index, CONSTANT_NameAndType);
+
+ /* store info in classinfo */
+
+ c->enclosingclass.any = cr.any;
+ c->enclosingmethod = cn;
+
+ return true;
+ }
+ #endif /* defined(ENABLE_JAVASE) */
+
+
+ /* class_load_attributes *******************************************************
+
+ Read attributes from ClassFile.
+
+ attribute_info {
+ u2 attribute_name_index;
+ u4 attribute_length;
+ u1 info[attribute_length];
+ }
+
+ InnerClasses_attribute {
+ u2 attribute_name_index;
+ u4 attribute_length;
+ }
+
+ *******************************************************************************/
+
+ bool class_load_attributes(classbuffer *cb)
+ {
+ classinfo *c;
+ uint16_t attributes_count;
+ uint16_t attribute_name_index;
+ utf *attribute_name;
+ innerclassinfo *info;
+ classref_or_classinfo inner;
+ classref_or_classinfo outer;
+ utf *name;
+ uint16_t flags;
+ int i, j;
+
+ c = cb->clazz;
+
+ /* get attributes count */
+
+ if (!suck_check_classbuffer_size(cb, 2))
+ return false;
+
+ attributes_count = suck_u2(cb);
+
+ for (i = 0; i < attributes_count; i++) {
+ /* get attribute name */
+
+ if (!suck_check_classbuffer_size(cb, 2))
+ return false;
+
+ attribute_name_index = suck_u2(cb);
+ attribute_name =
+ class_getconstant(c, attribute_name_index, CONSTANT_Utf8);
+
+ if (attribute_name == NULL)
+ return false;
+
+ if (attribute_name == utf_InnerClasses) {
+ /* InnerClasses */
+
+ if (c->innerclass != NULL) {
+ exceptions_throw_classformaterror(c, "Multiple InnerClasses attributes");
+ return false;
+ }
+
+ if (!suck_check_classbuffer_size(cb, 4 + 2))
+ return false;
+
+ /* skip attribute length */
+ suck_u4(cb);
+
+ /* number of records */
+ c->innerclasscount = suck_u2(cb);
+
+ if (!suck_check_classbuffer_size(cb, (2 + 2 + 2 + 2) * c->innerclasscount))
+ return false;
+
+ /* allocate memory for innerclass structure */
+ c->innerclass = MNEW(innerclassinfo, c->innerclasscount);
+
+ for (j = 0; j < c->innerclasscount; j++) {
+ /* The innerclass structure contains a class with an encoded
+ name, its defining scope, its simple name and a bitmask of
+ the access flags. */
+
+ info = c->innerclass + j;
+
+ inner.ref = innerclass_getconstant(c, suck_u2(cb), CONSTANT_Class);
+ outer.ref = innerclass_getconstant(c, suck_u2(cb), CONSTANT_Class);
+ name = innerclass_getconstant(c, suck_u2(cb), CONSTANT_Utf8);
+ flags = suck_u2(cb);
+
+ /* If the current inner-class is the currently loaded
+ class check for some special flags. */
+
+ if (inner.ref->name == c->name) {
+ /* If an inner-class is not a member, its
+ outer-class is NULL. */
+
+ if (outer.ref != NULL) {
+ c->flags |= ACC_CLASS_MEMBER;
+
+ /* A member class doesn't have an
+ EnclosingMethod attribute, so set the
+ enclosing-class to be the same as the
+ declaring-class. */
+
+ c->declaringclass = outer;
+ c->enclosingclass = outer;
+ }
+
+ /* If an inner-class is anonymous, its name is
+ NULL. */
+
+ if (name == NULL)
+ c->flags |= ACC_CLASS_ANONYMOUS;
+ }
+
+ info->inner_class = inner;
+ info->outer_class = outer;
+ info->name = name;
+ info->flags = flags;
+ }
+ }
+ else if (attribute_name == utf_SourceFile) {
+ /* SourceFile */
+
+ if (!class_load_attribute_sourcefile(cb))
+ return false;
+ }
+ #if defined(ENABLE_JAVASE)
+ else if (attribute_name == utf_EnclosingMethod) {
+ /* EnclosingMethod */
+
+ if (!class_load_attribute_enclosingmethod(cb))
+ return false;
+ }
+ else if (attribute_name == utf_Signature) {
+ /* Signature */
+
+ if (!loader_load_attribute_signature(cb, &(c->signature)))
+ return false;
+ }
+ #endif
+
+ #if defined(ENABLE_ANNOTATIONS)
+ else if (attribute_name == utf_RuntimeVisibleAnnotations) {
+ /* RuntimeVisibleAnnotations */
+ if (!annotation_load_class_attribute_runtimevisibleannotations(cb))
+ return false;
+ }
+ else if (attribute_name == utf_RuntimeInvisibleAnnotations) {
+ /* RuntimeInvisibleAnnotations */
+ if (!annotation_load_class_attribute_runtimeinvisibleannotations(cb))
+ return false;
+ }
+ #endif
+
+ else {
+ /* unknown attribute */
+
+ if (!loader_skip_attribute_body(cb))
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+
+ /* class_freepool **************************************************************
+
+ Frees all resources used by this classes Constant Pool.
+
+ *******************************************************************************/
+
+ static void class_freecpool(classinfo *c)
+ {
+ u4 idx;
+ u4 tag;
+ void* info;
+
+ if (c->cptags && c->cpinfos) {
+ for (idx = 0; idx < c->cpcount; idx++) {
+ tag = c->cptags[idx];
+ info = c->cpinfos[idx];
+
+ if (info != NULL) {
+ switch (tag) {
+ case CONSTANT_Fieldref:
+ case CONSTANT_Methodref:
+ case CONSTANT_InterfaceMethodref:
+ FREE(info, constant_FMIref);
+ break;
+ case CONSTANT_Integer:
+ FREE(info, constant_integer);
+ break;
+ case CONSTANT_Float:
+ FREE(info, constant_float);
+ break;
+ case CONSTANT_Long:
+ FREE(info, constant_long);
+ break;
+ case CONSTANT_Double:
+ FREE(info, constant_double);
+ break;
+ case CONSTANT_NameAndType:
+ FREE(info, constant_nameandtype);
+ break;
+ }
+ }
+ }
+ }
+
+ if (c->cptags)
+ MFREE(c->cptags, u1, c->cpcount);
+
+ if (c->cpinfos)
+ MFREE(c->cpinfos, void*, c->cpcount);
+ }
+
+
+ /* class_getconstant ***********************************************************
+
+ Retrieves the value at position 'pos' of the constantpool of a
+ class. If the type of the value is other than 'ctype', an error is
+ thrown.
+
+ *******************************************************************************/
+
+ void* class_getconstant(classinfo *c, u4 pos, u4 ctype)
+ {
+ /* check index and type of constantpool entry */
+ /* (pos == 0 is caught by type comparison) */
+
+ if ((pos >= c->cpcount) || (c->cptags[pos] != ctype)) {
+ exceptions_throw_classformaterror(c, "Illegal constant pool index");
+ return NULL;
+ }
+
+ return c->cpinfos[pos];
+ }
+
+
+ /* innerclass_getconstant ******************************************************
+
+ Like class_getconstant, but if cptags is ZERO, null is returned.
+
+ *******************************************************************************/
+
+ void* innerclass_getconstant(classinfo *c, u4 pos, u4 ctype)
+ {
+ /* invalid position in constantpool */
+
+ if (pos >= c->cpcount) {
+ exceptions_throw_classformaterror(c, "Illegal constant pool index");
+ return NULL;
+ }
+
+ /* constantpool entry of type 0 */
+
+ if (c->cptags[pos] == 0)
+ return NULL;
+
+ /* check type of constantpool entry */
+
+ if (c->cptags[pos] != ctype) {
+ exceptions_throw_classformaterror(c, "Illegal constant pool index");
+ return NULL;
+ }
+
+ return c->cpinfos[pos];
+ }
+
+
+ /* class_free ******************************************************************
+
+ Frees all resources used by the class.
+
+ *******************************************************************************/
+
+ void class_free(classinfo *c)
+ {
+ s4 i;
+ vftbl_t *v;
+
++#if defined(ENABLE_JITCACHE)
++/* TODO: Find a way around the linker problem */
++/* jitcache_freeclass(c);*/
++#endif
++
+ class_freecpool(c);
+
+ if (c->interfaces != NULL)
+ MFREE(c->interfaces, classinfo*, c->interfacescount);
+
+ if (c->fields) {
+ for (i = 0; i < c->fieldscount; i++)
+ field_free(&(c->fields[i]));
+ MFREE(c->fields, fieldinfo, c->fieldscount);
+ }
+
+ if (c->methods) {
+ for (i = 0; i < c->methodscount; i++)
+ method_free(&(c->methods[i]));
+ MFREE(c->methods, methodinfo, c->methodscount);
+ }
+
+ if ((v = c->vftbl) != NULL) {
+ if (v->arraydesc)
+ mem_free(v->arraydesc,sizeof(arraydescriptor));
+
+ for (i = 0; i < v->interfacetablelength; i++) {
+ MFREE(v->interfacetable[-i], methodptr, v->interfacevftbllength[i]);
+ }
+ MFREE(v->interfacevftbllength, s4, v->interfacetablelength);
+
+ i = sizeof(vftbl_t) + sizeof(methodptr) * (v->vftbllength - 1) +
+ sizeof(methodptr*) * (v->interfacetablelength -
+ (v->interfacetablelength > 0));
+ v = (vftbl_t*) (((methodptr*) v) -
+ (v->interfacetablelength - 1) * (v->interfacetablelength > 1));
+ mem_free(v, i);
+ }
+
+ if (c->innerclass)
+ MFREE(c->innerclass, innerclassinfo, c->innerclasscount);
+
+ /* if (c->classvftbl)
+ mem_free(c->header.vftbl, sizeof(vftbl) + sizeof(methodptr)*(c->vftbl->vftbllength-1)); */
+
+ /* GCFREE(c); */
+ }
+
+
+ /* get_array_class *************************************************************
+
+ Returns the array class with the given name for the given
+ classloader, or NULL if an exception occurred.
+
+ Note: This function does eager loading.
+
+ *******************************************************************************/
+
+ static classinfo *get_array_class(utf *name,classloader_t *initloader,
+ classloader_t *defloader,bool link)
+ {
+ classinfo *c;
+
+ /* lookup this class in the classcache */
+ c = classcache_lookup(initloader,name);
+ if (!c)
+ c = classcache_lookup_defined(defloader,name);
+
+ if (!c) {
+ /* we have to create it */
+ c = class_create_classinfo(name);
+ c = load_newly_created_array(c,initloader);
+ if (c == NULL)
+ return NULL;
+ }
+
+ assert(c);
+ assert(c->state & CLASS_LOADED);
+ assert(c->classloader == defloader);
+
+ if (link && !(c->state & CLASS_LINKED))
+ if (!link_class(c))
+ return NULL;
+
+ assert(!link || (c->state & CLASS_LINKED));
+
+ return c;
+ }
+
+
+ /* class_array_of **************************************************************
+
+ Returns an array class with the given component class. The array
+ class is dynamically created if neccessary.
+
+ *******************************************************************************/
+
+ classinfo *class_array_of(classinfo *component, bool link)
+ {
+ classloader_t *cl;
+ s4 namelen;
+ char *namebuf;
+ utf *u;
+ classinfo *c;
+ int32_t dumpmarker;
+
+ cl = component->classloader;
+
+ DMARKER;
+
+ /* Assemble the array class name */
+ namelen = component->name->blength;
+
+ if (component->name->text[0] == '[') {
+ /* the component is itself an array */
+ namebuf = DMNEW(char, namelen + 1);
+ namebuf[0] = '[';
+ MCOPY(namebuf + 1, component->name->text, char, namelen);
+ namelen++;
+ }
+ else {
+ /* the component is a non-array class */
+ namebuf = DMNEW(char, namelen + 3);
+ namebuf[0] = '[';
+ namebuf[1] = 'L';
+ MCOPY(namebuf + 2, component->name->text, char, namelen);
+ namebuf[2 + namelen] = ';';
+ namelen += 3;
+ }
+
+ u = utf_new(namebuf, namelen);
+
+ c = get_array_class(u, cl, cl, link);
+
+ DRELEASE;
+
+ return c;
+ }
+
+
+ /* class_multiarray_of *********************************************************
+
+ Returns an array class with the given dimension and element class.
+ The array class is dynamically created if neccessary.
+
+ *******************************************************************************/
+
+ classinfo *class_multiarray_of(s4 dim, classinfo *element, bool link)
+ {
+ s4 namelen;
+ char *namebuf;
+ classinfo *c;
+ int32_t dumpmarker;
+
+ DMARKER;
+
+ if (dim < 1) {
+ log_text("Invalid array dimension requested");
+ assert(0);
+ }
+
+ /* Assemble the array class name */
+ namelen = element->name->blength;
+
+ if (element->name->text[0] == '[') {
+ /* the element is itself an array */
+ namebuf = DMNEW(char, namelen + dim);
+ memcpy(namebuf + dim, element->name->text, namelen);
+ namelen += dim;
+ }
+ else {
+ /* the element is a non-array class */
+ namebuf = DMNEW(char, namelen + 2 + dim);
+ namebuf[dim] = 'L';
+ memcpy(namebuf + dim + 1, element->name->text, namelen);
+ namelen += (2 + dim);
+ namebuf[namelen - 1] = ';';
+ }
+ memset(namebuf, '[', dim);
+
+ c = get_array_class(utf_new(namebuf, namelen),
+ element->classloader,
+ element->classloader,
+ link);
+
+ DRELEASE;
+
+ return c;
+ }
+
+
+ /* class_lookup_classref *******************************************************
+
+ Looks up the constant_classref for a given classname in the classref
+ tables of a class.
+
+ IN:
+ cls..............the class containing the reference
+ name.............the name of the class refered to
+
+ RETURN VALUE:
+ a pointer to a constant_classref, or
+ NULL if the reference was not found
+
+ *******************************************************************************/
+
+ constant_classref *class_lookup_classref(classinfo *cls, utf *name)
+ {
+ constant_classref *ref;
+ extra_classref *xref;
+ int count;
+
+ assert(cls);
+ assert(name);
+ assert(!cls->classrefcount || cls->classrefs);
+
+ /* first search the main classref table */
+ count = cls->classrefcount;
+ ref = cls->classrefs;
+ for (; count; --count, ++ref)
+ if (ref->name == name)
+ return ref;
+
+ /* next try the list of extra classrefs */
+ for (xref = cls->extclassrefs; xref; xref = xref->next) {
+ if (xref->classref.name == name)
+ return &(xref->classref);
+ }
+
+ /* not found */
+ return NULL;
+ }
+
+
+ /* class_get_classref **********************************************************
+
+ Returns the constant_classref for a given classname.
+
+ IN:
+ cls..............the class containing the reference
+ name.............the name of the class refered to
+
+ RETURN VALUE:
+ a pointer to a constant_classref (never NULL)
+
+ NOTE:
+ The given name is not checked for validity!
+
+ *******************************************************************************/
+
+ constant_classref *class_get_classref(classinfo *cls, utf *name)
+ {
+ constant_classref *ref;
+ extra_classref *xref;
+
+ assert(cls);
+ assert(name);
+
+ ref = class_lookup_classref(cls,name);
+ if (ref)
+ return ref;
+
+ xref = NEW(extra_classref);
+ CLASSREF_INIT(xref->classref,cls,name);
+
+ xref->next = cls->extclassrefs;
+ cls->extclassrefs = xref;
+
+ return &(xref->classref);
+ }
+
+
+ /* class_get_self_classref *****************************************************
+
+ Returns the constant_classref to the class itself.
+
+ IN:
+ cls..............the class containing the reference
+
+ RETURN VALUE:
+ a pointer to a constant_classref (never NULL)
+
+ *******************************************************************************/
+
+ constant_classref *class_get_self_classref(classinfo *cls)
+ {
+ /* XXX this should be done in a faster way. Maybe always make */
+ /* the classref of index 0 a self reference. */
+ return class_get_classref(cls,cls->name);
+ }
+
+ /* class_get_classref_multiarray_of ********************************************
+
+ Returns an array type reference with the given dimension and element class
+ reference.
+
+ IN:
+ dim..............the requested dimension
+ dim must be in [1;255]. This is NOT checked!
+ ref..............the component class reference
+
+ RETURN VALUE:
+ a pointer to the class reference for the array type
+
+ NOTE:
+ The referer of `ref` is used as the referer for the new classref.
+
+ *******************************************************************************/
+
+ constant_classref *class_get_classref_multiarray_of(s4 dim, constant_classref *ref)
+ {
+ s4 namelen;
+ char *namebuf;
+ constant_classref *cr;
+ int32_t dumpmarker;
+
+ assert(ref);
+ assert(dim >= 1 && dim <= 255);
+
+ DMARKER;
+
+ /* Assemble the array class name */
+ namelen = ref->name->blength;
+
+ if (ref->name->text[0] == '[') {
+ /* the element is itself an array */
+ namebuf = DMNEW(char, namelen + dim);
+ memcpy(namebuf + dim, ref->name->text, namelen);
+ namelen += dim;
+ }
+ else {
+ /* the element is a non-array class */
+ namebuf = DMNEW(char, namelen + 2 + dim);
+ namebuf[dim] = 'L';
+ memcpy(namebuf + dim + 1, ref->name->text, namelen);
+ namelen += (2 + dim);
+ namebuf[namelen - 1] = ';';
+ }
+ memset(namebuf, '[', dim);
+
+ cr = class_get_classref(ref->referer,utf_new(namebuf, namelen));
+
+ DRELEASE;
+
+ return cr;
+ }
+
+
+ /* class_get_classref_component_of *********************************************
+
+ Returns the component classref of a given array type reference
+
+ IN:
+ ref..............the array type reference
+
+ RETURN VALUE:
+ a reference to the component class, or
+ NULL if `ref` is not an object array type reference
+
+ NOTE:
+ The referer of `ref` is used as the referer for the new classref.
+
+ *******************************************************************************/
+
+ constant_classref *class_get_classref_component_of(constant_classref *ref)
+ {
+ s4 namelen;
+ char *name;
+
+ assert(ref);
+
+ name = ref->name->text;
+ if (*name++ != '[')
+ return NULL;
+
+ namelen = ref->name->blength - 1;
+ if (*name == 'L') {
+ name++;
+ namelen -= 2;
+ }
+ else if (*name != '[') {
+ return NULL;
+ }
+
+ return class_get_classref(ref->referer, utf_new(name, namelen));
+ }
+
+
+ /* class_findmethod ************************************************************
+
+ Searches a 'classinfo' structure for a method having the given name
+ and descriptor. If descriptor is NULL, it is ignored.
+
+ *******************************************************************************/
+
+ methodinfo *class_findmethod(classinfo *c, utf *name, utf *desc)
+ {
+ methodinfo *m;
+ s4 i;
+
+ for (i = 0; i < c->methodscount; i++) {
+ m = &(c->methods[i]);
+
+ if ((m->name == name) && ((desc == NULL) || (m->descriptor == desc)))
+ return m;
+ }
+
+ return NULL;
+ }
+
+
+ /* class_resolvemethod *********************************************************
+
+ Searches a class and it's super classes for a method.
+
+ Superinterfaces are *not* searched.
+
+ *******************************************************************************/
+
+ methodinfo *class_resolvemethod(classinfo *c, utf *name, utf *desc)
+ {
+ methodinfo *m;
+
+ while (c) {
+ m = class_findmethod(c, name, desc);
+
+ if (m)
+ return m;
+
+ /* JVM Specification bug:
+
+ It is important NOT to resolve special <init> and <clinit>
+ methods to super classes or interfaces; yet, this is not
+ explicited in the specification. Section 5.4.3.3 should be
+ updated appropriately. */
+
+ if (name == utf_init || name == utf_clinit)
+ return NULL;
+
+ c = c->super;
+ }
+
+ return NULL;
+ }
+
+
+ /* class_resolveinterfacemethod_intern *****************************************
+
+ Internally used helper function. Do not use this directly.
+
+ *******************************************************************************/
+
+ static methodinfo *class_resolveinterfacemethod_intern(classinfo *c,
+ utf *name, utf *desc)
+ {
+ methodinfo *m;
+ s4 i;
+
+ /* try to find the method in the class */
+
+ m = class_findmethod(c, name, desc);
+
+ if (m != NULL)
+ return m;
+
+ /* No method found? Try the super interfaces. */
+
+ for (i = 0; i < c->interfacescount; i++) {
+ m = class_resolveinterfacemethod_intern(c->interfaces[i], name, desc);
+
+ if (m != NULL)
+ return m;
+ }
+
+ /* no method found */
+
+ return NULL;
+ }
+
+
+ /* class_resolveclassmethod ****************************************************
+
+ Resolves a reference from REFERER to a method with NAME and DESC in
+ class C.
+
+ If the method cannot be resolved the return value is NULL. If
+ EXCEPT is true *exceptionptr is set, too.
+
+ *******************************************************************************/
+
+ methodinfo *class_resolveclassmethod(classinfo *c, utf *name, utf *desc,
+ classinfo *referer, bool throwexception)
+ {
+ classinfo *cls;
+ methodinfo *m;
+ s4 i;
+
+ /* if (c->flags & ACC_INTERFACE) { */
+ /* if (throwexception) */
+ /* *exceptionptr = */
+ /* new_exception(string_java_lang_IncompatibleClassChangeError); */
+ /* return NULL; */
+ /* } */
+
+ /* try class c and its superclasses */
+
+ cls = c;
+
+ m = class_resolvemethod(cls, name, desc);
+
+ if (m != NULL)
+ goto found;
+
+ /* Try the super interfaces. */
+
+ for (i = 0; i < c->interfacescount; i++) {
+ m = class_resolveinterfacemethod_intern(c->interfaces[i], name, desc);
+
+ if (m != NULL)
+ goto found;
+ }
+
+ if (throwexception)
+ exceptions_throw_nosuchmethoderror(c, name, desc);
+
+ return NULL;
+
+ found:
+ if ((m->flags & ACC_ABSTRACT) && !(c->flags & ACC_ABSTRACT)) {
+ if (throwexception)
+ exceptions_throw_abstractmethoderror();
+
+ return NULL;
+ }
+
+ /* XXX check access rights */
+
+ return m;
+ }
+
+
+ /* class_resolveinterfacemethod ************************************************
+
+ Resolves a reference from REFERER to a method with NAME and DESC in
+ interface C.
+
+ If the method cannot be resolved the return value is NULL. If
+ EXCEPT is true *exceptionptr is set, too.
+
+ *******************************************************************************/
+
+ methodinfo *class_resolveinterfacemethod(classinfo *c, utf *name, utf *desc,
+ classinfo *referer, bool throwexception)
+ {
+ methodinfo *mi;
+
+ if (!(c->flags & ACC_INTERFACE)) {
+ if (throwexception)
+ exceptions_throw_incompatibleclasschangeerror(c, "Not an interface");
+
+ return NULL;
+ }
+
+ mi = class_resolveinterfacemethod_intern(c, name, desc);
+
+ if (mi != NULL)
+ return mi;
+
+ /* try class java.lang.Object */
+
+ mi = class_findmethod(class_java_lang_Object, name, desc);
+
+ if (mi != NULL)
+ return mi;
+
+ if (throwexception)
+ exceptions_throw_nosuchmethoderror(c, name, desc);
+
+ return NULL;
+ }
+
+
+ /* class_findfield *************************************************************
+
+ Searches for field with specified name and type in a classinfo
+ structure. If no such field is found NULL is returned.
+
+ *******************************************************************************/
+
+ fieldinfo *class_findfield(classinfo *c, utf *name, utf *desc)
+ {
+ s4 i;
+
+ for (i = 0; i < c->fieldscount; i++)
+ if ((c->fields[i].name == name) && (c->fields[i].descriptor == desc))
+ return &(c->fields[i]);
+
+ if (c->super != NULL)
+ return class_findfield(c->super, name, desc);
+
+ return NULL;
+ }
+
+
+ /* class_findfield_approx ******************************************************
+
+ Searches in 'classinfo'-structure for a field with the specified
+ name.
+
+ *******************************************************************************/
+
+ fieldinfo *class_findfield_by_name(classinfo* c, utf* name)
+ {
+ for (int32_t i = 0; i < c->fieldscount; i++) {
+ fieldinfo* f = &(c->fields[i]);
+
+ if (f->name == name)
+ return f;
+ }
+
+ // Field not found.
+ exceptions_throw_nosuchfielderror(c, name);
+ return NULL;
+ }
+
+
+ /****************** Function: class_resolvefield_int ***************************
+
+ This is an internally used helper function. Do not use this directly.
+
+ Tries to resolve a field having the given name and type.
+ If the field cannot be resolved, NULL is returned.
+
+ *******************************************************************************/
+
+ static fieldinfo *class_resolvefield_int(classinfo *c, utf *name, utf *desc)
+ {
+ fieldinfo *fi;
+ s4 i;
+
+ /* search for field in class c */
+
+ for (i = 0; i < c->fieldscount; i++) {
+ if ((c->fields[i].name == name) && (c->fields[i].descriptor == desc)) {
+ return &(c->fields[i]);
+ }
+ }
+
+ /* Try super interfaces recursively. */
+
+ for (i = 0; i < c->interfacescount; i++) {
+ fi = class_resolvefield_int(c->interfaces[i], name, desc);
+
+ if (fi != NULL)
+ return fi;
+ }
+
+ /* Try super class. */
+
+ if (c->super != NULL)
+ return class_resolvefield_int(c->super, name, desc);
+
+ /* not found */
+
+ return NULL;
+ }
+
+
+ /********************* Function: class_resolvefield ***************************
+
+ Resolves a reference from REFERER to a field with NAME and DESC in class C.
+
+ If the field cannot be resolved, an exception is thrown and the
+ return value is NULL.
+
+ *******************************************************************************/
+
+ fieldinfo *class_resolvefield(classinfo *c, utf *name, utf *desc, classinfo *referer)
+ {
+ fieldinfo *fi;
+
+ fi = class_resolvefield_int(c, name, desc);
+
+ if (!fi) {
+ exceptions_throw_nosuchfielderror(c, name);
+ return NULL;
+ }
+
+ /* XXX check access rights */
+
+ return fi;
+ }
+
+
+ /* class_issubclass ************************************************************
+
+ Checks if sub is a descendant of super.
+
+ *******************************************************************************/
+
+ bool class_issubclass(classinfo *sub, classinfo *super)
+ {
+ classinfo *c;
+
+ c = sub;
+
+ for (;;) {
+ /* We reached java/lang/Object and did not find the requested
+ super class. */
+
+ if (c == NULL)
+ return false;
+
+ /* We found the requested super class. */
+
+ if (c == super)
+ return true;
+
+ c = c->super;
+ }
+ }
+
+
+ /* class_isanysubclass *********************************************************
+
+ Checks a subclass relation between two classes. Implemented
+ interfaces are interpreted as super classes.
+
+ Return value: 1 ... sub is subclass of super
+ 0 ... otherwise
+
+ *******************************************************************************/
+
+ bool class_isanysubclass(classinfo *sub, classinfo *super)
+ {
+ uint32_t diffval;
+ bool result;
+
+ /* This is the trivial case. */
+
+ if (sub == super)
+ return true;
+
+ /* Primitive classes are only subclasses of themselves. */
+
+ if (class_is_primitive(sub) || class_is_primitive(super))
+ return false;
+
+ /* Check for interfaces. */
+
+ if (super->flags & ACC_INTERFACE) {
+ result = (sub->vftbl->interfacetablelength > super->index) &&
+ (sub->vftbl->interfacetable[-super->index] != NULL);
+ }
+ else {
+ /* java.lang.Object is the only super class of any
+ interface. */
+
+ if (sub->flags & ACC_INTERFACE)
+ return (super == class_java_lang_Object);
+
+ LOCK_MONITOR_ENTER(linker_classrenumber_lock);
+
+ diffval = sub->vftbl->baseval - super->vftbl->baseval;
+ result = diffval <= (uint32_t) super->vftbl->diffval;
+
+ LOCK_MONITOR_EXIT(linker_classrenumber_lock);
+ }
+
+ return result;
+ }
+
+
+ /* class_is_assignable_from ****************************************************
+
+ Return whether an instance of the "from" class parameter would be
+ an instance of this class "to" as well.
+
+ ARGUMENTS:
+ to ..... class
+ from ... class
+
+ RETURN:
+ true .... is assignable
+ false ... is not assignable
+
+ *******************************************************************************/
+
+ bool class_is_assignable_from(classinfo *to, classinfo *from)
+ {
+ if (!(to->state & CLASS_LINKED))
+ if (!link_class(to))
+ return false;
+
+ if (!(from->state & CLASS_LINKED))
+ if (!link_class(from))
+ return false;
+
+ return class_isanysubclass(from, to);
+ }
+
+
+ /* class_is_instance ***********************************************************
+
+ Return if the given Java object is an instance of the given class.
+
+ ARGUMENTS:
+ c ... class
+ h ... Java object
+
+ RETURN:
+ true .... is instance
+ false ... is not instance
+
+ *******************************************************************************/
+
+ bool class_is_instance(classinfo *c, java_handle_t *h)
+ {
+ if (!(c->state & CLASS_LINKED))
+ if (!link_class(c))
+ return false;
+
+ return builtin_instanceof(h, c);
+ }
+
+
+ /* class_get_componenttype *****************************************************
+
+ Return the component class of the given class. If the given class
+ is not an array, return NULL.
+
+ *******************************************************************************/
+
+ classinfo *class_get_componenttype(classinfo *c)
+ {
+ classinfo *component;
+ arraydescriptor *ad;
+
+ /* XXX maybe we could find a way to do this without linking. */
+ /* This way should be safe and easy, however. */
+
+ if (!(c->state & CLASS_LINKED))
+ if (!link_class(c))
+ return NULL;
+
+ ad = c->vftbl->arraydesc;
+
+ if (ad == NULL)
+ return NULL;
+
+ if (ad->arraytype == ARRAYTYPE_OBJECT)
+ component = ad->componentvftbl->clazz;
+ else
+ component = Primitive_get_class_by_type(ad->arraytype);
+
+ return component;
+ }
+
+
+ /* class_get_declaredclasses ***************************************************
+
+ Return an array of declared classes of the given class.
+
+ *******************************************************************************/
+
+ java_handle_objectarray_t *class_get_declaredclasses(classinfo *c, bool publicOnly)
+ {
+ classref_or_classinfo inner;
+ classref_or_classinfo outer;
+ utf *outername;
+ int declaredclasscount; /* number of declared classes */
+ int pos; /* current declared class */
+ java_handle_objectarray_t *oa; /* array of declared classes */
+ int i;
+ classinfo *ic;
+
+ declaredclasscount = 0;
+
+ if (!class_is_primitive(c) && !class_is_array(c)) {
+ /* Determine number of declared classes. */
+
+ for (i = 0; i < c->innerclasscount; i++) {
+ /* Get outer-class. If the inner-class is not a member
+ class, the outer-class is NULL. */
+
+ outer = c->innerclass[i].outer_class;
+
+ if (outer.any == NULL)
+ continue;
+
+ /* Check if outer-class is a classref or a real class and
+ get the class name from the structure. */
+
+ outername = IS_CLASSREF(outer) ? outer.ref->name : outer.cls->name;
+
+ /* Outer class is this class. */
+
+ if ((outername == c->name) &&
+ ((publicOnly == 0) || (c->innerclass[i].flags & ACC_PUBLIC)))
+ declaredclasscount++;
+ }
+ }
+
+ /* Allocate Class[] and check for OOM. */
+
+ oa = builtin_anewarray(declaredclasscount, class_java_lang_Class);
+
+ if (oa == NULL)
+ return NULL;
+
+ for (i = 0, pos = 0; i < c->innerclasscount; i++) {
+ inner = c->innerclass[i].inner_class;
+ outer = c->innerclass[i].outer_class;
+
+ /* Get outer-class. If the inner-class is not a member class,
+ the outer-class is NULL. */
+
+ if (outer.any == NULL)
+ continue;
+
+ /* Check if outer_class is a classref or a real class and get
+ the class name from the structure. */
+
+ outername = IS_CLASSREF(outer) ? outer.ref->name : outer.cls->name;
+
+ /* Outer class is this class. */
+
+ if ((outername == c->name) &&
+ ((publicOnly == 0) || (c->innerclass[i].flags & ACC_PUBLIC))) {
+
+ ic = resolve_classref_or_classinfo_eager(inner, false);
+
+ if (ic == NULL)
+ return NULL;
+
+ if (!(ic->state & CLASS_LINKED))
+ if (!link_class(ic))
+ return NULL;
+
+ LLNI_array_direct(oa, pos++) = (java_object_t *) ic;
+ }
+ }
+
+ return oa;
+ }
+
+
+ /**
+ * Return an array of declared constructors of the given class.
+ *
+ * @param c class to get the constructors of
+ * @param publicOnly show only public fields
+ *
+ * @return array of java.lang.reflect.Constructor
+ */
+ #if defined(ENABLE_JAVASE)
+ java_handle_objectarray_t *class_get_declaredconstructors(classinfo *c, bool publicOnly)
+ {
+ methodinfo* m;
+ java_handle_objectarray_t* oa;
+ java_handle_t* rc;
+ int count;
+ int index;
+ int i;
+
+ /* Determine number of constructors. */
+
+ count = 0;
+
+ for (i = 0; i < c->methodscount; i++) {
+ m = &(c->methods[i]);
+
+ if (((m->flags & ACC_PUBLIC) || (publicOnly == 0)) &&
+ (m->name == utf_init))
+ count++;
+ }
+
+ /* Create array of constructors. */
+
+ oa = builtin_anewarray(count, class_java_lang_reflect_Constructor);
+
+ if (oa == NULL)
+ return NULL;
+
+ /* Get the constructors and store them in the array. */
+
+ for (i = 0, index = 0; i < c->methodscount; i++) {
+ m = &(c->methods[i]);
+
+ if (((m->flags & ACC_PUBLIC) || (publicOnly == 0)) &&
+ (m->name == utf_init)) {
+ // Create a java.lang.reflect.Constructor object.
+
+ rc = java_lang_reflect_Constructor_create(m);
+
+ /* Store object into array. */
+
+ array_objectarray_element_set(oa, index, rc);
+ index++;
+ }
+ }
+
+ return oa;
+ }
+ #endif
+
+
+ /* class_get_declaredfields ****************************************************
+
+ Return an array of declared fields of the given class.
+
+ ARGUMENTS:
+ c ............ class to get the fields of
+ publicOnly ... show only public fields
+
+ RETURN:
+ array of java.lang.reflect.Field
+
+ *******************************************************************************/
+
+ #if defined(ENABLE_JAVASE)
+ java_handle_objectarray_t *class_get_declaredfields(classinfo *c, bool publicOnly)
+ {
+ java_handle_objectarray_t *oa;
+ fieldinfo *f;
+ java_handle_t *h;
+ int count;
+ int index;
+ int i;
+
+ /* Determine number of fields. */
+
+ count = 0;
+
+ for (i = 0; i < c->fieldscount; i++)
+ if ((c->fields[i].flags & ACC_PUBLIC) || (publicOnly == 0))
+ count++;
+
+ /* Create array of fields. */
+
+ oa = builtin_anewarray(count, class_java_lang_reflect_Field);
+
+ if (oa == NULL)
+ return NULL;
+
+ /* Get the fields and store them in the array. */
+
+ for (i = 0, index = 0; i < c->fieldscount; i++) {
+ f = &(c->fields[i]);
+
+ if ((f->flags & ACC_PUBLIC) || (publicOnly == 0)) {
+ // Create a java.lang.reflect.Field object.
+
+ h = java_lang_reflect_Field_create(f);
+
+ /* Store object into array. */
+
+ array_objectarray_element_set(oa, index, h);
+ index++;
+ }
+ }
+
+ return oa;
+ }
+ #endif
+
+
+ /* class_get_declaredmethods ***************************************************
+
+ Return an array of declared methods of the given class.
+
+ ARGUMENTS:
+ c ............ class to get the methods of
+ publicOnly ... show only public methods
+
+ RETURN:
+ array of java.lang.reflect.Method
+
+ *******************************************************************************/
+
+ #if defined(ENABLE_JAVASE)
+ java_handle_objectarray_t *class_get_declaredmethods(classinfo *c, bool publicOnly)
+ {
+ java_handle_objectarray_t *oa; /* result: array of Method-objects */
+ methodinfo *m; /* the current method to be represented */
+ java_handle_t *h;
+ int count;
+ int index;
+ int i;
+
+ /* JOWENN: array classes do not declare methods according to mauve
+ test. It should be considered, if we should return to my old
+ clone method overriding instead of declaring it as a member
+ function. */
+
+ if (class_is_array(c))
+ return builtin_anewarray(0, class_java_lang_reflect_Method);
+
+ /* Determine number of methods. */
+
+ count = 0;
+
+ for (i = 0; i < c->methodscount; i++) {
+ m = &(c->methods[i]);
+
+ if (((m->flags & ACC_PUBLIC) || (publicOnly == false)) &&
+ ((m->name != utf_init) && (m->name != utf_clinit)) &&
+ !(m->flags & ACC_MIRANDA))
+ count++;
+ }
+
+ /* Create array of methods. */
+
+ oa = builtin_anewarray(count, class_java_lang_reflect_Method);
+
+ if (oa == NULL)
+ return NULL;
+
+ /* Get the methods and store them in the array. */
+
+ for (i = 0, index = 0; i < c->methodscount; i++) {
+ m = &(c->methods[i]);
+
+ if (((m->flags & ACC_PUBLIC) || (publicOnly == false)) &&
+ ((m->name != utf_init) && (m->name != utf_clinit)) &&
+ !(m->flags & ACC_MIRANDA)) {
+ // Create java.lang.reflect.Method object.
+
+ h = java_lang_reflect_Method_create(m);
+
+ /* Store object into array. */
+
+ array_objectarray_element_set(oa, index, h);
+ index++;
+ }
+ }
+
+ return oa;
+ }
+ #endif
+
+
+ /* class_get_declaringclass ****************************************************
+
+ If the class or interface given is a member of another class,
+ return the declaring class. For array and primitive classes return
+ NULL.
+
+ *******************************************************************************/
+
+ classinfo *class_get_declaringclass(classinfo *c)
+ {
+ classref_or_classinfo cr;
+ classinfo *dc;
+
+ /* Get declaring class. */
+
+ cr = c->declaringclass;
+
+ if (cr.any == NULL)
+ return NULL;
+
+ /* Resolve the class if necessary. */
+
+ if (IS_CLASSREF(cr)) {
+ /* dc = resolve_classref_eager(cr.ref); */
+ dc = resolve_classref_or_classinfo_eager(cr, true);
+
+ if (dc == NULL)
+ return NULL;
+
+ /* Store the resolved class in the class structure. */
+
+ cr.cls = dc;
+ }
+
+ dc = cr.cls;
+
+ return dc;
+ }
+
+
+ /* class_get_enclosingclass ****************************************************
+
+ Return the enclosing class for the given class.
+
+ *******************************************************************************/
+
+ classinfo *class_get_enclosingclass(classinfo *c)
+ {
+ classref_or_classinfo cr;
+ classinfo *ec;
+
+ /* Get enclosing class. */
+
+ cr = c->enclosingclass;
+
+ if (cr.any == NULL)
+ return NULL;
+
+ /* Resolve the class if necessary. */
+
+ if (IS_CLASSREF(cr)) {
+ /* ec = resolve_classref_eager(cr.ref); */
+ ec = resolve_classref_or_classinfo_eager(cr, true);
+
+ if (ec == NULL)
+ return NULL;
+
+ /* Store the resolved class in the class structure. */
+
+ cr.cls = ec;
+ }
+
+ ec = cr.cls;
+
+ return ec;
+ }
+
+
+ /**
+ * Return the enclosing constructor as java.lang.reflect.Constructor
+ * object for the given class.
+ *
+ * @param c class to return the enclosing constructor for
+ *
+ * @return java.lang.reflect.Constructor object of the enclosing
+ * constructor
+ */
+ #if defined(ENABLE_JAVASE)
+ java_handle_t* class_get_enclosingconstructor(classinfo *c)
+ {
+ methodinfo* m;
+ java_handle_t* rc;
+
+ m = class_get_enclosingmethod_raw(c);
+
+ if (m == NULL)
+ return NULL;
+
+ /* Check for <init>. */
+
+ if (m->name != utf_init)
+ return NULL;
+
+ // Create a java.lang.reflect.Constructor object.
+
+ rc = java_lang_reflect_Constructor_create(m);
+
+ return rc;
+ }
+ #endif
+
+
+ /* class_get_enclosingmethod ***************************************************
+
+ Return the enclosing method for the given class.
+
+ IN:
+ c ... class to return the enclosing method for
+
+ RETURN:
+ methodinfo of the enclosing method
+
+ *******************************************************************************/
+
+ methodinfo *class_get_enclosingmethod_raw(classinfo *c)
+ {
+ constant_nameandtype *cn;
+ classinfo *ec;
+ methodinfo *m;
+
+ /* get enclosing class and method */
+
+ ec = class_get_enclosingclass(c);
+ cn = c->enclosingmethod;
+
+ /* check for enclosing class and method */
+
+ if (ec == NULL)
+ return NULL;
+
+ if (cn == NULL)
+ return NULL;
+
+ /* find method in enclosing class */
+
+ m = class_findmethod(ec, cn->name, cn->descriptor);
+
+ if (m == NULL) {
+ exceptions_throw_internalerror("Enclosing method doesn't exist");
+ return NULL;
+ }
+
+ return m;
+ }
+
+
+ /**
+ * Return the enclosing method as java.lang.reflect.Method object for
+ * the given class.
+ *
+ * @param c class to return the enclosing method for
+ *
+ * @return java.lang.reflect.Method object of the enclosing method
+ */
+ #if defined(ENABLE_JAVASE)
+ java_handle_t* class_get_enclosingmethod(classinfo *c)
+ {
+ methodinfo* m;
+ java_handle_t* rm;
+
+ m = class_get_enclosingmethod_raw(c);
+
+ if (m == NULL)
+ return NULL;
+
+ /* check for <init> */
+
+ if (m->name == utf_init)
+ return NULL;
+
+ // Create a java.lang.reflect.Method object.
+
+ rm = java_lang_reflect_Method_create(m);
+
+ return rm;
+ }
+ #endif
+
+
+ /* class_get_interfaces ********************************************************
+
+ Return an array of interfaces of the given class.
+
+ *******************************************************************************/
+
+ java_handle_objectarray_t *class_get_interfaces(classinfo *c)
+ {
+ classinfo *ic;
+ java_handle_objectarray_t *oa;
+ u4 i;
+
+ if (!(c->state & CLASS_LINKED))
+ if (!link_class(c))
+ return NULL;
+
+ oa = builtin_anewarray(c->interfacescount, class_java_lang_Class);
+
+ if (oa == NULL)
+ return NULL;
+
+ for (i = 0; i < c->interfacescount; i++) {
+ ic = c->interfaces[i];
+
+ LLNI_array_direct(oa, i) = (java_object_t *) ic;
+ }
+
+ return oa;
+ }
+
+
+ /* class_get_annotations *******************************************************
+
+ Get the unparsed declared annotations in a byte array
+ of the given class.
+
+ IN:
+ c........the class of which the annotations should be returned
+
+ RETURN VALUE:
+ The unparsed declared annotations in a byte array
+ (or NULL if there aren't any).
+
+ *******************************************************************************/
+
+ java_handle_bytearray_t *class_get_annotations(classinfo *c)
+ {
+ #if defined(ENABLE_ANNOTATIONS)
+ java_handle_t *annotations; /* unparsed annotations */
+
+ LLNI_classinfo_field_get(c, annotations, annotations);
+
+ return (java_handle_bytearray_t*)annotations;
+ #else
+ return NULL;
+ #endif
+ }
+
+
+ /* class_get_modifiers *********************************************************
+
+ Get the modifier flags of the given class.
+
+ IN:
+ c....the class of which the modifier flags should be returned
+ ignoreInnerClassesAttrib
+ RETURN VALUE:
+ modifier flags
+
+ *******************************************************************************/
+
+ int32_t class_get_modifiers(classinfo *c, bool ignoreInnerClassesAttrib)
+ {
+ classref_or_classinfo inner;
+ classref_or_classinfo outer;
+ utf *innername;
+ int i;
+
+ if (!ignoreInnerClassesAttrib && (c->innerclasscount != 0)) {
+ /* search for passed class as inner class */
+
+ for (i = 0; i < c->innerclasscount; i++) {
+ inner = c->innerclass[i].inner_class;
+ outer = c->innerclass[i].outer_class;
+
+ /* Check if inner is a classref or a real class and get
+ the name of the structure */
+
+ innername = IS_CLASSREF(inner) ? inner.ref->name : inner.cls->name;
+
+ /* innerclass is this class */
+
+ if (innername == c->name) {
+ /* has the class actually an outer class? */
+
+ if (outer.any)
+ /* return flags got from the outer class file */
+ return c->innerclass[i].flags & ACC_CLASS_REFLECT_MASK;
+ else
+ return c->flags & ACC_CLASS_REFLECT_MASK;
+ }
+ }
+ }
+
+ /* passed class is no inner class or it was not requested */
+
+ return c->flags & ACC_CLASS_REFLECT_MASK;
+ }
+
+
+ /* class_get_signature *********************************************************
+
+ Return the signature of the given class. For array and primitive
+ classes return NULL.
+
+ *******************************************************************************/
+
+ #if defined(ENABLE_JAVASE)
+ utf *class_get_signature(classinfo *c)
+ {
+ /* For array and primitive classes return NULL. */
+
+ if (class_is_array(c) || class_is_primitive(c))
+ return NULL;
+
+ return c->signature;
+ }
+ #endif
+
+
+ /* class_printflags ************************************************************
+
+ Prints flags of a class.
+
+ *******************************************************************************/
+
+ #if !defined(NDEBUG)
+ void class_printflags(classinfo *c)
+ {
+ if (c == NULL) {
+ printf("NULL");
+ return;
+ }
+
+ if (c->flags & ACC_PUBLIC) printf(" PUBLIC");
+ if (c->flags & ACC_PRIVATE) printf(" PRIVATE");
+ if (c->flags & ACC_PROTECTED) printf(" PROTECTED");
+ if (c->flags & ACC_STATIC) printf(" STATIC");
+ if (c->flags & ACC_FINAL) printf(" FINAL");
+ if (c->flags & ACC_SYNCHRONIZED) printf(" SYNCHRONIZED");
+ if (c->flags & ACC_VOLATILE) printf(" VOLATILE");
+ if (c->flags & ACC_TRANSIENT) printf(" TRANSIENT");
+ if (c->flags & ACC_NATIVE) printf(" NATIVE");
+ if (c->flags & ACC_INTERFACE) printf(" INTERFACE");
+ if (c->flags & ACC_ABSTRACT) printf(" ABSTRACT");
+ }
+ #endif
+
+
+ /* class_print *****************************************************************
+
+ Prints classname plus flags.
+
+ *******************************************************************************/
+
+ #if !defined(NDEBUG)
+ void class_print(classinfo *c)
+ {
+ if (c == NULL) {
+ printf("NULL");
+ return;
+ }
+
+ utf_display_printable_ascii(c->name);
+ class_printflags(c);
+ }
+ #endif
+
+
+ /* class_classref_print ********************************************************
+
+ Prints classname plus referer class.
+
+ *******************************************************************************/
+
+ #if !defined(NDEBUG)
+ void class_classref_print(constant_classref *cr)
+ {
+ if (cr == NULL) {
+ printf("NULL");
+ return;
+ }
+
+ utf_display_printable_ascii(cr->name);
+ printf("(ref.by ");
+ if (cr->referer)
+ class_print(cr->referer);
+ else
+ printf("NULL");
+ printf(")");
+ }
+ #endif
+
+
+ /* class_println ***************************************************************
+
+ Prints classname plus flags and new line.
+
+ *******************************************************************************/
+
+ #if !defined(NDEBUG)
+ void class_println(classinfo *c)
+ {
+ class_print(c);
+ printf("\n");
+ }
+ #endif
+
+
+ /* class_classref_println ******************************************************
+
+ Prints classname plus referer class and new line.
+
+ *******************************************************************************/
+
+ #if !defined(NDEBUG)
+ void class_classref_println(constant_classref *cr)
+ {
+ class_classref_print(cr);
+ printf("\n");
+ }
+ #endif
+
+
+ /* class_classref_or_classinfo_print *******************************************
+
+ Prints classname plus referer class.
+
+ *******************************************************************************/
+
+ #if !defined(NDEBUG)
+ void class_classref_or_classinfo_print(classref_or_classinfo c)
+ {
+ if (c.any == NULL) {
+ printf("(classref_or_classinfo) NULL");
+ return;
+ }
+ if (IS_CLASSREF(c))
+ class_classref_print(c.ref);
+ else
+ class_print(c.cls);
+ }
+ #endif
+
+
+ /* class_classref_or_classinfo_println *****************************************
+
+ Prints classname plus referer class and a newline.
+
+ *******************************************************************************/
+
+ #if !defined(NDEBUG)
+ void class_classref_or_classinfo_println(classref_or_classinfo c)
+ {
+ class_classref_or_classinfo_print(c);
+ printf("\n");
+ }
+ #endif
+
+
+ /* class_showconstantpool ******************************************************
+
+ Dump the constant pool of the given class to stdout.
+
+ *******************************************************************************/
+
+ #if !defined(NDEBUG)
+ void class_showconstantpool (classinfo *c)
+ {
+ u4 i;
+ void* e;
+
+ printf ("---- dump of constant pool ----\n");
+
+ for (i=0; i<c->cpcount; i++) {
+ printf ("#%d: ", (int) i);
+
+ e = c -> cpinfos [i];
+ if (e) {
+
+ switch (c -> cptags [i]) {
+ case CONSTANT_Class:
+ printf ("Classreference -> ");
+ utf_display_printable_ascii ( ((constant_classref*)e) -> name );
+ break;
+ case CONSTANT_Fieldref:
+ printf ("Fieldref -> ");
+ field_fieldref_print((constant_FMIref *) e);
+ break;
+ case CONSTANT_Methodref:
+ printf ("Methodref -> ");
+ method_methodref_print((constant_FMIref *) e);
+ break;
+ case CONSTANT_InterfaceMethodref:
+ printf ("InterfaceMethod -> ");
+ method_methodref_print((constant_FMIref *) e);
+ break;
+ case CONSTANT_String:
+ printf ("String -> ");
+ utf_display_printable_ascii (e);
+ break;
+ case CONSTANT_Integer:
+ printf ("Integer -> %d", (int) ( ((constant_integer*)e) -> value) );
+ break;
+ case CONSTANT_Float:
+ printf ("Float -> %f", ((constant_float*)e) -> value);
+ break;
+ case CONSTANT_Double:
+ printf ("Double -> %f", ((constant_double*)e) -> value);
+ break;
+ case CONSTANT_Long:
+ {
+ u8 v = ((constant_long*)e) -> value;
+ #if U8_AVAILABLE
+ printf ("Long -> %ld", (long int) v);
+ #else
+ printf ("Long -> HI: %ld, LO: %ld\n",
+ (long int) v.high, (long int) v.low);
+ #endif
+ }
+ break;
+ case CONSTANT_NameAndType:
+ {
+ constant_nameandtype *cnt = e;
+ printf ("NameAndType: ");
+ utf_display_printable_ascii (cnt->name);
+ printf (" ");
+ utf_display_printable_ascii (cnt->descriptor);
+ }
+ break;
+ case CONSTANT_Utf8:
+ printf ("Utf8 -> ");
+ utf_display_printable_ascii (e);
+ break;
+ default:
+ log_text("Invalid type of ConstantPool-Entry");
+ assert(0);
+ }
+ }
+
+ printf ("\n");
+ }
+ }
+ #endif /* !defined(NDEBUG) */
+
+
+ /* class_showmethods ***********************************************************
+
+ Dump info about the fields and methods of the given class to stdout.
+
+ *******************************************************************************/
+
+ #if !defined(NDEBUG)
+ void class_showmethods (classinfo *c)
+ {
+ s4 i;
+
+ printf("--------- Fields and Methods ----------------\n");
+ printf("Flags: ");
+ class_printflags(c);
+ printf("\n");
+
+ printf("This: ");
+ utf_display_printable_ascii(c->name);
+ printf("\n");
+
+ if (c->super) {
+ printf("Super: ");
+ utf_display_printable_ascii(c->super->name);
+ printf ("\n");
+ }
+
+ printf("Index: %d\n", c->index);
+
+ printf("Interfaces:\n");
+ for (i = 0; i < c->interfacescount; i++) {
+ printf(" ");
+ utf_display_printable_ascii(c->interfaces[i]->name);
+ printf (" (%d)\n", c->interfaces[i]->index);
+ }
+
+ printf("Fields:\n");
+ for (i = 0; i < c->fieldscount; i++)
+ field_println(&(c->fields[i]));
+
+ printf("Methods:\n");
+ for (i = 0; i < c->methodscount; i++) {
+ methodinfo *m = &(c->methods[i]);
+
+ if (!(m->flags & ACC_STATIC))
+ printf("vftblindex: %d ", m->vftblindex);
+
+ method_println(m);
+ }
+
+ printf ("Virtual function table:\n");
+ for (i = 0; i < c->vftbl->vftbllength; i++)
+ printf ("entry: %d, %ld\n", i, (long int) (c->vftbl->table[i]));
+ }
+ #endif /* !defined(NDEBUG) */
+
+
+ /*
+ * 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
+ * Emacs will automagically detect them.
+ * ---------------------------------------------------------------------
+ * Local variables:
+ * mode: c
+ * indent-tabs-mode: t
+ * c-basic-offset: 4
+ * tab-width: 4
+ * End:
+ * vim:noexpandtab:sw=4:ts=4:
+ */
--- /dev/null
-
+ /* src/vm/class.h - class related functions header
+
+ Copyright (C) 1996-2005, 2006, 2007, 2008
+ CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
+
+ This file is part of CACAO.
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 2, or (at
+ your option) any later version.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ 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., 51 Franklin Street, Fifth Floor, Boston, MA
+ 02110-1301, USA.
+
+ */
+
+
+ #ifndef _CLASS_H
+ #define _CLASS_H
+
+ #ifdef __cplusplus
+ extern "C" {
+ #endif
+
+ /* forward typedefs ***********************************************************/
+
+ typedef struct classinfo classinfo;
+ typedef struct innerclassinfo innerclassinfo;
+ typedef struct extra_classref extra_classref;
+
+
+ #include "config.h"
+
+ #include <stdint.h>
+
+ #include "vm/types.h"
+
+ #include "toolbox/list.h"
+
+ #if defined(ENABLE_JAVASE)
+ # include "vm/annotation.h"
+ #endif
+
+ #include "vm/field.h"
+ #include "vm/global.h"
+ #include "vm/linker.h"
+ #include "vm/loader.h"
+ #include "vm/method.h"
+ #include "vm/references.h"
+ #include "vm/string.hpp"
+ #include "vm/utf8.h"
+
+ /* class state defines ********************************************************/
+
+ #define CLASS_LOADING 0x0001
+ #define CLASS_LOADED 0x0002
+ #define CLASS_LINKING 0x0004
+ #define CLASS_LINKED 0x0008
+ #define CLASS_INITIALIZING 0x0010
+ #define CLASS_INITIALIZED 0x0020
+ #define CLASS_ERROR 0x0040
+
+
+ /* some macros ****************************************************************/
+
+ #define CLASS_IS_OR_ALMOST_INITIALIZED(c) \
+ (((c)->state & CLASS_INITIALIZING) || ((c)->state & CLASS_INITIALIZED))
+
+
+ /* classinfo ******************************************************************/
+
+ /* We define this dummy structure of java_lang_Class so we can
+ bootstrap cacaoh without needing a java_lang_Class.h file. Whether
+ the size of the dummy structure is big enough is checked during
+ runtime in vm_create. */
+
+ typedef struct {
+ java_object_t header;
+ #if defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
+ intptr_t padding[4];
+ #elif defined(WITH_JAVA_RUNTIME_LIBRARY_OPENJDK)
+ intptr_t padding[19];
+ #elif defined(WITH_JAVA_RUNTIME_LIBRARY_CLDC1_1)
+ intptr_t padding[3];
+ #else
+ # error unknown classpath configuration
+ #endif
+ } dummy_java_lang_Class;
+
+ struct classinfo { /* class structure */
+ dummy_java_lang_Class object;
+
+ s4 flags; /* ACC flags */
+ utf *name; /* class name */
+
+ s4 cpcount; /* number of entries in constant pool */
+ u1 *cptags; /* constant pool tags */
+ void* *cpinfos; /* pointer to constant pool info structures */
+
+ s4 classrefcount; /* number of symbolic class references */
+ constant_classref *classrefs; /* table of symbolic class references */
+ extra_classref *extclassrefs; /* additional classrefs */
+ s4 parseddescsize; /* size of the parsed descriptors block */
+ u1 *parseddescs; /* parsed descriptors */
+
+ classinfo *super; /* super class */
+ classinfo *sub; /* sub class pointer */
+ classinfo *nextsub; /* pointer to next class in sub class list */
+
+ int32_t interfacescount; /* number of interfaces */
+ classinfo **interfaces; /* super interfaces */
+
+ int32_t fieldscount; /* number of fields */
+ fieldinfo *fields; /* field table */
+
+ int32_t methodscount; /* number of methods */
+ methodinfo *methods; /* method table */
+
+ s4 state; /* current class state */
+ s4 index; /* hierarchy depth (classes) or index */
+ /* (interfaces) */
+ s4 instancesize; /* size of an instance of this class */
+
+ vftbl_t *vftbl; /* pointer to virtual function table */
+
+ methodinfo *finalizer; /* finalizer method */
+
+ u2 innerclasscount; /* number of inner classes */
+ innerclassinfo *innerclass;
+
+ classref_or_classinfo declaringclass;
+ classref_or_classinfo enclosingclass; /* enclosing class */
+ constant_nameandtype *enclosingmethod; /* enclosing method */
+
+ utf *packagename; /* full name of the package */
+ utf *sourcefile; /* SourceFile attribute */
+ #if defined(ENABLE_JAVASE)
+ utf *signature; /* Signature attribute */
+ #if defined(ENABLE_ANNOTATIONS)
+ /* All the annotation attributes are NULL (and not a zero length array) */
+ /* if there is nothing. */
+ java_object_t *annotations; /* annotations of this class */
+
+ java_object_t *method_annotations; /* array of annotations of the methods */
+ java_object_t *method_parameterannotations; /* array of parameter */
+ /* annotations of the methods */
+ java_object_t *method_annotationdefaults; /* array of annotation default */
+ /* values of the methods */
+
+ java_object_t *field_annotations; /* array of annotations of the fields */
+
+ #endif
+ #endif
+ classloader_t *classloader; /* NULL for bootstrap classloader */
+
+ #if defined(ENABLE_JAVASE)
+ # if defined(WITH_JAVA_RUNTIME_LIBRARY_OPENJDK)
+ java_object_t *protectiondomain;
+ java_objectarray_t *signers;
+ # endif
+ #endif
++#if defined(ENABLE_JITCACHE)
++ int cache_file_fd;
++#endif
+ };
+
+
+ /* innerclassinfo *************************************************************/
+
+ struct innerclassinfo {
+ classref_or_classinfo inner_class; /* inner class pointer */
+ classref_or_classinfo outer_class; /* outer class pointer */
+ utf *name; /* innerclass name */
+ s4 flags; /* ACC flags */
+ };
+
+
+ /* extra_classref **************************************************************
+
+ for classrefs not occurring within descriptors
+
+ *******************************************************************************/
+
+ struct extra_classref {
+ extra_classref *next;
+ constant_classref classref;
+ };
+
+
+ /* inline functions ***********************************************************/
+
+ /**
+ * Returns the classname of the class, where slashes ('/') are
+ * replaced by dots ('.').
+ *
+ * @param c class to get name of
+ * @return classname
+ */
+ inline static java_handle_t* class_get_classname(classinfo* c)
+ {
+ java_handle_t *s;
+
+ /* Create a java string. */
+
+ s = javastring_new_slash_to_dot(c->name);
+
+ return s;
+ }
+
+
+ /* class_is_primitive **********************************************************
+
+ Checks if the given class is a primitive class.
+
+ *******************************************************************************/
+
+ static inline bool class_is_primitive(classinfo *c)
+ {
+ if (c->flags & ACC_CLASS_PRIMITIVE)
+ return true;
+
+ return false;
+ }
+
+
+ /* class_is_anonymousclass *****************************************************
+
+ Checks if the given class is an anonymous class.
+
+ *******************************************************************************/
+
+ static inline bool class_is_anonymousclass(classinfo *c)
+ {
+ if (c->flags & ACC_CLASS_ANONYMOUS)
+ return true;
+
+ return false;
+ }
+
+
+ /* class_is_array **************************************************************
+
+ Checks if the given class is an array class.
+
+ *******************************************************************************/
+
+ static inline bool class_is_array(classinfo *c)
+ {
+ if (!(c->state & CLASS_LINKED))
+ if (!link_class(c))
+ return false;
+
+ return (c->vftbl->arraydesc != NULL);
+ }
+
+
+ /* class_is_interface **********************************************************
+
+ Checks if the given class is an interface.
+
+ *******************************************************************************/
+
+ static inline bool class_is_interface(classinfo *c)
+ {
+ if (c->flags & ACC_INTERFACE)
+ return true;
+
+ return false;
+ }
+
+
+ /* class_is_localclass *********************************************************
+
+ Checks if the given class is a local class.
+
+ *******************************************************************************/
+
+ static inline bool class_is_localclass(classinfo *c)
+ {
+ if ((c->enclosingmethod != NULL) && !class_is_anonymousclass(c))
+ return true;
+
+ return false;
+ }
+
+
+ /* class_is_memberclass ********************************************************
+
+ Checks if the given class is a member class.
+
+ *******************************************************************************/
+
+ static inline bool class_is_memberclass(classinfo *c)
+ {
+ if (c->flags & ACC_CLASS_MEMBER)
+ return true;
+
+ return false;
+ }
+
+
+ /* class_get_classloader *******************************************************
+
+ Return the classloader of the given class.
+
+ *******************************************************************************/
+
+ static inline classloader_t *class_get_classloader(classinfo *c)
+ {
+ classloader_t *cl;
+
+ cl = c->classloader;
+
+ /* The classloader may be NULL. */
+
+ return cl;
+ }
+
+
+ /* class_get_superclass ********************************************************
+
+ Return the super class of the given class.
+
+ *******************************************************************************/
+
+ static inline classinfo *class_get_superclass(classinfo *c)
+ {
+ /* For interfaces we return NULL. */
+
+ if (c->flags & ACC_INTERFACE)
+ return NULL;
+
+ /* For java/lang/Object, primitive-type and Void classes c->super
+ is NULL and we return NULL. */
+
+ return c->super;
+ }
+
+
+ /* function prototypes ********************************************************/
+
+ classinfo *class_create_classinfo(utf *u);
+ void class_postset_header_vftbl(void);
+ classinfo *class_define(utf *name, classloader_t *cl, int32_t length, uint8_t *data, java_handle_t *pd);
+ void class_set_packagename(classinfo *c);
+
+ bool class_load_attributes(classbuffer *cb);
+
+ /* retrieve constantpool element */
+ void* class_getconstant(classinfo *c, u4 pos, u4 ctype);
+ void* innerclass_getconstant(classinfo *c, u4 pos, u4 ctype);
+
+ /* frees all resources used by the class */
+ void class_free(classinfo *);
+
+ /* return an array class with the given component class */
+ classinfo *class_array_of(classinfo *component,bool link);
+
+ /* return an array class with the given dimension and element class */
+ classinfo *class_multiarray_of(s4 dim, classinfo *element,bool link);
+
+ /* return a classref for the given class name */
+ /* (does a linear search!) */
+ constant_classref *class_lookup_classref(classinfo *cls,utf *name);
+
+ /* return a classref for the given class name */
+ /* (does a linear search!) */
+ constant_classref *class_get_classref(classinfo *cls,utf *name);
+
+ /* return a classref to the class itself */
+ /* (does a linear search!) */
+ constant_classref *class_get_self_classref(classinfo *cls);
+
+ /* return a classref for an array with the given dimension of with the */
+ /* given component type */
+ constant_classref *class_get_classref_multiarray_of(s4 dim,constant_classref *ref);
+
+ /* return a classref for the component type of the given array type */
+ constant_classref *class_get_classref_component_of(constant_classref *ref);
+
+ /* get a class' field by name and descriptor */
+ fieldinfo *class_findfield(classinfo *c, utf *name, utf *desc);
+
+ /* search 'classinfo'-structure for a field with the specified name */
+ fieldinfo *class_findfield_by_name(classinfo *c, utf *name);
+
+ /* search class for a field */
+ fieldinfo *class_resolvefield(classinfo *c, utf *name, utf *desc, classinfo *referer);
+
+ /* search for a method with a specified name and descriptor */
+ methodinfo *class_findmethod(classinfo *c, utf *name, utf *desc);
+ methodinfo *class_resolvemethod(classinfo *c, utf *name, utf *dest);
+ methodinfo *class_resolveclassmethod(classinfo *c, utf *name, utf *dest, classinfo *referer, bool throwexception);
+ methodinfo *class_resolveinterfacemethod(classinfo *c, utf *name, utf *dest, classinfo *referer, bool throwexception);
+
+ bool class_issubclass(classinfo *sub, classinfo *super);
+ bool class_isanysubclass(classinfo *sub, classinfo *super);
+ bool class_is_assignable_from(classinfo *to, classinfo *from);
+ bool class_is_instance(classinfo *c, java_handle_t *h);
+
+ classloader_t *class_get_classloader(classinfo *c);
+ classinfo *class_get_superclass(classinfo *c);
+ classinfo *class_get_componenttype(classinfo *c);
+ java_handle_objectarray_t *class_get_declaredclasses(classinfo *c, bool publicOnly);
+ java_handle_objectarray_t *class_get_declaredconstructors(classinfo *c, bool publicOnly);
+ java_handle_objectarray_t *class_get_declaredfields(classinfo *c, bool publicOnly);
+ java_handle_objectarray_t *class_get_declaredmethods(classinfo *c, bool publicOnly);
+ classinfo *class_get_declaringclass(classinfo *c);
+ classinfo *class_get_enclosingclass(classinfo *c);
+ java_handle_t* class_get_enclosingconstructor(classinfo *c);
+ methodinfo* class_get_enclosingmethod_raw(classinfo *c);
+ java_handle_t* class_get_enclosingmethod(classinfo *c);
+ java_handle_objectarray_t *class_get_interfaces(classinfo *c);
+ java_handle_bytearray_t *class_get_annotations(classinfo *c);
+ int32_t class_get_modifiers(classinfo *c, bool ignoreInnerClassesAttrib);
+ java_handle_t *class_get_name(classinfo *c);
+
+ #if defined(ENABLE_JAVASE)
+ utf *class_get_signature(classinfo *c);
+ #endif
+
+ /* some debugging functions */
+
+ #if !defined(NDEBUG)
+ void class_printflags(classinfo *c);
+ void class_print(classinfo *c);
+ void class_println(classinfo *c);
+ void class_classref_print(constant_classref *cr);
+ void class_classref_println(constant_classref *cr);
+ void class_classref_or_classinfo_print(classref_or_classinfo c);
+ void class_classref_or_classinfo_println(classref_or_classinfo c);
+ #endif
+
+ /* debug purposes */
+ void class_showmethods(classinfo *c);
+ void class_showconstantpool(classinfo *c);
+
+ #ifdef __cplusplus
+ }
+ #endif
+
+ #endif /* _CLASS_H */
+
+
+ /*
+ * 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
+ * Emacs will automagically detect them.
+ * ---------------------------------------------------------------------
+ * Local variables:
+ * mode: c
+ * indent-tabs-mode: t
+ * c-basic-offset: 4
+ * tab-width: 4
+ * End:
+ */
trap.h
endif
+if ENABLE_JITCACHE
+JITCACHE_SOURCES = \
+ jitcache.c \
+ jitcache.h
+
+endif
+
+
if ENABLE_REPLACEMENT
REPLACE_SOURCES += \
replace.c
verify/libverify.la
endif
+ if ENABLE_OPAGENT
+ OPAGENT_SOURCES = \
+ oprofile-agent.cpp \
+ oprofile-agent.hpp
+
+ endif
+
if WITH_BINUTILS_DISASSEMBLER
DISASS_SOURCES = disass-common.c
endif
patcher-common.h \
$(RECOMPILE_SOURCES) \
$(REG_SOURCES) \
+ $(JITCACHE_SOURCES) \
$(REPLACE_SOURCES) \
show.c \
show.h \
$(STACK_SOURCES) \
- stacktrace.c \
- stacktrace.h \
- trace.c \
- trace.h \
- $(TRAP_SOURCES)
+ stacktrace.cpp \
+ stacktrace.hpp \
+ trace.cpp \
+ trace.hpp \
+ $(TRAP_SOURCES) \
+ $(OPAGENT_SOURCES)
libjit_la_SOURCES += \
cfg.c \
#include "threads/lock-common.h"
#include "vm/builtin.h"
- #include "vm/exceptions.h"
+ #include "vm/exceptions.hpp"
#include "vm/global.h"
- #include "vm/vm.h"
+ #include "vm/loader.h"
+ #include "vm/options.h"
+ #include "vm/vm.hpp"
#include "vm/jit/abi.h"
#include "vm/jit/asmpart.h"
#include "vm/jit/dseg.h"
#include "vm/jit/emit-common.h"
#include "vm/jit/jit.h"
+#include "vm/jit/jitcache.h"
#include "vm/jit/linenumbertable.h"
#include "vm/jit/methodheader.h"
#include "vm/jit/parse.h"
#include "vm/jit/allocator/lsra.h"
#endif
- #include "vmcore/loader.h"
- #include "vmcore/options.h"
-
/* codegen_emit ****************************************************************
/* SECTION: Method Header */
/* create method header */
+#if defined(ENABLE_JITCACHE)
+ disp = dseg_add_unique_address(cd, code); /* CodeinfoPointer */
+ jitcache_add_cached_ref(code, CRT_CODEINFO, 0, disp);
+#else
(void) dseg_add_unique_address(cd, code); /* CodeinfoPointer */
+#endif
+
(void) dseg_add_unique_s4(cd, cd->stackframesize); /* FrameSize */
code->synchronizedoffset = rd->memuse * 8;
if (m->flags & ACC_STATIC) {
disp = dseg_add_address(cd, &m->clazz->object.header);
+ JITCACHE_ADD_CACHED_REF(code, CRT_OBJECT_HEADER, m->clazz, disp);
M_DSEG_LOAD(REG_A0, disp);
}
else {
M_STR(REG_A0, REG_SP, s1);
disp = dseg_add_functionptr(cd, LOCK_monitor_enter);
+ JITCACHE_ADD_CACHED_REF(code,
+ CRT_BUILTIN_FP, builtintable_get_internal(LOCK_monitor_enter), disp);
M_DSEG_BRANCH(disp);
s1 = (s4) (cd->mcodeptr - cd->mcodebase);
M_RECOMPUTE_PV(s1);
M_DSEG_LOAD(d, disp);
}
else {
+#if defined(ENABLE_JITCACHE)
+ /* Dealing with ICONST and the JIT cache is tricky because
+ * ICONST generates different code depending on the value of the
+ * number. We therefore go the slightly less optimal way and
+ * generate an entry in the data segment.
+ * For the null constant however we use the plain integer load.
+ */
+ if (iptr->sx.val.anyptr)
+ {
+ disp = dseg_add_unique_address(cd, iptr->sx.val.anyptr);
+
+ jitcache_add_cached_ref(code,
+ (iptr->flags.bits & INS_FLAG_CLASS) ? CRT_CLASSINFO
+ : CRT_STRING,
+ (iptr->flags.bits & INS_FLAG_CLASS) ? iptr->sx.val.c.cls
+ : iptr->sx.val.stringconst,
+ disp);
+
+ M_DSEG_LOAD(d, disp);
+ }
+ else {
+ ICONST(d, (u4) 0);
+ }
+
+#else
ICONST(d, (u4) iptr->sx.val.anyptr);
+#endif
}
emit_store_dst(jd, iptr, d);
break;
/* call builtin function */
bte = iptr->sx.s23.s3.bte;
disp = dseg_add_functionptr(cd, bte->fp);
+ JITCACHE_ADD_CACHED_REF(code, CRT_BUILTIN_FP, bte, disp);
M_DSEG_BRANCH(disp);
/* recompute pv */
/* call builtin function */
bte = iptr->sx.s23.s3.bte;
disp = dseg_add_functionptr(cd, bte->fp);
+ JITCACHE_ADD_CACHED_REF(code, CRT_BUILTIN_FP, bte, disp);
M_DSEG_BRANCH(disp);
/* recompute pv */
/* call builtin function */
disp = dseg_add_functionptr(cd, BUILTIN_FAST_canstore);
+ JITCACHE_ADD_CACHED_REF(
+ code, CRT_BUILTIN_FP,
+ builtintable_get_internal(BUILTIN_FAST_canstore), disp);
+
M_DSEG_BRANCH(disp);
/* recompute pv */
fi = iptr->sx.s23.s3.fmiref->p.field;
fieldtype = fi->type;
disp = dseg_add_address(cd, fi->value);
-
+ JITCACHE_ADD_CACHED_REF(code, CRT_FIELDINFO_VALUE, fi, disp);
if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->clazz)) {
patcher_add_patch_ref(jd, PATCHER_initialize_class,
fi->clazz, 0);
fi = iptr->sx.s23.s3.fmiref->p.field;
fieldtype = fi->type;
disp = dseg_add_address(cd, fi->value);
-
+ JITCACHE_ADD_CACHED_REF(code, CRT_FIELDINFO_VALUE, fi, disp);
if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->clazz)) {
patcher_add_patch_ref(jd, PATCHER_initialize_class,
fi->clazz, 0);
iptr->sx.s23.s2.uc, 0);
}
disp = dseg_add_functionptr(cd, asm_handle_exception);
+ JITCACHE_ADD_CACHED_REF(code, CRT_ASM_HANDLE_EXCEPTION, NULL, disp);
M_DSEG_LOAD(REG_ITMP3, disp);
M_MOV(REG_ITMP2_XPC, REG_PC);
M_MOV(REG_PC, REG_ITMP3);
M_LDR(REG_A0, REG_SP, s1);
disp = dseg_add_functionptr(cd, LOCK_monitor_exit);
+ JITCACHE_ADD_CACHED_REF(code,
+ CRT_BUILTIN_FP, builtintable_get_internal(LOCK_monitor_exit),
+ disp);
+
M_DSEG_BRANCH(disp);
/* we no longer need PV here, no more loading */
disp = dseg_add_functionptr(cd, bte->stub);
}
+ JITCACHE_ADD_CACHED_REF(code, CRT_BUILTIN, bte, disp);
+
M_DSEG_LOAD(REG_PV, disp); /* pointer to built-in-function */
/* generate the actual call */
um, disp);
}
else
+ {
disp = dseg_add_address(cd, lm->stubroutine);
+ JITCACHE_ADD_CACHED_REF(code, CRT_METHODINFO_STUBROUTINE, lm, disp);
+ }
M_DSEG_LOAD(REG_PV, disp); /* Pointer to method */
case ICMD_INVOKEVIRTUAL:
if (lm == NULL) {
+
patcher_add_patch_ref(jd, PATCHER_invokevirtual, um, 0);
s1 = 0;
else
s1 = OFFSET(vftbl_t, table[0]) +
sizeof(methodptr) * lm->vftblindex;
+
/* implicit null-pointer check */
M_LDR_INTERN(REG_METHODPTR, REG_A0,
OFFSET(java_object_t, vftbl));
M_LDR_INTERN(REG_PV, REG_METHODPTR, s1);
-
/* generate the actual call */
M_MOV(REG_LR, REG_PC);
M_LDR_INTERN(REG_METHODPTR, REG_A0,
OFFSET(java_object_t, vftbl));
M_LDR_INTERN(REG_METHODPTR, REG_METHODPTR, s1);
+
M_LDR_INTERN(REG_PV, REG_METHODPTR, s2);
+ JITCACHE_ADD_CACHED_REF_MD_JD(jd, CRT_METHODINFO_METHODOFFSET, 1, lm);
/* generate the actual call */
superindex = super->index;
}
- if ((super == NULL) || !(super->flags & ACC_INTERFACE))
- CODEGEN_CRITICAL_SECTION_NEW;
-
s1 = emit_load_s1(jd, iptr, REG_ITMP1);
/* if class is not resolved, check which code to call */
iptr->sx.s23.s3.c.ref, disp);
}
else {
+/*
+ JITCACHE_ADD_CACHED_REF_JD(jd, CRT_CLASSINFO_INDEX, super, disp);
+*/
M_TST(s1, s1);
emit_label_beq(cd, BRANCH_LABEL_3);
}
}
else {
disp = dseg_add_address(cd, super->vftbl);
-
+ JITCACHE_ADD_CACHED_REF(code, CRT_CLASSINFO_VFTBL, super, disp);
M_TST(s1, s1);
emit_label_beq(cd, BRANCH_LABEL_5);
}
M_LDR_INTERN(REG_ITMP2, s1, OFFSET(java_object_t, vftbl));
M_DSEG_LOAD(REG_ITMP3, disp);
- CODEGEN_CRITICAL_SECTION_START;
-
M_LDR_INTERN(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, baseval));
M_LDR_INTERN(REG_ITMP3, REG_ITMP3, OFFSET(vftbl_t, baseval));
M_SUB(REG_ITMP2, REG_ITMP2, REG_ITMP3);
M_DSEG_LOAD(REG_ITMP3, disp);
M_LDR_INTERN(REG_ITMP3, REG_ITMP3, OFFSET(vftbl_t, diffval));
- CODEGEN_CRITICAL_SECTION_END;
-
M_CMP(REG_ITMP2, REG_ITMP3);
emit_classcast_check(cd, iptr, BRANCH_UGT, 0, s1);
disp);
}
else
+ {
disp = dseg_add_address(cd, iptr->sx.s23.s3.c.cls);
+ JITCACHE_ADD_CACHED_REF(code, CRT_CLASSINFO, iptr->sx.s23.s3.c.cls, disp);
+ }
M_DSEG_LOAD(REG_A1, disp);
disp = dseg_add_functionptr(cd, BUILTIN_arraycheckcast);
+ JITCACHE_ADD_CACHED_REF(code, CRT_BUILTIN, builtintable_get_internal(BUILTIN_arraycheckcast), disp);
M_DSEG_BRANCH(disp);
/* recompute pv */
superindex = super->index;
}
- if ((super == NULL) || !(super->flags & ACC_INTERFACE))
- CODEGEN_CRITICAL_SECTION_NEW;
-
s1 = emit_load_s1(jd, iptr, REG_ITMP1);
d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
iptr->sx.s23.s3.c.ref, disp);
}
else {
+/* TODO: Not needed?
+ JITCACHE_ADD_CACHED_REF(code, CRT_CLASSINFO_INDEX, super, disp);
+*/
M_EOR(d, d, d);
M_TST(s1, s1);
emit_label_beq(cd, BRANCH_LABEL_3);
}
else {
disp = dseg_add_address(cd, super->vftbl);
+ JITCACHE_ADD_CACHED_REF(code, CRT_CLASSINFO_VFTBL, super, disp);
M_EOR(d, d, d);
M_TST(s1, s1);
M_LDR_INTERN(REG_ITMP1, s1, OFFSET(java_object_t, vftbl));
M_DSEG_LOAD(REG_ITMP2, disp);
- CODEGEN_CRITICAL_SECTION_START;
-
M_LDR_INTERN(REG_ITMP1, REG_ITMP1, OFFSET(vftbl_t, baseval));
M_LDR_INTERN(REG_ITMP3, REG_ITMP2, OFFSET(vftbl_t, baseval));
M_LDR_INTERN(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, diffval));
- CODEGEN_CRITICAL_SECTION_END;
-
M_SUB(REG_ITMP1, REG_ITMP1, REG_ITMP3);
M_CMP(REG_ITMP1, REG_ITMP2);
/* If d == REG_ITMP2, then it's destroyed */
iptr->sx.s23.s3.c.ref, disp);
}
else
+ {
disp = dseg_add_address(cd, iptr->sx.s23.s3.c.cls);
+ JITCACHE_ADD_CACHED_REF(code, CRT_CLASSINFO, iptr->sx.s23.s3.c.cls, disp);
+ }
/* a1 = arraydescriptor */
/* call builtin_multianewarray here */
disp = dseg_add_functionptr(cd, BUILTIN_multianewarray);
+ /*
+ * For some unknown reason this causes an illegal instruction.
+ * JITCACHE_ADD_CACHED_REF(code, CRT_BUILTIN, builtintable_get_internal(BUILTIN_multianewarray), disp);
+ */
+
M_DSEG_BRANCH(disp);
/* recompute pv */
/* put env into first argument register */
- disp = dseg_add_address(cd, _Jv_env);
+ disp = dseg_add_address(cd, VM_get_jnienv());
M_DSEG_LOAD(REG_A0, disp);
}
#include "native/native.h"
#include "vm/builtin.h"
- #include "vm/exceptions.h"
+ #include "vm/class.h"
+ #include "vm/field.h"
#include "vm/initialize.h"
+ #include "vm/options.h"
+ #include "vm/references.h"
+ #include "vm/resolve.h"
#include "vm/jit/asmpart.h"
#include "vm/jit/patcher-common.h"
- #include "vmcore/field.h"
- #include "vmcore/options.h"
- #include "vmcore/references.h"
- #include "vm/resolve.h"
-
#define PATCH_BACK_ORIGINAL_MCODE \
*((u4 *) pr->mpc) = (u4) pr->mcode; \
/*(inst) |= (1 << 23);*/ \
}
+/* This is the same as gen_resolveload but does not check whether the opcode
+ * is 'clean' (= current offset is zero).
+ */
+#define gen_resolveload_unchecked(inst,offset) \
+ assert((offset) >= -0x0fff && (offset) <= 0x0fff); \
+ if ((offset) < 0) { \
+ (inst) = ((inst) & 0xff7ff000) | ((-(offset)) & 0x0fff); \
+ /*(inst) &= ~(1 << 23);*/ \
+ } else { \
+ (inst) = ((inst) & 0xfffff000) | ((offset) & 0x0fff); \
+ /*(inst) |= (1 << 23);*/ \
+ }
+
+/* patch_md ********************************************************************
+
+ Patch back address in a machine dependent way
+
+*******************************************************************************/
+void patch_md(s4 md_patch, ptrint dest, voidptr ref)
+{
+ gen_resolveload_unchecked(*((s4 *) dest), (s4) ref);
+}
/* patcher_patch_code **********************************************************
#include "mm/memory.h"
- #include "vm/vm.h"
+ #include "vm/options.h"
+ #include "vm/vm.hpp"
#include "vm/jit/code.h"
#include "vm/jit/codegen-common.h"
-#include "vm/jit/patcher-common.h"
+#include "vm/jit/jitcache.h"
#include "vm/jit/methodtree.h"
+#include "vm/jit/patcher-common.h"
- #include "vmcore/options.h"
-
/* code_init *******************************************************************
The following fields are set in codeinfo:
m
patchers
+ cachedrefs
RETURN VALUE:
a new, initialized codeinfo, or
patcher_list_create(code);
-#if defined(ENABLE_STATISTICS)
+#if defined (ENABLE_JITCACHE)
+ jitcache_list_create(code);
+#endif
+
+#if defined (ENABLE_STATISTICS)
if (opt_stat)
size_codeinfo += sizeof(codeinfo);
#endif
patcher_list_free(code);
+#if defined(ENABLE_JITCACHE)
+ jitcache_list_free(code);
+#endif
+
#if defined(ENABLE_REPLACEMENT)
replace_free_replacement_points(code);
#endif
#include "toolbox/list.h"
#include "vm/global.h"
+ #include "vm/method.h"
#include "vm/jit/exceptiontable.h"
#include "vm/jit/linenumbertable.h"
#include "vm/jit/methodheader.h"
#include "vm/jit/replace.h"
- #include "vmcore/method.h"
-
/* constants ******************************************************************/
#define CODE_FLAG_INVALID 0x0001
#define CODE_FLAG_LEAFMETHOD 0x0002
#define CODE_FLAG_SYNCHRONIZED 0x0004
+ #define CODE_FLAG_TLH 0x0008
/* codeinfo *******************************************************************
/* patcher list */
list_t *patchers;
+#if defined (ENABLE_JITCACHE)
+ list_t *cachedrefs;
+#endif
+
/* replacement */
s4 stackframesize; /* size of the stackframe in slots */
#include <assert.h>
#include <string.h>
+#include "vm/jit/jitcache.h"
+
#include "vm/types.h"
#include "codegen.h"
#include "native/localref.h"
#include "native/native.h"
- #if defined(WITH_JAVA_RUNTIME_LIBRARY_OPENJDK)
- # include "native/include/java_lang_Object.h"
- # include "native/include/java_lang_String.h" /* required by j.l.CL */
- # include "native/include/java_nio_ByteBuffer.h" /* required by j.l.CL */
- # include "native/include/java_lang_ClassLoader.h"
- #endif
+ #include "threads/thread.hpp"
- #if defined(WITH_JAVA_RUNTIME_LIBRARY_CLDC1_1)
- # include "native/include/java_lang_String.h"
- #endif
+ #include "vm/builtin.h"
+ #include "vm/exceptions.hpp"
+ #include "vm/method.h"
+ #include "vm/options.h"
+ #include "vm/string.hpp"
- #include "native/include/java_lang_Class.h"
+ # include "vm/statistics.h"
- #include "threads/thread.h"
-
- #include "vm/builtin.h"
- #include "vm/exceptions.h"
- #include "vm/stringlocal.h"
#include "vm/jit/abi.h"
#include "vm/jit/asmpart.h"
# include "vm/jit/optimizing/lsra.h"
# include "vm/jit/optimizing/ssa.h"
#endif
- #include "vm/jit/stacktrace.h"
- #include "vm/jit/trace.h"
+ #include "vm/jit/stacktrace.hpp"
+ #include "vm/jit/trace.hpp"
#if defined(ENABLE_INTRP)
#include "vm/jit/intrp/intrp.h"
#endif
- #include "vmcore/method.h"
- #include "vmcore/options.h"
-
- # include "vmcore/statistics.h"
-
#if defined(ENABLE_VMLOG)
#include <vmlog_cacao.h>
#endif
#endif
cd->brancheslabel = list_create_dump(OFFSET(branch_label_ref_t, linkage));
- cd->listcritical = list_create_dump(OFFSET(critical_section_ref_t, linkage));
cd->linenumbers = list_create_dump(OFFSET(linenumbertable_list_entry_t, linkage));
}
#endif
cd->brancheslabel = list_create_dump(OFFSET(branch_label_ref_t, linkage));
- cd->listcritical = list_create_dump(OFFSET(critical_section_ref_t, linkage));
cd->linenumbers = list_create_dump(OFFSET(linenumbertable_list_entry_t, linkage));
/* We need to clear the mpc and the branch references from all
}
- /* codegen_critical_section_new ************************************************
-
- Allocates a new critical-section reference and adds it to the
- critical-section list.
-
- *******************************************************************************/
-
- #if defined(ENABLE_THREADS)
- void codegen_critical_section_new(codegendata *cd)
- {
- list_t *l;
- critical_section_ref_t *csr;
- s4 mpc;
-
- /* Get the critical section list. */
-
- l = cd->listcritical;
-
- /* calculate the current mpc */
-
- mpc = cd->mcodeptr - cd->mcodebase;
-
- csr = DNEW(critical_section_ref_t);
-
- /* We only can set restart right now, as start and end are set by
- the following, corresponding functions. */
-
- csr->start = -1;
- csr->end = -1;
- csr->restart = mpc;
-
- /* Add the branch to the list. */
-
- list_add_last(l, csr);
- }
- #endif
-
-
- /* codegen_critical_section_start **********************************************
-
- Set the start-point of the current critical section (which is the
- last element of the list).
-
- *******************************************************************************/
-
- #if defined(ENABLE_THREADS)
- void codegen_critical_section_start(codegendata *cd)
- {
- list_t *l;
- critical_section_ref_t *csr;
- s4 mpc;
-
- /* Get the critical section list. */
-
- l = cd->listcritical;
-
- /* calculate the current mpc */
-
- mpc = cd->mcodeptr - cd->mcodebase;
-
- /* Get the current critical section. */
-
- csr = list_last(l);
-
- /* set the start point */
-
- assert(csr->start == -1);
-
- csr->start = mpc;
- }
- #endif
-
-
- /* codegen_critical_section_end ************************************************
-
- Set the end-point of the current critical section (which is the
- last element of the list).
-
- *******************************************************************************/
-
- #if defined(ENABLE_THREADS)
- void codegen_critical_section_end(codegendata *cd)
- {
- list_t *l;
- critical_section_ref_t *csr;
- s4 mpc;
-
- /* Get the critical section list. */
-
- l = cd->listcritical;
-
- /* calculate the current mpc */
-
- mpc = cd->mcodeptr - cd->mcodebase;
-
- /* Get the current critical section. */
-
- csr = list_last(l);
-
- /* set the end point */
-
- assert(csr->end == -1);
-
- csr->end = mpc;
- }
- #endif
-
-
- /* codegen_critical_section_finish *********************************************
-
- Finish the critical sections, create the critical section nodes for
- the AVL tree and insert them into the tree.
-
- *******************************************************************************/
-
- #if defined(ENABLE_THREADS)
- static void codegen_critical_section_finish(jitdata *jd)
- {
- codeinfo *code;
- codegendata *cd;
- list_t *l;
- critical_section_ref_t *csr;
- critical_section_node_t *csn;
-
- /* get required compiler data */
-
- code = jd->code;
- cd = jd->cd;
-
- /* Get the critical section list. */
-
- l = cd->listcritical;
-
- /* iterate over all critical sections */
-
- for (csr = list_first(l); csr != NULL; csr = list_next(l, csr)) {
- /* check if all points are set */
-
- assert(csr->start != -1);
- assert(csr->end != -1);
- assert(csr->restart != -1);
-
- /* allocate tree node */
-
- csn = NEW(critical_section_node_t);
-
- csn->start = code->entrypoint + csr->start;
- csn->end = code->entrypoint + csr->end;
- csn->restart = code->entrypoint + csr->restart;
-
- /* insert into the tree */
-
- critical_section_register(csn);
- }
- }
- #endif
-
-
/* codegen_set_replacement_point_notrap ****************************************
Record the position of a non-trappable replacement point.
/* jump table resolving */
for (jr = cd->jumpreferences; jr != NULL; jr = jr->next)
+ {
*((functionptr *) ((ptrint) epoint + jr->tablepos)) =
(functionptr) ((ptrint) epoint + (ptrint) jr->target->mpc);
+ JITCACHE_ADD_CACHED_REF(code, CRT_JUMPREFERENCE, jr->target->mpc, jr->tablepos);
+ }
+
/* patcher resolving */
patcher_resolve(jd);
dseg_resolve_datareferences(jd);
#endif
- #if defined(ENABLE_THREADS)
- /* create cirtical sections */
-
- codegen_critical_section_finish(jd);
- #endif
-
/* flush the instruction and data caches */
md_cacheflush(code->mcode, code->mcodelength);
#include "threads/lock-common.h"
#include "vm/builtin.h"
- #include "vm/exceptions.h"
+ #include "vm/exceptions.hpp"
#include "vm/global.h"
- #include "vm/primitive.h"
- #include "vm/stringlocal.h"
- #include "vm/vm.h"
+ #include "vm/loader.h"
+ #include "vm/options.h"
+ #include "vm/primitive.hpp"
+ #include "vm/utf8.h"
+ #include "vm/vm.hpp"
#include "vm/jit/abi.h"
#include "vm/jit/asmpart.h"
#include "vm/jit/dseg.h"
#include "vm/jit/emit-common.h"
#include "vm/jit/jit.h"
++#include "vm/jit/jitcache.h"
#include "vm/jit/linenumbertable.h"
#include "vm/jit/parse.h"
#include "vm/jit/patcher-common.h"
#include "vm/jit/reg.h"
#include "vm/jit/replace.h"
- #include "vm/jit/stacktrace.h"
-
- #include "vm/jit/jitcache.h"
+ #include "vm/jit/stacktrace.hpp"
#include "vm/jit/trap.h"
#if defined(ENABLE_SSA)
# include "vm/jit/allocator/lsra.h"
#endif
- #include "vmcore/loader.h"
- #include "vmcore/options.h"
- #include "vmcore/utf8.h"
-
/* codegen_emit ****************************************************************
savedregs_num += (FLT_SAV_CNT - rd->savfltreguse);
cd->stackframesize = rd->memuse + savedregs_num;
-
#if defined(ENABLE_THREADS)
/* space to save argument of monitor_enter */
align_off = cd->stackframesize ? 4 : 0;
+#if defined(ENABLE_JITCACHE)
+ disp = dseg_add_unique_address(cd, code); /* CodeinfoPointer */
+ jitcache_add_cached_ref(code, CRT_CODEINFO, 0, disp);
+#else
(void) dseg_add_unique_address(cd, code); /* CodeinfoPointer */
+#endif
(void) dseg_add_unique_s4(
cd, cd->stackframesize * 8 + align_off); /* FrameSize */
/* count frequency */
M_MOV_IMM(code, REG_ITMP3);
+ JITCACHE_ADD_CACHED_REF_JD(jd, CRT_CODEINFO, NULL);
+
M_IADD_IMM_MEMBASE(1, REG_ITMP3, OFFSET(codeinfo, frequency));
}
#endif
if (m->flags & ACC_STATIC) {
M_MOV_IMM(&m->clazz->object.header, REG_ITMP1);
+ JITCACHE_ADD_CACHED_REF_JD(jd, CRT_OBJECT_HEADER, m->clazz);
}
else {
M_ALD(REG_ITMP1, REG_SP, cd->stackframesize * 8 + 4 + align_off);
M_AST(REG_ITMP1, REG_SP, s1 * 8);
M_AST(REG_ITMP1, REG_SP, 0 * 4);
M_MOV_IMM(LOCK_monitor_enter, REG_ITMP3);
+ JITCACHE_ADD_CACHED_REF_JD(jd, CRT_BUILTIN_FP,
+ builtintable_get_internal(LOCK_monitor_enter));
M_CALL(REG_ITMP3);
}
#endif
if (bptr->bitflags & BBFLAG_REPLACEMENT) {
if (cd->replacementpoint[-1].flags & RPLPOINT_FLAG_COUNTDOWN) {
MCODECHECK(32);
- disp = (s4) &(m->hitcountdown);
- M_ISUB_IMM_MEMABS(1, disp);
- M_BS(0);
+ emit_trap_countdown(cd, &(m->hitcountdown));
}
}
#endif
disp = dseg_add_float(cd, iptr->sx.val.f);
emit_mov_imm_reg(cd, 0, REG_ITMP1);
dseg_adddata(cd);
+ JITCACHE_ADD_CACHED_REF_JD(jd, CRT_ENTRYPOINT, NULL);
emit_flds_membase(cd, REG_ITMP1, disp);
}
emit_store_dst(jd, iptr, d);
disp = dseg_add_double(cd, iptr->sx.val.d);
emit_mov_imm_reg(cd, 0, REG_ITMP1);
dseg_adddata(cd);
+ JITCACHE_ADD_CACHED_REF_JD(jd, CRT_ENTRYPOINT, NULL);
emit_fldl_membase(cd, REG_ITMP1, disp);
}
emit_store_dst(jd, iptr, d);
if (iptr->sx.val.anyptr == NULL)
M_CLR(d);
else
+ {
M_MOV_IMM(iptr->sx.val.anyptr, d);
+ JITCACHE_ADD_CACHED_REF_JD(
+ jd,
+ (iptr->flags.bits & INS_FLAG_CLASS) ? CRT_CLASSINFO
+ : CRT_STRING,
+ (iptr->flags.bits & INS_FLAG_CLASS) ? iptr->sx.val.c.cls
+ : iptr->sx.val.stringconst);
+ }
}
emit_store_dst(jd, iptr, d);
break;
M_LST(s1, REG_SP, 0 * 4);
M_MOV_IMM(bte->fp, REG_ITMP3);
+ JITCACHE_ADD_CACHED_REF_JD(jd, CRT_BUILTIN_FP, bte);
M_CALL(REG_ITMP3);
emit_store_dst(jd, iptr, d);
break;
disp = dseg_add_unique_s4(cd, 0);
emit_mov_imm_reg(cd, 0, REG_ITMP1);
dseg_adddata(cd);
+ JITCACHE_ADD_CACHED_REF_JD(jd, CRT_ENTRYPOINT, NULL);
emit_mov_reg_membase(cd, var->vv.regoff, REG_ITMP1, disp);
emit_fildl_membase(cd, REG_ITMP1, disp);
}
emit_mov_imm_reg(cd, 0, REG_ITMP1);
dseg_adddata(cd);
+ JITCACHE_ADD_CACHED_REF_JD(jd, CRT_ENTRYPOINT, NULL);
/* Round to zero, 53-bit mode, exception masked */
disp = dseg_add_s4(cd, 0x0e7f);
/* XXX: change this when we use registers */
emit_flds_membase(cd, REG_SP, var1->vv.regoff);
emit_mov_imm_reg(cd, (ptrint) asm_builtin_f2i, REG_ITMP1);
+ JITCACHE_ADD_CACHED_REF_JD(jd, CRT_BUILTIN_FP,
+ builtintable_get_internal(BUILTIN_f2i));
emit_call_reg(cd, REG_ITMP1);
if (var->flags & INMEMORY) {
emit_mov_imm_reg(cd, 0, REG_ITMP1);
dseg_adddata(cd);
+ JITCACHE_ADD_CACHED_REF_JD(jd, CRT_ENTRYPOINT, NULL);
/* Round to zero, 53-bit mode, exception masked */
disp = dseg_add_s4(cd, 0x0e7f);
/* XXX: change this when we use registers */
emit_fldl_membase(cd, REG_SP, var1->vv.regoff);
emit_mov_imm_reg(cd, (ptrint) asm_builtin_d2i, REG_ITMP1);
+ JITCACHE_ADD_CACHED_REF_JD(jd, CRT_BUILTIN_FP,
+ builtintable_get_internal(BUILTIN_d2i));
emit_call_reg(cd, REG_ITMP1);
if (var->flags & INMEMORY) {
emit_mov_imm_reg(cd, 0, REG_ITMP1);
dseg_adddata(cd);
+ JITCACHE_ADD_CACHED_REF_JD(jd, CRT_ENTRYPOINT, NULL);
/* Round to zero, 53-bit mode, exception masked */
disp = dseg_add_s4(cd, 0x0e7f);
/* XXX: change this when we use registers */
emit_flds_membase(cd, REG_SP, var1->vv.regoff);
emit_mov_imm_reg(cd, (ptrint) asm_builtin_f2l, REG_ITMP1);
+ JITCACHE_ADD_CACHED_REF_JD(jd, CRT_BUILTIN_FP,
+ builtintable_get_internal(BUILTIN_f2l));
emit_call_reg(cd, REG_ITMP1);
emit_mov_reg_membase(cd, REG_RESULT, REG_SP, var->vv.regoff);
emit_mov_reg_membase(cd, REG_RESULT2,
emit_mov_imm_reg(cd, 0, REG_ITMP1);
dseg_adddata(cd);
+ JITCACHE_ADD_CACHED_REF_JD(jd, CRT_ENTRYPOINT, NULL);
/* Round to zero, 53-bit mode, exception masked */
disp = dseg_add_s4(cd, 0x0e7f);
/* XXX: change this when we use registers */
emit_fldl_membase(cd, REG_SP, var1->vv.regoff);
emit_mov_imm_reg(cd, (ptrint) asm_builtin_d2l, REG_ITMP1);
+ JITCACHE_ADD_CACHED_REF_JD(jd, CRT_BUILTIN_FP,
+ builtintable_get_internal(BUILTIN_d2l));
emit_call_reg(cd, REG_ITMP1);
emit_mov_reg_membase(cd, REG_RESULT, REG_SP, var->vv.regoff);
emit_mov_reg_membase(cd, REG_RESULT2,
M_AST(s1, REG_SP, 0 * 4);
M_AST(s3, REG_SP, 1 * 4);
M_MOV_IMM(BUILTIN_FAST_canstore, REG_ITMP1);
+ JITCACHE_ADD_CACHED_REF_JD(jd, CRT_BUILTIN_FP,
+ builtintable_get_internal(BUILTIN_FAST_canstore));
M_CALL(REG_ITMP1);
emit_arraystore_check(cd, iptr);
else {
fi = iptr->sx.s23.s3.fmiref->p.field;
fieldtype = fi->type;
+
disp = (intptr_t) fi->value;
if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->clazz))
}
M_MOV_IMM(disp, REG_ITMP1);
+ JITCACHE_ADD_CACHED_REF_JD_COND(jd, CRT_FIELDINFO_VALUE, fi, disp);
switch (fieldtype) {
case TYPE_INT:
case TYPE_ADR:
break;
case ICMD_PUTSTATIC: /* ..., value ==> ... */
-
+
if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
uf = iptr->sx.s23.s3.uf;
fieldtype = uf->fieldref->parseddesc.fd->type;
else {
fi = iptr->sx.s23.s3.fmiref->p.field;
fieldtype = fi->type;
+
disp = (intptr_t) fi->value;
if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->clazz))
patcher_add_patch_ref(jd, PATCHER_initialize_class, fi->clazz, 0);
}
-
M_MOV_IMM(disp, REG_ITMP1);
+ JITCACHE_ADD_CACHED_REF_JD_COND(jd, CRT_FIELDINFO_VALUE, fi, disp);
switch (fieldtype) {
case TYPE_INT:
case TYPE_ADR:
else {
fi = iptr->sx.s23.s3.fmiref->p.field;
fieldtype = fi->type;
+
disp = (intptr_t) fi->value;
if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->clazz))
}
M_MOV_IMM(disp, REG_ITMP1);
+ JITCACHE_ADD_CACHED_REF_JD_COND(jd, CRT_FIELDINFO_VALUE, fi, disp);
switch (fieldtype) {
case TYPE_INT:
case TYPE_ADR:
else {
fi = iptr->sx.s23.s3.fmiref->p.field;
fieldtype = fi->type;
+
disp = fi->offset;
+
}
switch (fieldtype) {
M_POP(REG_ITMP2_XPC);
M_MOV_IMM(asm_handle_exception, REG_ITMP3);
+ JITCACHE_ADD_CACHED_REF_JD(jd, CRT_ASM_HANDLE_EXCEPTION, 1);
M_JMP(REG_ITMP3);
break;
M_AST(REG_ITMP2, REG_SP, 0);
M_MOV_IMM(LOCK_monitor_exit, REG_ITMP3);
+ JITCACHE_ADD_CACHED_REF_JD(jd, CRT_BUILTIN_FP,
+ builtintable_get_internal(LOCK_monitor_exit));
M_CALL(REG_ITMP3);
/* and now restore the proper return value */
M_MOV_IMM(0, REG_ITMP2);
dseg_adddata(cd);
+ JITCACHE_ADD_CACHED_REF_JD(jd, CRT_ENTRYPOINT, NULL);
emit_mov_memindex_reg(cd, -(cd->dseglen), REG_ITMP2, REG_ITMP1, 2, REG_ITMP1);
M_JMP(REG_ITMP1);
}
bte = iptr->sx.s23.s3.bte;
md = bte->md;
+
+ #if defined(ENABLE_ESCAPE_REASON)
+ if (bte->fp == BUILTIN_escape_reason_new) {
+ void set_escape_reasons(void *);
+ M_ASUB_IMM(8, REG_SP);
+ M_MOV_IMM(iptr->escape_reasons, REG_ITMP1);
+ M_AST(EDX, REG_SP, 4);
+ M_AST(REG_ITMP1, REG_SP, 0);
+ M_MOV_IMM(set_escape_reasons, REG_ITMP1);
+ M_CALL(REG_ITMP1);
+ M_ALD(EDX, REG_SP, 4);
+ M_AADD_IMM(8, REG_SP);
+ }
+ #endif
+
goto gen_method;
case ICMD_INVOKESTATIC: /* ..., [arg1, [arg2 ...]] ==> ... */
else {
M_MOV_IMM(bte->stub, REG_ITMP1);
}
+ JITCACHE_ADD_CACHED_REF_JD(jd, CRT_BUILTIN, bte);
M_CALL(REG_ITMP1);
#if defined(ENABLE_ESCAPE_CHECK)
}
else {
disp = (ptrint) lm->stubroutine;
+
d = lm->parseddesc->returntype.type;
}
-
M_MOV_IMM(disp, REG_ITMP2);
+ JITCACHE_ADD_CACHED_REF_JD(jd, CRT_METHODINFO_STUBROUTINE, lm);
M_CALL(REG_ITMP2);
break;
else {
s1 = OFFSET(vftbl_t, table[0]) +
sizeof(methodptr) * lm->vftblindex;
+
d = md->returntype.type;
}
M_ALD(REG_METHODPTR, REG_ITMP1,
OFFSET(java_object_t, vftbl));
M_ALD32(REG_ITMP3, REG_METHODPTR, s1);
+ JITCACHE_ADD_CACHED_REF_JD(jd, CRT_METHODINFO_TABLE, lm);
M_CALL(REG_ITMP3);
break;
M_ALD(REG_METHODPTR, REG_ITMP1,
OFFSET(java_object_t, vftbl));
M_ALD32(REG_METHODPTR, REG_METHODPTR, s1);
+ JITCACHE_ADD_CACHED_REF_JD(jd, CRT_METHODINFO_INTERFACETABLE, lm);
M_ALD32(REG_ITMP3, REG_METHODPTR, s2);
+ JITCACHE_ADD_CACHED_REF_JD(jd, CRT_METHODINFO_METHODOFFSET, lm);
M_CALL(REG_ITMP3);
break;
}
superindex = super->index;
supervftbl = super->vftbl;
}
-
- if ((super == NULL) || !(super->flags & ACC_INTERFACE))
- CODEGEN_CRITICAL_SECTION_NEW;
-
-
s1 = emit_load_s1(jd, iptr, REG_ITMP1);
/* if class is not resolved, check which code to call */
-
if (super == NULL) {
M_TEST(s1);
emit_label_beq(cd, BRANCH_LABEL_1);
M_ILD32(REG_ITMP3,
REG_ITMP2, OFFSET(vftbl_t, interfacetablelength));
M_ISUB_IMM32(superindex, REG_ITMP3);
+ JITCACHE_ADD_CACHED_REF_JD(jd, CRT_CLASSINFO_INDEX, super);
/* XXX do we need this one? */
M_TEST(REG_ITMP3);
emit_classcast_check(cd, iptr, BRANCH_LE, REG_ITMP3, s1);
M_ALD32(REG_ITMP3, REG_ITMP2,
OFFSET(vftbl_t, interfacetable[0]) -
superindex * sizeof(methodptr*));
+ JITCACHE_ADD_CACHED_REF_JD(jd, CRT_CLASSINFO_INTERFACETABLE, super);
M_TEST(REG_ITMP3);
emit_classcast_check(cd, iptr, BRANCH_EQ, REG_ITMP3, s1);
}
M_MOV_IMM(supervftbl, REG_ITMP3);
+ JITCACHE_ADD_CACHED_REF_JD(jd, CRT_CLASSINFO_VFTBL, super);
- CODEGEN_CRITICAL_SECTION_START;
-
M_ILD32(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, baseval));
/* if (s1 != REG_ITMP1) { */
M_ILD32(REG_ITMP3, REG_ITMP3, OFFSET(vftbl_t, baseval));
M_ISUB(REG_ITMP3, REG_ITMP2);
M_MOV_IMM(supervftbl, REG_ITMP3);
+ JITCACHE_ADD_CACHED_REF_JD(jd, CRT_CLASSINFO_VFTBL, super);
M_ILD(REG_ITMP3, REG_ITMP3, OFFSET(vftbl_t, diffval));
- CODEGEN_CRITICAL_SECTION_END;
-
/* } */
M_CMP(REG_ITMP3, REG_ITMP2);
if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
patcher_add_patch_ref(jd, PATCHER_builtin_arraycheckcast,
iptr->sx.s23.s3.c.ref, 0);
+ disp = 0;
}
+ else {
+ disp = iptr->sx.s23.s3.c.cls;
+ }
+
+ M_AST_IMM(disp, REG_SP, 1 * 4);
+ JITCACHE_ADD_CACHED_REF_JD(jd, CRT_CLASSINFO, disp);
- M_AST_IMM(iptr->sx.s23.s3.c.cls, REG_SP, 1 * 4);
M_MOV_IMM(BUILTIN_arraycheckcast, REG_ITMP3);
+ JITCACHE_ADD_CACHED_REF_JD(jd, CRT_BUILTIN_FP,
+ builtintable_get_internal(BUILTIN_arraycheckcast));
M_CALL(REG_ITMP3);
s1 = emit_load_s1(jd, iptr, REG_ITMP2);
supervftbl = super->vftbl;
}
- if ((super == NULL) || !(super->flags & ACC_INTERFACE))
- CODEGEN_CRITICAL_SECTION_NEW;
-
s1 = emit_load_s1(jd, iptr, REG_ITMP1);
d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
emit_label_beq(cd, BRANCH_LABEL_3);
}
+
M_ALD(REG_ITMP1, s1, OFFSET(java_object_t, vftbl));
if (super == NULL) {
M_ILD32(REG_ITMP3,
REG_ITMP1, OFFSET(vftbl_t, interfacetablelength));
M_ISUB_IMM32(superindex, REG_ITMP3);
+ JITCACHE_ADD_CACHED_REF_JD(jd, CRT_CLASSINFO_INDEX, super);
+
M_TEST(REG_ITMP3);
disp = (2 + 4 /* mov_membase32_reg */ + 2 /* test */ +
M_ALD32(REG_ITMP1, REG_ITMP1,
OFFSET(vftbl_t, interfacetable[0]) -
superindex * sizeof(methodptr*));
+ JITCACHE_ADD_CACHED_REF_JD(jd, CRT_CLASSINFO_INTERFACETABLE, super);
M_TEST(REG_ITMP1);
/* emit_setcc_reg(cd, CC_A, d); */
/* emit_jcc(cd, CC_BE, 5); */
}
M_MOV_IMM(supervftbl, REG_ITMP2);
-
+ JITCACHE_ADD_CACHED_REF_JD(jd, CRT_CLASSINFO_VFTBL, super);
- CODEGEN_CRITICAL_SECTION_START;
-
M_ILD(REG_ITMP1, REG_ITMP1, OFFSET(vftbl_t, baseval));
M_ILD(REG_ITMP3, REG_ITMP2, OFFSET(vftbl_t, diffval));
M_ILD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, baseval));
- CODEGEN_CRITICAL_SECTION_END;
-
M_ISUB(REG_ITMP2, REG_ITMP1);
M_CLR(d); /* may be REG_ITMP2 */
M_CMP(REG_ITMP3, REG_ITMP1);
/* a1 = arraydescriptor */
M_IST_IMM(disp, REG_SP, 1 * 4);
+ JITCACHE_ADD_CACHED_REF_JD(jd, CRT_CLASSINFO, disp);
/* a2 = pointer to dimensions = stack pointer */
M_AST(REG_ITMP1, REG_SP, 2 * 4);
M_MOV_IMM(BUILTIN_multianewarray, REG_ITMP1);
+ JITCACHE_ADD_CACHED_REF_JD(jd, CRT_BUILTIN_FP,
+ builtintable_get_internal(BUILTIN_multianewarray));
M_CALL(REG_ITMP1);
/* check for exception before result assignment */
M_MOV_IMM(code, REG_ITMP1);
M_IADD_IMM_MEMBASE(1, REG_ITMP1, OFFSET(codeinfo, frequency));
+ JITCACHE_ADD_CACHED_REF_JD(jd, CRT_CODEINFO, 0);
}
#endif
/* put env into first argument */
- M_AST_IMM(_Jv_env, REG_SP, 0 * 4);
+ M_AST_IMM(VM_get_jnienv(), REG_SP, 0 * 4);
}
/* Call the native function. */
switch (md->returntype.type) {
case TYPE_INT:
case TYPE_ADR:
- switch (md->returntype.decltype) {
+ switch (md->returntype.primitivetype) {
case PRIMITIVETYPE_BOOLEAN:
M_BZEXT(REG_RESULT, REG_RESULT);
break;
#include "native/native.h"
#include "vm/builtin.h"
- #include "vm/exceptions.h"
+ #include "vm/class.h"
+ #include "vm/field.h"
#include "vm/initialize.h"
+ #include "vm/options.h"
+ #include "vm/references.h"
+ #include "vm/resolve.h"
#include "vm/jit/patcher-common.h"
- #include "vm/jit/stacktrace.h"
-
- #include "vmcore/class.h"
- #include "vmcore/field.h"
- #include "vmcore/options.h"
- #include "vm/resolve.h"
- #include "vmcore/references.h"
#define PATCH_BACK_ORIGINAL_MCODE *((u2 *) pr->mpc) = (u2) pr->mcode
Machine code:
- <patched call postition>
+ <patched call position>
c7 04 24 00 00 00 00 movl $0x0000000,(%esp)
b8 00 00 00 00 mov $0x0000000,%eax
ra = (u1 *) pr->mpc;
um = (unresolved_method *) pr->ref;
- /* get the fieldinfo */
+ /* get the methodinfo */
if (!(m = resolve_method_eager(um)))
return false;
#include "threads/lock-common.h"
+ #include "vm/class.h"
#include "vm/global.h"
+ #include "vm/globals.hpp"
#include "vm/initialize.h"
+ #include "vm/loader.h"
+ #include "vm/method.h"
+ #include "vm/options.h"
+ #include "vm/rt-timing.h"
+ #include "vm/statistics.h"
#include "vm/jit/asmpart.h"
#include "vm/jit/show.h"
#include "vm/jit/stack.h"
+#if defined(ENABLE_JITCACHE)
+# include "vm/jit/jitcache.h"
+#endif
+
+ #if defined(ENABLE_OPAGENT)
+ #include "vm/jit/oprofile-agent.hpp"
+ #endif
+
#include "vm/jit/allocator/simplereg.h"
#if defined(ENABLE_LSRA) && !defined(ENABLE_SSA)
# include "vm/jit/allocator/lsra.h"
#include "vm/jit/verify/typecheck.h"
- #include "vmcore/class.h"
- #include "vmcore/loader.h"
- #include "vmcore/method.h"
- #include "vmcore/options.h"
- #include "vmcore/rt-timing.h"
- #include "vmcore/statistics.h"
-
/* debug macros ***************************************************************/
#else
intrp_md_init();
#endif
+
+ #if defined(ENABLE_OPAGENT)
+ if (opt_EnableOpagent)
+ OprofileAgent_initialize();
+ #endif
}
void jit_close(void)
{
- /* do nothing */
+ #if defined(ENABLE_OPAGENT)
+ if (opt_EnableOpagent)
+ OprofileAgent_close();
+ #endif
}
STATISTICS(count_methods++);
+#if defined (ENABLE_JITCACHE)
+
+ if (jitcache_load (m))
+ {
+ LOCK_MONITOR_EXIT(m);
+
+ return m->code->entrypoint;
+ }
+
+#endif
+
#if defined(ENABLE_STATISTICS)
/* measure time */
jd->flags |= JITDATA_FLAG_VERBOSECALL;
#if defined(ENABLE_REPLACEMENT) && defined(ENABLE_INLINING)
- if (opt_Inline)
+ if (opt_Inline && (jd->m->hitcountdown > 0) && (jd->code->optlevel == 0)) {
jd->flags |= JITDATA_FLAG_COUNTDOWN;
+ }
#endif
#if defined(ENABLE_JIT)
DEBUG_JIT_COMPILEVERBOSE("Running: ");
}
+#if defined (ENABLE_JITCACHE)
+ jitcache_store(m);
+#endif
+
/* release dump area */
DRELEASE;
compilingtime_stop();
#endif
+ #if defined(ENABLE_OPAGENT)
+ if (opt_EnableOpagent)
+ OprofileAgent_newmethod(m);
+ #endif
+
/* leave the monitor */
LOCK_MONITOR_EXIT(m);
compilingtime_stop();
#endif
+ #if defined(ENABLE_OPAGENT)
+ if (opt_EnableOpagent)
+ OprofileAgent_newmethod(m);
+ #endif
+
DEBUG_JIT_COMPILEVERBOSE("Recompiling done: ");
/* return pointer to the methods entry point */
#endif
RT_TIMING_GET_TIME(time_typecheck);
- #if defined(ENABLE_SSA)
- if (opt_lsra) {
- fix_exception_handlers(jd);
- }
- #endif
-
- /* Build the CFG. This has to be done after stack_analyse, as
- there happens the JSR elimination. */
-
- if (!cfg_build(jd))
- return NULL;
-
#if defined(ENABLE_LOOP)
if (opt_loops) {
depthFirst(jd);
/* inlining */
- #if defined(ENABLE_INLINING)
+ #if defined(ENABLE_INLINING) && (!defined(ENABLE_ESCAPE) || 1)
if (JITDATA_HAS_FLAG_INLINE(jd)) {
if (!inline_inline(jd))
return NULL;
}
#endif
+ #if defined(ENABLE_SSA)
+ if (opt_lsra) {
+ fix_exception_handlers(jd);
+ }
+ #endif
+
+ /* Build the CFG. This has to be done after stack_analyse, as
+ there happens the JSR elimination. */
+
+ if (!cfg_build(jd))
+ return NULL;
+
#if defined(ENABLE_PROFILING)
/* Basic block reordering. I think this should be done after
if-conversion, as we could lose the ability to do the
#if defined(ENABLE_SSA)
/* allocate registers */
if (
- (opt_lsra)
- /*&& strncmp(jd->m->name->text, "banana", 6) == 0*/
+ (opt_lsra &&
+ jd->code->optlevel > 0)
+ /* strncmp(jd->m->name->text, "hottie", 6) == 0*/
/*&& jd->exceptiontablelength == 0*/
) {
- /* printf("=== %s ===\n", jd->m->name->text); */
+ /*printf("=== %s ===\n", jd->m->name->text);*/
jd->ls = DNEW(lsradata);
jd->ls = NULL;
ssa(jd);
/*lsra(jd);*/ regalloc(jd);
- eliminate_subbasicblocks(jd);
+ /*eliminate_subbasicblocks(jd);*/
STATISTICS(count_methods_allocated_by_lsra++);
} else
#include "toolbox/list.h"
#include "toolbox/logging.h" /* XXX remove me! */
- #include "vm/exceptions.h"
+ #include "vm/exceptions.hpp"
#include "vm/initialize.h"
+ #include "vm/options.h"
#include "vm/resolve.h"
- #include "vm/vm.h" /* for vm_abort */
+ #include "vm/vm.hpp" /* for vm_abort */
#include "vm/jit/code.h"
#include "vm/jit/disass.h"
#include "vm/jit/jit.h"
#include "vm/jit/patcher-common.h"
- #include "vmcore/options.h"
-
/* patcher_function_list *******************************************************
*******************************************************************************/
- void patcher_add_patch_ref(jitdata *jd, functionptr patcher, voidptr ref,
- s4 disp)
+ void patcher_add_patch_ref(jitdata *jd, functionptr patcher, void* ref, s4 disp)
{
codegendata *cd;
codeinfo *code;
pr->mcode = 0;
pr->done = false;
+#if defined(ENABLE_JITCACHE)
+ pr->attached_ref = NULL;
+#endif
+
/* Generate NOPs for opt_shownops. */
if (opt_shownops)
}
#endif
+#if defined(ENABLE_JITCACHE)
+ /* Put cached reference into the code and remove it from the patcher */
+ if (pr->attached_ref)
+ {
+ jitcache_handle_cached_ref(pr->attached_ref, code);
+ pr->attached_ref = NULL;
+ }
+#endif
+
/* check for return value and exit accordingly */
if (result == false) {
return true;
}
+/** Placeholder functions to calm down linker */
+#if defined(__I386__)
+bool patcher_resolve_classref_to_classinfo(patchref_t *pr)
+{
+ return true;
+}
+
+bool patcher_resolve_classref_to_vftbl(patchref_t *pr)
+{
+ return true;
+}
+
+bool patcher_resolve_classref_to_index(patchref_t *pr)
+{
+ return true;
+}
+
+bool patcher_resolve_classref_to_flags(patchref_t *pr)
+{
+ return true;
+}
+#endif
/*
* These are local overrides for various environment variables in Emacs.
/* src/vm/jit/patcher-common.h - architecture independent code patching stuff
- Copyright (C) 2007 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) 2007, 2008
+ CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
This file is part of CACAO.
#include "vm/jit/jit.h"
+#if defined (ENABLE_JITCACHE)
+struct cached_ref_t;
+#endif
/* patchref_t ******************************************************************
ptrint datap; /* absolute position in data segment */
s4 disp; /* displacement of ref in the data segment */
functionptr patcher; /* patcher function to call */
- voidptr ref; /* reference passed */
+ void* ref; /* reference passed */
u8 mcode; /* machine code to be patched back in */
bool done; /* XXX preliminary: patch already applied? */
+#if defined (ENABLE_JITCACHE)
+ struct cachedref_t *attached_ref;
+ /* cached reference which must be resolved *
+ * patcher has been run. */
+#endif
listnode_t linkage;
} patchref_t;
void patcher_list_reset(codeinfo *code);
void patcher_list_free(codeinfo *code);
- void patcher_add_patch_ref(jitdata *jd, functionptr patcher, voidptr ref,
- s4 disp);
+ void patcher_add_patch_ref(jitdata *jd, functionptr patcher, void* ref, s4 disp);
void patcher_resolve(jitdata* jd);
#endif /* defined(__I386__) */
+void patch_md(s4 md_patch, ptrint dest, voidptr ref);
#endif /* _PATCHER_COMMON_H */
--- /dev/null
+ /* src/vm/options.c - contains global options
+
+ Copyright (C) 1996-2005, 2006, 2007, 2008
+ CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
+
+ This file is part of CACAO.
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 2, or (at
+ your option) any later version.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ 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., 51 Franklin Street, Fifth Floor, Boston, MA
+ 02110-1301, USA.
+
+ */
+
+
+ #include "config.h"
+
+ #include <limits.h>
+ #include <stdint.h>
+ #include <stdio.h>
+ #include <stdlib.h>
+
+ #include "mm/memory.h"
+
+ #include "native/jni.h"
+
+ #include "vm/options.h"
+ #include "vm/os.hpp"
+ #include "vm/vm.hpp"
+
+
+ /* command line option ********************************************************/
+
+ s4 opt_index = 0; /* index of processed arguments */
+ char *opt_arg; /* this one exports the option argument */
+
+ bool opt_foo = false; /* option for development */
+
+ bool opt_jar = false;
+
+ #if defined(ENABLE_JIT)
+ bool opt_jit = true; /* JIT mode execution (default) */
+ bool opt_intrp = false; /* interpreter mode execution */
+ #else
+ bool opt_jit = false; /* JIT mode execution */
+ bool opt_intrp = true; /* interpreter mode execution (default) */
+ #endif
+
+ bool opt_run = true;
+
+ s4 opt_heapmaxsize = 0; /* maximum heap size */
+ s4 opt_heapstartsize = 0; /* initial heap size */
+ s4 opt_stacksize = 0; /* thread stack size */
+
+ bool opt_verbose = false;
+ bool opt_debugcolor = false; /* use ANSI terminal sequences */
+ bool compileall = false;
+
+ bool loadverbose = false;
+ bool initverbose = false;
+
+ bool opt_verboseclass = false;
+ bool opt_verbosegc = false;
+ bool opt_verbosejni = false;
+ bool opt_verbosecall = false; /* trace all method invocation */
+
+ bool showmethods = false;
+ bool showconstantpool = false;
+ bool showutf = false;
+
+ char *opt_method = NULL;
+ char *opt_signature = NULL;
+
+ bool compileverbose = false; /* trace compiler actions */
+ bool showstack = false;
+
+ bool opt_showdisassemble = false; /* generate disassembler listing */
+ bool opt_shownops = false;
+ bool opt_showddatasegment = false; /* generate data segment listing */
+ bool opt_showintermediate = false; /* generate intermediate code listing */
+
+ bool checkbounds = true; /* check array bounds */
+ bool opt_noieee = false; /* don't implement ieee compliant floats */
+ bool checksync = true; /* do synchronization */
+ #if defined(ENABLE_LOOP)
+ bool opt_loops = false; /* optimize array accesses in loops */
+ #endif
+
+ bool makeinitializations = true;
+
+ #if defined(ENABLE_STATISTICS)
+ bool opt_stat = false;
+ bool opt_getloadingtime = false; /* to measure the runtime */
+ bool opt_getcompilingtime = false; /* compute compile time */
+ #endif
+ #if defined(ENABLE_VERIFIER)
+ bool opt_verify = true; /* true if classfiles should be verified */
+ #endif
+
+ #if defined(ENABLE_PROFILING)
+ bool opt_prof = false;
+ bool opt_prof_bb = false;
+ #endif
+
+ #if defined(ENABLE_OPAGENT)
+ bool opt_opagent = false;
+ #endif
+
+ /* optimization options *******************************************************/
+
+ #if defined(ENABLE_IFCONV)
+ bool opt_ifconv = false;
+ #endif
+
+ #if defined(ENABLE_LSRA) || defined(ENABLE_SSA)
+ bool opt_lsra = false;
+ #endif
+ #if defined(ENABLE_SSA)
+ bool opt_ssa_dce = false; /* enable dead code elemination */
+ bool opt_ssa_cp = false; /* enable copy propagation */
+ #endif
+
+
+ /* interpreter options ********************************************************/
+
+ #if defined(ENABLE_INTRP)
+ bool opt_no_dynamic = false; /* suppress dynamic superinstructions */
+ bool opt_no_replication = false; /* don't use replication in intrp */
+ bool opt_no_quicksuper = false; /* instructions for quickening cannot be
+ part of dynamic superinstructions */
+
+ s4 opt_static_supers = 0x7fffffff;
+ bool vm_debug = false; /* XXX this should be called `opt_trace' */
+ #endif
+
+ #if defined(ENABLE_DEBUG_FILTER)
+ const char *opt_filter_verbosecall_include = 0;
+ const char *opt_filter_verbosecall_exclude = 0;
+ const char *opt_filter_show_method = 0;
+ #endif
+
+
+ /* -XX options ****************************************************************/
+
+ /* NOTE: For better readability keep these alpha-sorted. */
+
+ /* Options which must always be available (production options in
+ HotSpot). */
+
+ int64_t opt_MaxDirectMemorySize = -1;
+ int opt_MaxPermSize = 0;
+ int opt_PermSize = 0;
+ int opt_ThreadStackSize = 0;
+
+ /* Debugging options which can be turned off. */
+
+ int opt_DebugExceptions = 0;
+ int opt_DebugFinalizer = 0;
++#if defined(ENABLE_JITCACHE)
++int opt_DebugJitCache = 0;
++#endif
+ int opt_DebugLocalReferences = 0;
+ int opt_DebugLocks = 0;
+ int opt_DebugPackage = 0;
+ int opt_DebugPatcher = 0;
+ int opt_DebugProperties = 0;
+ int opt_DebugStackFrameInfo = 0;
+ int opt_DebugStackTrace = 0;
+ int opt_DebugThreads = 0;
+ #if defined(ENABLE_DISASSEMBLER)
+ int opt_DisassembleStubs = 0;
+ #endif
+ #if defined(ENABLE_OPAGENT)
+ int opt_EnableOpagent = 0;
+ #endif
+ #if defined(ENABLE_GC_CACAO)
+ int opt_GCDebugRootSet = 0;
+ int opt_GCStress = 0;
+ #endif
+ #if defined(ENABLE_INLINING)
+ int opt_Inline = 0;
+ #if defined(ENABLE_INLINING_DEBUG) || !defined(NDEBUG)
+ int opt_InlineAll = 0;
+ int opt_InlineCount = INT_MAX;
+ int opt_InlineMaxSize = INT_MAX;
+ int opt_InlineMinSize = 0;
+ #endif
+ #endif
+ int opt_PrintConfig = 0;
+ int opt_ProfileGCMemoryUsage = 0;
+ int opt_ProfileMemoryUsage = 0;
+ FILE *opt_ProfileMemoryUsageGNUPlot = NULL;
+ #if defined(ENABLE_REPLACEMENT)
+ int opt_TestReplacement = 0;
+ #endif
+ int opt_TraceCompilerCalls = 0;
+ int opt_TraceExceptions = 0;
+ int opt_TraceHPI = 0;
+ #if defined(ENABLE_INLINING) && !defined(NDEBUG)
+ int opt_TraceInlining = 0;
+ #endif
+ int opt_TraceJavaCalls = 0;
+ int opt_TraceJNICalls = 0;
+ int opt_TraceJVMCalls = 0;
+ int opt_TraceJVMCallsVerbose = 0;
+ int opt_TraceLinkClass = 0;
+ #if defined(ENABLE_REPLACEMENT)
+ int opt_TraceReplacement = 0;
+ #endif
+ int opt_TraceSubsystemInitialization = 0;
+ int opt_TraceTraps = 0;
+
+
+ enum {
+ OPT_TYPE_BOOLEAN,
+ OPT_TYPE_VALUE
+ };
+
+ enum {
+ /* Options which must always be available (production options in
+ HotSpot). */
+
+ OPT_MaxDirectMemorySize,
+ OPT_MaxPermSize,
+ OPT_PermSize,
+ OPT_ThreadStackSize,
+
+ /* Debugging options which can be turned off. */
+
+ OPT_DebugExceptions,
+ OPT_DebugFinalizer,
++ OPT_DebugJitCache,
+ OPT_DebugLocalReferences,
+ OPT_DebugLocks,
+ OPT_DebugPackage,
+ OPT_DebugPatcher,
+ OPT_DebugProperties,
+ OPT_DebugStackFrameInfo,
+ OPT_DebugStackTrace,
+ OPT_DebugThreads,
+ OPT_DisassembleStubs,
+ OPT_EnableOpagent,
+ OPT_GCDebugRootSet,
+ OPT_GCStress,
+ OPT_Inline,
+ OPT_InlineAll,
+ OPT_InlineCount,
+ OPT_InlineMaxSize,
+ OPT_InlineMinSize,
+ OPT_PrintConfig,
+ OPT_ProfileGCMemoryUsage,
+ OPT_ProfileMemoryUsage,
+ OPT_ProfileMemoryUsageGNUPlot,
+ OPT_TestReplacement,
+ OPT_TraceCompilerCalls,
+ OPT_TraceExceptions,
+ OPT_TraceHPI,
+ OPT_TraceInlining,
+ OPT_TraceJavaCalls,
+ OPT_TraceJNICalls,
+ OPT_TraceJVMCalls,
+ OPT_TraceJVMCallsVerbose,
+ OPT_TraceLinkClass,
+ OPT_TraceReplacement,
+ OPT_TraceSubsystemInitialization,
+ OPT_TraceTraps,
+ OPT_Vmlog,
+ OPT_VmlogStrings,
+ OPT_VmlogIgnore
+ };
+
+
+ option_t options_XX[] = {
+ /* Options which must always be available (production options in
+ HotSpot). */
+
+ { "MaxDirectMemorySize", OPT_MaxDirectMemorySize, OPT_TYPE_VALUE, "Maximum total size of NIO direct-buffer allocations" },
+ { "MaxPermSize", OPT_MaxPermSize, OPT_TYPE_VALUE, "not implemented" },
+ { "PermSize", OPT_PermSize, OPT_TYPE_VALUE, "not implemented" },
+ { "ThreadStackSize", OPT_ThreadStackSize, OPT_TYPE_VALUE, "TODO" },
+
+ /* Debugging options which can be turned off. */
+
+ { "DebugExceptions", OPT_DebugExceptions, OPT_TYPE_BOOLEAN, "debug exceptions" },
+ { "DebugFinalizer", OPT_DebugFinalizer, OPT_TYPE_BOOLEAN, "debug finalizer thread" },
++#if defined (ENABLE_JITCACHE)
++ { "DebugJitCache", OPT_DebugJitCache, OPT_TYPE_BOOLEAN, "debug JIT cache actions" },
++#endif
+ { "DebugLocalReferences", OPT_DebugLocalReferences, OPT_TYPE_BOOLEAN, "print debug information for local reference tables" },
+ { "DebugLocks", OPT_DebugLocks, OPT_TYPE_BOOLEAN, "print debug information for locks" },
+ { "DebugPackage", OPT_DebugPackage, OPT_TYPE_BOOLEAN, "debug Java boot-packages" },
+ { "DebugPatcher", OPT_DebugPatcher, OPT_TYPE_BOOLEAN, "debug JIT code patching" },
+ { "DebugProperties", OPT_DebugProperties, OPT_TYPE_BOOLEAN, "print debug information for properties" },
+ { "DebugStackFrameInfo", OPT_DebugStackFrameInfo, OPT_TYPE_BOOLEAN, "TODO" },
+ { "DebugStackTrace", OPT_DebugStackTrace, OPT_TYPE_BOOLEAN, "debug stacktrace creation" },
+ { "DebugThreads", OPT_DebugThreads, OPT_TYPE_BOOLEAN, "print debug information for threads" },
+ #if defined(ENABLE_DISASSEMBLER)
+ { "DisassembleStubs", OPT_DisassembleStubs, OPT_TYPE_BOOLEAN, "disassemble builtin and native stubs when generated" },
+ #endif
+ #if defined(ENABLE_OPAGENT)
+ { "EnableOpagent", OPT_EnableOpagent, OPT_TYPE_BOOLEAN, "enable providing JIT output to Oprofile" },
+ #endif
+ #if defined(ENABLE_GC_CACAO)
+ { "GCDebugRootSet", OPT_GCDebugRootSet, OPT_TYPE_BOOLEAN, "GC: print root-set at collection" },
+ { "GCStress", OPT_GCStress, OPT_TYPE_BOOLEAN, "GC: forced collection at every allocation" },
+ #endif
+ #if defined(ENABLE_INLINING)
+ { "Inline", OPT_Inline, OPT_TYPE_BOOLEAN, "enable method inlining" },
+ #if defined(ENABLE_INLINING_DEBUG) || !defined(NDEBUG)
+ { "InlineAll", OPT_InlineAll, OPT_TYPE_BOOLEAN, "use inlining in all compilations" },
+ { "InlineCount", OPT_InlineCount, OPT_TYPE_VALUE, "stop inlining after the given number of roots" },
+ { "InlineMaxSize", OPT_InlineMaxSize, OPT_TYPE_VALUE, "maximum size for inlined result" },
+ { "InlineMinSize", OPT_InlineMinSize, OPT_TYPE_VALUE, "minimum size for inlined result" },
+ #endif
+ #endif
+ { "PrintConfig", OPT_PrintConfig, OPT_TYPE_BOOLEAN, "print VM configuration" },
+ { "ProfileGCMemoryUsage", OPT_ProfileGCMemoryUsage, OPT_TYPE_VALUE, "profiles GC memory usage in the given interval, <value> is in seconds (default: 5)" },
+ { "ProfileMemoryUsage", OPT_ProfileMemoryUsage, OPT_TYPE_VALUE, "TODO" },
+ { "ProfileMemoryUsageGNUPlot", OPT_ProfileMemoryUsageGNUPlot, OPT_TYPE_VALUE, "TODO" },
+ #if defined(ENABLE_REPLACEMENT)
+ { "TestReplacement", OPT_TestReplacement, OPT_TYPE_BOOLEAN, "activate all replacement points during code generation" },
+ #endif
+ { "TraceCompilerCalls", OPT_TraceCompilerCalls, OPT_TYPE_BOOLEAN, "trace JIT compiler calls" },
+ { "TraceExceptions", OPT_TraceExceptions, OPT_TYPE_BOOLEAN, "trace Exception throwing" },
+ { "TraceHPI", OPT_TraceHPI, OPT_TYPE_BOOLEAN, "Trace Host Porting Interface (HPI)" },
+ #if defined(ENABLE_INLINING) && !defined(NDEBUG)
+ { "TraceInlining", OPT_TraceInlining, OPT_TYPE_VALUE, "trace method inlining with the given verbosity level (default: 1)" },
+ #endif
+ #if !defined(ENABLE_VMLOG)
+ { "TraceJavaCalls", OPT_TraceJavaCalls, OPT_TYPE_BOOLEAN, "trace Java method calls" },
+ #endif
+ { "TraceJNICalls", OPT_TraceJNICalls, OPT_TYPE_BOOLEAN, "trace JNI method calls" },
+ { "TraceJVMCalls", OPT_TraceJVMCalls, OPT_TYPE_BOOLEAN, "trace JVM method calls but omit very frequent ones" },
+ { "TraceJVMCallsVerbose", OPT_TraceJVMCallsVerbose, OPT_TYPE_BOOLEAN, "trace all JVM method calls" },
+ { "TraceLinkClass", OPT_TraceLinkClass, OPT_TYPE_BOOLEAN, "trace class linking" },
+ #if defined(ENABLE_REPLACEMENT)
+ { "TraceReplacement", OPT_TraceReplacement, OPT_TYPE_VALUE, "trace on-stack replacement with the given verbosity level (default: 1)" },
+ #endif
+ { "TraceSubsystemInitialization", OPT_TraceSubsystemInitialization, OPT_TYPE_BOOLEAN, "trace initialization of subsystems" },
+ { "TraceTraps", OPT_TraceTraps, OPT_TYPE_BOOLEAN, "trace traps generated by JIT code" },
+ #if defined(ENABLE_VMLOG)
+ { "Vmlog", OPT_Vmlog, OPT_TYPE_VALUE, "prefix for vmlog trace files (enables vmlog)" },
+ { "VmlogStrings", OPT_VmlogStrings, OPT_TYPE_VALUE, "prefix of vmlog string file to load" },
+ { "VmlogIgnore", OPT_VmlogIgnore, OPT_TYPE_VALUE, "prefix of vmlog ignore file to load" },
+ #endif
+
+ /* end marker */
+
+ { NULL, -1, -1, NULL }
+ };
+
+
+ /* options_get *****************************************************************
+
+ DOCUMENT ME!!!
+
+ *******************************************************************************/
+
+ int options_get(opt_struct *opts, JavaVMInitArgs *vm_args)
+ {
+ char *option;
+ int i;
+
+ if (opt_index >= vm_args->nOptions)
+ return OPT_DONE;
+
+ /* get the current option */
+
+ option = vm_args->options[opt_index].optionString;
+
+ if ((option == NULL) || (option[0] != '-'))
+ return OPT_DONE;
+
+ for (i = 0; opts[i].name; i++) {
+ if (!opts[i].arg) {
+ /* boolean option found */
+
+ if (strcmp(option + 1, opts[i].name) == 0) {
+ opt_index++;
+ return opts[i].value;
+ }
+
+ } else {
+ /* parameter option found */
+
+ /* with a space between */
+
+ if (strcmp(option + 1, opts[i].name) == 0) {
+ opt_index++;
+
+ if (opt_index < vm_args->nOptions) {
+ opt_arg = os_strdup(vm_args->options[opt_index].optionString);
+ opt_index++;
+ return opts[i].value;
+ }
+
+ return OPT_ERROR;
+
+ } else {
+ /* parameter and option have no space between */
+
+ /* FIXME: this assumption is plain wrong, hits you if there is a
+ * parameter with no argument starting with same letter as param with argument
+ * but named after that one, ouch! */
+
+ size_t l = os_strlen(opts[i].name);
+
+ if (os_strlen(option + 1) > l) {
+ if (memcmp(option + 1, opts[i].name, l) == 0) {
+ opt_index++;
+ opt_arg = os_strdup(option + 1 + l);
+ return opts[i].value;
+ }
+ }
+ }
+ }
+ }
+
+ return OPT_ERROR;
+ }
+
+
+ /* options_xxusage *************************************************************
+
+ Print usage message for debugging options.
+
+ *******************************************************************************/
+
+ static void options_xxusage(void)
+ {
+ option_t *opt;
+ int length;
+ int i;
+ const char *c;
+
+ /* Prevent compiler warning. */
+
+ length = 0;
+
+ for (opt = options_XX; opt->name != NULL; opt++) {
+ printf(" -XX:");
+
+ switch (opt->type) {
+ case OPT_TYPE_BOOLEAN:
+ printf("+%s", opt->name);
+ length = os_strlen(" -XX:+") + os_strlen(opt->name);
+ break;
+
+ case OPT_TYPE_VALUE:
+ printf("%s=<value>", opt->name);
+ length = os_strlen(" -XX:") + os_strlen(opt->name) +
+ os_strlen("=<value>");
+ break;
+
+ default:
+ vm_abort("options_xxusage: unkown option type %d", opt->type);
+ }
+
+ /* Check if the help fits into one 80-column line.
+ Documentation starts at column 29. */
+
+ if (length < (29 - 1)) {
+ /* Print missing spaces up to column 29. */
+
+ for (i = length; i < 29; i++)
+ printf(" ");
+ }
+ else {
+ printf("\n");
+ printf(" "); /* 29 spaces */
+ }
+
+ /* Check documentation length. */
+
+ length = os_strlen(opt->doc);
+
+ if (length < (80 - 29)) {
+ printf("%s", opt->doc);
+ }
+ else {
+ for (c = opt->doc, i = 29; *c != 0; c++, i++) {
+ /* If we are at the end of the line, break it. */
+
+ if (i == 80) {
+ printf("\n");
+ printf(" "); /* 29 spaces */
+ i = 29;
+ }
+
+ printf("%c", *c);
+ }
+ }
+
+ printf("\n");
+ }
+
+ /* exit with error code */
+
+ exit(1);
+ }
+
+
+ /* options_xx ******************************************************************
+
+ Handle -XX: options.
+
+ *******************************************************************************/
+
+ void options_xx(JavaVMInitArgs *vm_args)
+ {
+ const char *name;
+ const char *start;
+ char *end;
+ int length;
+ int enable;
+ char *value;
+ option_t *opt;
+ char *filename;
+ FILE *file;
+ int i;
+
+ /* Iterate over all passed options. */
+
+ for (i = 0; i < vm_args->nOptions; i++) {
+ /* Get the current option. */
+
+ name = vm_args->options[i].optionString;
+
+ /* Check for help (-XX). */
+
+ if (strcmp(name, "-XX") == 0)
+ options_xxusage();
+
+ /* Check if the option start with -XX. */
+
+ start = strstr(name, "-XX:");
+
+ if ((start == NULL) || (start != name))
+ continue;
+
+ /* Check if the option is a boolean option. */
+
+ if (name[4] == '+') {
+ start = name + 4 + 1;
+ enable = 1;
+ }
+ else if (name[4] == '-') {
+ start = name + 4 + 1;
+ enable = 0;
+ }
+ else {
+ start = name + 4;
+ enable = -1;
+ }
+
+ /* Search for a '=' in the option name and get the option name
+ length and the value of the option. */
+
+ end = strchr(start, '=');
+
+ if (end == NULL) {
+ length = os_strlen(start);
+ value = NULL;
+ }
+ else {
+ length = end - start;
+ value = end + 1;
+ }
+
+ /* Search the option in the option array. */
+
+ for (opt = options_XX; opt->name != NULL; opt++) {
+ if (strncmp(opt->name, start, length) == 0) {
+ /* Check if the options passed fits to the type. */
+
+ switch (opt->type) {
+ case OPT_TYPE_BOOLEAN:
+ if ((enable == -1) || (value != NULL))
+ options_xxusage();
+ break;
+ case OPT_TYPE_VALUE:
+ if ((enable != -1) || (value == NULL))
+ options_xxusage();
+ break;
+ default:
+ vm_abort("options_xx: unknown option type %d for option %s",
+ opt->type, opt->name);
+ }
+
+ break;
+ }
+ }
+
+ /* Process the option. */
+
+ switch (opt->value) {
+
+ /* Options which must always be available (production options
+ in HotSpot). */
+
+ case OPT_MaxDirectMemorySize:
+ opt_MaxDirectMemorySize = os_atoi(value);
+ break;
+
+ case OPT_MaxPermSize:
+ /* Currently ignored. */
+ break;
+
+ case OPT_PermSize:
+ /* Currently ignored. */
+ break;
+
+ case OPT_ThreadStackSize:
+ /* currently ignored */
+ break;
+
+ /* Debugging options which can be turned off. */
+
+ case OPT_DebugExceptions:
+ opt_DebugExceptions = enable;
+ break;
+
+ case OPT_DebugFinalizer:
+ opt_DebugFinalizer = enable;
+ break;
+
++#if defined(ENABLE_JITCACHE)
++ case OPT_DebugJitCache:
++ opt_DebugJitCache = enable;
++ break;
++#endif
++
+ case OPT_DebugLocalReferences:
+ opt_DebugLocalReferences = enable;
+ break;
+
+ case OPT_DebugLocks:
+ opt_DebugLocks = enable;
+ break;
+
+ case OPT_DebugPackage:
+ opt_DebugPackage = enable;
+ break;
+
+ case OPT_DebugPatcher:
+ opt_DebugPatcher = enable;
+ break;
+
+ case OPT_DebugProperties:
+ opt_DebugProperties = enable;
+ break;
+
+ case OPT_DebugStackFrameInfo:
+ opt_DebugStackFrameInfo = enable;
+ break;
+
+ case OPT_DebugStackTrace:
+ opt_DebugStackTrace = enable;
+ break;
+
+ case OPT_DebugThreads:
+ opt_DebugThreads = enable;
+ break;
+
+ #if defined(ENABLE_DISASSEMBLER)
+ case OPT_DisassembleStubs:
+ opt_DisassembleStubs = enable;
+ break;
+ #endif
+
+ #if defined(ENABLE_OPAGENT)
+ case OPT_EnableOpagent:
+ opt_EnableOpagent = enable;
+ break;
+ #endif
+
+ #if defined(ENABLE_GC_CACAO)
+ case OPT_GCDebugRootSet:
+ opt_GCDebugRootSet = enable;
+ break;
+
+ case OPT_GCStress:
+ opt_GCStress = enable;
+ break;
+ #endif
+
+ #if defined(ENABLE_INLINING)
+ case OPT_Inline:
+ opt_Inline = enable;
+ break;
+ #if defined(ENABLE_INLINING_DEBUG) || !defined(NDEBUG)
+ case OPT_InlineAll:
+ opt_InlineAll = enable;
+ break;
+
+ case OPT_InlineCount:
+ if (value != NULL)
+ opt_InlineCount = os_atoi(value);
+ break;
+
+ case OPT_InlineMaxSize:
+ if (value != NULL)
+ opt_InlineMaxSize = os_atoi(value);
+ break;
+
+ case OPT_InlineMinSize:
+ if (value != NULL)
+ opt_InlineMinSize = os_atoi(value);
+ break;
+ #endif
+ #endif
+
+ case OPT_PrintConfig:
+ opt_PrintConfig = enable;
+ break;
+
+ case OPT_ProfileGCMemoryUsage:
+ if (value == NULL)
+ opt_ProfileGCMemoryUsage = 5;
+ else
+ opt_ProfileGCMemoryUsage = os_atoi(value);
+ break;
+
+ case OPT_ProfileMemoryUsage:
+ if (value == NULL)
+ opt_ProfileMemoryUsage = 5;
+ else
+ opt_ProfileMemoryUsage = os_atoi(value);
+
+ # if defined(ENABLE_STATISTICS)
+ /* we also need statistics */
+
+ opt_stat = true;
+ # endif
+ break;
+
+ case OPT_ProfileMemoryUsageGNUPlot:
+ if (value == NULL)
+ filename = "profile.dat";
+ else
+ filename = value;
+
+ file = fopen(filename, "w");
+
+ if (file == NULL)
+ vm_abort_errno("options_xx: fopen failed");
+
+ opt_ProfileMemoryUsageGNUPlot = file;
+ break;
+
+ #if defined(ENABLE_REPLACEMENT)
+ case OPT_TestReplacement:
+ opt_TestReplacement = enable;
+ break;
+ #endif
+
+ case OPT_TraceCompilerCalls:
+ opt_TraceCompilerCalls = enable;
+ break;
+
+ case OPT_TraceExceptions:
+ opt_TraceExceptions = enable;
+ break;
+
+ case OPT_TraceHPI:
+ opt_TraceHPI = enable;
+ break;
+
+ #if defined(ENABLE_INLINING) && !defined(NDEBUG)
+ case OPT_TraceInlining:
+ if (value == NULL)
+ opt_TraceInlining = 1;
+ else
+ opt_TraceInlining = os_atoi(value);
+ break;
+ #endif
+
+ case OPT_TraceJavaCalls:
+ opt_verbosecall = enable;
+ opt_TraceJavaCalls = enable;
+ break;
+
+ case OPT_TraceJNICalls:
+ opt_TraceJNICalls = enable;
+ break;
+
+ case OPT_TraceJVMCalls:
+ opt_TraceJVMCalls = enable;
+ break;
+
+ case OPT_TraceJVMCallsVerbose:
+ opt_TraceJVMCallsVerbose = enable;
+ break;
+
+ case OPT_TraceLinkClass:
+ opt_TraceLinkClass = enable;
+ break;
+
+ #if defined(ENABLE_REPLACEMENT)
+ case OPT_TraceReplacement:
+ if (value == NULL)
+ opt_TraceReplacement = 1;
+ else
+ opt_TraceReplacement = os_atoi(value);
+ break;
+ #endif
+
+ case OPT_TraceSubsystemInitialization:
+ opt_TraceSubsystemInitialization = enable;
+ break;
+
+ case OPT_TraceTraps:
+ opt_TraceTraps = enable;
+ break;
+
+ #if defined(ENABLE_VMLOG)
+ case OPT_Vmlog:
+ if (value == NULL)
+ vmlog_cacao_set_prefix("vmlog");
+ else
+ vmlog_cacao_set_prefix(value);
+ opt_verbosecall = 1;
+ opt_TraceJavaCalls = 1;
+ break;
+
+ case OPT_VmlogStrings:
+ if (value != NULL)
+ vmlog_cacao_set_stringprefix(value);
+ break;
+
+ case OPT_VmlogIgnore:
+ if (value != NULL)
+ vmlog_cacao_set_ignoreprefix(value);
+ break;
+ #endif
+
+ default:
+ printf("Unknown -XX option: %s\n", name);
+ break;
+ }
+ }
+ }
+
+
+ /*
+ * 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
+ * Emacs will automagically detect them.
+ * ---------------------------------------------------------------------
+ * Local variables:
+ * mode: c
+ * indent-tabs-mode: t
+ * c-basic-offset: 4
+ * tab-width: 4
+ * End:
+ */
--- /dev/null
+ /* src/vm/options.h - define global options extern
+
+ Copyright (C) 1996-2005, 2006, 2007, 2008
+ CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
+
+ This file is part of CACAO.
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 2, or (at
+ your option) any later version.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ 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., 51 Franklin Street, Fifth Floor, Boston, MA
+ 02110-1301, USA.
+
+ */
+
+
+ #ifndef _OPTIONS_H
+ #define _OPTIONS_H
+
+ #include "config.h"
+
+ #ifdef __cplusplus
+ extern "C" {
+ #endif
+
+ #include <stdint.h>
+
+ #include "vm/types.h"
+
+ #include "native/jni.h"
+
+ #include "vm/global.h"
+
+
+ /* reserved option numbers ****************************************************/
+
+ /* define these negative since the other options are an enum */
+
+ #define OPT_DONE -1
+ #define OPT_ERROR -2
+ #define OPT_IGNORE -3
+
+
+ typedef struct opt_struct opt_struct;
+
+ struct opt_struct {
+ const char *name;
+ bool arg;
+ int value;
+ };
+
+
+ typedef struct option_t option_t;
+
+ struct option_t {
+ const char *name;
+ int value;
+ int type;
+ const char *doc;
+ };
+
+
+ /* global variables ***********************************************************/
+
+ extern s4 opt_index;
+ extern char *opt_arg;
+
+ extern bool opt_foo;
+
+ extern bool opt_jit;
+ extern bool opt_intrp;
+
+ extern bool opt_jar;
+ extern bool opt_run;
+
+ extern s4 opt_heapmaxsize;
+ extern s4 opt_heapstartsize;
+ extern s4 opt_stacksize;
+
+ extern bool opt_verbose;
+ extern bool opt_debugcolor;
+ extern bool compileall;
+
+ extern bool loadverbose; /* Print debug messages during loading */
+ extern bool initverbose; /* Log class initialization */
+
+ extern bool opt_verboseclass;
+ extern bool opt_verbosegc;
+ extern bool opt_verbosejni;
+ extern bool opt_verbosecall;
+
+ extern bool showmethods;
+ extern bool showconstantpool;
+ extern bool showutf;
+
+ extern char *opt_method;
+ extern char *opt_signature;
+
+ extern bool compileverbose;
+ extern bool showstack;
+
+ extern bool opt_showdisassemble;
+ extern bool opt_shownops;
+ extern bool opt_showddatasegment;
+ extern bool opt_showintermediate;
+
+ extern bool checkbounds;
+ extern bool opt_noieee;
+ extern bool checksync;
+ #if defined(ENABLE_LOOP)
+ extern bool opt_loops;
+ #endif
+
+ extern bool makeinitializations;
+
+ #if defined(ENABLE_STATISTICS)
+ extern bool opt_stat;
+ extern bool opt_getloadingtime;
+ extern bool opt_getcompilingtime;
+ #endif
+ #if defined(ENABLE_VERIFIER)
+ extern bool opt_verify;
+ #endif
+
+ #if defined(ENABLE_PROFILING)
+ extern bool opt_prof;
+ extern bool opt_prof_bb;
+ #endif
+
+ /* optimization options *******************************************************/
+
+ #if defined(ENABLE_IFCONV)
+ extern bool opt_ifconv;
+ #endif
+
+ #if defined(ENABLE_LSRA) || defined(ENABLE_SSA)
+ extern bool opt_lsra;
+ #endif
+ #if defined(ENABLE_SSA)
+ extern bool opt_ssa_dce; /* enable dead code elemination */
+ extern bool opt_ssa_cp; /* enable copy propagation */
+ #endif
+
+ /* interpreter options ********************************************************/
+
+ #if defined(ENABLE_INTRP)
+ extern bool opt_no_dynamic;
+ extern bool opt_no_replication;
+ extern bool opt_no_quicksuper;
+
+ extern s4 opt_static_supers;
+ extern bool vm_debug;
+ #endif
+
+ /* debug output filtering options *********************************************/
+
+ #if defined(ENABLE_DEBUG_FILTER)
+ extern const char *opt_filter_verbosecall_include;
+ extern const char *opt_filter_verbosecall_exclude;
+ extern const char *opt_filter_show_method;
+ #endif
+
+
+ /* -XX options ****************************************************************/
+
+ /* NOTE: For better readability keep these alpha-sorted. */
+
+ /* Options which must always be available (production options in
+ HotSpot). */
+
+ extern int64_t opt_MaxDirectMemorySize;
+ extern int opt_MaxPermSize;
+ extern int opt_PermSize;
+ extern int opt_ThreadStackSize;
+
+ /* Debugging options which can be turned off. */
+
+ extern int opt_DebugExceptions;
+ extern int opt_DebugFinalizer;
++#if defined(ENABLE_JITCACHE)
++extern int opt_DebugJitCache;
++#endif
+ extern int opt_DebugLocalReferences;
+ extern int opt_DebugLocks;
+ extern int opt_DebugPatcher;
+ extern int opt_DebugPackage;
+ extern int opt_DebugProperties;
+ extern int opt_DebugStackFrameInfo;
+ extern int opt_DebugStackTrace;
+ extern int opt_DebugThreads;
+ #if defined(ENABLE_DISASSEMBLER)
+ extern int opt_DisassembleStubs;
+ #endif
+ #if defined(ENABLE_OPAGENT)
+ extern int opt_EnableOpagent;
+ #endif
+ #if defined(ENABLE_GC_CACAO)
+ extern int opt_GCDebugRootSet;
+ extern int opt_GCStress;
+ #endif
+ #if defined(ENABLE_INLINING)
+ extern int opt_Inline;
+ #if defined(ENABLE_INLINING_DEBUG) || !defined(NDEBUG)
+ extern int opt_InlineAll;
+ extern int opt_InlineCount;
+ extern int opt_InlineMaxSize;
+ extern int opt_InlineMinSize;
+ #endif
+ #endif
+ extern int opt_PrintConfig;
+ extern int opt_ProfileGCMemoryUsage;
+ extern int opt_ProfileMemoryUsage;
+ extern FILE *opt_ProfileMemoryUsageGNUPlot;
+ #if defined(ENABLE_REPLACEMENT)
+ extern int opt_TestReplacement;
+ #endif
+ extern int opt_TraceCompilerCalls;
+ extern int opt_TraceExceptions;
+ extern int opt_TraceHPI;
+ #if defined(ENABLE_INLINING) && !defined(NDEBUG)
+ extern int opt_TraceInlining;
+ #endif
+ extern int opt_TraceJavaCalls;
+ extern int opt_TraceJNICalls;
+ extern int opt_TraceJVMCalls;
+ extern int opt_TraceJVMCallsVerbose;
+ extern int opt_TraceLinkClass;
+ #if defined(ENABLE_REPLACEMENT)
+ extern int opt_TraceReplacement;
+ #endif
+ extern int opt_TraceSubsystemInitialization;
+ extern int opt_TraceTraps;
+
+
+ /* function prototypes ********************************************************/
+
+ int options_get(opt_struct *opts, JavaVMInitArgs *vm_args);
+ void options_xx(JavaVMInitArgs *vm_args);
+
+
+ /* debug **********************************************************************/
+
+ #if !defined(NDEBUG)
+ # define TRACESUBSYSTEMINITIALIZATION(text) \
+ do { \
+ if (opt_TraceSubsystemInitialization) { \
+ log_println("[Initializing subsystem: %s]", text); \
+ } \
+ } while (0)
+ #else
+ # define TRACESUBSYSTEMINITIALIZATION(text)
+ #endif
+
+ #ifdef __cplusplus
+ }
+ #endif
+
+ #endif /* _OPTIONS_H */
+
+
+ /*
+ * 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
+ * Emacs will automagically detect them.
+ * ---------------------------------------------------------------------
+ * Local variables:
+ * mode: c
+ * indent-tabs-mode: t
+ * c-basic-offset: 4
+ * tab-width: 4
+ * End:
+ */
--- /dev/null
+ /* src/vm/os.hpp - system (OS) functions
+
+ Copyright (C) 2007, 2008
+ CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
+
+ This file is part of CACAO.
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 2, or (at
+ your option) any later version.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ 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., 51 Franklin Street, Fifth Floor, Boston, MA
+ 02110-1301, USA.
+
+ */
+
+
+ #ifndef _OS_HPP
+ #define _OS_HPP
+
+ #include "config.h"
+
+ /* NOTE: In this file we check for all system headers, because we wrap
+ all system calls into inline functions for better portability. */
+
+ #if defined(HAVE_DIRENT_H)
+ # include <dirent.h>
+ #endif
+
+ #if defined(HAVE_DLFCN_H)
+ # include <dlfcn.h>
+ #endif
+
+ #if defined(HAVE_ERRNO_H)
+ # include <errno.h>
+ #endif
+
+ #if defined(HAVE_FCNTL_H)
+ # include <fcntl.h>
+ #endif
+
+ #if defined(ENABLE_JRE_LAYOUT)
+ # if defined(HAVE_LIBGEN_H)
+ # include <libgen.h>
+ # endif
+ #endif
+
+ #if defined(HAVE_SIGNAL_H)
+ # include <signal.h>
+ #endif
+
+ #if defined(HAVE_STDINT_H)
+ # include <stdint.h>
+ #endif
+
+ #if defined(HAVE_STDIO_H)
+ # include <stdio.h>
+ #endif
+
+ #if defined(HAVE_STDLIB_H)
+ # include <stdlib.h>
+ #endif
+
+ #if defined(HAVE_STRING_H)
+ # include <string.h>
+ #endif
+
+ #if defined(HAVE_UNISTD_H)
+ # include <unistd.h>
+ #endif
+
+ #if defined(HAVE_SYS_MMAN_H)
+ # include <sys/mman.h>
+ #endif
+
+ #if defined(HAVE_SYS_SOCKET_H)
+ # include <sys/socket.h>
+ #endif
+
+ #if defined(HAVE_SYS_STAT_H)
+ # include <sys/stat.h>
+ #endif
+
+ #if defined(HAVE_SYS_TYPES_H)
+ # include <sys/types.h>
+ #endif
+
+
+ #ifdef __cplusplus
+
+ // Class wrapping system (OS) functions.
+ class os {
+ public:
+ // Inline functions.
+ static inline void abort();
+ static inline int accept(int sockfd, struct sockaddr* addr, socklen_t* addrlen);
+ static inline int access(const char *pathname, int mode);
+ static inline int atoi(const char* nptr);
+ static inline void* calloc(size_t nmemb, size_t size);
+ static inline int close(int fd);
+ static inline int connect(int sockfd, const struct sockaddr* serv_addr, socklen_t addrlen);
+ #if defined(ENABLE_JRE_LAYOUT)
+ static inline char* dirname(char* path);
+ #endif
+ static inline int dlclose(void* handle);
+ static inline char* dlerror(void);
+ static inline void* dlopen(const char* filename, int flag);
+ static inline void* dlsym(void* handle, const char* symbol);
+ static inline int fclose(FILE* fp);
+ static inline FILE* fopen(const char* path, const char* mode);
+ static inline size_t fread(void* ptr, size_t size, size_t nmemb, FILE* stream);
+ static inline void free(void* ptr);
+ static inline int gethostname(char* name, size_t len);
+ static inline int getpagesize(void);
+ static inline int getsockname(int s, struct sockaddr* name, socklen_t* namelen);
+ static inline int getsockopt(int s, int level, int optname, void* optval, socklen_t* optlen);
+ static inline int listen(int sockfd, int backlog);
+ static inline void* malloc(size_t size);
+ static inline void* memcpy(void* dest, const void* src, size_t n);
+ static inline void* memset(void* s, int c, size_t n);
+ static inline int mprotect(void* addr, size_t len, int prot);
+ static inline int scandir(const char* dir, struct dirent*** namelist, int(*filter)(const struct dirent*), int(*compar)(const void*, const void*));
+ static inline int setsockopt(int s, int level, int optname, const void* optval, socklen_t optlen);
+ static inline int shutdown(int s, int how);
+ static inline int socket(int domain, int type, int protocol);
+ static inline int stat(const char* path, struct stat* buf);
+ #if defined(__SOLARIS__)
+ static inline int str2sig(const char* str, int* signum);
+ #endif
+ static inline char* strcat(char* dest, const char* src);
+ static inline char* strcpy(char* dest, const char* src);
+ static inline char* strdup(const char* s);
+ static inline size_t strlen(const char* s);
+ static inline char* strerror(int errnum);
+
+ static void* mmap_anonymous(void *addr, size_t len, int prot, int flags);
+ static int processors_online(void);
+ };
+
+
+ inline void os::abort(void)
+ {
+ #if defined(HAVE_ABORT)
+ ::abort();
+ #else
+ # error abort not available
+ #endif
+ }
+
+ inline int os::accept(int sockfd, struct sockaddr* addr, socklen_t* addrlen)
+ {
+ #if defined(HAVE_ACCEPT)
+ return ::accept(sockfd, addr, addrlen);
+ #else
+ # error accept not available
+ #endif
+ }
+
+ inline int os::access(const char* pathname, int mode)
+ {
+ #if defined(HAVE_ACCESS)
+ return ::access(pathname, mode);
+ #else
+ # error access not available
+ #endif
+ }
+
+ inline int os::atoi(const char* nptr)
+ {
+ #if defined(HAVE_ATOI)
+ return ::atoi(nptr);
+ #else
+ # error atoi not available
+ #endif
+ }
+
+ inline void* os::calloc(size_t nmemb, size_t size)
+ {
+ #if defined(HAVE_CALLOC)
+ return ::calloc(nmemb, size);
+ #else
+ # error calloc not available
+ #endif
+ }
+
+ inline int os::close(int fd)
+ {
+ #if defined(HAVE_CLOSE)
+ return ::close(fd);
+ #else
+ # error close not available
+ #endif
+ }
+
+ inline int os::connect(int sockfd, const struct sockaddr* serv_addr, socklen_t addrlen)
+ {
+ #if defined(HAVE_CONNECT)
+ return ::connect(sockfd, serv_addr, addrlen);
+ #else
+ # error connect not available
+ #endif
+ }
+
+ #if defined(ENABLE_JRE_LAYOUT)
+ inline char* os::dirname(char* path)
+ {
+ #if defined(HAVE_DIRNAME)
+ return ::dirname(path);
+ #else
+ # error dirname not available
+ #endif
+ }
+ #endif
+
+ inline int os::dlclose(void* handle)
+ {
+ #if defined(HAVE_DLCLOSE)
+ return ::dlclose(handle);
+ #else
+ # error dlclose not available
+ #endif
+ }
+
+ inline char* os::dlerror(void)
+ {
+ #if defined(HAVE_DLERROR)
+ return ::dlerror();
+ #else
+ # error dlerror not available
+ #endif
+ }
+
+ inline void* os::dlopen(const char* filename, int flag)
+ {
+ #if defined(HAVE_DLOPEN)
+ return ::dlopen(filename, flag);
+ #else
+ # error dlopen not available
+ #endif
+ }
+
+ inline void* os::dlsym(void* handle, const char* symbol)
+ {
+ #if defined(HAVE_DLSYM)
+ return ::dlsym(handle, symbol);
+ #else
+ # error dlsym not available
+ #endif
+ }
+
+ inline int os::fclose(FILE* fp)
+ {
+ #if defined(HAVE_FCLOSE)
+ return ::fclose(fp);
+ #else
+ # error fclose not available
+ #endif
+ }
+
+ inline FILE* os::fopen(const char* path, const char* mode)
+ {
+ #if defined(HAVE_FOPEN)
+ return ::fopen(path, mode);
+ #else
+ # error fopen not available
+ #endif
+ }
+
+ inline size_t os::fread(void* ptr, size_t size, size_t nmemb, FILE* stream)
+ {
+ #if defined(HAVE_FREAD)
+ return ::fread(ptr, size, nmemb, stream);
+ #else
+ # error fread not available
+ #endif
+ }
+
++inline static int system_fseek(FILE *stream, off_t offset, int whence)
++{
++#if defined(HAVE_FSEEK)
++ return fseek(stream, offset, whence);
++#else
++# error fseek not available
++#endif
++}
++
+ inline void os::free(void* ptr)
+ {
+ #if defined(HAVE_FREE)
+ ::free(ptr);
+ #else
+ # error free not available
+ #endif
+ }
+
+ inline static int system_fsync(int fd)
+ {
+ #if defined(HAVE_FSYNC)
+ return fsync(fd);
+ #else
+ # error fsync not available
+ #endif
+ }
+
+ inline static int system_ftruncate(int fd, off_t length)
+ {
+ #if defined(HAVE_FTRUNCATE)
+ return ftruncate(fd, length);
+ #else
+ # error ftruncate not available
+ #endif
+ }
+
+ inline int os::gethostname(char* name, size_t len)
+ {
+ #if defined(HAVE_GETHOSTNAME)
+ return ::gethostname(name, len);
+ #else
+ # error gethostname not available
+ #endif
+ }
+
+ inline int os::getpagesize(void)
+ {
+ #if defined(HAVE_GETPAGESIZE)
+ return ::getpagesize();
+ #else
+ # error getpagesize not available
+ #endif
+ }
+
+ inline int os::getsockname(int s, struct sockaddr* name, socklen_t* namelen)
+ {
+ #if defined(HAVE_GETSOCKNAME)
+ return ::getsockname(s, name, namelen);
+ #else
+ # error getsockname not available
+ #endif
+ }
+
+ inline int os::getsockopt(int s, int level, int optname, void* optval, socklen_t* optlen)
+ {
+ #if defined(HAVE_GETSOCKOPT)
+ return ::getsockopt(s, level, optname, optval, optlen);
+ #else
+ # error getsockopt not available
+ #endif
+ }
+
+ inline int os::listen(int sockfd, int backlog)
+ {
+ #if defined(HAVE_LISTEN)
+ return ::listen(sockfd, backlog);
+ #else
+ # error listen not available
+ #endif
+ }
+
+ inline static off_t system_lseek(int fildes, off_t offset, int whence)
+ {
+ #if defined(HAVE_LSEEK)
+ return lseek(fildes, offset, whence);
+ #else
+ # error lseek not available
+ #endif
+ }
+
+ inline void* os::malloc(size_t size)
+ {
+ #if defined(HAVE_MALLOC)
+ return ::malloc(size);
+ #else
+ # error malloc not available
+ #endif
+ }
+
+ inline void* os::memcpy(void* dest, const void* src, size_t n)
+ {
+ #if defined(HAVE_MEMCPY)
+ return ::memcpy(dest, src, n);
+ #else
+ # error memcpy not available
+ #endif
+ }
+
+ inline void* os::memset(void* s, int c, size_t n)
+ {
+ #if defined(HAVE_MEMSET)
+ return ::memset(s, c, n);
+ #else
+ # error memset not available
+ #endif
+ }
+
+ inline int os::mprotect(void* addr, size_t len, int prot)
+ {
+ #if defined(HAVE_MPROTECT)
+ return ::mprotect(addr, len, prot);
+ #else
+ # error mprotect not available
+ #endif
+ }
+
+ inline static int system_open(const char *pathname, int flags, mode_t mode)
+ {
+ #if defined(HAVE_OPEN)
+ return open(pathname, flags, mode);
+ #else
+ # error open not available
+ #endif
+ }
+
+ inline static ssize_t system_read(int fd, void *buf, size_t count)
+ {
+ #if defined(HAVE_READ)
+ return read(fd, buf, count);
+ #else
+ # error read not available
+ #endif
+ }
+
+ inline static void *system_realloc(void *ptr, size_t size)
+ {
+ #if defined(HAVE_REALLOC)
+ return realloc(ptr, size);
+ #else
+ # error realloc not available
+ #endif
+ }
+
+ inline int os::scandir(const char *dir, struct dirent ***namelist, int(*filter)(const struct dirent *), int(*compar)(const void *, const void *))
+ /*
+ #elif defined(__SOLARIS__)
+ inline int os::scandir(const char *dir, struct dirent ***namelist, int(*filter)(const struct dirent *), int(*compar)(const struct dirent **, const struct dirent **))
+ #elif defined(__IRIX__)
+ inline int os::scandir(const char *dir, struct dirent ***namelist, int(*filter)(dirent_t *), int(*compar)(dirent_t **, dirent_t **))
+ #else
+ inline int os::scandir(const char *dir, struct dirent ***namelist, int(*filter)(struct dirent *), int(*compar)(const void *, const void *))
+ #endif
+ */
+ {
+ #if defined(HAVE_SCANDIR)
+ # if defined(__LINUX__)
+ return ::scandir(dir, namelist, filter, compar);
+ #elif defined(__SOLARIS__)
+ return ::scandir(dir, namelist, filter, (int (*)(const dirent**, const dirent**)) compar);
+ # else
+ return ::scandir(dir, namelist, (int (*)(struct dirent*)) filter, compar);
+ # endif
+ #else
+ # error scandir not available
+ #endif
+ }
+
+ inline int os::setsockopt(int s, int level, int optname, const void* optval, socklen_t optlen)
+ {
+ #if defined(HAVE_SETSOCKOPT)
+ return ::setsockopt(s, level, optname, optval, optlen);
+ #else
+ # error setsockopt not available
+ #endif
+ }
+
+ inline int os::shutdown(int s, int how)
+ {
+ #if defined(HAVE_SHUTDOWN)
+ return ::shutdown(s, how);
+ #else
+ # error shutdown not available
+ #endif
+ }
+
+ inline int os::socket(int domain, int type, int protocol)
+ {
+ #if defined(HAVE_SOCKET)
+ return ::socket(domain, type, protocol);
+ #else
+ # error socket not available
+ #endif
+ }
+
+ inline int os::stat(const char* path, struct stat* buf)
+ {
+ #if defined(HAVE_STAT)
+ return ::stat(path, buf);
+ #else
+ # error stat not available
+ #endif
+ }
+
+ #if defined(__SOLARIS__)
+ inline int os::str2sig(const char* str, int* signum)
+ {
+ #if defined(HAVE_STR2SIG)
+ return ::str2sig(str, signum);
+ #else
+ # error str2sig not available
+ #endif
+ }
+ #endif
+
+ inline char* os::strcat(char* dest, const char* src)
+ {
+ #if defined(HAVE_STRCAT)
+ return ::strcat(dest, src);
+ #else
+ # error strcat not available
+ #endif
+ }
+
+ inline char* os::strcpy(char* dest, const char* src)
+ {
+ #if defined(HAVE_STRCPY)
+ return ::strcpy(dest, src);
+ #else
+ # error strcpy not available
+ #endif
+ }
+
+ inline char* os::strdup(const char* s)
+ {
+ #if defined(HAVE_STRDUP)
+ return ::strdup(s);
+ #else
+ # error strdup not available
+ #endif
+ }
+
+ inline char* os::strerror(int errnum)
+ {
+ #if defined(HAVE_STRERROR)
+ return ::strerror(errnum);
+ #else
+ # error strerror not available
+ #endif
+ }
+
+ inline size_t os::strlen(const char* s)
+ {
+ #if defined(HAVE_STRLEN)
+ return ::strlen(s);
+ #else
+ # error strlen not available
+ #endif
+ }
+
+ inline static ssize_t system_write(int fd, const void *buf, size_t count)
+ {
+ #if defined(HAVE_WRITE)
+ return write(fd, buf, count);
+ #else
+ # error write not available
+ #endif
+ }
+
+ #else
+
+ void* os_mmap_anonymous(void *addr, size_t len, int prot, int flags);
+
+ void os_abort(void);
+ int os_access(const char* pathname, int mode);
+ int os_atoi(const char* nptr);
+ void* os_calloc(size_t nmemb, size_t size);
+ char* os_dirname(char* path);
+ int os_dlclose(void* handle);
+ char* os_dlerror(void);
+ void* os_dlopen(const char* filename, int flag);
+ void* os_dlsym(void* handle, const char* symbol);
+ int os_fclose(FILE* fp);
+ FILE* os_fopen(const char* path, const char* mode);
+ size_t os_fread(void* ptr, size_t size, size_t nmemb, FILE* stream);
+ void os_free(void* ptr);
+ int os_getpagesize(void);
+ void* os_memcpy(void* dest, const void* src, size_t n);
+ void* os_memset(void* s, int c, size_t n);
+ int os_mprotect(void* addr, size_t len, int prot);
+ int os_scandir(const char* dir, struct dirent*** namelist, int(*filter)(const struct dirent*), int(*compar)(const void*, const void*));
+ int os_stat(const char* path, struct stat* buf);
+ char* os_strcat(char* dest, const char* src);
+ char* os_strcpy(char* dest, const char* src);
+ char* os_strdup(const char* s);
+ int os_strlen(const char* s);
+
+ #endif
+
+ #endif // _OS_HPP
+
+
+ /*
+ * 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
+ * Emacs will automagically detect them.
+ * ---------------------------------------------------------------------
+ * Local variables:
+ * mode: c++
+ * indent-tabs-mode: t
+ * c-basic-offset: 4
+ * tab-width: 4
+ * End:
+ * vim:noexpandtab:sw=4:ts=4:
+ */
--- /dev/null
-/* macro for accessing the class name of a method reference */
+ /* src/vm/references.h - references to classes/fields/methods
+
+ Copyright (C) 1996-2005, 2006, 2007, 2008
+ CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
+
+ This file is part of CACAO.
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 2, or (at
+ your option) any later version.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ 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., 51 Franklin Street, Fifth Floor, Boston, MA
+ 02110-1301, USA.
+
+ */
+
+ #ifndef _REFERENCES_H_
+ #define _REFERENCES_H_
+
+ /* forward typedefs ***********************************************************/
+
+ typedef struct constant_classref constant_classref;
+ typedef struct constant_FMIref constant_FMIref;
+
+
+ /* constant_classref **********************************************************/
+
+ struct constant_classref {
+ void *pseudo_vftbl; /* for distinguishing it from classinfo */
+ struct classinfo *referer; /* class containing the reference */
+ struct utf *name; /* name of the class refered to */
+ };
+
+
+ /* classref_or_classinfo ******************************************************/
+
+ typedef union classref_or_classinfo {
+ constant_classref *ref; /* a symbolic class reference */
+ struct classinfo *cls; /* an already loaded class */
+ void *any; /* used for general access (x != NULL,...) */
+ } classref_or_classinfo;
+
+
+ /* parseddesc_t ***************************************************************/
+
+ typedef union parseddesc {
+ struct typedesc *fd; /* parsed field descriptor */
+ struct methoddesc *md; /* parsed method descriptor */
+ void *any; /* used for simple test against NULL */
+ } parseddesc_t;
+
+
+ #include "config.h"
+ #include "vm/types.h"
+
+ #include "vm/class.h"
+ #include "vm/descriptor.h"
+ #include "vm/field.h"
+ #include "vm/global.h"
+ #include "vm/method.h"
+ #include "vm/utf8.h"
+
+
+ /*----------------------------------------------------------------------------*/
+ /* References */
+ /* */
+ /* This header files defines the following types used for references to */
+ /* classes/methods/fields and descriptors: */
+ /* */
+ /* classinfo * a loaded class */
+ /* constant_classref a symbolic reference */
+ /* classref_or_classinfo a loaded class or a symbolic reference */
+ /* */
+ /* constant_FMIref a symb. ref. to a field/method/intf.method */
+ /* */
+ /* typedesc * describes a field type */
+ /* methoddesc * descrives a method type */
+ /* parseddesc describes a field type or a method type */
+ /*----------------------------------------------------------------------------*/
+
+ /* structs ********************************************************************/
+
+ /* constant_FMIref ************************************************************/
+
+ struct constant_FMIref{ /* Fieldref, Methodref and InterfaceMethodref */
+ union {
+ s4 index; /* used only within the loader */
+ constant_classref *classref; /* class having this field/meth./intfm. */
+ fieldinfo *field; /* resolved field */
+ methodinfo *method; /* resolved method */
+ } p;
+ utf *name; /* field/method/interfacemethod name */
+ utf *descriptor; /* field/method/intfmeth. type descriptor string */
+ parseddesc_t parseddesc; /* parsed descriptor */
+ };
+
+
+ /* macros *********************************************************************/
+
+ /* a value that never occurrs in classinfo.header.vftbl */
+ #define CLASSREF_PSEUDO_VFTBL ((void *) 1)
+
+ /* macro for testing if a classref_or_classinfo is a classref */
+ /* `reforinfo` is only evaluated once */
+ #define IS_CLASSREF(reforinfo) \
+ ((reforinfo).ref->pseudo_vftbl == CLASSREF_PSEUDO_VFTBL)
+
+ /* macro for testing if a constant_FMIref has been resolved */
+ /* `fmiref` is only evaluated once */
+ #define IS_FMIREF_RESOLVED(fmiref) \
+ ((fmiref)->p.classref->pseudo_vftbl != CLASSREF_PSEUDO_VFTBL)
+
+ /* the same as IS_CLASSREF, but also check against NULL */
+ #define IS_XCLASSREF(reforinfo) \
+ ((reforinfo).any && IS_CLASSREF(reforinfo))
+
+ /* macro for casting a classref/classinfo * to a classref_or_classinfo */
+ #define CLASSREF_OR_CLASSINFO(value) \
+ (*((classref_or_classinfo *)(&(value))))
+
+ /* macro for accessing the name of a classref/classinfo */
+ #define CLASSREF_OR_CLASSINFO_NAME(value) \
+ (IS_CLASSREF(value) ? (value).ref->name : (value).cls->name)
+
+ /* macro for accessing the class name of a method reference */
+ #define METHODREF_CLASSNAME(fmiref) \
+ (IS_FMIREF_RESOLVED(fmiref) ? (fmiref)->p.method->clazz->name \
+ : (fmiref)->p.classref->name)
+
++/* macro for accessing the class name of a field reference */
+ #define FIELDREF_CLASSNAME(fmiref) \
+ (IS_FMIREF_RESOLVED(fmiref) ? (fmiref)->p.field->clazz->name \
+ : (fmiref)->p.classref->name)
+
+ /* initialize a constant_classref with referer `ref` and name `classname` */
+
+ #define CLASSREF_INIT(c,ref,classname) \
+ do { \
+ (c).pseudo_vftbl = CLASSREF_PSEUDO_VFTBL; \
+ (c).referer = (ref); \
+ (c).name = (classname); \
+ } while (0)
+
+ #endif /* _REFERENCES_H_ */
+
+ /*
+ * 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
+ * Emacs will automagically detect them.
+ * ---------------------------------------------------------------------
+ * Local variables:
+ * mode: c
+ * indent-tabs-mode: t
+ * c-basic-offset: 4
+ * tab-width: 4
+ * End:
+ * vim:noexpandtab:sw=4:ts=4:
+ */
+
#include "mm/memory.h"
#include "vm/access.h"
- #include "vm/exceptions.h"
+ #include "vm/classcache.h"
+ #include "vm/descriptor.h"
+ #include "vm/exceptions.hpp"
#include "vm/global.h"
- #include "vm/primitive.h"
+ #include "vm/globals.hpp"
+ #include "vm/linker.h"
+ #include "vm/loader.h"
+ #include "vm/options.h"
+ #include "vm/primitive.hpp"
#include "vm/resolve.h"
#include "vm/jit/jit.h"
#include "vm/jit/verify/typeinfo.h"
- #include "vmcore/classcache.h"
- #include "vmcore/descriptor.h"
- #include "vmcore/linker.h"
- #include "vmcore/loader.h"
- #include "vmcore/options.h"
-
/******************************************************************************/
/* DEBUG HELPERS */
else {
/* a primitive type */
- cls = primitive_class_get_by_type(d->decltype);
+ cls = Primitive_get_class_by_type(d->primitivetype);
assert(cls->state & CLASS_LOADED);
fi = class_resolvefield(container,
fieldref->name, fieldref->descriptor,
- referer, true);
+ referer);
if (!fi) {
/* The field does not exist. But since we were called lazily, */
/* this error must not be reported now. (It will be reported */
fi = class_resolvefield(container,
ref->fieldref->name,ref->fieldref->descriptor,
- referer,true);
+ referer);
if (!fi) {
if (mode == resolveLazy) {
/* The field does not exist. But since we were called lazily, */
/* check subtype constraints for TYPE_ADR parameters */
- assert(mi->parseddesc->paramcount == ref->methodref->parseddesc.md->paramcount);
+ assert(mi == ref->methodref->p.method || mi->parseddesc->paramcount == ref->methodref->parseddesc.md->paramcount);
paramtypes = mi->parseddesc->paramtypes;
for (i = 0; i < mi->parseddesc->paramcount-instancecount; i++) {
--- /dev/null
- size_patchref;
+ /* src/vm/statistics.c - global variables for statistics
+
+ Copyright (C) 1996-2005, 2006, 2007, 2008
+ CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
+
+ This file is part of CACAO.
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 2, or (at
+ your option) any later version.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ 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., 51 Franklin Street, Fifth Floor, Boston, MA
+ 02110-1301, USA.
+
+ */
+
+
+ #include "config.h"
+
+ #include <stdint.h>
+ #include <string.h>
+
+ #if defined(HAVE_TIME_H)
+ # include <time.h>
+ #endif
+
+ #if defined(HAVE_SYS_TIME_H)
+ # include <sys/time.h>
+ #endif
+
+ #if defined(HAVE_SYS_RESOURCE_H)
+ # include <sys/resource.h>
+ #endif
+
+ #include "vm/types.h"
+
+ #include "mm/gc.hpp"
+
+ #include "toolbox/logging.h"
+
+ #include "vm/class.h"
+ #include "vm/field.h"
+ #include "vm/global.h"
+ #include "vm/method.h"
+ #include "vm/options.h"
+ #include "vm/statistics.h"
+
+ #include "vm/jit/code.h"
+
+
+ /* global variables ***********************************************************/
+
+ static s8 loadingtime = 0; /* accumulated loading time */
+ static s8 loadingstarttime = 0;
+ static s8 loadingstoptime = 0;
+ static s4 loadingtime_recursion = 0;
+
+ static s8 compilingtime = 0; /* accumulated compile time */
+ static s8 compilingstarttime = 0;
+ static s8 compilingstoptime = 0;
+ static s4 compilingtime_recursion = 0;
+
+ s4 codememusage = 0;
+ s4 maxcodememusage = 0;
+
+ s4 memoryusage = 0;
+ s4 maxmemusage = 0;
+
+ s4 maxdumpsize = 0;
+
+ s4 globalallocateddumpsize = 0;
+ s4 globaluseddumpsize = 0;
+
+
+ /* variables for measurements *************************************************/
+
+ s4 size_classinfo = 0;
+ s4 size_fieldinfo = 0;
+ s4 size_methodinfo = 0;
+ s4 size_lineinfo = 0;
+ s4 size_codeinfo = 0;
+
+ s4 size_stub_native = 0;
+
+ s4 size_stack_map = 0;
+ s4 size_string = 0;
+
+ s4 size_threadobject = 0;
+ int32_t size_thread_index_t = 0;
+ int32_t size_stacksize = 0;
+
+ s4 size_lock_record = 0;
+ s4 size_lock_hashtable = 0;
+ s4 size_lock_waiter = 0;
+
+ int32_t count_linenumbertable = 0;
+ int32_t size_linenumbertable = 0;
+
+ s4 size_patchref = 0;
+
++s4 size_cachedref = 0;
++
+ u8 count_calls_java_to_native = 0;
+ u8 count_calls_native_to_java = 0;
+
+ int count_const_pool_len = 0;
+ int count_classref_len = 0;
+ int count_parsed_desc_len = 0;
+ int count_vftbl_len = 0;
+ int count_all_methods = 0;
+ int count_methods_marked_used = 0; /* RTA */
+
+ int count_vmcode_len = 0;
+ int count_extable_len = 0;
+ int count_class_loads = 0;
+ int count_class_inits = 0;
+
+ int count_utf_len = 0; /* size of utf hash */
+ int count_utf_new = 0; /* calls of utf_new */
+ int count_utf_new_found = 0; /* calls of utf_new with fast return */
+
+ int count_locals_conflicts = 0; /* register allocator statistics */
+ int count_locals_spilled = 0;
+ int count_locals_register = 0;
+ int count_ss_spilled = 0;
+ int count_ss_register = 0;
+ int count_methods_allocated_by_lsra = 0;
+ int count_mem_move_bb = 0;
+ int count_interface_size = 0;
+ int count_argument_mem_ss = 0;
+ int count_argument_reg_ss = 0;
+ int count_method_in_register = 0;
+ int count_mov_reg_reg = 0;
+ int count_mov_mem_reg = 0;
+ int count_mov_reg_mem = 0;
+ int count_mov_mem_mem = 0;
+
+ int count_jit_calls = 0;
+ int count_methods = 0;
+ int count_spills_read_ila = 0;
+ int count_spills_read_flt = 0;
+ int count_spills_read_dbl = 0;
+ int count_spills_write_ila = 0;
+ int count_spills_write_flt = 0;
+ int count_spills_write_dbl = 0;
+ int count_pcmd_activ = 0;
+ int count_pcmd_drop = 0;
+ int count_pcmd_zero = 0;
+ int count_pcmd_const_store = 0;
+ int count_pcmd_const_alu = 0;
+ int count_pcmd_const_bra = 0;
+ int count_pcmd_load = 0;
+ int count_pcmd_move = 0;
+ int count_load_instruction = 0;
+ int count_pcmd_store = 0;
+ int count_pcmd_store_comb = 0;
+ int count_dup_instruction = 0;
+ int count_pcmd_op = 0;
+ int count_pcmd_mem = 0;
+ int count_pcmd_met = 0;
+ int count_pcmd_bra = 0;
+ int count_pcmd_table = 0;
+ int count_pcmd_return = 0;
+ int count_pcmd_returnx = 0;
+ int count_check_null = 0;
+ int count_check_bound = 0;
+ int count_max_basic_blocks = 0;
+ int count_basic_blocks = 0;
+ int count_javainstr = 0;
+ int count_max_javainstr = 0;
+ int count_javacodesize = 0;
+ int count_javaexcsize = 0;
+ int count_calls = 0;
+ int count_tryblocks = 0;
+ int count_code_len = 0;
+ int count_data_len = 0;
+ int count_cstub_len = 0;
+ int count_max_new_stack = 0;
+ int count_upper_bound_new_stack = 0;
+
+ int count_emit_branch = 0;
+ int count_emit_branch_8bit = 0;
+ int count_emit_branch_16bit = 0;
+ int count_emit_branch_32bit = 0;
+ int count_emit_branch_64bit = 0;
+
+ s4 count_branches_resolved = 0;
+ s4 count_branches_unresolved = 0;
+
+ u8 count_jni_callXmethod_calls=0;
+ u8 count_jni_calls=0;
+
+
+ static int count_block_stack_init[11] = {
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0
+ };
+ int *count_block_stack = count_block_stack_init;
+ static int count_analyse_iterations_init[5] = {
+ 0, 0, 0, 0, 0
+ };
+ int *count_analyse_iterations = count_analyse_iterations_init;
+ static int count_method_bb_distribution_init[9] = {
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0
+ };
+ int *count_method_bb_distribution = count_method_bb_distribution_init;
+ static int count_block_size_distribution_init[18] = {
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0
+ };
+ int *count_block_size_distribution = count_block_size_distribution_init;
+ static int count_store_length_init[21] = {
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0
+ };
+ int *count_store_length = count_store_length_init;
+ static int count_store_depth_init[11] = {
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0
+ };
+ int *count_store_depth = count_store_depth_init;
+
+
+ /* instruction scheduler statistics *******************************************/
+
+ s4 count_schedule_basic_blocks = 0;
+ s4 count_schedule_nodes = 0;
+ s4 count_schedule_leaders = 0;
+ s4 count_schedule_max_leaders = 0;
+ s4 count_schedule_critical_path = 0;
+
+
+ /* jnicallXmethodinvokation ***************************************************
+
+ increments the jni CallXMethod invokation count by one
+
+ *******************************************************************************/
+
+ void jnicallXmethodnvokation(void)
+ {
+ /* XXX do locking here */
+ count_jni_callXmethod_calls++;
+ }
+
+
+ /* jniinvokation *************************************************************
+
+ increments the jni overall invokation count by one
+
+ *******************************************************************************/
+
+ void jniinvokation(void)
+ {
+ /* XXX do locking here */
+ count_jni_calls++;
+ }
+
+
+ /* getcputime *********************************** ******************************
+
+ Returns the used CPU time in microseconds
+
+ *******************************************************************************/
+
+ s8 getcputime(void)
+ {
+ #if defined(HAVE_GETRUSAGE)
+ struct rusage ru;
+ int sec, usec;
+
+ getrusage(RUSAGE_SELF, &ru);
+
+ sec = ru.ru_utime.tv_sec + ru.ru_stime.tv_sec;
+ usec = ru.ru_utime.tv_usec + ru.ru_stime.tv_usec;
+
+ return sec * 1000000 + usec;
+ #else
+ /* If we don't have getrusage, simply return 0. */
+
+ return 0;
+ #endif
+ }
+
+
+ /* loadingtime_stop ************************************************************
+
+ XXX
+
+ *******************************************************************************/
+
+ void loadingtime_start(void)
+ {
+ loadingtime_recursion++;
+
+ if (loadingtime_recursion == 1)
+ loadingstarttime = getcputime();
+ }
+
+
+ /* loadingtime_stop ************************************************************
+
+ XXX
+
+ *******************************************************************************/
+
+ void loadingtime_stop(void)
+ {
+ if (loadingtime_recursion == 1) {
+ loadingstoptime = getcputime();
+ loadingtime += (loadingstoptime - loadingstarttime);
+ }
+
+ loadingtime_recursion--;
+ }
+
+
+ /* compilingtime_stop **********************************************************
+
+ XXX
+
+ *******************************************************************************/
+
+ void compilingtime_start(void)
+ {
+ compilingtime_recursion++;
+
+ if (compilingtime_recursion == 1)
+ compilingstarttime = getcputime();
+ }
+
+
+ /* compilingtime_stop **********************************************************
+
+ XXX
+
+ *******************************************************************************/
+
+ void compilingtime_stop(void)
+ {
+ if (compilingtime_recursion == 1) {
+ compilingstoptime = getcputime();
+ compilingtime += (compilingstoptime - compilingstarttime);
+ }
+
+ compilingtime_recursion--;
+ }
+
+
+ /* print_times *****************************************************************
+
+ Prints a summary of CPU time usage.
+
+ *******************************************************************************/
+
+ void print_times(void)
+ {
+ s8 totaltime;
+ s8 runtime;
+
+ totaltime = getcputime();
+ runtime = totaltime - loadingtime - compilingtime;
+
+ #if SIZEOF_VOID_P == 8
+ dolog("Time for loading classes: %6ld ms", loadingtime / 1000);
+ dolog("Time for compiling code: %6ld ms", compilingtime / 1000);
+ dolog("Time for running program: %6ld ms", runtime / 1000);
+ dolog("Total time: %6ld ms", totaltime / 1000);
+ #else
+ dolog("Time for loading classes: %6lld ms", loadingtime / 1000);
+ dolog("Time for compiling code: %6lld ms", compilingtime / 1000);
+ dolog("Time for running program: %6lld ms", runtime / 1000);
+ dolog("Total time: %6lld ms", totaltime / 1000);
+ #endif
+ }
+
+
+ /* print_stats *****************************************************************
+
+ outputs detailed compiler statistics
+
+ *******************************************************************************/
+
+ void print_stats(void)
+ {
+ s4 i;
+ float f;
+ s4 sum;
+
+
+ dolog("Number of JIT compiler calls: %6d", count_jit_calls);
+ dolog("Number of compiled methods: %6d", count_methods);
+
+ dolog("Number of compiled basic blocks: %6d",
+ count_basic_blocks);
+ dolog("Number of max. basic blocks per method: %6d",
+ count_max_basic_blocks);
+
+ dolog("Number of compiled JavaVM instructions: %6d",
+ count_javainstr);
+ dolog("Number of max. JavaVM instructions per method: %6d",
+ count_max_javainstr);
+ dolog("Size of compiled JavaVM instructions: %6d(%d)",
+ count_javacodesize, count_javacodesize - count_methods * 18);
+
+ dolog("Size of compiled Exception Tables: %d", count_javaexcsize);
+ dolog("Number of Machine-Instructions: %d", count_code_len >> 2);
+ dolog("Number of Spills (write to memory) <all [i/l/a|flt|dbl]>: %d [%d|%d|%d]",
+ count_spills_write_ila + count_spills_write_flt + count_spills_write_dbl,
+ count_spills_write_ila, count_spills_write_flt, count_spills_write_dbl);
+ dolog("Number of Spills (read from memory) <all [i/l/a|flt|dbl]>: %d [%d|%d|%d]",
+ count_spills_read_ila + count_spills_read_flt + count_spills_read_dbl,
+ count_spills_read_ila, count_spills_read_flt, count_spills_read_dbl);
+ dolog("Number of Activ Pseudocommands: %6d", count_pcmd_activ);
+ dolog("Number of Drop Pseudocommands: %6d", count_pcmd_drop);
+ dolog("Number of Const Pseudocommands: %6d (zero:%5d)",
+ count_pcmd_load, count_pcmd_zero);
+ dolog("Number of ConstAlu Pseudocommands: %6d (cmp: %5d, store:%5d)",
+ count_pcmd_const_alu, count_pcmd_const_bra, count_pcmd_const_store);
+ dolog("Number of Move Pseudocommands: %6d", count_pcmd_move);
+ dolog("Number of Load Pseudocommands: %6d", count_load_instruction);
+ dolog("Number of Store Pseudocommands: %6d (combined: %5d)",
+ count_pcmd_store, count_pcmd_store - count_pcmd_store_comb);
+ dolog("Number of OP Pseudocommands: %6d", count_pcmd_op);
+ dolog("Number of DUP Pseudocommands: %6d", count_dup_instruction);
+ dolog("Number of Mem Pseudocommands: %6d", count_pcmd_mem);
+ dolog("Number of Method Pseudocommands: %6d", count_pcmd_met);
+ dolog("Number of Branch Pseudocommands: %6d (rets:%5d, Xrets: %5d)",
+ count_pcmd_bra, count_pcmd_return, count_pcmd_returnx);
+ log_println(" resolved branches: %6d", count_branches_resolved);
+ log_println(" unresolved branches: %6d", count_branches_unresolved);
+ dolog("Number of Table Pseudocommands: %6d", count_pcmd_table);
+ dolog("Number of Useful Pseudocommands: %6d", count_pcmd_table +
+ count_pcmd_bra + count_pcmd_load + count_pcmd_mem + count_pcmd_op);
+ dolog("Number of Null Pointer Checks: %6d", count_check_null);
+ dolog("Number of Array Bound Checks: %6d", count_check_bound);
+ dolog("Number of Try-Blocks: %d", count_tryblocks);
+
+ dolog("Number of branch_emit (total, 8bit/16bit/32bit/64bit offset): %d, %d/%d/%d/%d",
+ count_emit_branch, count_emit_branch_8bit, count_emit_branch_16bit,
+ count_emit_branch_32bit, count_emit_branch_64bit);
+
+ dolog("Maximal count of stack elements: %d", count_max_new_stack);
+ dolog("Upper bound of max stack elements: %d", count_upper_bound_new_stack);
+ dolog("Distribution of stack sizes at block boundary");
+ dolog(" 0 1 2 3 4 5 6 7 8 9 >=10");
+ dolog("%6d%6d%6d%6d%6d%6d%6d%6d%6d%6d%6d",
+ count_block_stack[0], count_block_stack[1], count_block_stack[2],
+ count_block_stack[3], count_block_stack[4], count_block_stack[5],
+ count_block_stack[6], count_block_stack[7], count_block_stack[8],
+ count_block_stack[9], count_block_stack[10]);
+ dolog("Distribution of store stack depth");
+ dolog(" 0 1 2 3 4 5 6 7 8 9 >=10");
+ dolog("%6d%6d%6d%6d%6d%6d%6d%6d%6d%6d%6d",
+ count_store_depth[0], count_store_depth[1], count_store_depth[2],
+ count_store_depth[3], count_store_depth[4], count_store_depth[5],
+ count_store_depth[6], count_store_depth[7], count_store_depth[8],
+ count_store_depth[9], count_store_depth[10]);
+ dolog("Distribution of store creator chains first part");
+ dolog(" 0 1 2 3 4 5 6 7 8 9");
+ dolog("%6d%6d%6d%6d%6d%6d%6d%6d%6d%6d",
+ count_store_length[0], count_store_length[1], count_store_length[2],
+ count_store_length[3], count_store_length[4], count_store_length[5],
+ count_store_length[6], count_store_length[7], count_store_length[8],
+ count_store_length[9]);
+ dolog("Distribution of store creator chains second part");
+ dolog(" 10 11 12 13 14 15 16 17 18 19 >=20");
+ dolog("%6d%6d%6d%6d%6d%6d%6d%6d%6d%6d%6d",
+ count_store_length[10], count_store_length[11],
+ count_store_length[12], count_store_length[13],
+ count_store_length[14], count_store_length[15],
+ count_store_length[16], count_store_length[17],
+ count_store_length[18], count_store_length[19],
+ count_store_length[20]);
+ dolog("Distribution of analysis iterations");
+ dolog(" 1 2 3 4 >=5");
+ dolog("%6d%6d%6d%6d%6d",
+ count_analyse_iterations[0], count_analyse_iterations[1],
+ count_analyse_iterations[2], count_analyse_iterations[3],
+ count_analyse_iterations[4]);
+
+
+ /* Distribution of basic blocks per method ********************************/
+
+ log_println("Distribution of basic blocks per method:");
+ log_println(" <=5 <=10 <=15 <=20 <=30 <=40 <=50 <=75 >75");
+
+ log_start();
+ for (i = 0; i <= 8; i++)
+ log_print("%6d", count_method_bb_distribution[i]);
+ log_finish();
+
+ /* print ratio */
+
+ f = (float) count_methods;
+
+ log_start();
+ for (i = 0; i <= 8; i++)
+ log_print("%6.2f", (float) count_method_bb_distribution[i] / f);
+ log_finish();
+
+ /* print cumulated ratio */
+
+ log_start();
+ for (i = 0, sum = 0; i <= 8; i++) {
+ sum += count_method_bb_distribution[i];
+ log_print("%6.2f", (float) sum / f);
+ }
+ log_finish();
+
+
+ /* Distribution of basic block sizes **************************************/
+
+ log_println("Distribution of basic block sizes:");
+ log_println(" 0 1 2 3 4 5 6 7 8 9 <13 <15 <17 <19 <21 <26 <31 >30");
+
+ /* print block sizes */
+
+ log_start();
+ for (i = 0; i <= 17; i++)
+ log_print("%6d", count_block_size_distribution[i]);
+ log_finish();
+
+ /* print ratio */
+
+ f = (float) count_basic_blocks;
+
+ log_start();
+ for (i = 0; i <= 17; i++)
+ log_print("%6.2f", (float) count_block_size_distribution[i] / f);
+ log_finish();
+
+ /* print cumulated ratio */
+
+ log_start();
+ for (i = 0, sum = 0; i <= 17; i++) {
+ sum += count_block_size_distribution[i];
+ log_print("%6.2f", (float) sum / f);
+ }
+ log_finish();
+
+ statistics_print_memory_usage();
+
+ dolog("Number of class loads: %6d", count_class_loads);
+ dolog("Number of class inits: %6d", count_class_inits);
+ dolog("Number of loaded Methods: %6d\n", count_all_methods);
+
+ dolog("Calls of utf_new: %6d", count_utf_new);
+ dolog("Calls of utf_new (element found): %6d\n", count_utf_new_found);
+
+
+ /* LSRA statistics ********************************************************/
+
+ dolog("Moves reg -> reg: %6d", count_mov_reg_reg);
+ dolog("Moves mem -> reg: %6d", count_mov_mem_reg);
+ dolog("Moves reg -> mem: %6d", count_mov_reg_mem);
+ dolog("Moves mem -> mem: %6d", count_mov_mem_mem);
+
+ dolog("Methods allocated by LSRA: %6d",
+ count_methods_allocated_by_lsra);
+ dolog("Conflicts between local Variables: %6d", count_locals_conflicts);
+ dolog("Local Variables held in Memory: %6d", count_locals_spilled);
+ dolog("Local Variables held in Registers: %6d", count_locals_register);
+ dolog("Stackslots held in Memory: %6d", count_ss_spilled);
+ dolog("Stackslots held in Registers: %6d", count_ss_register);
+ dolog("Memory moves at BB Boundaries: %6d", count_mem_move_bb);
+ dolog("Number of interface slots: %6d\n", count_interface_size);
+ dolog("Number of Argument stack slots in register: %6d",
+ count_argument_reg_ss);
+ dolog("Number of Argument stack slots in memory: %6d\n",
+ count_argument_mem_ss);
+ dolog("Number of Methods kept in registers: %6d\n",
+ count_method_in_register);
+
+
+ /* instruction scheduler statistics ***************************************/
+
+ #if defined(USE_SCHEDULER)
+ dolog("Instruction scheduler statistics:");
+ dolog("Number of basic blocks: %7d", count_schedule_basic_blocks);
+ dolog("Number of nodes: %7d", count_schedule_nodes);
+ dolog("Number of leaders nodes: %7d", count_schedule_leaders);
+ dolog("Number of max. leaders nodes: %7d", count_schedule_max_leaders);
+ dolog("Length of critical path: %7d\n", count_schedule_critical_path);
+ #endif
+
+
+ /* call statistics ********************************************************/
+
+ dolog("Function call statistics:");
+ dolog("Number of jni->CallXMethod function invokations: %ld",
+ count_jni_callXmethod_calls);
+ dolog("Overall number of jni invokations: %ld",
+ count_jni_calls);
+
+ log_println("java-to-native calls: %10ld", count_calls_java_to_native);
+ log_println("native-to-java calls: %10ld", count_calls_native_to_java);
+
+
+ /* now print other statistics ********************************************/
+
+ #if defined(ENABLE_INTRP)
+ print_dynamic_super_statistics();
+ #endif
+ }
+
+
+ /* statistics_print_date *******************************************************
+
+ Print current date and time.
+
+ *******************************************************************************/
+
+ void statistics_print_date(void)
+ {
+ time_t t;
+ struct tm tm;
+
+ #if defined(HAVE_TIME)
+ time(&t);
+ #else
+ # error !HAVE_TIME
+ #endif
+
+ #if defined(HAVE_LOCALTIME_R)
+ localtime_r(&t, &tm);
+ #else
+ # error !HAVE_LOCALTIME_R
+ #endif
+
+ log_println("%d-%02d-%02d %02d:%02d:%02d",
+ 1900 + tm.tm_year, tm.tm_mon + 1, tm.tm_mday,
+ tm.tm_hour, tm.tm_min, tm.tm_sec);
+ }
+
+
+ /* statistics_print_memory_usage ***********************************************
+
+ Print current memory usage.
+
+ *******************************************************************************/
+
+ void statistics_print_memory_usage(void)
+ {
+ s4 sum;
+
+ log_println("memory usage ----------------------");
+ log_println("");
+ log_println("code: %10d", count_code_len);
+ log_println("data: %10d", count_data_len);
+ log_println(" ----------");
+
+ sum =
+ count_code_len +
+ count_data_len;
+
+ log_println(" %10d", sum);
+
+ log_println("");
+
+ log_println("classinfo (%3d B): %10d", (int) sizeof(classinfo), size_classinfo);
+ log_println("fieldinfo (%3d B): %10d", (int) sizeof(fieldinfo), size_fieldinfo);
+ log_println("methodinfo (%3d B): %10d", (int) sizeof(methodinfo), size_methodinfo);
+ log_println("lineinfo (%3d B): %10d", (int) sizeof(lineinfo), size_lineinfo);
+ log_println("codeinfo (%3d B): %10d", (int) sizeof(codeinfo), size_codeinfo);
+ log_println(" ----------");
+
+ sum =
+ size_classinfo +
+ size_fieldinfo +
+ size_methodinfo +
+ size_lineinfo +
+ size_codeinfo;
+
+ log_println(" %10d", sum);
+
+ log_println("");
+
+ log_println("linenumber tables (%5d): %10d", count_linenumbertable, size_linenumbertable);
+ log_println("exception tables: %10d", count_extable_len);
+ log_println("patcher references: %10d", size_patchref);
++ log_println("cached references: %10d", size_cachedref);
+ log_println(" ----------");
+
+ sum =
+ size_linenumbertable +
+ count_extable_len +
++ size_patchref +
++ size_cachedref;
+
+ log_println(" %10d", sum);
+
+ log_println("");
+
+ log_println("constant pool: %10d", count_const_pool_len);
+ log_println("classref: %10d", count_classref_len);
+ log_println("parsed descriptors: %10d", count_parsed_desc_len);
+ log_println("vftbl: %10d", count_vftbl_len);
+ log_println("compiler stubs: %10d", count_cstub_len);
+ log_println("native stubs: %10d", size_stub_native);
+ log_println("utf: %10d", count_utf_len);
+ log_println("vmcode: %10d", count_vmcode_len);
+ log_println("stack map: %10d", size_stack_map);
+ log_println("string: %10d", size_string);
+ log_println("threadobject: %10d", size_threadobject);
+ log_println("thread index: %10d", size_thread_index_t);
+ log_println("stack size: %10d", size_stacksize);
+ log_println("lock record: %10d", size_lock_record);
+ log_println("lock hashtable: %10d", size_lock_hashtable);
+ log_println("lock waiter: %10d", size_lock_waiter);
+ log_println(" ----------");
+
+ sum =
+ count_const_pool_len +
+ count_classref_len +
+ count_parsed_desc_len +
+ count_vftbl_len +
+ count_cstub_len +
+ size_stub_native +
+ count_utf_len +
+ count_vmcode_len +
+ size_stack_map +
+ size_string +
+ size_threadobject +
+ size_thread_index_t +
+ size_stacksize +
+ size_lock_record +
+ size_lock_hashtable +
+ size_lock_waiter;
+
+ log_println(" %10d", sum);
+
+ log_println("");
+
+ log_println("max. code memory: %10d", maxcodememusage);
+ log_println("max. heap memory: %10d", maxmemusage);
+ log_println("max. dump memory: %10d", maxdumpsize);
+ log_println("");
+ log_println("heap memory not freed: %10d", (int32_t) memoryusage);
+ log_println("dump memory not freed: %10d", (int32_t) globalallocateddumpsize);
+
+ log_println("");
+ }
+
+
+ /* statistics_print_gc_memory_usage ********************************************
+
+ Print current GC memory usage.
+
+ *******************************************************************************/
+
+ void statistics_print_gc_memory_usage(void)
+ {
+ static int64_t count = 0;
+ int64_t max;
+ int64_t size;
+ int64_t free;
+ int64_t used;
+ int64_t total;
+
+ count++;
+
+ max = gc_get_max_heap_size();
+ size = gc_get_heap_size();
+ free = gc_get_free_bytes();
+ used = size - free;
+ total = gc_get_total_bytes();
+
+ if (opt_ProfileMemoryUsageGNUPlot) {
+ if (count == 1)
+ fprintf(opt_ProfileMemoryUsageGNUPlot, "plot \"profile.dat\" using 1:2 with lines title \"max. Java heap size\", \"profile.dat\" using 1:3 with lines title \"Java heap size\", \"profile.dat\" using 1:4 with lines title \"used\", \"profile.dat\" using 1:5 with lines title \"free\"\n");
+
+ #if SIZEOF_VOID_P == 8
+ fprintf(opt_ProfileMemoryUsageGNUPlot, "%ld %ld %ld %ld %ld\n", count, max, size, used, free);
+ #else
+ fprintf(opt_ProfileMemoryUsageGNUPlot, "%lld %lld %lld %lld %lld\n", count, max, size, used, free);
+ #endif
+
+ fflush(opt_ProfileMemoryUsageGNUPlot);
+ }
+ else {
+ log_println("GC memory usage -------------------");
+ log_println("");
+ log_println("max. Java heap size: %10lld", max);
+ log_println("");
+ log_println("Java heap size: %10lld", size);
+ log_println("used: %10lld", used);
+ log_println("free: %10lld", free);
+ log_println("totally used: %10lld", total);
+ log_println("");
+ }
+ }
+
+
+ /*
+ * 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
+ * Emacs will automagically detect them.
+ * ---------------------------------------------------------------------
+ * Local variables:
+ * mode: c
+ * indent-tabs-mode: t
+ * c-basic-offset: 4
+ * tab-width: 4
+ * End:
+ * vim:noexpandtab:sw=4:ts=4:
+ */
--- /dev/null
+ /* src/vm/statistics.h - exports global varables for statistics
+
+ Copyright (C) 1996-2005, 2006, 2007, 2008
+ CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
+
+ This file is part of CACAO.
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 2, or (at
+ your option) any later version.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ 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., 51 Franklin Street, Fifth Floor, Boston, MA
+ 02110-1301, USA.
+
+ */
+
+
+ #ifndef _STATISTICS_H
+ #define _STATISTICS_H
+
+ #include "config.h"
+
+ #include <stdint.h>
+
+ #include "vm/types.h"
+
+ #include "vm/global.h"
+
+
+ /* statistic macros ***********************************************************/
+
+ #if defined(ENABLE_STATISTICS)
+ #define STATISTICS(x) \
+ do { \
+ if (opt_stat) { \
+ x; \
+ } \
+ } while (0)
+ #else
+ #define STATISTICS(x) /* nothing */
+ #endif
+
+ /* in_ inline statistics */
+
+ #define IN_MAX 9
+ #define IN_UNIQUEVIRT 0x0000
+ #define IN_UNIQUE_INTERFACE 0x0001
+ #define IN_OUTSIDERS 0x0004
+ #define IN_MAXDEPTH 0x0008
+ #define IN_MAXCODE 0x0010
+ #define IN_JCODELENGTH 0x0020
+ #define IN_EXCEPTION 0x0040
+ #define IN_NOT_UNIQUE_VIRT 0x0080
+ #define IN_NOT_UNIQUE_INTERFACE 0x0100
+
+ #define N_UNIQUEVIRT 0
+ #define N_UNIQUE_INTERFACE 1
+ #define N_OUTSIDERS 2
+ #define N_MAXDEPTH 3
+ #define N_MAXCODE 4
+ #define N_JCODELENGTH 5
+ #define N_EXCEPTION 6
+ #define N_NOT_UNIQUE_VIRT 7
+ #define N_NOT_UNIQUE_INTERFACE 8
+
+
+ /* global variables ***********************************************************/
+
+ extern s4 codememusage;
+ extern s4 maxcodememusage;
+
+ extern s4 memoryusage;
+ extern s4 maxmemusage;
+
+ extern s4 maxdumpsize;
+
+ extern s4 globalallocateddumpsize;
+ extern s4 globaluseddumpsize;
+
+
+ /* variables for measurements *************************************************/
+
+ extern s4 size_classinfo;
+ extern s4 size_fieldinfo;
+ extern s4 size_methodinfo;
+ extern s4 size_lineinfo;
+ extern s4 size_codeinfo;
+
+ extern s4 size_stub_native;
+
+ extern s4 size_stack_map;
+ extern s4 size_string;
+
+ extern s4 size_threadobject;
+ extern int32_t size_thread_index_t;
+ extern int32_t size_stacksize;
+
+ extern s4 size_lock_record;
+ extern s4 size_lock_hashtable;
+ extern s4 size_lock_waiter;
+
+ extern int32_t count_linenumbertable;
+ extern int32_t size_linenumbertable;
+
+ extern s4 size_patchref;
+
++extern s4 size_cachedref;
++
+ extern u8 count_calls_java_to_native;
+ extern u8 count_calls_native_to_java;
+
+ extern int count_const_pool_len;
+ extern int count_classref_len;
+ extern int count_parsed_desc_len;
+ extern int count_vftbl_len;
+ extern int count_all_methods;
+ extern int count_methods_marked_used; /*RTA*/
+ extern int count_vmcode_len;
+ extern int count_extable_len;
+ extern int count_class_loads;
+ extern int count_class_inits;
+
+ extern int count_utf_len; /* size of utf hash */
+ extern int count_utf_new;
+ extern int count_utf_new_found;
+
+ extern int count_locals_conflicts;
+ extern int count_locals_spilled;
+ extern int count_locals_register;
+ extern int count_ss_spilled;
+ extern int count_ss_register;
+ extern int count_methods_allocated_by_lsra;
+ extern int count_mem_move_bb;
+ extern int count_interface_size;
+ extern int count_argument_mem_ss;
+ extern int count_argument_reg_ss;
+ extern int count_method_in_register;
+ extern int count_mov_reg_reg;
+ extern int count_mov_mem_reg;
+ extern int count_mov_reg_mem;
+ extern int count_mov_mem_mem;
+
+ extern int count_jit_calls;
+ extern int count_methods;
+ extern int count_spills_read_ila;
+ extern int count_spills_read_flt;
+ extern int count_spills_read_dbl;
+ extern int count_spills_write_ila;
+ extern int count_spills_write_flt;
+ extern int count_spills_write_dbl;
+ extern int count_pcmd_activ;
+ extern int count_pcmd_drop;
+ extern int count_pcmd_zero;
+ extern int count_pcmd_const_store;
+ extern int count_pcmd_const_alu;
+ extern int count_pcmd_const_bra;
+ extern int count_pcmd_load;
+ extern int count_pcmd_move;
+ extern int count_load_instruction;
+ extern int count_pcmd_store;
+ extern int count_pcmd_store_comb;
+ extern int count_dup_instruction;
+ extern int count_pcmd_op;
+ extern int count_pcmd_mem;
+ extern int count_pcmd_met;
+ extern int count_pcmd_bra;
+ extern int count_pcmd_table;
+ extern int count_pcmd_return;
+ extern int count_pcmd_returnx;
+ extern int count_check_null;
+ extern int count_check_bound;
+ extern int count_max_basic_blocks;
+ extern int count_basic_blocks;
+ extern int count_max_javainstr;
+ extern int count_javainstr;
+ extern int count_javacodesize;
+ extern int count_javaexcsize;
+ extern int count_calls;
+ extern int count_tryblocks;
+ extern int count_code_len;
+ extern int count_data_len;
+ extern int count_cstub_len;
+ extern int count_max_new_stack;
+ extern int count_upper_bound_new_stack;
+
+ extern int count_emit_branch;
+ extern int count_emit_branch_8bit;
+ extern int count_emit_branch_16bit;
+ extern int count_emit_branch_32bit;
+ extern int count_emit_branch_64bit;
+
+ extern s4 count_branches_resolved;
+ extern s4 count_branches_unresolved;
+
+ extern int *count_block_stack;
+ extern int *count_analyse_iterations;
+ extern int *count_method_bb_distribution;
+ extern int *count_block_size_distribution;
+ extern int *count_store_length;
+ extern int *count_store_depth;
+ /* in_ inline statistics */
+ extern int count_in;
+ extern int count_in_uniqVirt;
+ extern int count_in_uniqIntf;
+ extern int count_in_rejected;
+ extern int count_in_rejected_mult;
+ extern int count_in_outsiders;
+ extern int count_in_uniqueVirt_not_inlined;
+ extern int count_in_uniqueInterface_not_inlined;
+ extern int count_in_maxDepth;
+ extern int count_in_maxMethods;
+
+ extern u2 count_in_not [512];
+
+ /* instruction scheduler statistics *******************************************/
+
+ extern s4 count_schedule_basic_blocks;
+ extern s4 count_schedule_nodes;
+ extern s4 count_schedule_leaders;
+ extern s4 count_schedule_max_leaders;
+ extern s4 count_schedule_critical_path;
+
+
+ /* function prototypes ********************************************************/
+
+ s8 getcputime(void);
+
+ void loadingtime_start(void);
+ void loadingtime_stop(void);
+ void compilingtime_start(void);
+ void compilingtime_stop(void);
+
+ void print_times(void);
+ void print_stats(void);
+
+ void statistics_print_date(void);
+ void statistics_print_memory_usage(void);
+ void statistics_print_gc_memory_usage(void);
+
+ void mem_usagelog(bool givewarnings);
+
+ void compiledinvokation(void);
+ void jnicallXmethodnvokation(void);
+ void jniinvokation(void);
+
+ #endif /* _STATISTICS_H */
+
+
+ /*
+ * 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
+ * Emacs will automagically detect them.
+ * ---------------------------------------------------------------------
+ * Local variables:
+ * mode: c
+ * indent-tabs-mode: t
+ * c-basic-offset: 4
+ * tab-width: 4
+ * End:
+ */
--- /dev/null
+ /* src/vm/vm.cpp - VM startup and shutdown functions
+
+ Copyright (C) 1996-2005, 2006, 2007, 2008
+ CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
+
+ This file is part of CACAO.
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 2, or (at
+ your option) any later version.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ 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., 51 Franklin Street, Fifth Floor, Boston, MA
+ 02110-1301, USA.
+
+ */
+
+
+ #include "config.h"
+
+ #include <stdint.h>
+
+ #include <exception>
+
+ #include <assert.h>
+ #include <errno.h>
+ #include <stdlib.h>
+
+ #include "vm/types.h"
+
+ #include "arch.h"
+ #include "md-abi.h"
+
+ #include "vm/jit/abi-asm.h"
+
+ #include "mm/codememory.h"
+ #include "mm/gc.hpp"
+ #include "mm/memory.h"
+
+ #include "native/jni.h"
+ #include "native/llni.h"
+ #include "native/localref.h"
+ #include "native/native.h"
+
+ #include "native/vm/nativevm.h"
+
+ #include "threads/lock-common.h"
+ #include "threads/threadlist.h"
+ #include "threads/thread.hpp"
+
+ #include "toolbox/logging.h"
+
+ #include "vm/array.h"
+
+ #if defined(ENABLE_ASSERTION)
+ #include "vm/assertion.h"
+ #endif
+
+ #include "vm/builtin.h"
+ #include "vm/classcache.h"
+ #include "vm/exceptions.hpp"
+ #include "vm/finalizer.h"
+ #include "vm/global.h"
+ #include "vm/globals.hpp"
+ #include "vm/initialize.h"
+ #include "vm/options.h"
+ #include "vm/os.hpp"
+ #include "vm/package.hpp"
+ #include "vm/primitive.hpp"
+ #include "vm/properties.h"
+ #include "vm/signallocal.h"
+ #include "vm/statistics.h"
+ #include "vm/string.hpp"
+ #include "vm/suck.h"
+ #include "vm/vm.hpp"
+
+ #include "vm/jit/argument.h"
+ #include "vm/jit/asmpart.h"
+ #include "vm/jit/code.h"
+
+ #if defined(ENABLE_DISASSEMBLER)
+ # include "vm/jit/disass.h"
+ #endif
+
+ #include "vm/jit/jit.h"
++#include "vm/jit/jitcache.h"
+ #include "vm/jit/methodtree.h"
+
+ #if defined(ENABLE_PROFILING)
+ # include "vm/jit/optimizing/profile.h"
+ #endif
+
+ #include "vm/jit/optimizing/recompile.h"
+
+ #if defined(ENABLE_PYTHON)
+ # include "vm/jit/python.h"
+ #endif
+
+ #include "vm/jit/trap.h"
+
+ #if defined(ENABLE_JVMTI)
+ # include "native/jvmti/cacaodbg.h"
+ #endif
+
+ #if defined(ENABLE_VMLOG)
+ #include <vmlog_cacao.h>
+ #endif
+
+
+ /**
+ * This is _the_ instance of the VM.
+ */
+ VM* vm;
+
+
+ /* global variables ***********************************************************/
+
+ s4 vms = 0; /* number of VMs created */
+
+ static classinfo *mainclass = NULL;
+
+ #if defined(ENABLE_INTRP)
+ u1 *intrp_main_stack = NULL;
+ #endif
+
+
+ /* define heap sizes **********************************************************/
+
+ #define HEAP_MAXSIZE 128 * 1024 * 1024 /* default 128MB */
+ #define HEAP_STARTSIZE 2 * 1024 * 1024 /* default 2MB */
+ #define STACK_SIZE 128 * 1024 /* default 64kB */
+
+
+ /* define command line options ************************************************/
+
+ enum {
+ OPT_FOO,
+
+ /* Java options */
+
+ OPT_JAR,
+
+ OPT_D32,
+ OPT_D64,
+
+ OPT_CLASSPATH,
+ OPT_D,
+
+ OPT_VERBOSE,
+
+ OPT_VERSION,
+ OPT_SHOWVERSION,
+ OPT_FULLVERSION,
+
+ OPT_HELP,
+ OPT_X,
+ OPT_XX,
+
+ OPT_EA,
+ OPT_DA,
+ OPT_EA_NOARG,
+ OPT_DA_NOARG,
+
+
+ OPT_ESA,
+ OPT_DSA,
+
+ /* Java non-standard options */
+
+ OPT_JIT,
+ OPT_INTRP,
+
+ OPT_BOOTCLASSPATH,
+ OPT_BOOTCLASSPATH_A,
+ OPT_BOOTCLASSPATH_P,
+
+ OPT_BOOTCLASSPATH_C,
+
+ #if defined(ENABLE_PROFILING)
+ OPT_PROF,
+ OPT_PROF_OPTION,
+ #endif
+
+ OPT_MS,
+ OPT_MX,
+
+ /* CACAO options */
+
+ OPT_VERBOSE1,
+ OPT_NOIEEE,
+
+ #if defined(ENABLE_STATISTICS)
+ OPT_TIME,
+ OPT_STAT,
+ #endif
+
+ OPT_LOG,
+ OPT_CHECK,
+ OPT_LOAD,
+ OPT_SHOW,
+ OPT_DEBUGCOLOR,
+
+ #if !defined(NDEBUG)
+ OPT_ALL,
+ OPT_METHOD,
+ OPT_SIGNATURE,
+ #endif
+
+ #if defined(ENABLE_VERIFIER)
+ OPT_NOVERIFY,
+ #if defined(TYPECHECK_VERBOSE)
+ OPT_VERBOSETC,
+ #endif
+ #endif /* defined(ENABLE_VERIFIER) */
+
+ /* optimization options */
+
+ #if defined(ENABLE_LOOP)
+ OPT_OLOOP,
+ #endif
+
+ #if defined(ENABLE_IFCONV)
+ OPT_IFCONV,
+ #endif
+
+ #if defined(ENABLE_LSRA) || defined(ENABLE_SSA)
+ OPT_LSRA,
+ #endif
+
+ #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_XRUNJDWP,
+ OPT_NOAGENT,
+ OPT_AGENTLIB,
+ OPT_AGENTPATH,
+ #endif
+
+ #if defined(ENABLE_DEBUG_FILTER)
+ OPT_FILTER_VERBOSECALL_INCLUDE,
+ OPT_FILTER_VERBOSECALL_EXCLUDE,
+ OPT_FILTER_SHOW_METHOD,
+ #endif
+
+ DUMMY
+ };
+
+
+ opt_struct opts[] = {
+ { "foo", false, OPT_FOO },
+
+ /* Java options */
+
+ { "jar", false, OPT_JAR },
+
+ { "d32", false, OPT_D32 },
+ { "d64", false, OPT_D64 },
+ { "client", false, OPT_IGNORE },
+ { "server", false, OPT_IGNORE },
+ { "jvm", false, OPT_IGNORE },
+ { "hotspot", false, OPT_IGNORE },
+
+ { "classpath", true, OPT_CLASSPATH },
+ { "cp", true, OPT_CLASSPATH },
+ { "D", true, OPT_D },
+ { "version", false, OPT_VERSION },
+ { "showversion", false, OPT_SHOWVERSION },
+ { "fullversion", false, OPT_FULLVERSION },
+ { "help", false, OPT_HELP },
+ { "?", false, OPT_HELP },
+ { "X", false, OPT_X },
+ { "XX:", true, OPT_XX },
+
+ { "ea:", true, OPT_EA },
+ { "da:", true, OPT_DA },
+ { "ea", false, OPT_EA_NOARG },
+ { "da", false, OPT_DA_NOARG },
+
+ { "enableassertions:", true, OPT_EA },
+ { "disableassertions:", true, OPT_DA },
+ { "enableassertions", false, OPT_EA_NOARG },
+ { "disableassertions", false, OPT_DA_NOARG },
+
+ { "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 },
+ { "Xverify:none", false, OPT_NOVERIFY },
+ #endif
+ { "v", false, OPT_VERBOSE1 },
+ { "verbose:", true, OPT_VERBOSE },
+
+ #if defined(ENABLE_VERIFIER) && defined(TYPECHECK_VERBOSE)
+ { "verbosetc", false, OPT_VERBOSETC },
+ #endif
+ #if defined(__ALPHA__)
+ { "noieee", false, OPT_NOIEEE },
+ #endif
+ #if defined(ENABLE_STATISTICS)
+ { "time", false, OPT_TIME },
+ { "stat", false, OPT_STAT },
+ #endif
+ { "log", true, OPT_LOG },
+ { "c", true, OPT_CHECK },
+ { "l", false, OPT_LOAD },
+
+ #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)
+ { "lsra", false, OPT_LSRA },
+ #endif
+ #if defined(ENABLE_SSA)
+ { "lsra", true, OPT_LSRA },
+ #endif
+
+ #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
+
+ /* Java non-standard options */
+
+ { "Xjit", false, OPT_JIT },
+ { "Xint", false, OPT_INTRP },
+ { "Xbootclasspath:", true, OPT_BOOTCLASSPATH },
+ { "Xbootclasspath/a:", true, OPT_BOOTCLASSPATH_A },
+ { "Xbootclasspath/p:", true, OPT_BOOTCLASSPATH_P },
+ { "Xbootclasspath/c:", true, OPT_BOOTCLASSPATH_C },
+
+ #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 },
+ { "mx", true, OPT_MX },
+ { "Xss", true, OPT_SS },
+ { "ss", true, OPT_SS },
+
+ #if defined(ENABLE_PROFILING)
+ { "Xprof:", true, OPT_PROF_OPTION },
+ { "Xprof", false, OPT_PROF },
+ #endif
+
+ /* keep these at the end of the list */
+
+ #if !defined(NDEBUG)
+ { "m", true, OPT_METHOD },
+ #endif
+
+ { "s", true, OPT_SHOW },
+ { "debug-color", false, OPT_DEBUGCOLOR },
+
+ #if defined(ENABLE_DEBUG_FILTER)
+ { "XXfi", true, OPT_FILTER_VERBOSECALL_INCLUDE },
+ { "XXfx", true, OPT_FILTER_VERBOSECALL_EXCLUDE },
+ { "XXfm", true, OPT_FILTER_SHOW_METHOD },
+ #endif
+
+ { NULL, false, 0 }
+ };
+
+
+ /* usage ***********************************************************************
+
+ Prints the correct usage syntax to stdout.
+
+ *******************************************************************************/
+
+ void usage(void)
+ {
+ puts("Usage: cacao [-options] classname [arguments]");
+ puts(" (to run a class file)");
+ puts(" or cacao [-options] -jar jarfile [arguments]");
+ puts(" (to run a standalone jar file)\n");
+
+ puts("where options include:");
+ puts(" -d32 use 32-bit data model if available");
+ puts(" -d64 use 64-bit data model if available");
+ puts(" -client compatibility (currently ignored)");
+ puts(" -server compatibility (currently ignored)");
+ puts(" -jvm compatibility (currently ignored)");
+ puts(" -hotspot compatibility (currently ignored)\n");
+
+ puts(" -cp <path> specify a path to look for classes");
+ puts(" -classpath <path> specify a path to look for classes");
+ puts(" -D<name>=<value> add an entry to the property list");
+ puts(" -verbose[:class|gc|jni] enable specific verbose output");
+ puts(" -version print product version and exit");
+ puts(" -fullversion print jpackage-compatible product version and exit");
+ puts(" -showversion print product version and continue");
+ puts(" -help, -? print this help message");
+ puts(" -X print help on non-standard Java options");
+ puts(" -XX print help on debugging options");
+ puts(" -ea[:<packagename>...|:<classname>]");
+ puts(" -enableassertions[:<packagename>...|:<classname>]");
+ puts(" enable assertions with specified granularity");
+ puts(" -da[:<packagename>...|:<classname>]");
+ puts(" -disableassertions[:<packagename>...|:<classname>]");
+ puts(" disable assertions with specified granularity");
+ puts(" -esa | -enablesystemassertions");
+ puts(" enable system assertions");
+ puts(" -dsa | -disablesystemassertions");
+ puts(" disable system assertions");
+
+ #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
+
+ /* exit with error code */
+
+ exit(1);
+ }
+
+
+ static void Xusage(void)
+ {
+ #if defined(ENABLE_JIT)
+ puts(" -Xjit JIT mode execution (default)");
+ #endif
+ #if defined(ENABLE_INTRP)
+ puts(" -Xint interpreter mode execution");
+ #endif
+ puts(" -Xbootclasspath:<zip/jar files and directories separated by :>");
+ puts(" value is set as bootstrap class path");
+ puts(" -Xbootclasspath/a:<zip/jar files and directories separated by :>");
+ puts(" value is appended to the bootstrap class path");
+ puts(" -Xbootclasspath/p:<zip/jar files and directories separated by :>");
+ puts(" value is prepended to the bootstrap class path");
+ puts(" -Xbootclasspath/c:<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_PROFILING)
+ puts(" -Xprof[:bb] collect and print profiling data");
+ #endif
+
+ #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(" -Xrunjdwp transport=[dt_socket|...],address=<hostname:port>,server=[y|n],suspend=[y|n]\n");
+ puts(" enable remote debugging\n");
+ #endif
+
+ /* exit with error code */
+
+ exit(1);
+ }
+
+
+ #if 0
+ static void XXusage(void)
+ {
+ puts(" -v write state-information");
+ #if !defined(NDEBUG)
+ puts(" -verbose:jit enable specific verbose output");
+ puts(" -debug-color colored output for ANSI terms");
+ #endif
+ #ifdef TYPECHECK_VERBOSE
+ puts(" -verbosetc write debug messages while typechecking");
+ #endif
+ #if defined(__ALPHA__)
+ puts(" -noieee don't use ieee compliant arithmetic");
+ #endif
+ #if defined(ENABLE_VERIFIER)
+ puts(" -noverify don't verify classfiles");
+ #endif
+ #if defined(ENABLE_STATISTICS)
+ puts(" -time measure the runtime");
+ puts(" -stat detailed compiler statistics");
+ #endif
+ puts(" -log logfile specify a name for the logfile");
+ puts(" -c(heck)b(ounds) don't check array bounds");
+ puts(" s(ync) don't check for synchronization");
+ #if defined(ENABLE_LOOP)
+ puts(" -oloop optimize array accesses in loops");
+ #endif
+ puts(" -l don't start the class after loading");
+ #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");
+ #endif
+
+ puts(" -s... 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(" n(o)ps show NOPs in disassembler output");
+ #endif
+ puts(" (d)atasegment data segment listing");
+
+ #if defined(ENABLE_IFCONV)
+ puts(" -ifconv use if-conversion");
+ #endif
+ #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)");
+ puts(" (d)ead code elimination");
+ puts(" (c)opy propagation");
+ #endif
+ #if defined(ENABLE_DEBUG_FILTER)
+ puts(" -XXfi <regex> begin of dynamic scope for verbosecall filter");
+ puts(" -XXfx <regex> end of dynamic scope for verbosecall filter");
+ puts(" -XXfm <regex> filter for show options");
+ #endif
+ /* exit with error code */
+
+ exit(1);
+ }
+ #endif
+
+
+ /* version *********************************************************************
+
+ Only prints cacao version information.
+
+ *******************************************************************************/
+
+ static void version(bool opt_exit)
+ {
+ puts("java version \""JAVA_VERSION"\"");
+ puts("CACAO version "VERSION"\n");
+
+ puts("Copyright (C) 1996-2005, 2006, 2007, 2008");
+ puts("CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO");
+ puts("This is free software; see the source for copying conditions. There is NO");
+ puts("warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.");
+
+ /* exit normally, if requested */
+
+ if (opt_exit)
+ exit(0);
+ }
+
+
+ /* fullversion *****************************************************************
+
+ Prints a Sun compatible version information (required e.g. by
+ jpackage, www.jpackage.org).
+
+ *******************************************************************************/
+
+ static void fullversion(void)
+ {
+ puts("java full version \"cacao-"JAVA_VERSION"\"");
+
+ /* exit normally */
+
+ exit(0);
+ }
+
+
+ static void vm_printconfig(void)
+ {
+ puts("Configure/Build options:\n");
+ puts(" ./configure: "VERSION_CONFIGURE_ARGS"");
+ #if defined(__VERSION__)
+ puts(" CC : "VERSION_CC" ("__VERSION__")");
+ #else
+ puts(" CC : "VERSION_CC"");
+ #endif
+ puts(" CFLAGS : "VERSION_CFLAGS"\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);
+
+ #if defined(ENABLE_JRE_LAYOUT)
+ /* When we're building with JRE-layout, the default paths are the
+ same as the runtime paths. */
+ #else
+ # if defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
+ puts(" gnu.classpath.boot.library.path: "JAVA_RUNTIME_LIBRARY_LIBDIR);
+ puts(" java.boot.class.path : "CACAO_VM_ZIP":"JAVA_RUNTIME_LIBRARY_CLASSES"");
+ # elif defined(WITH_JAVA_RUNTIME_LIBRARY_OPENJDK)
+ puts(" sun.boot.library.path : "JAVA_RUNTIME_LIBRARY_LIBDIR);
+ puts(" java.boot.class.path : "JAVA_RUNTIME_LIBRARY_CLASSES);
+ # endif
+ #endif
+
+ puts("");
+
+ 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);
+
+ #if defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
+ printf(" gnu.classpath.boot.library.path: %s\n", properties_get("gnu.classpath.boot.library.path"));
+ #elif defined(WITH_JAVA_RUNTIME_LIBRARY_OPENJDK)
+ printf(" sun.boot.library.path : %s\n", properties_get("sun.boot.library.path"));
+ #endif
+
+ printf(" java.boot.class.path : %s\n", properties_get("java.boot.class.path"));
+ printf(" java.class.path : %s\n", properties_get("java.class.path"));
+ }
+
+
+ /* 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(char* mainname);
+ #endif
+
+
+ /**
+ * Implementation for JNI_CreateJavaVM. This function creates a VM
+ * object.
+ *
+ * @param p_vm
+ * @param p_env
+ * @param vm_args
+ *
+ * @return true on success, false otherwise.
+ */
+ bool VM::create(JavaVM** p_vm, void** p_env, void* vm_args)
+ {
+ JavaVMInitArgs* _vm_args;
+
+ // Get the arguments for the new JVM.
+ _vm_args = (JavaVMInitArgs *) vm_args;
+
+ // Instantiate a new VM.
+ try {
+ vm = new VM(_vm_args);
+ }
+ catch (std::exception e) {
+ // FIXME How can we delete the resources allocated?
+ // /* release allocated memory */
+ // FREE(env, _Jv_JNIEnv);
+ // FREE(vm, _Jv_JavaVM);
+
+ vm = NULL;
+
+ return false;
+ }
+
+ // Return the values.
+
+ *p_vm = vm->get_javavm();
+ *p_env = vm->get_jnienv();
+
+ return true;
+ }
+
+
+ /**
+ * C wrapper for VM::create.
+ */
+ extern "C" {
+ bool VM_create(JavaVM** p_vm, void** p_env, void* vm_args)
+ {
+ return VM::create(p_vm, p_env, vm_args);
+ }
+ }
+
+
+ /**
+ * VM constructor.
+ */
+ VM::VM(JavaVMInitArgs* vm_args)
+ {
+ // Very first thing to do: we are initializing.
+ _initializing = true;
+
+ // Make ourself globally visible.
+ // XXX Is this a good idea?
+ vm = this;
+
+ /* create and fill a JavaVM structure */
+
+ _javavm = new JavaVM();
+
+ #if defined(ENABLE_JNI)
+ _javavm->functions = &_Jv_JNIInvokeInterface;
+ #endif
+
+ /* get the VM and Env tables (must be set before vm_create) */
+ /* XXX JVMTI Agents needs a JavaVM */
+
+ _jnienv = new JNIEnv();
+
+ #if defined(ENABLE_JNI)
+ _jnienv->functions = &_Jv_JNINativeInterface;
+ #endif
+
+ /* actually create the JVM */
+
+ int len;
+ char *p;
+ char *boot_class_path;
+ char *class_path;
+ int opt;
+ bool opt_version;
+ bool opt_exit;
+
+ #if defined(ENABLE_JVMTI)
+ lt_dlhandle handle;
+ char *libname, *agentarg;
+ bool jdwp,agentbypath;
+ jdwp = agentbypath = false;
+ #endif
+
+ #if defined(ENABLE_JNI)
+ /* Check the JNI version requested. */
+
+ if (!jni_version_check(vm_args->version))
+ throw std::exception();
+ #endif
+
+ /* We only support 1 JVM instance. */
+
+ if (vms > 0)
+ throw std::exception();
+
+ /* Install the exit handler. */
+
+ if (atexit(vm_exit_handler))
+ vm_abort("atexit failed: %s\n", strerror(errno));
+
+ /* Set some options. */
+
+ opt_version = false;
+ opt_exit = false;
+
+ opt_noieee = false;
+
+ opt_heapmaxsize = HEAP_MAXSIZE;
+ opt_heapstartsize = HEAP_STARTSIZE;
+ opt_stacksize = STACK_SIZE;
+
+ /* Initialize the properties list before command-line handling.
+ Otherwise -XX:+PrintConfig crashes. */
+
+ properties_init();
+
+ /* First of all, parse the -XX options. */
+
+ #if defined(ENABLE_VMLOG)
+ vmlog_cacao_init_options();
+ #endif
+
+ options_xx(vm_args);
+
+ #if defined(ENABLE_VMLOG)
+ vmlog_cacao_init();
+ #endif
+
+ /* We need to check if the actual size of a java.lang.Class object
+ is smaller or equal than the assumption made in
+ src/vm/class.h. */
+
+ #warning FIXME We need to check the size of java.lang.Class!!!
+ // if (sizeof(java_lang_Class) > sizeof(dummy_java_lang_Class))
+ // vm_abort("vm_create: java_lang_Class structure is bigger than classinfo.object (%d > %d)", sizeof(java_lang_Class), sizeof(dummy_java_lang_Class));
+
+ /* set the VM starttime */
+
+ _starttime = builtin_currenttimemillis();
+
+ #if defined(ENABLE_JVMTI)
+ /* initialize JVMTI related **********************************************/
+ jvmti = false;
+ #endif
+
+ /* Fill the properties before command-line handling. */
+
+ properties_set();
+
+ /* 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;
+
+ case OPT_JAR:
+ opt_jar = true;
+ break;
+
+ case OPT_D32:
+ #if SIZEOF_VOID_P == 8
+ puts("Running a 32-bit JVM is not supported on this platform.");
+ exit(1);
+ #endif
+ break;
+
+ case OPT_D64:
+ #if SIZEOF_VOID_P == 4
+ puts("Running a 64-bit JVM is not supported on this platform.");
+ exit(1);
+ #endif
+ break;
+
+ case OPT_CLASSPATH:
+ /* Forget old classpath and set the argument as new
+ classpath. */
+
+ // FIXME Make class_path const char*.
+ class_path = (char*) properties_get("java.class.path");
+
+ p = MNEW(char, strlen(opt_arg) + strlen("0"));
+
+ strcpy(p, opt_arg);
+
+ #if defined(ENABLE_JAVASE)
+ properties_add("java.class.path", p);
+ #endif
+
+ MFREE(class_path, char, strlen(class_path));
+ break;
+
+ case OPT_D:
+ for (unsigned int i = 0; i < strlen(opt_arg); i++) {
+ if (opt_arg[i] == '=') {
+ opt_arg[i] = '\0';
+ properties_add(opt_arg, opt_arg + i + 1);
+ goto opt_d_done;
+ }
+ }
+
+ /* if no '=' is given, just create an empty property */
+
+ properties_add(opt_arg, "");
+
+ opt_d_done:
+ break;
+
+ case OPT_BOOTCLASSPATH:
+ /* Forget default bootclasspath and set the argument as
+ new boot classpath. */
+
+ // FIXME Make boot_class_path const char*.
+ boot_class_path = (char*) properties_get("sun.boot.class.path");
+
+ p = MNEW(char, strlen(opt_arg) + strlen("0"));
+
+ strcpy(p, opt_arg);
+
+ properties_add("sun.boot.class.path", p);
+ properties_add("java.boot.class.path", p);
+
+ MFREE(boot_class_path, char, strlen(boot_class_path));
+ break;
+
+ case OPT_BOOTCLASSPATH_A:
+ /* Append to bootclasspath. */
+
+ // FIXME Make boot_class_path const char*.
+ boot_class_path = (char*) properties_get("sun.boot.class.path");
+
+ len = strlen(boot_class_path);
+
+ // XXX (char*) quick hack
+ p = (char*) MREALLOC(boot_class_path,
+ char,
+ len + strlen("0"),
+ len + strlen(":") +
+ strlen(opt_arg) + strlen("0"));
+
+ strcat(p, ":");
+ strcat(p, opt_arg);
+
+ properties_add("sun.boot.class.path", p);
+ properties_add("java.boot.class.path", p);
+ break;
+
+ case OPT_BOOTCLASSPATH_P:
+ /* Prepend to bootclasspath. */
+
+ // FIXME Make boot_class_path const char*.
+ boot_class_path = (char*) properties_get("sun.boot.class.path");
+
+ len = strlen(boot_class_path);
+
+ p = MNEW(char, strlen(opt_arg) + strlen(":") + len + strlen("0"));
+
+ strcpy(p, opt_arg);
+ strcat(p, ":");
+ strcat(p, boot_class_path);
+
+ properties_add("sun.boot.class.path", p);
+ properties_add("java.boot.class.path", p);
+
+ MFREE(boot_class_path, char, len);
+ break;
+
+ case OPT_BOOTCLASSPATH_C:
+ /* Use as Java core library, but prepend VM interface
+ classes. */
+
+ // FIXME Make boot_class_path const char*.
+ boot_class_path = (char*) properties_get("sun.boot.class.path");
+
+ len =
+ strlen(CACAO_VM_ZIP) +
+ strlen(":") +
+ strlen(opt_arg) +
+ strlen("0");
+
+ p = MNEW(char, len);
+
+ strcpy(p, CACAO_VM_ZIP);
+ strcat(p, ":");
+ strcat(p, opt_arg);
+
+ properties_add("sun.boot.class.path", p);
+ properties_add("java.boot.class.path", p);
+
+ MFREE(boot_class_path, char, strlen(boot_class_path));
+ break;
+
+ #if defined(ENABLE_JVMTI)
+ case OPT_DEBUG:
+ /* this option exists only for compatibility reasons */
+ break;
+
+ case OPT_NOAGENT:
+ /* I don't know yet what Xnoagent should do. This is only for
+ compatiblity with eclipse - motse */
+ break;
+
+ case OPT_XRUNJDWP:
+ agentbypath = 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;
+ agentarg = opt_arg;
+ break;
+ #endif
+
+ case OPT_MX:
+ case OPT_MS:
+ case OPT_SS:
+ {
+ char c;
+ int j;
+
+ c = opt_arg[strlen(opt_arg) - 1];
+
+ if ((c == 'k') || (c == 'K')) {
+ j = atoi(opt_arg) * 1024;
+
+ } else if ((c == 'm') || (c == 'M')) {
+ j = atoi(opt_arg) * 1024 * 1024;
+
+ } else
+ j = atoi(opt_arg);
+
+ if (opt == OPT_MX)
+ opt_heapmaxsize = j;
+ else if (opt == OPT_MS)
+ opt_heapstartsize = j;
+ else
+ opt_stacksize = j;
+ }
+ break;
+
+ case OPT_VERBOSE1:
+ opt_verbose = true;
+ break;
+
+ case OPT_VERBOSE:
+ 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;
+ }
+ #if !defined(NDEBUG)
+ else if (strcmp("jit", opt_arg) == 0) {
+ opt_verbose = true;
+ loadverbose = true;
+ initverbose = true;
+ compileverbose = true;
+ }
+ #endif
+ else {
+ printf("Unknown -verbose option: %s\n", opt_arg);
+ usage();
+ }
+ break;
+
+ case OPT_DEBUGCOLOR:
+ opt_debugcolor = true;
+ break;
+
+ #if defined(ENABLE_VERIFIER) && defined(TYPECHECK_VERBOSE)
+ case OPT_VERBOSETC:
+ opt_typecheckverbose = true;
+ break;
+ #endif
+
+ case OPT_VERSION:
+ opt_version = true;
+ opt_exit = true;
+ break;
+
+ case OPT_FULLVERSION:
+ fullversion();
+ break;
+
+ case OPT_SHOWVERSION:
+ opt_version = true;
+ break;
+
+ case OPT_NOIEEE:
+ opt_noieee = true;
+ break;
+
+ #if defined(ENABLE_VERIFIER)
+ case OPT_NOVERIFY:
+ opt_verify = false;
+ break;
+ #endif
+
+ #if defined(ENABLE_STATISTICS)
+ case OPT_TIME:
+ opt_getcompilingtime = true;
+ opt_getloadingtime = true;
+ break;
+
+ case OPT_STAT:
+ opt_stat = true;
+ break;
+ #endif
+
+ case OPT_LOG:
+ log_init(opt_arg);
+ break;
+
+ case OPT_CHECK:
+ for (unsigned int i = 0; i < strlen(opt_arg); i++) {
+ switch (opt_arg[i]) {
+ case 'b':
+ checkbounds = false;
+ break;
+ case 's':
+ checksync = false;
+ break;
+ default:
+ usage();
+ }
+ }
+ break;
+
+ case OPT_LOAD:
+ opt_run = false;
+ makeinitializations = false;
+ 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;
+ #endif
+
+ case OPT_SHOW: /* Display options */
+ for (unsigned int i = 0; i < strlen(opt_arg); i++) {
+ switch (opt_arg[i]) {
+ case 'c':
+ showconstantpool = true;
+ break;
+
+ case 'u':
+ showutf = true;
+ break;
+
+ case 'm':
+ showmethods = true;
+ break;
+
+ case 'i':
+ opt_showintermediate = true;
+ compileverbose = true;
+ break;
+
+ #if defined(ENABLE_DISASSEMBLER)
+ case 'a':
+ opt_showdisassemble = true;
+ compileverbose = true;
+ break;
+
+ case 'o':
+ opt_shownops = true;
+ break;
+ #endif
+
+ case 'd':
+ opt_showddatasegment = true;
+ break;
+
+ default:
+ usage();
+ }
+ }
+ break;
+
+ #if defined(ENABLE_LOOP)
+ case OPT_OLOOP:
+ opt_loops = true;
+ break;
+ #endif
+
+ #if defined(ENABLE_IFCONV)
+ case OPT_IFCONV:
+ opt_ifconv = true;
+ break;
+ #endif
+
+ #if defined(ENABLE_LSRA)
+ case OPT_LSRA:
+ opt_lsra = true;
+ break;
+ #endif
+ #if defined(ENABLE_SSA)
+ case OPT_LSRA:
+ opt_lsra = true;
+ for (unsigned int i = 0; i < strlen(opt_arg); i++) {
+ switch (opt_arg[i]) {
+ case 'c':
+ opt_ssa_cp = true;
+ break;
+
+ case 'd':
+ opt_ssa_dce = true;
+ break;
+
+ case ':':
+ break;
+
+ default:
+ usage();
+ }
+ }
+ break;
+ #endif
+
+ case OPT_HELP:
+ usage();
+ break;
+
+ case OPT_X:
+ Xusage();
+ break;
+
+ case OPT_XX:
+ /* Already parsed. */
+ break;
+
+ case OPT_EA:
+ #if defined(ENABLE_ASSERTION)
+ assertion_ea_da(opt_arg, true);
+ #endif
+ break;
+
+ case OPT_DA:
+ #if defined(ENABLE_ASSERTION)
+ assertion_ea_da(opt_arg, false);
+ #endif
+ break;
+
+ case OPT_EA_NOARG:
+ #if defined(ENABLE_ASSERTION)
+ assertion_user_enabled = true;
+ #endif
+ break;
+
+ case OPT_DA_NOARG:
+ #if defined(ENABLE_ASSERTION)
+ assertion_user_enabled = false;
+ #endif
+ break;
+
+ case OPT_ESA:
+ #if defined(ENABLE_ASSERTION)
+ assertion_system_enabled = true;
+ #endif
+ break;
+
+ case OPT_DSA:
+ #if defined(ENABLE_ASSERTION)
+ assertion_system_enabled = false;
+ #endif
+ break;
+
+ #if defined(ENABLE_PROFILING)
+ case OPT_PROF_OPTION:
+ /* use <= to get the last \0 too */
+
+ for (unsigned int i = 0, j = 0; i <= strlen(opt_arg); i++) {
+ if (opt_arg[i] == ',')
+ opt_arg[i] = '\0';
+
+ if (opt_arg[i] == '\0') {
+ if (strcmp("bb", opt_arg + j) == 0)
+ opt_prof_bb = true;
+
+ else {
+ printf("Unknown option: -Xprof:%s\n", opt_arg + j);
+ usage();
+ }
+
+ /* set k to next char */
+
+ j = i + 1;
+ }
+ }
+ /* fall through */
+
+ case OPT_PROF:
+ opt_prof = true;
+ break;
+ #endif
+
+ 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
+
+ #if defined(ENABLE_DEBUG_FILTER)
+ case OPT_FILTER_VERBOSECALL_INCLUDE:
+ opt_filter_verbosecall_include = opt_arg;
+ break;
+
+ case OPT_FILTER_VERBOSECALL_EXCLUDE:
+ opt_filter_verbosecall_exclude = opt_arg;
+ break;
+
+ case OPT_FILTER_SHOW_METHOD:
+ opt_filter_show_method = opt_arg;
+ break;
+
+ #endif
+ default:
+ printf("Unknown option: %s\n",
+ vm_args->options[opt_index].optionString);
+ usage();
+ }
+ }
+
+ #if defined(ENABLE_JVMTI)
+ if (jvmti) {
+ jvmti_set_phase(JVMTI_PHASE_ONLOAD);
+ jvmti_agentload(agentarg, agentbypath, &handle, &libname);
+
+ if (jdwp)
+ MFREE(agentarg, char, strlen(agentarg));
+
+ jvmti_set_phase(JVMTI_PHASE_PRIMORDIAL);
+ }
+ #endif
+
+ /* initialize the garbage collector */
+
+ gc_init(opt_heapmaxsize, opt_heapstartsize);
+
+ #if defined(ENABLE_THREADS)
+ /* BEFORE: threads_preinit */
+
+ threadlist_init();
+
+ /* AFTER: gc_init */
+
+ threads_preinit();
+ lock_init();
+ #endif
+
+ /* install architecture dependent signal handlers */
+
+ if (!signal_init())
+ vm_abort("vm_create: signal_init failed");
+
+ #if defined(ENABLE_INTRP)
+ /* Allocate main thread stack on the Java heap. */
+
+ if (opt_intrp) {
+ intrp_main_stack = GCMNEW(u1, opt_stacksize);
+ MSET(intrp_main_stack, 0, u1, opt_stacksize);
+ }
+ #endif
+
+ /* AFTER: threads_preinit */
+
+ if (!string_init())
+ vm_abort("vm_create: string_init failed");
+
+ /* AFTER: threads_preinit */
+
+ utf8_init();
+
+ /* AFTER: thread_preinit */
+
+ if (!suck_init())
+ vm_abort("vm_create: suck_init failed");
+
+ suck_add_from_property("java.endorsed.dirs");
+
+ /* Now we have all options handled and we can print the version
+ information.
+
+ AFTER: suck_add_from_property("java.endorsed.dirs"); */
+
+ if (opt_version)
+ version(opt_exit);
+
+ /* AFTER: utf8_init */
+
+ // FIXME Make boot_class_path const char*.
+ boot_class_path = (char*) properties_get("sun.boot.class.path");
+ suck_add(boot_class_path);
+
+ /* initialize the classcache hashtable stuff: lock, hashtable
+ (must be done _after_ threads_preinit) */
+
+ if (!classcache_init())
+ vm_abort("vm_create: classcache_init failed");
+
+ /* Initialize the code memory management. */
+ /* AFTER: threads_preinit */
+
+ codememory_init();
+
+ /* initialize the finalizer stuff (must be done _after_
+ threads_preinit) */
+
+ if (!finalizer_init())
+ vm_abort("vm_create: finalizer_init failed");
+
+ /* Initialize the JIT compiler. */
+
+ jit_init();
+ code_init();
+ methodtree_init();
+
+ #if defined(ENABLE_PYTHON)
+ pythonpass_init();
+ #endif
+
+ /* BEFORE: loader_preinit */
+
+ Package::initialize();
+
+ /* AFTER: utf8_init, classcache_init */
+
+ loader_preinit();
+ linker_preinit();
+
+ /* AFTER: loader_preinit, linker_preinit */
+
+ primitive_init();
+
+ loader_init();
+ linker_init();
+
+ /* AFTER: loader_init, linker_init */
+
+ primitive_postinit();
+ method_init();
+
+ #if defined(ENABLE_JIT)
+ trap_init();
+ #endif
+
+ if (!builtin_init())
+ vm_abort("vm_create: builtin_init failed");
+
+ /* Initialize the native subsystem. */
+ /* BEFORE: threads_init */
+
+ if (!native_init())
+ vm_abort("vm_create: native_init failed");
+
+ /* Register the native methods implemented in the VM. */
+ /* BEFORE: threads_init */
+
+ nativevm_preinit();
+
+ #if defined(ENABLE_JNI)
+ /* Initialize the JNI subsystem (must be done _before_
+ threads_init, as threads_init can call JNI methods
+ (e.g. NewGlobalRef). */
+
+ if (!jni_init())
+ vm_abort("vm_create: jni_init failed");
+ #endif
+
+ #if defined(ENABLE_JNI) || defined(ENABLE_HANDLES)
+ /* Initialize the local reference table for the main thread. */
+ /* BEFORE: threads_init */
+
+ if (!localref_table_init())
+ vm_abort("vm_create: localref_table_init failed");
+ #endif
+
+ /* Iinitialize some important system classes. */
+ /* BEFORE: threads_init */
+
+ initialize_init();
+
+ #if defined(ENABLE_THREADS)
+ threads_init();
+ #endif
+
+ /* Initialize the native VM subsystem. */
+ /* AFTER: threads_init (at least for SUN's classes) */
+
+ nativevm_init();
+
+ #if defined(ENABLE_PROFILING)
+ /* initialize profiling */
+
+ if (!profile_init())
+ vm_abort("vm_create: profile_init failed");
+ #endif
+
+ #if defined(ENABLE_THREADS)
+ /* initialize recompilation */
+
+ if (!recompile_init())
+ vm_abort("vm_create: recompile_init failed");
+
+ /* start the signal handler thread */
+
+ #if defined(__LINUX__)
+ /* XXX Remove for exact-GC. */
+ if (threads_pthreads_implementation_nptl)
+ #endif
+ if (!signal_start_thread())
+ vm_abort("vm_create: signal_start_thread failed");
+
+ /* finally, start the finalizer thread */
+
+ if (!finalizer_start_thread())
+ vm_abort("vm_create: finalizer_start_thread failed");
+
+ # if !defined(NDEBUG)
+ /* start the memory profiling thread */
+
+ if (opt_ProfileMemoryUsage || opt_ProfileGCMemoryUsage)
+ if (!memory_start_thread())
+ vm_abort("vm_create: memory_start_thread failed");
+ # endif
+
+ /* start the recompilation thread (must be done before the
+ profiling thread) */
+
+ if (!recompile_start_thread())
+ vm_abort("vm_create: recompile_start_thread failed");
+
+ # if defined(ENABLE_PROFILING)
+ /* start the profile sampling thread */
+
+ /* if (opt_prof) */
+ /* if (!profile_start_thread()) */
+ /* vm_abort("vm_create: profile_start_thread failed"); */
+ # endif
+ #endif
+
+ #if defined(ENABLE_JVMTI)
+ # if defined(ENABLE_GC_CACAO)
+ /* XXX this will not work with the new indirection cells for classloaders!!! */
+ assert(0);
+ # endif
+ if (jvmti) {
+ /* add agent library to native library hashtable */
+ native_hashtable_library_add(utf_new_char(libname), class_java_lang_Object->classloader, handle);
+ }
+ #endif
+
+ /* Increment the number of VMs. */
+
+ vms++;
+
+ // Initialization is done, VM is created.
+ _created = true;
+ _initializing = false;
+
+ /* Print the VM configuration after all stuff is set and the VM is
+ initialized. */
+
+ if (opt_PrintConfig)
+ vm_printconfig();
+ }
+
+
+ /* vm_run **********************************************************************
+
+ Runs the main-method of the passed class.
+
+ *******************************************************************************/
+
+ void vm_run(JavaVM *vm, JavaVMInitArgs *vm_args)
+ {
+ char* option;
+ char* mainname;
+ char* p;
+ utf *mainutf;
+ classinfo *mainclass;
+ java_handle_t *e;
+ methodinfo *m;
+ java_handle_objectarray_t *oa;
+ s4 oalength;
+ utf *u;
+ java_handle_t *s;
+ int status;
+
+ // Prevent compiler warnings.
+ oa = NULL;
+
+ #if !defined(NDEBUG)
+ if (compileall) {
+ vm_compile_all();
+ return;
+ }
+ #endif
+
+ /* Get the main class plus it's arguments. */
+
+ mainname = NULL;
+
+ if (opt_index < vm_args->nOptions) {
+ /* Get main-class argument. */
+
+ mainname = vm_args->options[opt_index].optionString;
+
+ /* If the main class argument is a jar file, put it into the
+ classpath. */
+
+ if (opt_jar == true) {
+ p = MNEW(char, strlen(mainname) + strlen("0"));
+
+ strcpy(p, mainname);
+
+ #if defined(ENABLE_JAVASE)
+ properties_add("java.class.path", p);
+ #endif
+ }
+ else {
+ /* Replace dots with slashes in the class name. */
+
+ for (unsigned int i = 0; i < strlen(mainname); i++)
+ if (mainname[i] == '.')
+ mainname[i] = '/';
+ }
+
+ /* Build argument array. Move index to first argument. */
+
+ opt_index++;
+
+ oalength = vm_args->nOptions - opt_index;
+
+ oa = builtin_anewarray(oalength, class_java_lang_String);
+
+ for (int i = 0; i < oalength; i++) {
+ option = vm_args->options[opt_index + i].optionString;
+
+ u = utf_new_char(option);
+ s = javastring_new(u);
+
+ array_objectarray_element_set(oa, i, s);
+ }
+ }
+
+ /* Do we have a main-class argument? */
+
+ if (mainname == NULL)
+ usage();
+
+ #if !defined(NDEBUG)
+ if (opt_method != NULL) {
+ vm_compile_method(mainname);
+ return;
+ }
+ #endif
+
+ /* set return value to OK */
+
+ status = 0;
+
+ if (opt_jar == true) {
+ /* open jar file with java.util.jar.JarFile */
+
+ mainname = vm_get_mainclass_from_jar(mainname);
+
+ if (mainname == NULL)
+ vm_exit(1);
+ }
+
+ /* load the main class */
+
+ mainutf = utf_new_char(mainname);
+
+ #if defined(ENABLE_JAVAME_CLDC1_1)
+ mainclass = load_class_bootstrap(mainutf);
+ #else
+ mainclass = load_class_from_sysloader(mainutf);
+ #endif
+
+ /* error loading class */
+
+ e = exceptions_get_and_clear_exception();
+
+ if ((e != NULL) || (mainclass == NULL)) {
+ exceptions_throw_noclassdeffounderror_cause(e);
+ exceptions_print_stacktrace();
+ vm_exit(1);
+ }
+
+ if (!link_class(mainclass)) {
+ exceptions_print_stacktrace();
+ vm_exit(1);
+ }
+
+ /* 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 (exceptions_get_exception()) {
+ exceptions_print_stacktrace();
+ vm_exit(1);
+ }
+
+ /* there is no main method or it isn't static */
+
+ if ((m == NULL) || !(m->flags & ACC_STATIC)) {
+ exceptions_clear_exception();
+ exceptions_throw_nosuchmethoderror(mainclass,
+ utf_new_char("main"),
+ utf_new_char("([Ljava/lang/String;)V"));
+
+ exceptions_print_stacktrace();
+ vm_exit(1);
+ }
+
+ #ifdef TYPEINFO_DEBUG_TEST
+ /* test the typeinfo system */
+ typeinfo_test();
+ #endif
+
+ #if defined(ENABLE_JVMTI)
+ jvmti_set_phase(JVMTI_PHASE_LIVE);
+ #endif
+
+ /* set ThreadMXBean variables */
+
+ // _Jv_jvm->java_lang_management_ThreadMXBean_ThreadCount++;
+ // _Jv_jvm->java_lang_management_ThreadMXBean_TotalStartedThreadCount++;
+
+ // if (_Jv_jvm->java_lang_management_ThreadMXBean_ThreadCount >
+ // _Jv_jvm->java_lang_management_ThreadMXBean_PeakThreadCount)
+ // _Jv_jvm->java_lang_management_ThreadMXBean_PeakThreadCount =
+ // _Jv_jvm->java_lang_management_ThreadMXBean_ThreadCount;
+ #warning Move to C++
+
+ /* start the main thread */
+
+ (void) vm_call_method(m, NULL, oa);
+
+ /* exception occurred? */
+
+ if (exceptions_get_exception()) {
+ exceptions_print_stacktrace();
+ status = 1;
+ }
+
+ #if defined(ENABLE_THREADS)
+ /* Detach the main thread so that it appears to have ended when
+ the application's main method exits. */
+
+ if (!thread_detach_current_thread())
+ vm_abort("vm_run: Could not detach main thread.");
+ #endif
+
+ /* Destroy the JavaVM. */
+
+ (void) vm_destroy(vm);
+
+ /* And exit. */
+
+ vm_exit(status);
+ }
+
+
+ /* vm_destroy ******************************************************************
+
+ Unloads a Java VM and reclaims its resources.
+
+ *******************************************************************************/
+
+ int vm_destroy(JavaVM *vm)
+ {
+ #if defined(ENABLE_THREADS)
+ /* Create a a trivial new Java waiter thread called
+ "DestroyJavaVM". */
+
+ JavaVMAttachArgs args;
+
+ args.name = (char*) "DestroyJavaVM";
+ args.group = NULL;
+
+ if (!thread_attach_current_thread(&args, false))
+ return 1;
+
+ /* Wait until we are the last non-daemon thread. */
+
+ threads_join_all_threads();
+ #endif
+
+ /* VM is gone. */
+
+ // _created = false;
+ #warning Move to C++
+
+ /* Everything is ok. */
+
+ return 0;
+ }
+
+
+ /* vm_exit *********************************************************************
+
+ Calls java.lang.System.exit(I)V to exit the JavaVM correctly.
+
+ *******************************************************************************/
+
+ void vm_exit(s4 status)
+ {
+ methodinfo *m;
+
+ /* signal that we are exiting */
+
+ // _exiting = true;
+ #warning Move to C++
+
+ assert(class_java_lang_System);
+ assert(class_java_lang_System->state & CLASS_LOADED);
+
+ #if defined(ENABLE_JVMTI)
+ if (jvmti || (dbgcom!=NULL)) {
+ jvmti_set_phase(JVMTI_PHASE_DEAD);
+ if (jvmti) jvmti_agentunload();
+ }
+ #endif
+
+ if (!link_class(class_java_lang_System)) {
+ exceptions_print_stacktrace();
+ exit(1);
+ }
+
+ /* call java.lang.System.exit(I)V */
+
+ m = class_resolveclassmethod(class_java_lang_System,
+ utf_new_char("exit"),
+ utf_int__void,
+ class_java_lang_Object,
+ true);
+
+ if (m == NULL) {
+ exceptions_print_stacktrace();
+ exit(1);
+ }
+
+ /* call the exit function with passed exit status */
+
+ (void) vm_call_method(m, NULL, status);
+
+ /* If we had an exception, just ignore the exception and exit with
+ the proper code. */
+
+ vm_shutdown(status);
+ }
+
+
+ /* vm_shutdown *****************************************************************
+
+ Terminates the system immediately without freeing memory explicitly
+ (to be used only for abnormal termination).
+
+ *******************************************************************************/
+
+ void vm_shutdown(s4 status)
+ {
+ if (opt_verbose
+ #if defined(ENABLE_STATISTICS)
+ || opt_getcompilingtime || opt_stat
+ #endif
+ )
+ {
+ log_text("CACAO terminated by shutdown");
+ dolog("Exit status: %d\n", (s4) status);
+
+ }
+
+ #if defined(ENABLE_JVMTI)
+ /* terminate cacaodbgserver */
+ if (dbgcom!=NULL) {
+ mutex_lock(&dbgcomlock);
+ dbgcom->running=1;
+ mutex_unlock(&dbgcomlock);
+ jvmti_cacaodbgserver_quit();
+ }
+ #endif
+
++#if defined (ENABLE_JITCACHE)
++ jitcache_quit();
++#endif
++
+ exit(status);
+ }
+
+
+ /* vm_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 vm_exit_handler(void)
+ {
+ #if !defined(NDEBUG)
+ if (showmethods)
+ class_showmethods(mainclass);
+
+ if (showconstantpool)
+ class_showconstantpool(mainclass);
+
+ if (showutf)
+ utf_show();
+
+ # if defined(ENABLE_PROFILING)
+ if (opt_prof)
+ profile_printstats();
+ # endif
+ #endif /* !defined(NDEBUG) */
+
+ #if defined(ENABLE_RT_TIMING)
+ rt_timing_print_time_stats(stderr);
+ #endif
+
+ #if defined(ENABLE_CYCLES_STATS)
+ builtin_print_cycles_stats(stderr);
+ stacktrace_print_cycles_stats(stderr);
+ #endif
+
+ if (opt_verbose
+ #if defined(ENABLE_STATISTICS)
+ || opt_getcompilingtime || opt_stat
+ #endif
+ )
+ {
+ log_text("CACAO terminated");
+
+ #if defined(ENABLE_STATISTICS)
+ if (opt_stat) {
+ print_stats();
+ #ifdef TYPECHECK_STATISTICS
+ typecheck_print_statistics(get_logfile());
+ #endif
+ }
+
+ if (opt_getcompilingtime)
+ print_times();
+ #endif /* defined(ENABLE_STATISTICS) */
+ }
+ /* vm_print_profile(stderr);*/
+ }
+
+
+ /* vm_abort ********************************************************************
+
+ Prints an error message and aborts the VM.
+
+ IN:
+ text ... error message to print
+
+ *******************************************************************************/
+
+ void vm_abort(const char *text, ...)
+ {
+ va_list ap;
+
+ /* Print the log message. */
+
+ log_start();
+
+ va_start(ap, text);
+ log_vprint(text, ap);
+ va_end(ap);
+
+ log_finish();
+
+ /* Now abort the VM. */
+
+ os::abort();
+ }
+
+
+ /* vm_abort_errnum *************************************************************
+
+ Prints an error message, appends ":" plus the strerror-message of
+ errnum and aborts the VM.
+
+ IN:
+ errnum ... error number
+ text ..... error message to print
+
+ *******************************************************************************/
+
+ void vm_abort_errnum(int errnum, const char *text, ...)
+ {
+ va_list ap;
+
+ /* Print the log message. */
+
+ log_start();
+
+ va_start(ap, text);
+ log_vprint(text, ap);
+ va_end(ap);
+
+ /* Print the strerror-message of errnum. */
+
+ log_print(": %s", os::strerror(errnum));
+
+ log_finish();
+
+ /* Now abort the VM. */
+
+ os::abort();
+ }
+
+
+ /* vm_abort_errno **************************************************************
+
+ Equal to vm_abort_errnum, but uses errno to get the error number.
+
+ IN:
+ text ... error message to print
+
+ *******************************************************************************/
+
+ void vm_abort_errno(const char *text, ...)
+ {
+ va_list ap;
+
+ va_start(ap, text);
+ vm_abort_errnum(errno, text, ap);
+ va_end(ap);
+ }
+
+
+ /* vm_abort_disassemble ********************************************************
+
+ Prints an error message, disassemble the given code range (if
+ enabled) and aborts the VM.
+
+ IN:
+ pc.......PC to disassemble
+ count....number of instructions to disassemble
+
+ *******************************************************************************/
+
+ void vm_abort_disassemble(void *pc, int count, const char *text, ...)
+ {
+ va_list ap;
+ #if defined(ENABLE_DISASSEMBLER)
+ int i;
+ #endif
+
+ /* Print debug message. */
+
+ log_start();
+
+ va_start(ap, text);
+ log_vprint(text, ap);
+ va_end(ap);
+
+ log_finish();
+
+ /* Print the PC. */
+
+ #if SIZEOF_VOID_P == 8
+ log_println("PC=0x%016lx", pc);
+ #else
+ log_println("PC=0x%08x", pc);
+ #endif
+
+ #if defined(ENABLE_DISASSEMBLER)
+ log_println("machine instructions at PC:");
+
+ /* Disassemble the given number of instructions. */
+
+ for (i = 0; i < count; i++)
+ // FIXME disassinstr should use void*.
+ pc = disassinstr((u1*) pc);
+ #endif
+
+ vm_abort("Aborting...");
+ }
+
+
+ /* 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 *mainname)
+ {
+ classinfo *c;
+ java_handle_t *o;
+ methodinfo *m;
+ java_handle_t *s;
+
+ c = load_class_from_sysloader(utf_new_char("java/util/jar/JarFile"));
+
+ if (c == NULL) {
+ exceptions_print_stacktrace();
+ return NULL;
+ }
+
+ /* create JarFile object */
+
+ o = builtin_new(c);
+
+ if (o == NULL) {
+ exceptions_print_stacktrace();
+ return NULL;
+ }
+
+ m = class_resolveclassmethod(c,
+ utf_init,
+ utf_java_lang_String__void,
+ class_java_lang_Object,
+ true);
+
+ if (m == NULL) {
+ exceptions_print_stacktrace();
+ return NULL;
+ }
+
+ s = javastring_new_from_ascii(mainname);
+
+ (void) vm_call_method(m, o, s);
+
+ if (exceptions_get_exception()) {
+ exceptions_print_stacktrace();
+ return NULL;
+ }
+
+ /* 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) {
+ exceptions_print_stacktrace();
+ return NULL;
+ }
+
+ o = vm_call_method(m, o);
+
+ if (o == NULL) {
+ fprintf(stderr, "Could not get manifest from %s (invalid or corrupt jarfile?)\n", mainname);
+ return NULL;
+ }
+
+
+ /* get Main Attributes */
+
+ LLNI_class_get(o, c);
+
+ m = class_resolveclassmethod(c,
+ utf_new_char("getMainAttributes"),
+ utf_new_char("()Ljava/util/jar/Attributes;"),
+ class_java_lang_Object,
+ true);
+
+ if (m == NULL) {
+ exceptions_print_stacktrace();
+ return NULL;
+ }
+
+ o = vm_call_method(m, o);
+
+ if (o == NULL) {
+ fprintf(stderr, "Could not get main attributes from %s (invalid or corrupt jarfile?)\n", mainname);
+ return NULL;
+ }
+
+
+ /* get property Main-Class */
+
+ LLNI_class_get(o, c);
+
+ m = class_resolveclassmethod(c,
+ utf_new_char("getValue"),
+ utf_new_char("(Ljava/lang/String;)Ljava/lang/String;"),
+ class_java_lang_Object,
+ true);
+
+ if (m == NULL) {
+ exceptions_print_stacktrace();
+ return NULL;
+ }
+
+ s = javastring_new_from_ascii("Main-Class");
+
+ o = vm_call_method(m, o, s);
+
+ if (o == NULL) {
+ fprintf(stderr, "Failed to load Main-Class manifest attribute from\n");
+ fprintf(stderr, "%s\n", mainname);
+ return NULL;
+ }
+
+ 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_current_exception();
+
+ /* 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_current_exception();
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ #endif /* !defined(NDEBUG) */
+
+
+ /* vm_compile_method ***********************************************************
+
+ Compile a specific method.
+
+ *******************************************************************************/
+
+ #if !defined(NDEBUG)
+ static void vm_compile_method(char* mainname)
+ {
+ methodinfo *m;
+
+ /* create, load and link the main class */
+
+ mainclass = load_class_bootstrap(utf_new_char(mainname));
+
+ if (mainclass == NULL)
+ exceptions_print_stacktrace();
+
+ if (!link_class(mainclass))
+ exceptions_print_stacktrace();
+
+ 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)
+ vm_abort("vm_compile_method: java.lang.NoSuchMethodException: %s.%s",
+ opt_method, opt_signature ? opt_signature : "");
+
+ jit_compile(m);
+ }
+ #endif /* !defined(NDEBUG) */
+
+
+ /* vm_call_array ***************************************************************
+
+ Calls a Java method with a variable number of arguments, passed via
+ an argument array.
+
+ ATTENTION: This function has to be used outside the nativeworld.
+
+ *******************************************************************************/
+
+ #define VM_CALL_ARRAY(name, type) \
+ static type vm_call##name##_array(methodinfo *m, uint64_t *array) \
+ { \
+ methoddesc *md; \
+ void *pv; \
+ type value; \
+ \
+ assert(m->code != NULL); \
+ \
+ md = m->parseddesc; \
+ pv = m->code->entrypoint; \
+ \
+ STATISTICS(count_calls_native_to_java++); \
+ \
+ value = asm_vm_call_method##name(pv, array, md->memuse); \
+ \
+ return value; \
+ }
+
+ static java_handle_t *vm_call_array(methodinfo *m, uint64_t *array)
+ {
+ methoddesc *md;
+ void *pv;
+ java_object_t *o;
+
+ assert(m->code != NULL);
+
+ md = m->parseddesc;
+ pv = m->code->entrypoint;
+
+ STATISTICS(count_calls_native_to_java++);
+
+ o = asm_vm_call_method(pv, array, md->memuse);
+
+ if (md->returntype.type == TYPE_VOID)
+ o = NULL;
+
+ return LLNI_WRAP(o);
+ }
+
+ VM_CALL_ARRAY(_int, int32_t)
+ VM_CALL_ARRAY(_long, int64_t)
+ VM_CALL_ARRAY(_float, float)
+ VM_CALL_ARRAY(_double, double)
+
+
+ /* vm_call_method **************************************************************
+
+ Calls a Java method with a variable number of arguments.
+
+ *******************************************************************************/
+
+ #define VM_CALL_METHOD(name, type) \
+ type vm_call_method##name(methodinfo *m, java_handle_t *o, ...) \
+ { \
+ va_list ap; \
+ type value; \
+ \
+ va_start(ap, o); \
+ value = vm_call_method##name##_valist(m, o, ap); \
+ va_end(ap); \
+ \
+ return value; \
+ }
+
+ VM_CALL_METHOD(, java_handle_t *)
+ VM_CALL_METHOD(_int, int32_t)
+ VM_CALL_METHOD(_long, int64_t)
+ VM_CALL_METHOD(_float, float)
+ VM_CALL_METHOD(_double, double)
+
+
+ /* vm_call_method_valist *******************************************************
+
+ Calls a Java method with a variable number of arguments, passed via
+ a va_list.
+
+ *******************************************************************************/
+
+ #define VM_CALL_METHOD_VALIST(name, type) \
+ type vm_call_method##name##_valist(methodinfo *m, java_handle_t *o, \
+ va_list ap) \
+ { \
+ uint64_t *array; \
+ type value; \
+ int32_t dumpmarker; \
+ \
+ if (m->code == NULL) \
+ if (!jit_compile(m)) \
+ return 0; \
+ \
+ THREAD_NATIVEWORLD_EXIT; \
+ DMARKER; \
+ \
+ array = argument_vmarray_from_valist(m, o, ap); \
+ value = vm_call##name##_array(m, array); \
+ \
+ DRELEASE; \
+ THREAD_NATIVEWORLD_ENTER; \
+ \
+ return value; \
+ }
+
+ VM_CALL_METHOD_VALIST(, java_handle_t *)
+ VM_CALL_METHOD_VALIST(_int, int32_t)
+ VM_CALL_METHOD_VALIST(_long, int64_t)
+ VM_CALL_METHOD_VALIST(_float, float)
+ VM_CALL_METHOD_VALIST(_double, double)
+
+
+ /* vm_call_method_jvalue *******************************************************
+
+ Calls a Java method with a variable number of arguments, passed via
+ a jvalue array.
+
+ *******************************************************************************/
+
+ #define VM_CALL_METHOD_JVALUE(name, type) \
+ type vm_call_method##name##_jvalue(methodinfo *m, java_handle_t *o, \
+ const jvalue *args) \
+ { \
+ uint64_t *array; \
+ type value; \
+ int32_t dumpmarker; \
+ \
+ if (m->code == NULL) \
+ if (!jit_compile(m)) \
+ return 0; \
+ \
+ THREAD_NATIVEWORLD_EXIT; \
+ DMARKER; \
+ \
+ array = argument_vmarray_from_jvalue(m, o, args); \
+ value = vm_call##name##_array(m, array); \
+ \
+ DRELEASE; \
+ THREAD_NATIVEWORLD_ENTER; \
+ \
+ return value; \
+ }
+
+ VM_CALL_METHOD_JVALUE(, java_handle_t *)
+ VM_CALL_METHOD_JVALUE(_int, int32_t)
+ VM_CALL_METHOD_JVALUE(_long, int64_t)
+ VM_CALL_METHOD_JVALUE(_float, float)
+ VM_CALL_METHOD_JVALUE(_double, double)
+
+
+ /* vm_call_method_objectarray **************************************************
+
+ Calls a Java method with a variable number if arguments, passed via
+ an objectarray of boxed values. Returns a boxed value.
+
+ *******************************************************************************/
+
+ java_handle_t *vm_call_method_objectarray(methodinfo *m, java_handle_t *o,
+ java_handle_objectarray_t *params)
+ {
+ uint64_t *array;
+ java_handle_t *xptr;
+ java_handle_t *ro;
+ imm_union value;
+ int32_t dumpmarker;
+
+ /* Prevent compiler warnings. */
+
+ ro = NULL;
+
+ /* compile methods which are not yet compiled */
+
+ if (m->code == NULL)
+ if (!jit_compile(m))
+ return NULL;
+
+ /* leave the nativeworld */
+
+ THREAD_NATIVEWORLD_EXIT;
+
+ /* mark start of dump memory area */
+
+ DMARKER;
+
+ /* Fill the argument array from a object-array. */
+
+ array = argument_vmarray_from_objectarray(m, o, params);
+
+ if (array == NULL) {
+ /* release dump area */
+
+ DRELEASE;
+
+ /* enter the nativeworld again */
+
+ THREAD_NATIVEWORLD_ENTER;
+
+ exceptions_throw_illegalargumentexception();
+
+ return NULL;
+ }
+
+ switch (m->parseddesc->returntype.primitivetype) {
+ case PRIMITIVETYPE_VOID:
+ value.a = vm_call_array(m, array);
+ break;
+
+ case PRIMITIVETYPE_BOOLEAN:
+ case PRIMITIVETYPE_BYTE:
+ case PRIMITIVETYPE_CHAR:
+ case PRIMITIVETYPE_SHORT:
+ case PRIMITIVETYPE_INT:
+ value.i = vm_call_int_array(m, array);
+ break;
+
+ case PRIMITIVETYPE_LONG:
+ value.l = vm_call_long_array(m, array);
+ break;
+
+ case PRIMITIVETYPE_FLOAT:
+ value.f = vm_call_float_array(m, array);
+ break;
+
+ case PRIMITIVETYPE_DOUBLE:
+ value.d = vm_call_double_array(m, array);
+ break;
+
+ case TYPE_ADR:
+ ro = vm_call_array(m, array);
+ break;
+
+ default:
+ vm_abort("vm_call_method_objectarray: invalid return type %d", m->parseddesc->returntype.primitivetype);
+ }
+
+ /* release dump area */
+
+ DRELEASE;
+
+ /* enter the nativeworld again */
+
+ THREAD_NATIVEWORLD_ENTER;
+
+ /* box the return value if necesarry */
+
+ if (m->parseddesc->returntype.primitivetype != TYPE_ADR)
+ ro = Primitive::box(m->parseddesc->returntype.primitivetype, value);
+
+ /* check for an exception */
+
+ xptr = exceptions_get_exception();
+
+ if (xptr != NULL) {
+ /* clear exception pointer, we are calling JIT code again */
+
+ exceptions_clear_exception();
+
+ exceptions_throw_invocationtargetexception(xptr);
+ }
+
+ return ro;
+ }
+
+
+ /* Legacy C interface *********************************************************/
+
+ extern "C" {
+
+ JavaVM* VM_get_javavm() { return vm->get_javavm(); }
+ JNIEnv* VM_get_jnienv() { return vm->get_jnienv(); }
+ bool VM_is_initializing() { return vm->is_initializing(); }
+ bool VM_is_created() { return vm->is_created(); }
+ int64_t VM_get_starttime() { return vm->get_starttime(); }
+
+ }
+
+
+ /*
+ * 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
+ * Emacs will automagically detect them.
+ * ---------------------------------------------------------------------
+ * Local variables:
+ * mode: c++
+ * indent-tabs-mode: t
+ * c-basic-offset: 4
+ * tab-width: 4
+ * End:
+ * vim:noexpandtab:sw=4:ts=4:
+ */